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 #ifndef Py_RETURN_NONE
39 #define Py_RETURN_NONE return Py_INCREF(Py_None), Py_None
42 /* FIXME: These should be in a header file somewhere, once we finish moving
43 * away from SWIG .. */
44 #define PyErr_LDB_OR_RAISE(py_ldb, ldb) \
45 /* if (!PyLdb_Check(py_ldb)) { \
46 PyErr_SetString(py_ldb_get_exception(), "Ldb connection object required"); \
49 ldb = PyLdb_AsLdbContext(py_ldb);
51 static void PyErr_SetLdbError(PyObject *error, int ret, struct ldb_context *ldb_ctx)
53 if (ret == LDB_ERR_PYTHON_EXCEPTION)
54 return; /* Python exception should already be set, just keep that */
56 PyErr_SetObject(error,
57 Py_BuildValue(discard_const_p(char, "(i,s)"), ret,
58 ldb_ctx == NULL?ldb_strerror(ret):ldb_errstring(ldb_ctx)));
61 static PyObject *py_ldb_get_exception(void)
63 PyObject *mod = PyImport_ImportModule("ldb");
67 return PyObject_GetAttrString(mod, "LdbError");
70 static PyObject *py_generate_random_str(PyObject *self, PyObject *args)
75 if (!PyArg_ParseTuple(args, "i", &len))
78 retstr = generate_random_str(NULL, len);
79 ret = PyString_FromString(retstr);
84 static PyObject *py_unix2nttime(PyObject *self, PyObject *args)
88 if (!PyArg_ParseTuple(args, "I", &t))
91 unix_to_nt_time(&nt, t);
93 return PyInt_FromLong((uint64_t)nt);
96 static PyObject *py_set_debug_level(PyObject *self, PyObject *args)
99 if (!PyArg_ParseTuple(args, "I", &level))
101 (DEBUGLEVEL) = level;
105 static PyObject *py_ldb_set_session_info(PyObject *self, PyObject *args)
107 PyObject *py_session_info, *py_ldb;
108 struct auth_session_info *info;
109 struct ldb_context *ldb;
110 if (!PyArg_ParseTuple(args, "OO", &py_ldb, &py_session_info))
113 PyErr_LDB_OR_RAISE(py_ldb, ldb);
114 /*if (!PyAuthSession_Check(py_session_info)) {
115 PyErr_SetString(PyExc_TypeError, "Expected session info object");
119 info = PyAuthSession_AsSession(py_session_info);
121 ldb_set_opaque(ldb, "sessionInfo", info);
126 static PyObject *py_ldb_set_credentials(PyObject *self, PyObject *args)
128 PyObject *py_creds, *py_ldb;
129 struct cli_credentials *creds;
130 struct ldb_context *ldb;
131 if (!PyArg_ParseTuple(args, "OO", &py_ldb, &py_creds))
134 PyErr_LDB_OR_RAISE(py_ldb, ldb);
136 creds = cli_credentials_from_py_object(py_creds);
138 PyErr_SetString(PyExc_TypeError, "Expected credentials object");
142 ldb_set_opaque(ldb, "credentials", creds);
147 static PyObject *py_ldb_set_loadparm(PyObject *self, PyObject *args)
149 PyObject *py_lp_ctx, *py_ldb;
150 struct loadparm_context *lp_ctx;
151 struct ldb_context *ldb;
152 if (!PyArg_ParseTuple(args, "OO", &py_ldb, &py_lp_ctx))
155 PyErr_LDB_OR_RAISE(py_ldb, ldb);
157 lp_ctx = lp_from_py_object(py_lp_ctx);
158 if (lp_ctx == NULL) {
159 PyErr_SetString(PyExc_TypeError, "Expected loadparm object");
163 ldb_set_opaque(ldb, "loadparm", lp_ctx);
168 static PyObject *py_ldb_set_utf8_casefold(PyObject *self, PyObject *args)
171 struct ldb_context *ldb;
173 if (!PyArg_ParseTuple(args, "O", &py_ldb))
176 PyErr_LDB_OR_RAISE(py_ldb, ldb);
178 ldb_set_utf8_fns(ldb, NULL, wrap_casefold);
183 static PyObject *py_samdb_set_domain_sid(PyLdbObject *self, PyObject *args)
185 PyObject *py_ldb, *py_sid;
186 struct ldb_context *ldb;
190 if (!PyArg_ParseTuple(args, "OO", &py_ldb, &py_sid))
193 PyErr_LDB_OR_RAISE(py_ldb, ldb);
195 sid = dom_sid_parse_talloc(NULL, PyString_AsString(py_sid));
197 ret = samdb_set_domain_sid(ldb, sid);
199 PyErr_SetString(PyExc_RuntimeError, "set_domain_sid failed");
205 static PyObject *py_samdb_get_domain_sid(PyLdbObject *self, PyObject *args)
208 struct ldb_context *ldb;
209 const struct dom_sid *sid;
213 if (!PyArg_ParseTuple(args, "O", &py_ldb))
216 PyErr_LDB_OR_RAISE(py_ldb, ldb);
218 sid = samdb_domain_sid(ldb);
220 PyErr_SetString(PyExc_RuntimeError, "samdb_domain_sid failed");
223 retstr = dom_sid_string(NULL, sid);
224 ret = PyString_FromString(retstr);
229 static PyObject *py_ldb_register_samba_handlers(PyObject *self, PyObject *args)
232 struct ldb_context *ldb;
235 if (!PyArg_ParseTuple(args, "O", &py_ldb))
238 PyErr_LDB_OR_RAISE(py_ldb, ldb);
239 ret = ldb_register_samba_handlers(ldb);
241 PyErr_LDB_ERROR_IS_ERR_RAISE(py_ldb_get_exception(), ret, ldb);
245 static PyObject *py_dsdb_set_ntds_invocation_id(PyObject *self, PyObject *args)
247 PyObject *py_ldb, *py_guid;
250 struct ldb_context *ldb;
251 if (!PyArg_ParseTuple(args, "OO", &py_ldb, &py_guid))
254 PyErr_LDB_OR_RAISE(py_ldb, ldb);
255 GUID_from_string(PyString_AsString(py_guid), &guid);
257 ret = samdb_set_ntds_invocation_id(ldb, &guid);
259 PyErr_SetString(PyExc_RuntimeError, "set_ntds_invocation_id failed");
265 static PyObject *py_dsdb_set_opaque_integer(PyObject *self, PyObject *args)
269 int *old_val, *new_val;
270 char *py_opaque_name, *opaque_name_talloc;
271 struct ldb_context *ldb;
274 if (!PyArg_ParseTuple(args, "Osi", &py_ldb, &py_opaque_name, &value))
277 PyErr_LDB_OR_RAISE(py_ldb, ldb);
279 /* see if we have a cached copy */
280 old_val = (int *)ldb_get_opaque(ldb,
288 tmp_ctx = talloc_new(ldb);
289 if (tmp_ctx == NULL) {
293 new_val = talloc(tmp_ctx, int);
298 opaque_name_talloc = talloc_strdup(tmp_ctx, py_opaque_name);
299 if (!opaque_name_talloc) {
305 /* cache the domain_sid in the ldb */
306 if (ldb_set_opaque(ldb, opaque_name_talloc, new_val) != LDB_SUCCESS) {
310 talloc_steal(ldb, new_val);
311 talloc_steal(ldb, opaque_name_talloc);
312 talloc_free(tmp_ctx);
317 talloc_free(tmp_ctx);
318 PyErr_SetString(PyExc_RuntimeError, "Failed to set opaque integer into the ldb!\n");
322 static PyObject *py_dsdb_set_global_schema(PyObject *self, PyObject *args)
325 struct ldb_context *ldb;
327 if (!PyArg_ParseTuple(args, "O", &py_ldb))
330 PyErr_LDB_OR_RAISE(py_ldb, ldb);
332 ret = dsdb_set_global_schema(ldb);
333 PyErr_LDB_ERROR_IS_ERR_RAISE(py_ldb_get_exception(), ret, ldb);
338 static PyObject *py_dsdb_set_schema_from_ldif(PyObject *self, PyObject *args)
343 struct ldb_context *ldb;
345 if (!PyArg_ParseTuple(args, "Oss", &py_ldb, &pf, &df))
348 PyErr_LDB_OR_RAISE(py_ldb, ldb);
350 result = dsdb_set_schema_from_ldif(ldb, pf, df);
351 PyErr_WERROR_IS_ERR_RAISE(result);
356 static PyObject *py_dsdb_convert_schema_to_openldap(PyObject *self, PyObject *args)
358 char *target_str, *mapping;
360 struct ldb_context *ldb;
364 if (!PyArg_ParseTuple(args, "Oss", &py_ldb, &target_str, &mapping))
367 PyErr_LDB_OR_RAISE(py_ldb, ldb);
369 retstr = dsdb_convert_schema_to_openldap(ldb, target_str, mapping);
371 PyErr_SetString(PyExc_RuntimeError, "dsdb_convert_schema_to_openldap failed");
374 ret = PyString_FromString(retstr);
379 static PyObject *py_dsdb_write_prefixes_from_schema_to_ldb(PyObject *self, PyObject *args)
382 struct ldb_context *ldb;
384 struct dsdb_schema *schema;
386 if (!PyArg_ParseTuple(args, "O", &py_ldb))
389 PyErr_LDB_OR_RAISE(py_ldb, ldb);
391 schema = dsdb_get_schema(ldb);
393 PyErr_SetString(PyExc_RuntimeError, "Failed to set find a schema on ldb!\n");
397 result = dsdb_write_prefixes_from_schema_to_ldb(NULL, ldb, schema);
398 PyErr_WERROR_IS_ERR_RAISE(result);
403 static PyObject *py_dsdb_set_schema_from_ldb(PyObject *self, PyObject *args)
406 struct ldb_context *ldb;
407 PyObject *py_from_ldb;
408 struct ldb_context *from_ldb;
409 struct dsdb_schema *schema;
411 if (!PyArg_ParseTuple(args, "OO", &py_ldb, &py_from_ldb))
414 PyErr_LDB_OR_RAISE(py_ldb, ldb);
416 PyErr_LDB_OR_RAISE(py_from_ldb, from_ldb);
418 schema = dsdb_get_schema(from_ldb);
420 PyErr_SetString(PyExc_RuntimeError, "Failed to set find a schema on 'from' ldb!\n");
424 ret = dsdb_reference_schema(ldb, schema, true);
425 PyErr_LDB_ERROR_IS_ERR_RAISE(py_ldb_get_exception(), ret, ldb);
430 static PyObject *py_dsdb_make_schema_global(PyObject *self, PyObject *args)
433 struct ldb_context *ldb;
435 if (!PyArg_ParseTuple(args, "O", &py_ldb))
438 PyErr_LDB_OR_RAISE(py_ldb, ldb);
440 dsdb_make_schema_global(ldb);
445 static PyMethodDef py_misc_methods[] = {
446 { "generate_random_str", (PyCFunction)py_generate_random_str, METH_VARARGS,
447 "random_password(len) -> string\n"
448 "Generate random password with specified length." },
449 { "unix2nttime", (PyCFunction)py_unix2nttime, METH_VARARGS,
450 "unix2nttime(timestamp) -> nttime" },
451 { "ldb_set_session_info", (PyCFunction)py_ldb_set_session_info, METH_VARARGS,
452 "ldb_set_session_info(ldb, session_info)\n"
453 "Set session info to use when connecting." },
454 { "ldb_set_credentials", (PyCFunction)py_ldb_set_credentials, METH_VARARGS,
455 "ldb_set_credentials(ldb, credentials)\n"
456 "Set credentials to use when connecting." },
457 { "ldb_set_loadparm", (PyCFunction)py_ldb_set_loadparm, METH_VARARGS,
458 "ldb_set_loadparm(ldb, session_info)\n"
459 "Set loadparm context to use when connecting." },
460 { "samdb_set_domain_sid", (PyCFunction)py_samdb_set_domain_sid, METH_VARARGS,
461 "samdb_set_domain_sid(samdb, sid)\n"
462 "Set SID of domain to use." },
463 { "samdb_get_domain_sid", (PyCFunction)py_samdb_get_domain_sid, METH_VARARGS,
464 "samdb_get_domain_sid(samdb)\n"
465 "Get SID of domain in use." },
466 { "ldb_register_samba_handlers", (PyCFunction)py_ldb_register_samba_handlers, METH_VARARGS,
467 "ldb_register_samba_handlers(ldb)\n"
468 "Register Samba-specific LDB modules and schemas." },
469 { "ldb_set_utf8_casefold", (PyCFunction)py_ldb_set_utf8_casefold, METH_VARARGS,
470 "ldb_set_utf8_casefold(ldb)\n"
471 "Set the right Samba casefolding function for UTF8 charset." },
472 { "dsdb_set_ntds_invocation_id", (PyCFunction)py_dsdb_set_ntds_invocation_id, METH_VARARGS,
474 { "dsdb_set_opaque_integer", (PyCFunction)py_dsdb_set_opaque_integer, METH_VARARGS,
476 { "dsdb_set_global_schema", (PyCFunction)py_dsdb_set_global_schema, METH_VARARGS,
478 { "dsdb_set_schema_from_ldif", (PyCFunction)py_dsdb_set_schema_from_ldif, METH_VARARGS,
480 { "dsdb_write_prefixes_from_schema_to_ldb", (PyCFunction)py_dsdb_write_prefixes_from_schema_to_ldb, METH_VARARGS,
482 { "dsdb_set_schema_from_ldb", (PyCFunction)py_dsdb_set_schema_from_ldb, METH_VARARGS,
484 { "dsdb_convert_schema_to_openldap", (PyCFunction)py_dsdb_convert_schema_to_openldap, METH_VARARGS,
486 { "dsdb_make_schema_global", (PyCFunction)py_dsdb_make_schema_global, METH_VARARGS,
488 { "set_debug_level", (PyCFunction)py_set_debug_level, METH_VARARGS,
497 m = Py_InitModule3("glue", py_misc_methods,
498 "Python bindings for miscellaneous Samba functions.");
502 PyModule_AddObject(m, "version", PyString_FromString(SAMBA_VERSION_STRING));
504 /* "userAccountControl" flags */
505 PyModule_AddObject(m, "UF_NORMAL_ACCOUNT", PyInt_FromLong(UF_NORMAL_ACCOUNT));
506 PyModule_AddObject(m, "UF_TEMP_DUPLICATE_ACCOUNT", PyInt_FromLong(UF_TEMP_DUPLICATE_ACCOUNT));
507 PyModule_AddObject(m, "UF_SERVER_TRUST_ACCOUNT", PyInt_FromLong(UF_SERVER_TRUST_ACCOUNT));
508 PyModule_AddObject(m, "UF_WORKSTATION_TRUST_ACCOUNT", PyInt_FromLong(UF_WORKSTATION_TRUST_ACCOUNT));
509 PyModule_AddObject(m, "UF_INTERDOMAIN_TRUST_ACCOUNT", PyInt_FromLong(UF_INTERDOMAIN_TRUST_ACCOUNT));
510 PyModule_AddObject(m, "UF_PASSWD_NOTREQD", PyInt_FromLong(UF_PASSWD_NOTREQD));
511 PyModule_AddObject(m, "UF_ACCOUNTDISABLE", PyInt_FromLong(UF_ACCOUNTDISABLE));
513 /* "groupType" flags */
514 PyModule_AddObject(m, "GTYPE_SECURITY_BUILTIN_LOCAL_GROUP", PyInt_FromLong(GTYPE_SECURITY_BUILTIN_LOCAL_GROUP));
515 PyModule_AddObject(m, "GTYPE_SECURITY_GLOBAL_GROUP", PyInt_FromLong(GTYPE_SECURITY_GLOBAL_GROUP));
516 PyModule_AddObject(m, "GTYPE_SECURITY_DOMAIN_LOCAL_GROUP", PyInt_FromLong(GTYPE_SECURITY_DOMAIN_LOCAL_GROUP));
517 PyModule_AddObject(m, "GTYPE_SECURITY_UNIVERSAL_GROUP", PyInt_FromLong(GTYPE_SECURITY_UNIVERSAL_GROUP));
518 PyModule_AddObject(m, "GTYPE_DISTRIBUTION_GLOBAL_GROUP", PyInt_FromLong(GTYPE_DISTRIBUTION_GLOBAL_GROUP));
519 PyModule_AddObject(m, "GTYPE_DISTRIBUTION_DOMAIN_LOCAL_GROUP", PyInt_FromLong(GTYPE_DISTRIBUTION_DOMAIN_LOCAL_GROUP));
520 PyModule_AddObject(m, "GTYPE_DISTRIBUTION_UNIVERSAL_GROUP", PyInt_FromLong(GTYPE_DISTRIBUTION_UNIVERSAL_GROUP));
522 /* "sAMAccountType" flags */
523 PyModule_AddObject(m, "ATYPE_NORMAL_ACCOUNT", PyInt_FromLong(ATYPE_NORMAL_ACCOUNT));
524 PyModule_AddObject(m, "ATYPE_WORKSTATION_TRUST", PyInt_FromLong(ATYPE_WORKSTATION_TRUST));
525 PyModule_AddObject(m, "ATYPE_INTERDOMAIN_TRUST", PyInt_FromLong(ATYPE_INTERDOMAIN_TRUST));
526 PyModule_AddObject(m, "ATYPE_SECURITY_GLOBAL_GROUP", PyInt_FromLong(ATYPE_SECURITY_GLOBAL_GROUP));
527 PyModule_AddObject(m, "ATYPE_SECURITY_LOCAL_GROUP", PyInt_FromLong(ATYPE_SECURITY_LOCAL_GROUP));
528 PyModule_AddObject(m, "ATYPE_SECURITY_UNIVERSAL_GROUP", PyInt_FromLong(ATYPE_SECURITY_UNIVERSAL_GROUP));
529 PyModule_AddObject(m, "ATYPE_DISTRIBUTION_GLOBAL_GROUP", PyInt_FromLong(ATYPE_DISTRIBUTION_GLOBAL_GROUP));
530 PyModule_AddObject(m, "ATYPE_DISTRIBUTION_LOCAL_GROUP", PyInt_FromLong(ATYPE_DISTRIBUTION_LOCAL_GROUP));
531 PyModule_AddObject(m, "ATYPE_DISTRIBUTION_UNIVERSAL_GROUP", PyInt_FromLong(ATYPE_DISTRIBUTION_UNIVERSAL_GROUP));
533 /* "domainFunctionality", "forestFunctionality" flags in the rootDSE */
534 PyModule_AddObject(m, "DS_DOMAIN_FUNCTION_2000", PyInt_FromLong(DS_DOMAIN_FUNCTION_2000));
535 PyModule_AddObject(m, "DS_DOMAIN_FUNCTION_2003_MIXED", PyInt_FromLong(DS_DOMAIN_FUNCTION_2003_MIXED));
536 PyModule_AddObject(m, "DS_DOMAIN_FUNCTION_2003", PyInt_FromLong(DS_DOMAIN_FUNCTION_2003));
537 PyModule_AddObject(m, "DS_DOMAIN_FUNCTION_2008", PyInt_FromLong(DS_DOMAIN_FUNCTION_2008));
538 PyModule_AddObject(m, "DS_DOMAIN_FUNCTION_2008_R2", PyInt_FromLong(DS_DOMAIN_FUNCTION_2008_R2));
540 /* "domainControllerFunctionality" flags in the rootDSE */
541 PyModule_AddObject(m, "DS_DC_FUNCTION_2000", PyInt_FromLong(DS_DC_FUNCTION_2000));
542 PyModule_AddObject(m, "DS_DC_FUNCTION_2003", PyInt_FromLong(DS_DC_FUNCTION_2003));
543 PyModule_AddObject(m, "DS_DC_FUNCTION_2008", PyInt_FromLong(DS_DC_FUNCTION_2008));
544 PyModule_AddObject(m, "DS_DC_FUNCTION_2008_R2", PyInt_FromLong(DS_DC_FUNCTION_2008_R2));
546 /* "LDAP_SERVER_SD_FLAGS_OID" */
547 PyModule_AddObject(m, "SECINFO_OWNER", PyInt_FromLong(SECINFO_OWNER));
548 PyModule_AddObject(m, "SECINFO_GROUP", PyInt_FromLong(SECINFO_GROUP));
549 PyModule_AddObject(m, "SECINFO_DACL", PyInt_FromLong(SECINFO_DACL));
550 PyModule_AddObject(m, "SECINFO_SACL", PyInt_FromLong(SECINFO_SACL));
552 /* one of the most annoying things about python scripts is
553 that they don't die when you hit control-C. This fixes that
554 sillyness. As we do all database operations using
555 transactions, this is also safe. In fact, not dying
556 immediately is unsafe as we could end up treating the
557 control-C exception as a different error and try to modify
558 as database incorrectly
560 signal(SIGINT, SIG_DFL);