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"
37 #include "lib/socket/netif.h"
38 #include "lib/socket/netif_proto.h"
40 /* FIXME: These should be in a header file somewhere, once we finish moving
41 * away from SWIG .. */
42 #define PyErr_LDB_OR_RAISE(py_ldb, ldb) \
43 /* if (!PyLdb_Check(py_ldb)) { \
44 PyErr_SetString(py_ldb_get_exception(), "Ldb connection object required"); \
47 ldb = PyLdb_AsLdbContext(py_ldb);
49 static void PyErr_SetLdbError(PyObject *error, int ret, struct ldb_context *ldb_ctx)
51 if (ret == LDB_ERR_PYTHON_EXCEPTION)
52 return; /* Python exception should already be set, just keep that */
54 PyErr_SetObject(error,
55 Py_BuildValue(discard_const_p(char, "(i,s)"), ret,
56 ldb_ctx == NULL?ldb_strerror(ret):ldb_errstring(ldb_ctx)));
59 static PyObject *py_ldb_get_exception(void)
61 PyObject *mod = PyImport_ImportModule("ldb");
65 return PyObject_GetAttrString(mod, "LdbError");
68 static PyObject *py_generate_random_str(PyObject *self, PyObject *args)
73 if (!PyArg_ParseTuple(args, "i", &len))
76 retstr = generate_random_str(NULL, len);
77 ret = PyString_FromString(retstr);
82 static PyObject *py_generate_random_password(PyObject *self, PyObject *args)
87 if (!PyArg_ParseTuple(args, "ii", &min, &max))
90 retstr = generate_random_password(NULL, min, max);
94 ret = PyString_FromString(retstr);
99 static PyObject *py_unix2nttime(PyObject *self, PyObject *args)
103 if (!PyArg_ParseTuple(args, "I", &t))
106 unix_to_nt_time(&nt, t);
108 return PyInt_FromLong((uint64_t)nt);
111 static PyObject *py_set_debug_level(PyObject *self, PyObject *args)
114 if (!PyArg_ParseTuple(args, "I", &level))
116 (DEBUGLEVEL) = level;
120 static PyObject *py_ldb_set_session_info(PyObject *self, PyObject *args)
122 PyObject *py_session_info, *py_ldb;
123 struct auth_session_info *info;
124 struct ldb_context *ldb;
125 if (!PyArg_ParseTuple(args, "OO", &py_ldb, &py_session_info))
128 PyErr_LDB_OR_RAISE(py_ldb, ldb);
129 /*if (!PyAuthSession_Check(py_session_info)) {
130 PyErr_SetString(PyExc_TypeError, "Expected session info object");
134 info = PyAuthSession_AsSession(py_session_info);
136 ldb_set_opaque(ldb, "sessionInfo", info);
141 static PyObject *py_ldb_set_credentials(PyObject *self, PyObject *args)
143 PyObject *py_creds, *py_ldb;
144 struct cli_credentials *creds;
145 struct ldb_context *ldb;
146 if (!PyArg_ParseTuple(args, "OO", &py_ldb, &py_creds))
149 PyErr_LDB_OR_RAISE(py_ldb, ldb);
151 creds = cli_credentials_from_py_object(py_creds);
153 PyErr_SetString(PyExc_TypeError, "Expected credentials object");
157 ldb_set_opaque(ldb, "credentials", creds);
162 static PyObject *py_ldb_set_loadparm(PyObject *self, PyObject *args)
164 PyObject *py_lp_ctx, *py_ldb;
165 struct loadparm_context *lp_ctx;
166 struct ldb_context *ldb;
167 if (!PyArg_ParseTuple(args, "OO", &py_ldb, &py_lp_ctx))
170 PyErr_LDB_OR_RAISE(py_ldb, ldb);
172 lp_ctx = lp_from_py_object(py_lp_ctx);
173 if (lp_ctx == NULL) {
174 PyErr_SetString(PyExc_TypeError, "Expected loadparm object");
178 ldb_set_opaque(ldb, "loadparm", lp_ctx);
183 static PyObject *py_ldb_set_utf8_casefold(PyObject *self, PyObject *args)
186 struct ldb_context *ldb;
188 if (!PyArg_ParseTuple(args, "O", &py_ldb))
191 PyErr_LDB_OR_RAISE(py_ldb, ldb);
193 ldb_set_utf8_fns(ldb, NULL, wrap_casefold);
198 static PyObject *py_samdb_set_domain_sid(PyLdbObject *self, PyObject *args)
200 PyObject *py_ldb, *py_sid;
201 struct ldb_context *ldb;
205 if (!PyArg_ParseTuple(args, "OO", &py_ldb, &py_sid))
208 PyErr_LDB_OR_RAISE(py_ldb, ldb);
210 sid = dom_sid_parse_talloc(NULL, PyString_AsString(py_sid));
212 ret = samdb_set_domain_sid(ldb, sid);
214 PyErr_SetString(PyExc_RuntimeError, "set_domain_sid failed");
220 static PyObject *py_samdb_get_domain_sid(PyLdbObject *self, PyObject *args)
223 struct ldb_context *ldb;
224 const struct dom_sid *sid;
228 if (!PyArg_ParseTuple(args, "O", &py_ldb))
231 PyErr_LDB_OR_RAISE(py_ldb, ldb);
233 sid = samdb_domain_sid(ldb);
235 PyErr_SetString(PyExc_RuntimeError, "samdb_domain_sid failed");
238 retstr = dom_sid_string(NULL, sid);
239 ret = PyString_FromString(retstr);
244 static PyObject *py_ldb_register_samba_handlers(PyObject *self, PyObject *args)
247 struct ldb_context *ldb;
250 if (!PyArg_ParseTuple(args, "O", &py_ldb))
253 PyErr_LDB_OR_RAISE(py_ldb, ldb);
254 ret = ldb_register_samba_handlers(ldb);
256 PyErr_LDB_ERROR_IS_ERR_RAISE(py_ldb_get_exception(), ret, ldb);
260 static PyObject *py_dsdb_set_ntds_invocation_id(PyObject *self, PyObject *args)
262 PyObject *py_ldb, *py_guid;
265 struct ldb_context *ldb;
266 if (!PyArg_ParseTuple(args, "OO", &py_ldb, &py_guid))
269 PyErr_LDB_OR_RAISE(py_ldb, ldb);
270 GUID_from_string(PyString_AsString(py_guid), &guid);
272 ret = samdb_set_ntds_invocation_id(ldb, &guid);
274 PyErr_SetString(PyExc_RuntimeError, "set_ntds_invocation_id failed");
280 static PyObject *py_dsdb_set_opaque_integer(PyObject *self, PyObject *args)
284 int *old_val, *new_val;
285 char *py_opaque_name, *opaque_name_talloc;
286 struct ldb_context *ldb;
289 if (!PyArg_ParseTuple(args, "Osi", &py_ldb, &py_opaque_name, &value))
292 PyErr_LDB_OR_RAISE(py_ldb, ldb);
294 /* see if we have a cached copy */
295 old_val = (int *)ldb_get_opaque(ldb,
303 tmp_ctx = talloc_new(ldb);
304 if (tmp_ctx == NULL) {
308 new_val = talloc(tmp_ctx, int);
313 opaque_name_talloc = talloc_strdup(tmp_ctx, py_opaque_name);
314 if (!opaque_name_talloc) {
320 /* cache the domain_sid in the ldb */
321 if (ldb_set_opaque(ldb, opaque_name_talloc, new_val) != LDB_SUCCESS) {
325 talloc_steal(ldb, new_val);
326 talloc_steal(ldb, opaque_name_talloc);
327 talloc_free(tmp_ctx);
332 talloc_free(tmp_ctx);
333 PyErr_SetString(PyExc_RuntimeError, "Failed to set opaque integer into the ldb!\n");
337 static PyObject *py_dsdb_set_global_schema(PyObject *self, PyObject *args)
340 struct ldb_context *ldb;
342 if (!PyArg_ParseTuple(args, "O", &py_ldb))
345 PyErr_LDB_OR_RAISE(py_ldb, ldb);
347 ret = dsdb_set_global_schema(ldb);
348 PyErr_LDB_ERROR_IS_ERR_RAISE(py_ldb_get_exception(), ret, ldb);
353 static PyObject *py_dsdb_set_schema_from_ldif(PyObject *self, PyObject *args)
358 struct ldb_context *ldb;
360 if (!PyArg_ParseTuple(args, "Oss", &py_ldb, &pf, &df))
363 PyErr_LDB_OR_RAISE(py_ldb, ldb);
365 result = dsdb_set_schema_from_ldif(ldb, pf, df);
366 PyErr_WERROR_IS_ERR_RAISE(result);
371 static PyObject *py_dsdb_convert_schema_to_openldap(PyObject *self, PyObject *args)
373 char *target_str, *mapping;
375 struct ldb_context *ldb;
379 if (!PyArg_ParseTuple(args, "Oss", &py_ldb, &target_str, &mapping))
382 PyErr_LDB_OR_RAISE(py_ldb, ldb);
384 retstr = dsdb_convert_schema_to_openldap(ldb, target_str, mapping);
386 PyErr_SetString(PyExc_RuntimeError, "dsdb_convert_schema_to_openldap failed");
389 ret = PyString_FromString(retstr);
394 static PyObject *py_dsdb_write_prefixes_from_schema_to_ldb(PyObject *self, PyObject *args)
397 struct ldb_context *ldb;
399 struct dsdb_schema *schema;
401 if (!PyArg_ParseTuple(args, "O", &py_ldb))
404 PyErr_LDB_OR_RAISE(py_ldb, ldb);
406 schema = dsdb_get_schema(ldb, NULL);
408 PyErr_SetString(PyExc_RuntimeError, "Failed to set find a schema on ldb!\n");
412 result = dsdb_write_prefixes_from_schema_to_ldb(NULL, ldb, schema);
413 PyErr_WERROR_IS_ERR_RAISE(result);
418 static PyObject *py_dsdb_set_schema_from_ldb(PyObject *self, PyObject *args)
421 struct ldb_context *ldb;
422 PyObject *py_from_ldb;
423 struct ldb_context *from_ldb;
424 struct dsdb_schema *schema;
426 if (!PyArg_ParseTuple(args, "OO", &py_ldb, &py_from_ldb))
429 PyErr_LDB_OR_RAISE(py_ldb, ldb);
431 PyErr_LDB_OR_RAISE(py_from_ldb, from_ldb);
433 schema = dsdb_get_schema(from_ldb, NULL);
435 PyErr_SetString(PyExc_RuntimeError, "Failed to set find a schema on 'from' ldb!\n");
439 ret = dsdb_reference_schema(ldb, schema, true);
440 PyErr_LDB_ERROR_IS_ERR_RAISE(py_ldb_get_exception(), ret, ldb);
445 static PyObject *py_dsdb_load_partition_usn(PyObject *self, PyObject *args)
447 PyObject *py_dn, *py_ldb, *result;
449 uint64_t highest_uSN, urgent_uSN;
450 struct ldb_context *ldb;
454 mem_ctx = talloc_new(NULL);
455 if (mem_ctx == NULL) {
460 if (!PyArg_ParseTuple(args, "OO", &py_ldb, &py_dn)) {
461 talloc_free(mem_ctx);
465 PyErr_LDB_OR_RAISE(py_ldb, ldb);
467 if (!PyObject_AsDn(mem_ctx, py_dn, ldb, &dn)) {
468 talloc_free(mem_ctx);
472 ret = dsdb_load_partition_usn(ldb, dn, &highest_uSN, &urgent_uSN);
473 if (ret != LDB_SUCCESS) {
474 char *errstr = talloc_asprintf(mem_ctx, "Failed to load partition uSN - %s", ldb_errstring(ldb));
475 PyErr_SetString(PyExc_RuntimeError, errstr);
476 talloc_free(mem_ctx);
480 talloc_free(mem_ctx);
482 result = PyDict_New();
484 PyDict_SetItemString(result, "uSNHighest", PyInt_FromLong((uint64_t)highest_uSN));
485 PyDict_SetItemString(result, "uSNUrgent", PyInt_FromLong((uint64_t)urgent_uSN));
494 static PyObject *py_samdb_ntds_invocation_id(PyObject *self, PyObject *args)
496 PyObject *py_ldb, *result;
497 struct ldb_context *ldb;
499 const struct GUID *guid;
501 mem_ctx = talloc_new(NULL);
502 if (mem_ctx == NULL) {
507 if (!PyArg_ParseTuple(args, "O", &py_ldb)) {
508 talloc_free(mem_ctx);
512 PyErr_LDB_OR_RAISE(py_ldb, ldb);
514 guid = samdb_ntds_invocation_id(ldb);
516 PyErr_SetStringError("Failed to find NTDS invocation ID");
517 talloc_free(mem_ctx);
521 result = PyString_FromString(GUID_string(mem_ctx, guid));
522 talloc_free(mem_ctx);
527 static PyObject *py_samdb_ntds_objectGUID(PyObject *self, PyObject *args)
529 PyObject *py_ldb, *result;
530 struct ldb_context *ldb;
532 const struct GUID *guid;
534 mem_ctx = talloc_new(NULL);
535 if (mem_ctx == NULL) {
540 if (!PyArg_ParseTuple(args, "O", &py_ldb)) {
541 talloc_free(mem_ctx);
545 PyErr_LDB_OR_RAISE(py_ldb, ldb);
547 guid = samdb_ntds_objectGUID(ldb);
549 PyErr_SetStringError("Failed to find NTDS GUID");
550 talloc_free(mem_ctx);
554 result = PyString_FromString(GUID_string(mem_ctx, guid));
555 talloc_free(mem_ctx);
561 return the list of interface IPs we have configured
562 takes an loadparm context, returns a list of IPs in string form
564 Does not return addresses on 127.0.0.0/8
566 static PyObject *py_interface_ips(PyObject *self, PyObject *args)
572 struct loadparm_context *lp_ctx;
573 struct interface *ifaces;
577 if (!PyArg_ParseTuple(args, "Oi", &py_lp_ctx, &all_interfaces))
580 lp_ctx = lp_from_py_object(py_lp_ctx);
581 if (lp_ctx == NULL) {
582 PyErr_SetString(PyExc_TypeError, "Expected loadparm object");
586 tmp_ctx = talloc_new(NULL);
588 load_interfaces(tmp_ctx, lp_interfaces(lp_ctx), &ifaces);
590 count = iface_count(ifaces);
592 /* first count how many are not loopback addresses */
593 for (ifcount = i = 0; i<count; i++) {
594 const char *ip = iface_n_ip(ifaces, i);
595 if (!(!all_interfaces && iface_same_net(ip, "127.0.0.1", "255.0.0.0"))) {
600 pylist = PyList_New(ifcount);
601 for (ifcount = i = 0; i<count; i++) {
602 const char *ip = iface_n_ip(ifaces, i);
603 if (!(!all_interfaces && iface_same_net(ip, "127.0.0.1", "255.0.0.0"))) {
604 PyList_SetItem(pylist, ifcount, PyString_FromString(ip));
608 talloc_free(tmp_ctx);
613 static PyMethodDef py_misc_methods[] = {
614 { "generate_random_str", (PyCFunction)py_generate_random_str, METH_VARARGS,
615 "generate_random_str(len) -> string\n"
616 "Generate random string with specified length." },
617 { "generate_random_password", (PyCFunction)py_generate_random_password, METH_VARARGS,
618 "generate_random_password(min, max) -> string\n"
619 "Generate random password with a length >= min and <= max." },
620 { "unix2nttime", (PyCFunction)py_unix2nttime, METH_VARARGS,
621 "unix2nttime(timestamp) -> nttime" },
622 { "ldb_set_session_info", (PyCFunction)py_ldb_set_session_info, METH_VARARGS,
623 "ldb_set_session_info(ldb, session_info)\n"
624 "Set session info to use when connecting." },
625 { "ldb_set_credentials", (PyCFunction)py_ldb_set_credentials, METH_VARARGS,
626 "ldb_set_credentials(ldb, credentials)\n"
627 "Set credentials to use when connecting." },
628 { "ldb_set_loadparm", (PyCFunction)py_ldb_set_loadparm, METH_VARARGS,
629 "ldb_set_loadparm(ldb, session_info)\n"
630 "Set loadparm context to use when connecting." },
631 { "samdb_set_domain_sid", (PyCFunction)py_samdb_set_domain_sid, METH_VARARGS,
632 "samdb_set_domain_sid(samdb, sid)\n"
633 "Set SID of domain to use." },
634 { "samdb_get_domain_sid", (PyCFunction)py_samdb_get_domain_sid, METH_VARARGS,
635 "samdb_get_domain_sid(samdb)\n"
636 "Get SID of domain in use." },
637 { "ldb_register_samba_handlers", (PyCFunction)py_ldb_register_samba_handlers, METH_VARARGS,
638 "ldb_register_samba_handlers(ldb)\n"
639 "Register Samba-specific LDB modules and schemas." },
640 { "ldb_set_utf8_casefold", (PyCFunction)py_ldb_set_utf8_casefold, METH_VARARGS,
641 "ldb_set_utf8_casefold(ldb)\n"
642 "Set the right Samba casefolding function for UTF8 charset." },
643 { "dsdb_set_ntds_invocation_id", (PyCFunction)py_dsdb_set_ntds_invocation_id, METH_VARARGS,
645 { "dsdb_set_opaque_integer", (PyCFunction)py_dsdb_set_opaque_integer, METH_VARARGS,
647 { "dsdb_set_global_schema", (PyCFunction)py_dsdb_set_global_schema, METH_VARARGS,
649 { "dsdb_set_schema_from_ldif", (PyCFunction)py_dsdb_set_schema_from_ldif, METH_VARARGS,
651 { "dsdb_write_prefixes_from_schema_to_ldb", (PyCFunction)py_dsdb_write_prefixes_from_schema_to_ldb, METH_VARARGS,
653 { "dsdb_set_schema_from_ldb", (PyCFunction)py_dsdb_set_schema_from_ldb, METH_VARARGS,
655 { "dsdb_convert_schema_to_openldap", (PyCFunction)py_dsdb_convert_schema_to_openldap, METH_VARARGS,
657 { "set_debug_level", (PyCFunction)py_set_debug_level, METH_VARARGS,
659 { "dsdb_load_partition_usn", (PyCFunction)py_dsdb_load_partition_usn, METH_VARARGS,
660 "get uSNHighest and uSNUrgent from the partition @REPLCHANGED"},
661 { "samdb_ntds_invocation_id", (PyCFunction)py_samdb_ntds_invocation_id, METH_VARARGS,
662 "get the NTDS invocation ID GUID as a string"},
663 { "samdb_ntds_objectGUID", (PyCFunction)py_samdb_ntds_objectGUID, METH_VARARGS,
664 "get the NTDS objectGUID as a string"},
665 { "interface_ips", (PyCFunction)py_interface_ips, METH_VARARGS,
666 "get interface IP address list"},
674 debug_setup_talloc_log();
676 m = Py_InitModule3("glue", py_misc_methods,
677 "Python bindings for miscellaneous Samba functions.");
681 PyModule_AddObject(m, "version", PyString_FromString(SAMBA_VERSION_STRING));
683 /* one of the most annoying things about python scripts is
684 that they don't die when you hit control-C. This fixes that
685 sillyness. As we do all database operations using
686 transactions, this is also safe. In fact, not dying
687 immediately is unsafe as we could end up treating the
688 control-C exception as a different error and try to modify
689 as database incorrectly
691 signal(SIGINT, SIG_DFL);