2 Unix SMB/CIFS implementation.
3 Copyright (C) Jelmer Vernooij <jelmer@samba.org> 2007
4 Copyright (C) Matthias Dieter Wallnöfer 2009
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 3 of the License, or
9 (at your option) any later version.
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program. If not, see <http://www.gnu.org/licenses/>.
23 #include "ldb_errors.h"
25 #include "param/param.h"
26 #include "auth/credentials/credentials.h"
27 #include "dsdb/samdb/samdb.h"
28 #include "lib/ldb-samba/ldif_handlers.h"
29 #include "librpc/ndr/libndr.h"
31 #include "lib/ldb/pyldb.h"
32 #include "libcli/util/pyerrors.h"
33 #include "libcli/security/security.h"
34 #include "auth/pyauth.h"
35 #include "param/pyparam.h"
36 #include "auth/credentials/pycredentials.h"
38 /* FIXME: These should be in a header file somewhere, once we finish moving
39 * away from SWIG .. */
40 #define PyErr_LDB_OR_RAISE(py_ldb, ldb) \
41 /* if (!PyLdb_Check(py_ldb)) { \
42 PyErr_SetString(py_ldb_get_exception(), "Ldb connection object required"); \
45 ldb = PyLdb_AsLdbContext(py_ldb);
47 static void PyErr_SetLdbError(PyObject *error, int ret, struct ldb_context *ldb_ctx)
49 if (ret == LDB_ERR_PYTHON_EXCEPTION)
50 return; /* Python exception should already be set, just keep that */
52 PyErr_SetObject(error,
53 Py_BuildValue(discard_const_p(char, "(i,s)"), ret,
54 ldb_ctx == NULL?ldb_strerror(ret):ldb_errstring(ldb_ctx)));
57 static PyObject *py_ldb_get_exception(void)
59 PyObject *mod = PyImport_ImportModule("ldb");
63 return PyObject_GetAttrString(mod, "LdbError");
66 static PyObject *py_generate_random_str(PyObject *self, PyObject *args)
71 if (!PyArg_ParseTuple(args, "i", &len))
74 retstr = generate_random_str(NULL, len);
75 ret = PyString_FromString(retstr);
80 static PyObject *py_unix2nttime(PyObject *self, PyObject *args)
84 if (!PyArg_ParseTuple(args, "I", &t))
87 unix_to_nt_time(&nt, t);
89 return PyInt_FromLong((uint64_t)nt);
92 static PyObject *py_set_debug_level(PyObject *self, PyObject *args)
95 if (!PyArg_ParseTuple(args, "I", &level))
101 static PyObject *py_ldb_set_session_info(PyObject *self, PyObject *args)
103 PyObject *py_session_info, *py_ldb;
104 struct auth_session_info *info;
105 struct ldb_context *ldb;
106 if (!PyArg_ParseTuple(args, "OO", &py_ldb, &py_session_info))
109 PyErr_LDB_OR_RAISE(py_ldb, ldb);
110 /*if (!PyAuthSession_Check(py_session_info)) {
111 PyErr_SetString(PyExc_TypeError, "Expected session info object");
115 info = PyAuthSession_AsSession(py_session_info);
117 ldb_set_opaque(ldb, "sessionInfo", info);
122 static PyObject *py_ldb_set_credentials(PyObject *self, PyObject *args)
124 PyObject *py_creds, *py_ldb;
125 struct cli_credentials *creds;
126 struct ldb_context *ldb;
127 if (!PyArg_ParseTuple(args, "OO", &py_ldb, &py_creds))
130 PyErr_LDB_OR_RAISE(py_ldb, ldb);
132 creds = cli_credentials_from_py_object(py_creds);
134 PyErr_SetString(PyExc_TypeError, "Expected credentials object");
138 ldb_set_opaque(ldb, "credentials", creds);
143 static PyObject *py_ldb_set_loadparm(PyObject *self, PyObject *args)
145 PyObject *py_lp_ctx, *py_ldb;
146 struct loadparm_context *lp_ctx;
147 struct ldb_context *ldb;
148 if (!PyArg_ParseTuple(args, "OO", &py_ldb, &py_lp_ctx))
151 PyErr_LDB_OR_RAISE(py_ldb, ldb);
153 lp_ctx = lp_from_py_object(py_lp_ctx);
154 if (lp_ctx == NULL) {
155 PyErr_SetString(PyExc_TypeError, "Expected loadparm object");
159 ldb_set_opaque(ldb, "loadparm", lp_ctx);
164 static PyObject *py_ldb_set_utf8_casefold(PyObject *self, PyObject *args)
167 struct ldb_context *ldb;
169 if (!PyArg_ParseTuple(args, "O", &py_ldb))
172 PyErr_LDB_OR_RAISE(py_ldb, ldb);
174 ldb_set_utf8_fns(ldb, NULL, wrap_casefold);
179 static PyObject *py_samdb_set_domain_sid(PyLdbObject *self, PyObject *args)
181 PyObject *py_ldb, *py_sid;
182 struct ldb_context *ldb;
186 if (!PyArg_ParseTuple(args, "OO", &py_ldb, &py_sid))
189 PyErr_LDB_OR_RAISE(py_ldb, ldb);
191 sid = dom_sid_parse_talloc(NULL, PyString_AsString(py_sid));
193 ret = samdb_set_domain_sid(ldb, sid);
195 PyErr_SetString(PyExc_RuntimeError, "set_domain_sid failed");
201 static PyObject *py_samdb_get_domain_sid(PyLdbObject *self, PyObject *args)
204 struct ldb_context *ldb;
205 const struct dom_sid *sid;
209 if (!PyArg_ParseTuple(args, "O", &py_ldb))
212 PyErr_LDB_OR_RAISE(py_ldb, ldb);
214 sid = samdb_domain_sid(ldb);
216 PyErr_SetString(PyExc_RuntimeError, "samdb_domain_sid failed");
219 retstr = dom_sid_string(NULL, sid);
220 ret = PyString_FromString(retstr);
225 static PyObject *py_ldb_register_samba_handlers(PyObject *self, PyObject *args)
228 struct ldb_context *ldb;
231 if (!PyArg_ParseTuple(args, "O", &py_ldb))
234 PyErr_LDB_OR_RAISE(py_ldb, ldb);
235 ret = ldb_register_samba_handlers(ldb);
237 PyErr_LDB_ERROR_IS_ERR_RAISE(py_ldb_get_exception(), ret, ldb);
241 static PyObject *py_dsdb_set_ntds_invocation_id(PyObject *self, PyObject *args)
243 PyObject *py_ldb, *py_guid;
246 struct ldb_context *ldb;
247 if (!PyArg_ParseTuple(args, "OO", &py_ldb, &py_guid))
250 PyErr_LDB_OR_RAISE(py_ldb, ldb);
251 GUID_from_string(PyString_AsString(py_guid), &guid);
253 ret = samdb_set_ntds_invocation_id(ldb, &guid);
255 PyErr_SetString(PyExc_RuntimeError, "set_ntds_invocation_id failed");
261 static PyObject *py_dsdb_set_opaque_integer(PyObject *self, PyObject *args)
265 int *old_val, *new_val;
266 char *py_opaque_name, *opaque_name_talloc;
267 struct ldb_context *ldb;
270 if (!PyArg_ParseTuple(args, "Osi", &py_ldb, &py_opaque_name, &value))
273 PyErr_LDB_OR_RAISE(py_ldb, ldb);
275 /* see if we have a cached copy */
276 old_val = (int *)ldb_get_opaque(ldb,
284 tmp_ctx = talloc_new(ldb);
285 if (tmp_ctx == NULL) {
289 new_val = talloc(tmp_ctx, int);
294 opaque_name_talloc = talloc_strdup(tmp_ctx, py_opaque_name);
295 if (!opaque_name_talloc) {
301 /* cache the domain_sid in the ldb */
302 if (ldb_set_opaque(ldb, opaque_name_talloc, new_val) != LDB_SUCCESS) {
306 talloc_steal(ldb, new_val);
307 talloc_steal(ldb, opaque_name_talloc);
308 talloc_free(tmp_ctx);
313 talloc_free(tmp_ctx);
314 PyErr_SetString(PyExc_RuntimeError, "Failed to set opaque integer into the ldb!\n");
318 static PyObject *py_dsdb_set_global_schema(PyObject *self, PyObject *args)
321 struct ldb_context *ldb;
323 if (!PyArg_ParseTuple(args, "O", &py_ldb))
326 PyErr_LDB_OR_RAISE(py_ldb, ldb);
328 ret = dsdb_set_global_schema(ldb);
329 PyErr_LDB_ERROR_IS_ERR_RAISE(py_ldb_get_exception(), ret, ldb);
334 static PyObject *py_dsdb_set_schema_from_ldif(PyObject *self, PyObject *args)
339 struct ldb_context *ldb;
341 if (!PyArg_ParseTuple(args, "Oss", &py_ldb, &pf, &df))
344 PyErr_LDB_OR_RAISE(py_ldb, ldb);
346 result = dsdb_set_schema_from_ldif(ldb, pf, df);
347 PyErr_WERROR_IS_ERR_RAISE(result);
352 static PyObject *py_dsdb_convert_schema_to_openldap(PyObject *self, PyObject *args)
354 char *target_str, *mapping;
356 struct ldb_context *ldb;
360 if (!PyArg_ParseTuple(args, "Oss", &py_ldb, &target_str, &mapping))
363 PyErr_LDB_OR_RAISE(py_ldb, ldb);
365 retstr = dsdb_convert_schema_to_openldap(ldb, target_str, mapping);
367 PyErr_SetString(PyExc_RuntimeError, "dsdb_convert_schema_to_openldap failed");
370 ret = PyString_FromString(retstr);
375 static PyObject *py_dsdb_write_prefixes_from_schema_to_ldb(PyObject *self, PyObject *args)
378 struct ldb_context *ldb;
380 struct dsdb_schema *schema;
382 if (!PyArg_ParseTuple(args, "O", &py_ldb))
385 PyErr_LDB_OR_RAISE(py_ldb, ldb);
387 schema = dsdb_get_schema(ldb);
389 PyErr_SetString(PyExc_RuntimeError, "Failed to set find a schema on ldb!\n");
393 result = dsdb_write_prefixes_from_schema_to_ldb(NULL, ldb, schema);
394 PyErr_WERROR_IS_ERR_RAISE(result);
399 static PyObject *py_dsdb_set_schema_from_ldb(PyObject *self, PyObject *args)
402 struct ldb_context *ldb;
403 PyObject *py_from_ldb;
404 struct ldb_context *from_ldb;
405 struct dsdb_schema *schema;
407 if (!PyArg_ParseTuple(args, "OO", &py_ldb, &py_from_ldb))
410 PyErr_LDB_OR_RAISE(py_ldb, ldb);
412 PyErr_LDB_OR_RAISE(py_from_ldb, from_ldb);
414 schema = dsdb_get_schema(from_ldb);
416 PyErr_SetString(PyExc_RuntimeError, "Failed to set find a schema on 'from' ldb!\n");
420 ret = dsdb_reference_schema(ldb, schema, true);
421 PyErr_LDB_ERROR_IS_ERR_RAISE(py_ldb_get_exception(), ret, ldb);
426 static PyObject *py_dsdb_make_schema_global(PyObject *self, PyObject *args)
429 struct ldb_context *ldb;
431 if (!PyArg_ParseTuple(args, "O", &py_ldb))
434 PyErr_LDB_OR_RAISE(py_ldb, ldb);
436 dsdb_make_schema_global(ldb);
441 static PyObject *py_dsdb_load_partition_usn(PyObject *self, PyObject *args)
443 PyObject *py_dn, *py_ldb, *result;
445 uint64_t highest_uSN, urgent_uSN;
446 struct ldb_context *ldb;
450 mem_ctx = talloc_new(NULL);
451 if (mem_ctx == NULL) {
456 if (!PyArg_ParseTuple(args, "OO", &py_ldb, &py_dn)) {
457 talloc_free(mem_ctx);
461 PyErr_LDB_OR_RAISE(py_ldb, ldb);
463 if (!PyObject_AsDn(mem_ctx, py_dn, ldb, &dn)) {
464 talloc_free(mem_ctx);
468 ret = dsdb_load_partition_usn(ldb, dn, &highest_uSN, &urgent_uSN);
469 if (ret != LDB_SUCCESS) {
470 char *errstr = talloc_asprintf(mem_ctx, "Failed to load partition uSN - %s", ldb_errstring(ldb));
471 PyErr_SetString(PyExc_RuntimeError, errstr);
472 talloc_free(mem_ctx);
476 talloc_free(mem_ctx);
478 result = PyDict_New();
480 PyDict_SetItemString(result, "uSNHighest", PyInt_FromLong((uint64_t)highest_uSN));
481 PyDict_SetItemString(result, "uSNUrgent", PyInt_FromLong((uint64_t)urgent_uSN));
489 static PyMethodDef py_misc_methods[] = {
490 { "generate_random_str", (PyCFunction)py_generate_random_str, METH_VARARGS,
491 "random_password(len) -> string\n"
492 "Generate random password with specified length." },
493 { "unix2nttime", (PyCFunction)py_unix2nttime, METH_VARARGS,
494 "unix2nttime(timestamp) -> nttime" },
495 { "ldb_set_session_info", (PyCFunction)py_ldb_set_session_info, METH_VARARGS,
496 "ldb_set_session_info(ldb, session_info)\n"
497 "Set session info to use when connecting." },
498 { "ldb_set_credentials", (PyCFunction)py_ldb_set_credentials, METH_VARARGS,
499 "ldb_set_credentials(ldb, credentials)\n"
500 "Set credentials to use when connecting." },
501 { "ldb_set_loadparm", (PyCFunction)py_ldb_set_loadparm, METH_VARARGS,
502 "ldb_set_loadparm(ldb, session_info)\n"
503 "Set loadparm context to use when connecting." },
504 { "samdb_set_domain_sid", (PyCFunction)py_samdb_set_domain_sid, METH_VARARGS,
505 "samdb_set_domain_sid(samdb, sid)\n"
506 "Set SID of domain to use." },
507 { "samdb_get_domain_sid", (PyCFunction)py_samdb_get_domain_sid, METH_VARARGS,
508 "samdb_get_domain_sid(samdb)\n"
509 "Get SID of domain in use." },
510 { "ldb_register_samba_handlers", (PyCFunction)py_ldb_register_samba_handlers, METH_VARARGS,
511 "ldb_register_samba_handlers(ldb)\n"
512 "Register Samba-specific LDB modules and schemas." },
513 { "ldb_set_utf8_casefold", (PyCFunction)py_ldb_set_utf8_casefold, METH_VARARGS,
514 "ldb_set_utf8_casefold(ldb)\n"
515 "Set the right Samba casefolding function for UTF8 charset." },
516 { "dsdb_set_ntds_invocation_id", (PyCFunction)py_dsdb_set_ntds_invocation_id, METH_VARARGS,
518 { "dsdb_set_opaque_integer", (PyCFunction)py_dsdb_set_opaque_integer, METH_VARARGS,
520 { "dsdb_set_global_schema", (PyCFunction)py_dsdb_set_global_schema, METH_VARARGS,
522 { "dsdb_set_schema_from_ldif", (PyCFunction)py_dsdb_set_schema_from_ldif, METH_VARARGS,
524 { "dsdb_write_prefixes_from_schema_to_ldb", (PyCFunction)py_dsdb_write_prefixes_from_schema_to_ldb, METH_VARARGS,
526 { "dsdb_set_schema_from_ldb", (PyCFunction)py_dsdb_set_schema_from_ldb, METH_VARARGS,
528 { "dsdb_convert_schema_to_openldap", (PyCFunction)py_dsdb_convert_schema_to_openldap, METH_VARARGS,
530 { "dsdb_make_schema_global", (PyCFunction)py_dsdb_make_schema_global, METH_VARARGS,
532 { "set_debug_level", (PyCFunction)py_set_debug_level, METH_VARARGS,
534 { "dsdb_load_partition_usn", (PyCFunction)py_dsdb_load_partition_usn, METH_VARARGS,
535 "get uSNHighest and uSNUrgent from the partition @REPLCHANGED"},
543 m = Py_InitModule3("glue", py_misc_methods,
544 "Python bindings for miscellaneous Samba functions.");
548 PyModule_AddObject(m, "version", PyString_FromString(SAMBA_VERSION_STRING));
550 /* "userAccountControl" flags */
551 PyModule_AddObject(m, "UF_NORMAL_ACCOUNT", PyInt_FromLong(UF_NORMAL_ACCOUNT));
552 PyModule_AddObject(m, "UF_TEMP_DUPLICATE_ACCOUNT", PyInt_FromLong(UF_TEMP_DUPLICATE_ACCOUNT));
553 PyModule_AddObject(m, "UF_SERVER_TRUST_ACCOUNT", PyInt_FromLong(UF_SERVER_TRUST_ACCOUNT));
554 PyModule_AddObject(m, "UF_WORKSTATION_TRUST_ACCOUNT", PyInt_FromLong(UF_WORKSTATION_TRUST_ACCOUNT));
555 PyModule_AddObject(m, "UF_INTERDOMAIN_TRUST_ACCOUNT", PyInt_FromLong(UF_INTERDOMAIN_TRUST_ACCOUNT));
556 PyModule_AddObject(m, "UF_PASSWD_NOTREQD", PyInt_FromLong(UF_PASSWD_NOTREQD));
557 PyModule_AddObject(m, "UF_ACCOUNTDISABLE", PyInt_FromLong(UF_ACCOUNTDISABLE));
559 /* "groupType" flags */
560 PyModule_AddObject(m, "GTYPE_SECURITY_BUILTIN_LOCAL_GROUP", PyInt_FromLong(GTYPE_SECURITY_BUILTIN_LOCAL_GROUP));
561 PyModule_AddObject(m, "GTYPE_SECURITY_GLOBAL_GROUP", PyInt_FromLong(GTYPE_SECURITY_GLOBAL_GROUP));
562 PyModule_AddObject(m, "GTYPE_SECURITY_DOMAIN_LOCAL_GROUP", PyInt_FromLong(GTYPE_SECURITY_DOMAIN_LOCAL_GROUP));
563 PyModule_AddObject(m, "GTYPE_SECURITY_UNIVERSAL_GROUP", PyInt_FromLong(GTYPE_SECURITY_UNIVERSAL_GROUP));
564 PyModule_AddObject(m, "GTYPE_DISTRIBUTION_GLOBAL_GROUP", PyInt_FromLong(GTYPE_DISTRIBUTION_GLOBAL_GROUP));
565 PyModule_AddObject(m, "GTYPE_DISTRIBUTION_DOMAIN_LOCAL_GROUP", PyInt_FromLong(GTYPE_DISTRIBUTION_DOMAIN_LOCAL_GROUP));
566 PyModule_AddObject(m, "GTYPE_DISTRIBUTION_UNIVERSAL_GROUP", PyInt_FromLong(GTYPE_DISTRIBUTION_UNIVERSAL_GROUP));
568 /* "sAMAccountType" flags */
569 PyModule_AddObject(m, "ATYPE_NORMAL_ACCOUNT", PyInt_FromLong(ATYPE_NORMAL_ACCOUNT));
570 PyModule_AddObject(m, "ATYPE_WORKSTATION_TRUST", PyInt_FromLong(ATYPE_WORKSTATION_TRUST));
571 PyModule_AddObject(m, "ATYPE_INTERDOMAIN_TRUST", PyInt_FromLong(ATYPE_INTERDOMAIN_TRUST));
572 PyModule_AddObject(m, "ATYPE_SECURITY_GLOBAL_GROUP", PyInt_FromLong(ATYPE_SECURITY_GLOBAL_GROUP));
573 PyModule_AddObject(m, "ATYPE_SECURITY_LOCAL_GROUP", PyInt_FromLong(ATYPE_SECURITY_LOCAL_GROUP));
574 PyModule_AddObject(m, "ATYPE_SECURITY_UNIVERSAL_GROUP", PyInt_FromLong(ATYPE_SECURITY_UNIVERSAL_GROUP));
575 PyModule_AddObject(m, "ATYPE_DISTRIBUTION_GLOBAL_GROUP", PyInt_FromLong(ATYPE_DISTRIBUTION_GLOBAL_GROUP));
576 PyModule_AddObject(m, "ATYPE_DISTRIBUTION_LOCAL_GROUP", PyInt_FromLong(ATYPE_DISTRIBUTION_LOCAL_GROUP));
577 PyModule_AddObject(m, "ATYPE_DISTRIBUTION_UNIVERSAL_GROUP", PyInt_FromLong(ATYPE_DISTRIBUTION_UNIVERSAL_GROUP));
579 /* "domainFunctionality", "forestFunctionality" flags in the rootDSE */
580 PyModule_AddObject(m, "DS_DOMAIN_FUNCTION_2000", PyInt_FromLong(DS_DOMAIN_FUNCTION_2000));
581 PyModule_AddObject(m, "DS_DOMAIN_FUNCTION_2003_MIXED", PyInt_FromLong(DS_DOMAIN_FUNCTION_2003_MIXED));
582 PyModule_AddObject(m, "DS_DOMAIN_FUNCTION_2003", PyInt_FromLong(DS_DOMAIN_FUNCTION_2003));
583 PyModule_AddObject(m, "DS_DOMAIN_FUNCTION_2008", PyInt_FromLong(DS_DOMAIN_FUNCTION_2008));
584 PyModule_AddObject(m, "DS_DOMAIN_FUNCTION_2008_R2", PyInt_FromLong(DS_DOMAIN_FUNCTION_2008_R2));
586 /* "domainControllerFunctionality" flags in the rootDSE */
587 PyModule_AddObject(m, "DS_DC_FUNCTION_2000", PyInt_FromLong(DS_DC_FUNCTION_2000));
588 PyModule_AddObject(m, "DS_DC_FUNCTION_2003", PyInt_FromLong(DS_DC_FUNCTION_2003));
589 PyModule_AddObject(m, "DS_DC_FUNCTION_2008", PyInt_FromLong(DS_DC_FUNCTION_2008));
590 PyModule_AddObject(m, "DS_DC_FUNCTION_2008_R2", PyInt_FromLong(DS_DC_FUNCTION_2008_R2));
592 /* "LDAP_SERVER_SD_FLAGS_OID" */
593 PyModule_AddObject(m, "SECINFO_OWNER", PyInt_FromLong(SECINFO_OWNER));
594 PyModule_AddObject(m, "SECINFO_GROUP", PyInt_FromLong(SECINFO_GROUP));
595 PyModule_AddObject(m, "SECINFO_DACL", PyInt_FromLong(SECINFO_DACL));
596 PyModule_AddObject(m, "SECINFO_SACL", PyInt_FromLong(SECINFO_SACL));
598 /* one of the most annoying things about python scripts is
599 that they don't die when you hit control-C. This fixes that
600 sillyness. As we do all database operations using
601 transactions, this is also safe. In fact, not dying
602 immediately is unsafe as we could end up treating the
603 control-C exception as a different error and try to modify
604 as database incorrectly
606 signal(SIGINT, SIG_DFL);