7bd10ca522cd0efc18adc4a5053660aa3a2aff3b
[kai/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 "lib/ldb_wrap.h"
25 #include "ldb/include/ldb.h"
26 #include "ldb_errors.h"
27 #include "libcli/raw/libcliraw.h"
28 #include "librpc/ndr/libndr.h"
29
30 #include "param/param.h"
31 #include "param/provision.h"
32 #include "param/secrets.h"
33 #include "lib/talloc/pytalloc.h"
34 #include "librpc/rpc/pyrpc.h"
35 #include "scripting/python/modules.h"
36 #include "lib/ldb/pyldb.h"
37 #include "param/pyparam.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 = 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_load_samba_modules();
93         Py_Initialize();
94         py_update_path("bin"); /* FIXME: Can't assume this is always the case */
95
96         provision_mod = provision_module();
97
98         if (provision_mod == NULL) {
99                 PyErr_Print();
100                 DEBUG(0, ("Unable to import provision Python module.\n"));
101                 return NT_STATUS_UNSUCCESSFUL;
102         }
103
104         provision_dict = PyModule_GetDict(provision_mod);
105
106         if (provision_dict == NULL) {
107                 DEBUG(0, ("Unable to get dictionary for provision module\n"));
108                 return NT_STATUS_UNSUCCESSFUL;
109         }
110
111         provision_fn = PyDict_GetItemString(provision_dict, "provision_become_dc");
112         if (provision_fn == NULL) {
113                 PyErr_Print();
114                 DEBUG(0, ("Unable to get provision_become_dc function\n"));
115                 return NT_STATUS_UNSUCCESSFUL;
116         }
117         
118         DEBUG(0,("New Server in Site[%s]\n", 
119                  settings->site_name));
120
121         DEBUG(0,("DSA Instance [%s]\n"
122                 "\tinvocationId[%s]\n",
123                 settings->ntds_dn_str,
124                 settings->invocation_id == NULL?"None":GUID_string(mem_ctx, settings->invocation_id)));
125
126         DEBUG(0,("Pathes under targetdir[%s]\n",
127                  settings->targetdir));
128         parameters = PyDict_New();
129
130         configfile = lp_configfile(lp_ctx);
131         if (configfile != NULL) {
132                 PyDict_SetItemString(parameters, "smbconf", 
133                                      PyString_FromString(configfile));
134         }
135
136         PyDict_SetItemString(parameters, "rootdn", 
137                                                  PyString_FromString(settings->root_dn_str));
138         if (settings->targetdir != NULL)
139                 PyDict_SetItemString(parameters, "targetdir", 
140                                                          PyString_FromString(settings->targetdir));
141         PyDict_SetItemString(parameters, "setup_dir", 
142                              PyString_FromString("setup"));
143         PyDict_SetItemString(parameters, "hostname", 
144                                                  PyString_FromString(settings->netbios_name));
145         PyDict_SetItemString(parameters, "domain", 
146                                                  PyString_FromString(settings->domain));
147         PyDict_SetItemString(parameters, "realm", 
148                                                  PyString_FromString(settings->realm));
149         if (settings->root_dn_str)
150                 PyDict_SetItemString(parameters, "rootdn", 
151                                      PyString_FromString(settings->root_dn_str));
152
153         if (settings->domain_dn_str) 
154                 PyDict_SetItemString(parameters, "domaindn", 
155                                      PyString_FromString(settings->domain_dn_str));
156
157         if (settings->schema_dn_str) 
158                 PyDict_SetItemString(parameters, "schemadn", 
159                                      PyString_FromString(settings->schema_dn_str));
160         
161         if (settings->config_dn_str) 
162                 PyDict_SetItemString(parameters, "configdn", 
163                                      PyString_FromString(settings->config_dn_str));
164         
165         if (settings->server_dn_str) 
166                 PyDict_SetItemString(parameters, "serverdn", 
167                                      PyString_FromString(settings->server_dn_str));
168         
169         if (settings->site_name) 
170                 PyDict_SetItemString(parameters, "sitename", 
171                                      PyString_FromString(settings->site_name));
172
173         PyDict_SetItemString(parameters, "machinepass", 
174                              PyString_FromString(settings->machine_password));
175
176         
177         PyDict_SetItemString(parameters, "debuglevel", PyInt_FromLong(DEBUGLEVEL));
178
179         py_result = PyEval_CallObjectWithKeywords(provision_fn, NULL, parameters);
180
181         Py_DECREF(parameters);
182
183         if (py_result == NULL) {
184                 PyErr_Print();
185                 PyErr_Clear();
186                 return NT_STATUS_UNSUCCESSFUL;
187         }
188
189         result->domaindn = talloc_strdup(mem_ctx, PyString_AsString(PyObject_GetAttrString(py_result, "domaindn")));
190
191         /* FIXME paths */
192         result->lp_ctx = lp_from_py_object(PyObject_GetAttrString(py_result, "lp"));
193         result->samdb = PyLdb_AsLdbContext(PyObject_GetAttrString(py_result, "samdb"));
194
195         return NT_STATUS_OK;
196 }
197
198 static PyObject *py_dom_sid_FromSid(struct dom_sid *sid)
199 {
200         PyObject *mod_security, *dom_sid_Type;
201
202         mod_security = PyImport_ImportModule("samba.dcerpc.security");
203         if (mod_security == NULL)
204                 return NULL;
205
206         dom_sid_Type = PyObject_GetAttrString(mod_security, "dom_sid");
207         if (dom_sid_Type == NULL)
208                 return NULL;
209
210         return py_talloc_reference((PyTypeObject *)dom_sid_Type, sid);
211 }
212
213 NTSTATUS provision_store_self_join(TALLOC_CTX *mem_ctx, struct loadparm_context *lp_ctx,
214                                    struct tevent_context *event_ctx,
215                                    struct provision_store_self_join_settings *settings,
216                                    const char **error_string)
217 {
218         int ret;
219         PyObject *provision_mod, *provision_dict, *provision_fn, *py_result, *parameters, *py_sid;
220         struct ldb_context *ldb;
221         TALLOC_CTX *tmp_mem = talloc_new(mem_ctx);
222         if (!tmp_mem) {
223                 return NT_STATUS_NO_MEMORY;
224         }
225
226         /* Open the secrets database */
227         ldb = secrets_db_connect(tmp_mem, event_ctx, lp_ctx);
228         if (!ldb) {
229                 *error_string
230                         = talloc_asprintf(mem_ctx, 
231                                           "Could not open secrets database");
232                 talloc_free(tmp_mem);
233                 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
234         }
235
236         ret = ldb_transaction_start(ldb);
237
238         if (ret != LDB_SUCCESS) {
239                 *error_string
240                         = talloc_asprintf(mem_ctx, 
241                                           "Could not start transaction on secrets database: %s", ldb_errstring(ldb));
242                 talloc_free(tmp_mem);
243                 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
244         }
245
246         py_load_samba_modules();
247         Py_Initialize();
248         py_update_path("bin"); /* FIXME: Can't assume this is always the case */
249         provision_mod = provision_module();
250
251         if (provision_mod == NULL) {
252                 PyErr_Print();
253                 *error_string
254                         = talloc_asprintf(mem_ctx, "Unable to import provision Python module.");
255                 talloc_free(tmp_mem);
256                 return NT_STATUS_UNSUCCESSFUL;
257         }
258
259         provision_dict = PyModule_GetDict(provision_mod);
260
261         if (provision_dict == NULL) {
262                 *error_string
263                         = talloc_asprintf(mem_ctx, "Unable to get dictionary for provision module");
264                 talloc_free(tmp_mem);
265                 return NT_STATUS_UNSUCCESSFUL;
266         }
267
268         provision_fn = PyDict_GetItemString(provision_dict, "secretsdb_self_join");
269         if (provision_fn == NULL) {
270                 PyErr_Print();
271                 *error_string
272                         = talloc_asprintf(mem_ctx, "Unable to get provision_become_dc function");
273                 talloc_free(tmp_mem);
274                 return NT_STATUS_UNSUCCESSFUL;
275         }
276         
277         parameters = PyDict_New();
278
279         PyDict_SetItemString(parameters, "secretsdb", 
280                              PyLdb_FromLdbContext(ldb));
281         PyDict_SetItemString(parameters, "domain", 
282                              PyString_FromString(settings->domain_name));
283         PyDict_SetItemString(parameters, "realm", 
284                              PyString_FromString(settings->realm));
285         PyDict_SetItemString(parameters, "machinepass", 
286                              PyString_FromString(settings->machine_password));
287         PyDict_SetItemString(parameters, "netbiosname", 
288                              PyString_FromString(settings->netbios_name));
289
290         py_sid = py_dom_sid_FromSid(settings->domain_sid);
291         if (py_sid == NULL) {
292                 Py_DECREF(parameters);
293                 goto failure;
294         }
295
296         PyDict_SetItemString(parameters, "domainsid", 
297                              py_sid);
298
299         PyDict_SetItemString(parameters, "secure_channel_type", 
300                        PyInt_FromLong(settings->secure_channel_type));
301
302         PyDict_SetItemString(parameters, "key_version_number", 
303                        PyInt_FromLong(settings->key_version_number));
304
305         py_result = PyEval_CallObjectWithKeywords(provision_fn, NULL, parameters);
306
307         Py_DECREF(parameters);
308
309         if (py_result == NULL) {
310                 goto failure;
311         }
312
313         ret = ldb_transaction_commit(ldb);
314         if (ret != LDB_SUCCESS) {
315                 *error_string
316                         = talloc_asprintf(mem_ctx, 
317                                           "Could not commit transaction on secrets database: %s", ldb_errstring(ldb));
318                 talloc_free(tmp_mem);
319                 return NT_STATUS_INTERNAL_DB_ERROR;
320         }
321
322         talloc_free(tmp_mem);
323
324         return NT_STATUS_OK;
325
326 failure:
327         ldb_transaction_cancel(ldb);
328         talloc_free(tmp_mem);
329
330         PyErr_Print();
331         PyErr_Clear();
332         return NT_STATUS_UNSUCCESSFUL;
333 }
334
335
336 struct ldb_context *provision_get_schema(TALLOC_CTX *mem_ctx, struct loadparm_context *lp_ctx)
337 {
338         const char *setupdir;
339         PyObject *schema_mod, *schema_dict, *schema_fn, *py_result, *parameters;
340         
341         DEBUG(0,("Schema for DRS tests using python\n"));
342
343         py_load_samba_modules();
344         Py_Initialize();
345         py_update_path("bin"); /* FIXME: Can't assume this is always the case */
346
347         schema_mod = schema_module();
348
349         if (schema_mod == NULL) {
350                 PyErr_Print();
351                 DEBUG(0, ("Unable to import schema Python module.\n"));
352                 return NULL;
353         }
354
355         schema_dict = PyModule_GetDict(schema_mod);
356
357         if (schema_dict == NULL) {
358                 DEBUG(0, ("Unable to get dictionary for schema module\n"));
359                 return NULL;
360         }
361
362         schema_fn = PyDict_GetItemString(schema_dict, "ldb_with_schema");
363         if (schema_fn == NULL) {
364                 PyErr_Print();
365                 DEBUG(0, ("Unable to get schema_get_ldb function\n"));
366                 return NULL;
367         }
368         
369         parameters = PyDict_New();
370
371         setupdir = lp_setupdir(lp_ctx);
372         PyDict_SetItemString(parameters, "setup_dir", 
373                              PyString_FromString(setupdir));
374
375         py_result = PyEval_CallObjectWithKeywords(schema_fn, NULL, parameters);
376
377         Py_DECREF(parameters);
378
379         if (py_result == NULL) {
380                 PyErr_Print();
381                 PyErr_Clear();
382                 return NULL;
383         }
384
385         return PyLdb_AsLdbContext(PyObject_GetAttrString(py_result, "ldb"));
386 }