s4-loadparm: 2nd half of lp_ to lpcfg_ conversion
[bbaumbach/samba-autobuild/.git] / source4 / param / provision.c
1 /* 
2    Unix SMB/CIFS implementation.
3    Samba utility functions
4    Copyright (C) Jelmer Vernooij <jelmer@samba.org> 2008-2009
5    Copyright (C) Andrew Bartlett <abartlet@samba.org> 2005
6
7    This program is free software; you can redistribute it and/or modify
8    it under the terms of the GNU General Public License as published by
9    the Free Software Foundation; either version 3 of the License, or
10    (at your option) any later version.
11    
12    This program is distributed in the hope that it will be useful,
13    but WITHOUT ANY WARRANTY; without even the implied warranty of
14    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15    GNU General Public License for more details.
16    
17    You should have received a copy of the GNU General Public License
18    along with this program.  If not, see <http://www.gnu.org/licenses/>.
19 */
20
21 #include <Python.h>
22 #include "includes.h"
23 #include "auth/auth.h"
24 #include "ldb/include/ldb.h"
25 #include "ldb_errors.h"
26 #include "libcli/raw/libcliraw.h"
27 #include "librpc/ndr/libndr.h"
28
29 #include "param/param.h"
30 #include "param/provision.h"
31 #include "param/secrets.h"
32 #include "lib/talloc/pytalloc.h"
33 #include "librpc/rpc/pyrpc.h"
34 #include "scripting/python/modules.h"
35 #include "lib/ldb/pyldb.h"
36 #include "param/pyparam.h"
37 #include "dynconfig/dynconfig.h"
38
39 static PyObject *provision_module(void)
40 {
41         PyObject *name = PyString_FromString("samba.provision");
42         if (name == NULL)
43                 return NULL;
44         return PyImport_Import(name);
45 }
46
47 static PyObject *schema_module(void)
48 {
49         PyObject *name = PyString_FromString("samba.schema");
50         if (name == NULL)
51                 return NULL;
52         return PyImport_Import(name);
53 }
54
55 static PyObject *ldb_module(void)
56 {
57         PyObject *name = PyString_FromString("ldb");
58         if (name == NULL)
59                 return NULL;
60         return PyImport_Import(name);
61 }
62
63 static PyObject *PyLdb_FromLdbContext(struct ldb_context *ldb_ctx)
64 {
65         PyLdbObject *ret;
66         PyObject *ldb_mod = ldb_module();
67         PyTypeObject *ldb_ctx_type;
68         if (ldb_mod == NULL)
69                 return NULL;
70
71         ldb_ctx_type = (PyTypeObject *)PyObject_GetAttrString(ldb_mod, "Ldb");
72
73         ret = (PyLdbObject *)ldb_ctx_type->tp_alloc(ldb_ctx_type, 0);
74         if (ret == NULL) {
75                 PyErr_NoMemory();
76                 return NULL;
77         }
78         ret->mem_ctx = talloc_new(NULL);
79         ret->ldb_ctx = talloc_reference(ret->mem_ctx, ldb_ctx);
80         return (PyObject *)ret;
81 }
82
83 NTSTATUS provision_bare(TALLOC_CTX *mem_ctx, struct loadparm_context *lp_ctx,
84                         struct provision_settings *settings, 
85                         struct provision_result *result)
86 {
87         const char *configfile;
88         PyObject *provision_mod, *provision_dict, *provision_fn, *py_result, *parameters;
89         
90         DEBUG(0,("Provision for Become-DC test using python\n"));
91
92         Py_Initialize();
93         py_update_path("bin"); /* FIXME: Can't assume this is always the case */
94
95         provision_mod = provision_module();
96
97         if (provision_mod == NULL) {
98                 PyErr_Print();
99                 DEBUG(0, ("Unable to import provision Python module.\n"));
100                 return NT_STATUS_UNSUCCESSFUL;
101         }
102
103         provision_dict = PyModule_GetDict(provision_mod);
104
105         if (provision_dict == NULL) {
106                 DEBUG(0, ("Unable to get dictionary for provision module\n"));
107                 return NT_STATUS_UNSUCCESSFUL;
108         }
109
110         provision_fn = PyDict_GetItemString(provision_dict, "provision_become_dc");
111         if (provision_fn == NULL) {
112                 PyErr_Print();
113                 DEBUG(0, ("Unable to get provision_become_dc function\n"));
114                 return NT_STATUS_UNSUCCESSFUL;
115         }
116         
117         DEBUG(0,("New Server in Site[%s]\n", 
118                  settings->site_name));
119
120         DEBUG(0,("DSA Instance [%s]\n"
121                 "\tinvocationId[%s]\n",
122                 settings->ntds_dn_str,
123                 settings->invocation_id == NULL?"None":GUID_string(mem_ctx, settings->invocation_id)));
124
125         DEBUG(0,("Paths under targetdir[%s]\n",
126                  settings->targetdir));
127         parameters = PyDict_New();
128
129         configfile = lpcfg_configfile(lp_ctx);
130         if (configfile != NULL) {
131                 PyDict_SetItemString(parameters, "smbconf", 
132                                      PyString_FromString(configfile));
133         }
134
135         PyDict_SetItemString(parameters, "rootdn", 
136                                                  PyString_FromString(settings->root_dn_str));
137         if (settings->targetdir != NULL)
138                 PyDict_SetItemString(parameters, "targetdir", 
139                                                          PyString_FromString(settings->targetdir));
140         if (file_exist("setup/provision.smb.conf.dc")) {
141                 PyDict_SetItemString(parameters, "setup_dir",
142                                      PyString_FromString("setup"));
143         } else {
144                 PyDict_SetItemString(parameters, "setup_dir",
145                                      PyString_FromString(dyn_SETUPDIR));
146         }
147         PyDict_SetItemString(parameters, "hostname", 
148                                                  PyString_FromString(settings->netbios_name));
149         PyDict_SetItemString(parameters, "domain", 
150                                                  PyString_FromString(settings->domain));
151         PyDict_SetItemString(parameters, "realm", 
152                                                  PyString_FromString(settings->realm));
153         if (settings->root_dn_str)
154                 PyDict_SetItemString(parameters, "rootdn", 
155                                      PyString_FromString(settings->root_dn_str));
156
157         if (settings->domain_dn_str) 
158                 PyDict_SetItemString(parameters, "domaindn", 
159                                      PyString_FromString(settings->domain_dn_str));
160
161         if (settings->schema_dn_str) 
162                 PyDict_SetItemString(parameters, "schemadn", 
163                                      PyString_FromString(settings->schema_dn_str));
164         
165         if (settings->config_dn_str) 
166                 PyDict_SetItemString(parameters, "configdn", 
167                                      PyString_FromString(settings->config_dn_str));
168         
169         if (settings->server_dn_str) 
170                 PyDict_SetItemString(parameters, "serverdn", 
171                                      PyString_FromString(settings->server_dn_str));
172         
173         if (settings->site_name) 
174                 PyDict_SetItemString(parameters, "sitename", 
175                                      PyString_FromString(settings->site_name));
176
177         PyDict_SetItemString(parameters, "machinepass", 
178                              PyString_FromString(settings->machine_password));
179
180         
181         PyDict_SetItemString(parameters, "debuglevel", PyInt_FromLong(DEBUGLEVEL));
182
183         py_result = PyEval_CallObjectWithKeywords(provision_fn, NULL, parameters);
184
185         Py_DECREF(parameters);
186
187         if (py_result == NULL) {
188                 PyErr_Print();
189                 PyErr_Clear();
190                 return NT_STATUS_UNSUCCESSFUL;
191         }
192
193         result->domaindn = talloc_strdup(mem_ctx, PyString_AsString(PyObject_GetAttrString(py_result, "domaindn")));
194
195         /* FIXME paths */
196         result->lp_ctx = lpcfg_from_py_object(result, PyObject_GetAttrString(py_result, "lp"));
197         result->samdb = PyLdb_AsLdbContext(PyObject_GetAttrString(py_result, "samdb"));
198
199         return NT_STATUS_OK;
200 }
201
202 static PyObject *py_dom_sid_FromSid(struct dom_sid *sid)
203 {
204         PyObject *mod_security, *dom_sid_Type;
205
206         mod_security = PyImport_ImportModule("samba.dcerpc.security");
207         if (mod_security == NULL)
208                 return NULL;
209
210         dom_sid_Type = PyObject_GetAttrString(mod_security, "dom_sid");
211         if (dom_sid_Type == NULL)
212                 return NULL;
213
214         return py_talloc_reference((PyTypeObject *)dom_sid_Type, sid);
215 }
216
217 NTSTATUS provision_store_self_join(TALLOC_CTX *mem_ctx, struct loadparm_context *lp_ctx,
218                                    struct tevent_context *event_ctx,
219                                    struct provision_store_self_join_settings *settings,
220                                    const char **error_string)
221 {
222         int ret;
223         PyObject *provision_mod, *provision_dict, *provision_fn, *py_result, *parameters, *py_sid;
224         struct ldb_context *ldb;
225         TALLOC_CTX *tmp_mem = talloc_new(mem_ctx);
226         if (!tmp_mem) {
227                 return NT_STATUS_NO_MEMORY;
228         }
229
230         /* Open the secrets database */
231         ldb = secrets_db_connect(tmp_mem, event_ctx, lp_ctx);
232         if (!ldb) {
233                 *error_string
234                         = talloc_asprintf(mem_ctx, 
235                                           "Could not open secrets database");
236                 talloc_free(tmp_mem);
237                 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
238         }
239
240         ret = ldb_transaction_start(ldb);
241
242         if (ret != LDB_SUCCESS) {
243                 *error_string
244                         = talloc_asprintf(mem_ctx, 
245                                           "Could not start transaction on secrets database: %s", ldb_errstring(ldb));
246                 talloc_free(tmp_mem);
247                 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
248         }
249
250         Py_Initialize();
251         py_update_path("bin"); /* FIXME: Can't assume this is always the case */
252         provision_mod = provision_module();
253
254         if (provision_mod == NULL) {
255                 PyErr_Print();
256                 *error_string
257                         = talloc_asprintf(mem_ctx, "Unable to import provision Python module.");
258                 talloc_free(tmp_mem);
259                 return NT_STATUS_UNSUCCESSFUL;
260         }
261
262         provision_dict = PyModule_GetDict(provision_mod);
263
264         if (provision_dict == NULL) {
265                 *error_string
266                         = talloc_asprintf(mem_ctx, "Unable to get dictionary for provision module");
267                 talloc_free(tmp_mem);
268                 return NT_STATUS_UNSUCCESSFUL;
269         }
270
271         provision_fn = PyDict_GetItemString(provision_dict, "secretsdb_self_join");
272         if (provision_fn == NULL) {
273                 PyErr_Print();
274                 *error_string
275                         = talloc_asprintf(mem_ctx, "Unable to get provision_become_dc function");
276                 talloc_free(tmp_mem);
277                 return NT_STATUS_UNSUCCESSFUL;
278         }
279         
280         parameters = PyDict_New();
281
282         PyDict_SetItemString(parameters, "secretsdb", 
283                              PyLdb_FromLdbContext(ldb));
284         PyDict_SetItemString(parameters, "domain", 
285                              PyString_FromString(settings->domain_name));
286         if (settings->realm != NULL) {
287                 PyDict_SetItemString(parameters, "realm",
288                                      PyString_FromString(settings->realm));
289         }
290         PyDict_SetItemString(parameters, "machinepass", 
291                              PyString_FromString(settings->machine_password));
292         PyDict_SetItemString(parameters, "netbiosname", 
293                              PyString_FromString(settings->netbios_name));
294
295         py_sid = py_dom_sid_FromSid(settings->domain_sid);
296         if (py_sid == NULL) {
297                 Py_DECREF(parameters);
298                 goto failure;
299         }
300
301         PyDict_SetItemString(parameters, "domainsid", 
302                              py_sid);
303
304         PyDict_SetItemString(parameters, "secure_channel_type", 
305                        PyInt_FromLong(settings->secure_channel_type));
306
307         PyDict_SetItemString(parameters, "key_version_number", 
308                        PyInt_FromLong(settings->key_version_number));
309
310         py_result = PyEval_CallObjectWithKeywords(provision_fn, NULL, parameters);
311
312         Py_DECREF(parameters);
313
314         if (py_result == NULL) {
315                 goto failure;
316         }
317
318         ret = ldb_transaction_commit(ldb);
319         if (ret != LDB_SUCCESS) {
320                 *error_string
321                         = talloc_asprintf(mem_ctx, 
322                                           "Could not commit transaction on secrets database: %s", ldb_errstring(ldb));
323                 talloc_free(tmp_mem);
324                 return NT_STATUS_INTERNAL_DB_ERROR;
325         }
326
327         talloc_free(tmp_mem);
328
329         return NT_STATUS_OK;
330
331 failure:
332         ldb_transaction_cancel(ldb);
333         talloc_free(tmp_mem);
334
335         PyErr_Print();
336         PyErr_Clear();
337         return NT_STATUS_UNSUCCESSFUL;
338 }
339
340
341 struct ldb_context *provision_get_schema(TALLOC_CTX *mem_ctx, struct loadparm_context *lp_ctx,
342                                          DATA_BLOB *override_prefixmap)
343 {
344         const char *setupdir;
345         PyObject *schema_mod, *schema_dict, *schema_fn, *py_result, *parameters;
346         
347         DEBUG(0,("Schema for DRS tests using python\n"));
348
349         Py_Initialize();
350         py_update_path("bin"); /* FIXME: Can't assume this is always the case */
351
352         schema_mod = schema_module();
353
354         if (schema_mod == NULL) {
355                 PyErr_Print();
356                 DEBUG(0, ("Unable to import schema Python module.\n"));
357                 return NULL;
358         }
359
360         schema_dict = PyModule_GetDict(schema_mod);
361
362         if (schema_dict == NULL) {
363                 DEBUG(0, ("Unable to get dictionary for schema module\n"));
364                 return NULL;
365         }
366
367         schema_fn = PyDict_GetItemString(schema_dict, "ldb_with_schema");
368         if (schema_fn == NULL) {
369                 PyErr_Print();
370                 DEBUG(0, ("Unable to get schema_get_ldb function\n"));
371                 return NULL;
372         }
373         
374         parameters = PyDict_New();
375
376         setupdir = lpcfg_setupdir(lp_ctx);
377         PyDict_SetItemString(parameters, "setup_dir", 
378                              PyString_FromString(setupdir));
379         if (override_prefixmap) {
380                 PyDict_SetItemString(parameters, "override_prefixmap",
381                                      PyString_FromStringAndSize((const char *)override_prefixmap->data,
382                                                                 override_prefixmap->length));
383         }
384
385         py_result = PyEval_CallObjectWithKeywords(schema_fn, NULL, parameters);
386
387         Py_DECREF(parameters);
388
389         if (py_result == NULL) {
390                 PyErr_Print();
391                 PyErr_Clear();
392                 return NULL;
393         }
394
395         return PyLdb_AsLdbContext(PyObject_GetAttrString(py_result, "ldb"));
396 }