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
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.
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.
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/>.
21 #include "lib/replace/system/python.h"
22 #include "python/py3compat.h"
26 #include "librpc/ndr/libndr.h"
27 #include "param/provision.h"
28 #include "param/secrets.h"
30 #include "python/modules.h"
31 #include "param/pyparam.h"
32 #include "dynconfig/dynconfig.h"
34 static bool dict_insert(PyObject
* dict
,
41 if (PyDict_SetItemString(dict
, key
, value
) == -1) {
49 static PyObject
*provision_module(void)
51 PyObject
*name
= PyUnicode_FromString("samba.provision");
55 mod
= PyImport_Import(name
);
60 static PyObject
*schema_module(void)
62 PyObject
*name
= PyUnicode_FromString("samba.schema");
66 mod
= PyImport_Import(name
);
71 static PyObject
*ldb_module(void)
73 PyObject
*name
= PyUnicode_FromString("ldb");
77 mod
= PyImport_Import(name
);
82 static PyObject
*PyLdb_FromLdbContext(struct ldb_context
*ldb_ctx
)
85 PyObject
*ldb_mod
= ldb_module();
86 PyTypeObject
*ldb_ctx_type
;
90 ldb_ctx_type
= (PyTypeObject
*)PyObject_GetAttrString(ldb_mod
, "Ldb");
92 ret
= (PyLdbObject
*)ldb_ctx_type
->tp_alloc(ldb_ctx_type
, 0);
95 Py_XDECREF(ldb_ctx_type
);
98 ret
->mem_ctx
= talloc_new(NULL
);
99 ret
->ldb_ctx
= talloc_reference(ret
->mem_ctx
, ldb_ctx
);
100 Py_XDECREF(ldb_ctx_type
);
101 return (PyObject
*)ret
;
104 static PyObject
*call_wrapper(PyObject
*callable
, PyObject
*kwargs
)
107 * Helper for calls with zero non-keyword arguments.
109 PyObject
*empty
= PyTuple_New(0), *result
= NULL
;
111 result
= PyObject_Call(callable
, empty
, kwargs
);
116 NTSTATUS
provision_bare(TALLOC_CTX
*mem_ctx
, struct loadparm_context
*lp_ctx
,
117 struct provision_settings
*settings
,
118 struct provision_result
*result
)
120 const char *configfile
;
121 PyObject
*provision_mod
= NULL
, *provision_dict
= NULL
;
122 PyObject
*provision_fn
= NULL
, *py_result
= NULL
;
123 PyObject
*parameters
= NULL
, *py_lp_ctx
= NULL
, *py_domaindn
= NULL
;
125 struct ldb_context
*samdb
;
126 NTSTATUS status
= NT_STATUS_OK
;
128 DEBUG(0,("Provision for Become-DC test using python\n"));
131 py_update_path(); /* Put the samba path at the start of sys.path */
133 provision_mod
= provision_module();
135 if (provision_mod
== NULL
) {
137 DEBUG(0, ("Unable to import provision Python module.\n"));
138 return NT_STATUS_UNSUCCESSFUL
;
141 provision_dict
= PyModule_GetDict(provision_mod
);
143 if (provision_dict
== NULL
) {
144 DEBUG(0, ("Unable to get dictionary for provision module\n"));
145 return NT_STATUS_UNSUCCESSFUL
;
148 provision_fn
= PyDict_GetItemString(provision_dict
, "provision_become_dc");
149 if (provision_fn
== NULL
) {
151 DEBUG(0, ("Unable to get provision_become_dc function\n"));
152 return NT_STATUS_UNSUCCESSFUL
;
155 DEBUG(0,("New Server in Site[%s]\n",
156 settings
->site_name
));
158 DEBUG(0,("DSA Instance [%s]\n"
159 "\tinvocationId[%s]\n",
160 settings
->ntds_dn_str
,
161 settings
->invocation_id
== NULL
?"None":GUID_string(mem_ctx
, settings
->invocation_id
)));
163 DEBUG(0,("Paths under targetdir[%s]\n",
164 settings
->targetdir
));
165 parameters
= PyDict_New();
167 configfile
= lpcfg_configfile(lp_ctx
);
168 if (configfile
!= NULL
) {
169 if (!dict_insert(parameters
, "smbconf",
170 PyUnicode_FromString(configfile
))) {
171 status
= NT_STATUS_UNSUCCESSFUL
;
176 if (!dict_insert(parameters
,
178 PyUnicode_FromString(settings
->root_dn_str
))) {
179 status
= NT_STATUS_UNSUCCESSFUL
;
182 if (settings
->targetdir
!= NULL
) {
183 if (!dict_insert(parameters
,
185 PyUnicode_FromString(settings
->targetdir
))) {
186 status
= NT_STATUS_UNSUCCESSFUL
;
190 if (!dict_insert(parameters
,
192 PyUnicode_FromString(settings
->netbios_name
))) {
193 status
= NT_STATUS_UNSUCCESSFUL
;
196 if (!dict_insert(parameters
,
198 PyUnicode_FromString(settings
->domain
))) {
199 status
= NT_STATUS_UNSUCCESSFUL
;
202 if (!dict_insert(parameters
,
204 PyUnicode_FromString(settings
->realm
))) {
205 status
= NT_STATUS_UNSUCCESSFUL
;
208 if (settings
->root_dn_str
) {
209 if (!dict_insert(parameters
,
211 PyUnicode_FromString(settings
->root_dn_str
))) {
212 status
= NT_STATUS_UNSUCCESSFUL
;
217 if (settings
->domain_dn_str
) {
218 if (!dict_insert(parameters
,
220 PyUnicode_FromString(settings
->domain_dn_str
))) {
221 status
= NT_STATUS_UNSUCCESSFUL
;
226 if (settings
->schema_dn_str
) {
227 if (!dict_insert(parameters
,
229 PyUnicode_FromString(settings
->schema_dn_str
))) {
230 status
= NT_STATUS_UNSUCCESSFUL
;
234 if (settings
->config_dn_str
) {
235 if (!dict_insert(parameters
,
237 PyUnicode_FromString(settings
->config_dn_str
))) {
238 status
= NT_STATUS_UNSUCCESSFUL
;
242 if (settings
->server_dn_str
) {
243 if (!dict_insert(parameters
,
245 PyUnicode_FromString(settings
->server_dn_str
))) {
246 status
= NT_STATUS_UNSUCCESSFUL
;
250 if (settings
->site_name
) {
251 if (!dict_insert(parameters
,
253 PyUnicode_FromString(settings
->site_name
))) {
254 status
= NT_STATUS_UNSUCCESSFUL
;
259 if (!dict_insert(parameters
,
261 PyUnicode_FromString(settings
->machine_password
))){
262 status
= NT_STATUS_UNSUCCESSFUL
;
266 if (!dict_insert(parameters
,
268 PyLong_FromLong(DEBUGLEVEL
))) {
269 status
= NT_STATUS_UNSUCCESSFUL
;
273 if (!dict_insert(parameters
,
275 PyLong_FromLong(settings
->use_ntvfs
))) {
276 status
= NT_STATUS_UNSUCCESSFUL
;
280 py_result
= call_wrapper(provision_fn
, parameters
);
282 if (py_result
== NULL
) {
283 status
= NT_STATUS_UNSUCCESSFUL
;
287 py_domaindn
= PyObject_GetAttrString(py_result
, "domaindn");
288 result
->domaindn
= talloc_strdup(mem_ctx
, PyUnicode_AsUTF8(py_domaindn
));
291 py_lp_ctx
= PyObject_GetAttrString(py_result
, "lp");
292 if (py_lp_ctx
== NULL
) {
293 DEBUG(0, ("Missing 'lp' attribute\n"));
294 status
= NT_STATUS_UNSUCCESSFUL
;
297 result
->lp_ctx
= lpcfg_from_py_object(mem_ctx
, py_lp_ctx
);
299 samdb
= pyldb_Ldb_AsLdbContext(PyObject_GetAttrString(py_result
, "samdb"));
301 DEBUG(0, ("Missing 'samdb' attribute\n"));
302 status
= NT_STATUS_UNSUCCESSFUL
;
305 result
->samdb
= samdb
;
306 status
= NT_STATUS_OK
;
308 Py_CLEAR(parameters
);
309 Py_CLEAR(provision_mod
);
310 Py_CLEAR(provision_fn
);
311 Py_CLEAR(provision_dict
);
314 Py_CLEAR(py_domaindn
);
315 if (!NT_STATUS_IS_OK(status
)) {
322 static PyObject
*py_dom_sid_FromSid(struct dom_sid
*sid
)
324 PyObject
*mod_security
= NULL
, *dom_sid_Type
= NULL
, *result
= NULL
;
326 mod_security
= PyImport_ImportModule("samba.dcerpc.security");
327 if (mod_security
== NULL
) {
331 dom_sid_Type
= PyObject_GetAttrString(mod_security
, "dom_sid");
332 if (dom_sid_Type
== NULL
) {
333 Py_DECREF(mod_security
);
337 result
= pytalloc_reference((PyTypeObject
*)dom_sid_Type
, sid
);
338 Py_DECREF(mod_security
);
339 Py_DECREF(dom_sid_Type
);
343 NTSTATUS
provision_store_self_join(TALLOC_CTX
*mem_ctx
, struct loadparm_context
*lp_ctx
,
344 struct tevent_context
*event_ctx
,
345 struct provision_store_self_join_settings
*settings
,
346 const char **error_string
)
349 PyObject
*provision_mod
= NULL
, *provision_dict
= NULL
;
350 PyObject
*provision_fn
= NULL
, *py_result
= NULL
;
351 PyObject
*parameters
= NULL
;
352 struct ldb_context
*ldb
= NULL
;
353 TALLOC_CTX
*tmp_mem
= talloc_new(mem_ctx
);
355 NTSTATUS status
= NT_STATUS_OK
;
356 *error_string
= NULL
;
359 status
= NT_STATUS_UNSUCCESSFUL
;
363 /* Create/Open the secrets database */
364 ldb
= secrets_db_create(tmp_mem
, lp_ctx
);
367 = talloc_asprintf(mem_ctx
,
368 "Could not open secrets database");
369 status
= NT_STATUS_CANT_ACCESS_DOMAIN_INFO
;
373 ret
= ldb_transaction_start(ldb
);
375 if (ret
!= LDB_SUCCESS
) {
377 = talloc_asprintf(mem_ctx
,
378 "Could not start transaction on secrets database: %s", ldb_errstring(ldb
));
379 status
= NT_STATUS_CANT_ACCESS_DOMAIN_INFO
;
384 py_update_path(); /* Put the samba path at the start of sys.path */
385 provision_mod
= provision_module();
387 if (provision_mod
== NULL
) {
389 = talloc_asprintf(mem_ctx
, "Unable to import provision Python module.");
390 status
= NT_STATUS_UNSUCCESSFUL
;
394 provision_dict
= PyModule_GetDict(provision_mod
);
396 if (provision_dict
== NULL
) {
398 = talloc_asprintf(mem_ctx
, "Unable to get dictionary for provision module");
399 status
= NT_STATUS_UNSUCCESSFUL
;
403 provision_fn
= PyDict_GetItemString(provision_dict
, "secretsdb_self_join");
404 if (provision_fn
== NULL
) {
406 = talloc_asprintf(mem_ctx
, "Unable to get provision_become_dc function");
407 status
= NT_STATUS_UNSUCCESSFUL
;
411 parameters
= PyDict_New();
413 if(!dict_insert(parameters
,
415 PyLdb_FromLdbContext(ldb
))){
416 status
= NT_STATUS_UNSUCCESSFUL
;
419 if (!dict_insert(parameters
,
421 PyUnicode_FromString(settings
->domain_name
))) {
422 status
= NT_STATUS_UNSUCCESSFUL
;
425 if (settings
->realm
!= NULL
) {
426 if (!dict_insert(parameters
,
428 PyUnicode_FromString(settings
->realm
))) {
429 status
= NT_STATUS_UNSUCCESSFUL
;
433 if (!dict_insert(parameters
,
435 PyUnicode_FromString(settings
->machine_password
))) {
436 status
= NT_STATUS_UNSUCCESSFUL
;
439 if (!dict_insert(parameters
,
441 PyUnicode_FromString(settings
->netbios_name
))) {
442 status
= NT_STATUS_UNSUCCESSFUL
;
447 if (!dict_insert(parameters
,
449 py_dom_sid_FromSid(settings
->domain_sid
))) {
450 status
= NT_STATUS_UNSUCCESSFUL
;
454 if (!dict_insert(parameters
,
455 "secure_channel_type",
456 PyLong_FromLong(settings
->secure_channel_type
))) {
457 status
= NT_STATUS_UNSUCCESSFUL
;
461 if (!dict_insert(parameters
,
462 "key_version_number",
463 PyLong_FromLong(settings
->key_version_number
))) {
464 status
= NT_STATUS_UNSUCCESSFUL
;
468 py_result
= call_wrapper(provision_fn
, parameters
);
470 if (py_result
== NULL
) {
471 ldb_transaction_cancel(ldb
);
472 status
= NT_STATUS_UNSUCCESSFUL
;
476 ret
= ldb_transaction_commit(ldb
);
477 if (ret
!= LDB_SUCCESS
) {
479 = talloc_asprintf(mem_ctx
,
480 "Could not commit transaction on secrets database: %s", ldb_errstring(ldb
));
481 status
= NT_STATUS_INTERNAL_DB_ERROR
;
485 status
= NT_STATUS_OK
;
487 talloc_free(tmp_mem
);
488 Py_CLEAR(parameters
);
489 Py_CLEAR(provision_mod
);
490 Py_CLEAR(provision_dict
);
492 if (!NT_STATUS_IS_OK(status
)) {
500 struct ldb_context
*provision_get_schema(TALLOC_CTX
*mem_ctx
,
501 struct loadparm_context
*lp_ctx
,
502 const char *schema_dn
,
503 DATA_BLOB
*override_prefixmap
)
505 PyObject
*schema_mod
, *schema_dict
, *schema_fn
, *py_result
, *parameters
;
506 PyObject
*py_ldb
= NULL
;
507 struct ldb_context
*ldb_result
= NULL
;
509 py_update_path(); /* Put the samba path at the start of sys.path */
511 schema_mod
= schema_module();
513 if (schema_mod
== NULL
) {
515 DEBUG(0, ("Unable to import schema Python module.\n"));
519 schema_dict
= PyModule_GetDict(schema_mod
);
521 if (schema_dict
== NULL
) {
522 DEBUG(0, ("Unable to get dictionary for schema module\n"));
526 schema_fn
= PyDict_GetItemString(schema_dict
, "ldb_with_schema");
527 if (schema_fn
== NULL
) {
529 DEBUG(0, ("Unable to get schema_get_ldb function\n"));
533 parameters
= PyDict_New();
536 if (!dict_insert(parameters
,
538 PyUnicode_FromString(schema_dn
))) {
543 if (override_prefixmap
) {
544 if (!dict_insert(parameters
,
545 "override_prefixmap",
546 PyBytes_FromStringAndSize(
547 (const char *)override_prefixmap
->data
,
548 override_prefixmap
->length
))) {
553 py_result
= call_wrapper(schema_fn
, parameters
);
555 Py_DECREF(parameters
);
557 if (py_result
== NULL
) {
563 py_ldb
= PyObject_GetAttrString(py_result
, "ldb");
564 Py_DECREF(py_result
);
565 ldb_result
= pyldb_Ldb_AsLdbContext(py_ldb
);
566 if (talloc_reference(mem_ctx
, ldb_result
) == NULL
) {