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_global_schema(PyObject *self, PyObject *args)
283 struct ldb_context *ldb;
285 if (!PyArg_ParseTuple(args, "O", &py_ldb))
288 PyErr_LDB_OR_RAISE(py_ldb, ldb);
290 ret = dsdb_set_global_schema(ldb);
291 PyErr_LDB_ERROR_IS_ERR_RAISE(py_ldb_get_exception(), ret, ldb);
296 static PyObject *py_dsdb_set_schema_from_ldif(PyObject *self, PyObject *args)
301 struct ldb_context *ldb;
303 if (!PyArg_ParseTuple(args, "Oss", &py_ldb, &pf, &df))
306 PyErr_LDB_OR_RAISE(py_ldb, ldb);
308 result = dsdb_set_schema_from_ldif(ldb, pf, df);
309 PyErr_WERROR_IS_ERR_RAISE(result);
314 static PyObject *py_dsdb_convert_schema_to_openldap(PyObject *self, PyObject *args)
316 char *target_str, *mapping;
318 struct ldb_context *ldb;
322 if (!PyArg_ParseTuple(args, "Oss", &py_ldb, &target_str, &mapping))
325 PyErr_LDB_OR_RAISE(py_ldb, ldb);
327 retstr = dsdb_convert_schema_to_openldap(ldb, target_str, mapping);
329 PyErr_SetString(PyExc_RuntimeError, "dsdb_convert_schema_to_openldap failed");
332 ret = PyString_FromString(retstr);
337 static PyObject *py_dsdb_write_prefixes_from_schema_to_ldb(PyObject *self, PyObject *args)
340 struct ldb_context *ldb;
342 struct dsdb_schema *schema;
344 if (!PyArg_ParseTuple(args, "O", &py_ldb))
347 PyErr_LDB_OR_RAISE(py_ldb, ldb);
349 schema = dsdb_get_schema(ldb, NULL);
351 PyErr_SetString(PyExc_RuntimeError, "Failed to set find a schema on ldb!\n");
355 result = dsdb_write_prefixes_from_schema_to_ldb(NULL, ldb, schema);
356 PyErr_WERROR_IS_ERR_RAISE(result);
361 static PyObject *py_dsdb_set_schema_from_ldb(PyObject *self, PyObject *args)
364 struct ldb_context *ldb;
365 PyObject *py_from_ldb;
366 struct ldb_context *from_ldb;
367 struct dsdb_schema *schema;
369 if (!PyArg_ParseTuple(args, "OO", &py_ldb, &py_from_ldb))
372 PyErr_LDB_OR_RAISE(py_ldb, ldb);
374 PyErr_LDB_OR_RAISE(py_from_ldb, from_ldb);
376 schema = dsdb_get_schema(from_ldb, NULL);
378 PyErr_SetString(PyExc_RuntimeError, "Failed to set find a schema on 'from' ldb!\n");
382 ret = dsdb_reference_schema(ldb, schema, true);
383 PyErr_LDB_ERROR_IS_ERR_RAISE(py_ldb_get_exception(), ret, ldb);
388 static PyObject *py_dsdb_load_partition_usn(PyObject *self, PyObject *args)
390 PyObject *py_dn, *py_ldb, *result;
392 uint64_t highest_uSN, urgent_uSN;
393 struct ldb_context *ldb;
397 mem_ctx = talloc_new(NULL);
398 if (mem_ctx == NULL) {
403 if (!PyArg_ParseTuple(args, "OO", &py_ldb, &py_dn)) {
404 talloc_free(mem_ctx);
408 PyErr_LDB_OR_RAISE(py_ldb, ldb);
410 if (!PyObject_AsDn(mem_ctx, py_dn, ldb, &dn)) {
411 talloc_free(mem_ctx);
415 ret = dsdb_load_partition_usn(ldb, dn, &highest_uSN, &urgent_uSN);
416 if (ret != LDB_SUCCESS) {
417 char *errstr = talloc_asprintf(mem_ctx, "Failed to load partition uSN - %s", ldb_errstring(ldb));
418 PyErr_SetString(PyExc_RuntimeError, errstr);
419 talloc_free(mem_ctx);
423 talloc_free(mem_ctx);
425 result = PyDict_New();
427 PyDict_SetItemString(result, "uSNHighest", PyInt_FromLong((uint64_t)highest_uSN));
428 PyDict_SetItemString(result, "uSNUrgent", PyInt_FromLong((uint64_t)urgent_uSN));
434 static PyObject *py_samdb_ntds_invocation_id(PyObject *self, PyObject *args)
436 PyObject *py_ldb, *result;
437 struct ldb_context *ldb;
439 const struct GUID *guid;
441 mem_ctx = talloc_new(NULL);
442 if (mem_ctx == NULL) {
447 if (!PyArg_ParseTuple(args, "O", &py_ldb)) {
448 talloc_free(mem_ctx);
452 PyErr_LDB_OR_RAISE(py_ldb, ldb);
454 guid = samdb_ntds_invocation_id(ldb);
456 PyErr_SetString(PyExc_RuntimeError, "Failed to find NTDS invocation ID");
457 talloc_free(mem_ctx);
461 result = PyString_FromString(GUID_string(mem_ctx, guid));
462 talloc_free(mem_ctx);
467 static PyObject *py_samdb_ntds_objectGUID(PyObject *self, PyObject *args)
469 PyObject *py_ldb, *result;
470 struct ldb_context *ldb;
472 const struct GUID *guid;
474 mem_ctx = talloc_new(NULL);
475 if (mem_ctx == NULL) {
480 if (!PyArg_ParseTuple(args, "O", &py_ldb)) {
481 talloc_free(mem_ctx);
485 PyErr_LDB_OR_RAISE(py_ldb, ldb);
487 guid = samdb_ntds_objectGUID(ldb);
489 PyErr_SetString(PyExc_RuntimeError, "Failed to find NTDS GUID");
490 talloc_free(mem_ctx);
494 result = PyString_FromString(GUID_string(mem_ctx, guid));
495 talloc_free(mem_ctx);
501 return the list of interface IPs we have configured
502 takes an loadparm context, returns a list of IPs in string form
504 Does not return addresses on 127.0.0.0/8
506 static PyObject *py_interface_ips(PyObject *self, PyObject *args)
512 struct loadparm_context *lp_ctx;
513 struct interface *ifaces;
517 if (!PyArg_ParseTuple(args, "Oi", &py_lp_ctx, &all_interfaces))
520 lp_ctx = lp_from_py_object(py_lp_ctx);
521 if (lp_ctx == NULL) {
522 PyErr_SetString(PyExc_TypeError, "Expected loadparm object");
526 tmp_ctx = talloc_new(NULL);
528 load_interfaces(tmp_ctx, lp_interfaces(lp_ctx), &ifaces);
530 count = iface_count(ifaces);
532 /* first count how many are not loopback addresses */
533 for (ifcount = i = 0; i<count; i++) {
534 const char *ip = iface_n_ip(ifaces, i);
535 if (!(!all_interfaces && iface_same_net(ip, "127.0.0.1", "255.0.0.0"))) {
540 pylist = PyList_New(ifcount);
541 for (ifcount = i = 0; i<count; i++) {
542 const char *ip = iface_n_ip(ifaces, i);
543 if (!(!all_interfaces && iface_same_net(ip, "127.0.0.1", "255.0.0.0"))) {
544 PyList_SetItem(pylist, ifcount, PyString_FromString(ip));
548 talloc_free(tmp_ctx);
553 static PyMethodDef py_misc_methods[] = {
554 { "generate_random_str", (PyCFunction)py_generate_random_str, METH_VARARGS,
555 "generate_random_str(len) -> string\n"
556 "Generate random string with specified length." },
557 { "generate_random_password", (PyCFunction)py_generate_random_password, METH_VARARGS,
558 "generate_random_password(min, max) -> string\n"
559 "Generate random password with a length >= min and <= max." },
560 { "unix2nttime", (PyCFunction)py_unix2nttime, METH_VARARGS,
561 "unix2nttime(timestamp) -> nttime" },
562 { "ldb_set_session_info", (PyCFunction)py_ldb_set_session_info, METH_VARARGS,
563 "ldb_set_session_info(ldb, session_info)\n"
564 "Set session info to use when connecting." },
565 { "ldb_set_credentials", (PyCFunction)py_ldb_set_credentials, METH_VARARGS,
566 "ldb_set_credentials(ldb, credentials)\n"
567 "Set credentials to use when connecting." },
568 { "ldb_set_loadparm", (PyCFunction)py_ldb_set_loadparm, METH_VARARGS,
569 "ldb_set_loadparm(ldb, session_info)\n"
570 "Set loadparm context to use when connecting." },
571 { "samdb_set_domain_sid", (PyCFunction)py_samdb_set_domain_sid, METH_VARARGS,
572 "samdb_set_domain_sid(samdb, sid)\n"
573 "Set SID of domain to use." },
574 { "samdb_get_domain_sid", (PyCFunction)py_samdb_get_domain_sid, METH_VARARGS,
575 "samdb_get_domain_sid(samdb)\n"
576 "Get SID of domain in use." },
577 { "ldb_register_samba_handlers", (PyCFunction)py_ldb_register_samba_handlers, METH_VARARGS,
578 "ldb_register_samba_handlers(ldb)\n"
579 "Register Samba-specific LDB modules and schemas." },
580 { "ldb_set_utf8_casefold", (PyCFunction)py_ldb_set_utf8_casefold, METH_VARARGS,
581 "ldb_set_utf8_casefold(ldb)\n"
582 "Set the right Samba casefolding function for UTF8 charset." },
583 { "dsdb_set_ntds_invocation_id", (PyCFunction)py_dsdb_set_ntds_invocation_id, METH_VARARGS,
585 { "dsdb_set_global_schema", (PyCFunction)py_dsdb_set_global_schema, METH_VARARGS,
587 { "dsdb_set_schema_from_ldif", (PyCFunction)py_dsdb_set_schema_from_ldif, METH_VARARGS,
589 { "dsdb_write_prefixes_from_schema_to_ldb", (PyCFunction)py_dsdb_write_prefixes_from_schema_to_ldb, METH_VARARGS,
591 { "dsdb_set_schema_from_ldb", (PyCFunction)py_dsdb_set_schema_from_ldb, METH_VARARGS,
593 { "dsdb_convert_schema_to_openldap", (PyCFunction)py_dsdb_convert_schema_to_openldap, METH_VARARGS,
595 { "set_debug_level", (PyCFunction)py_set_debug_level, METH_VARARGS,
597 { "dsdb_load_partition_usn", (PyCFunction)py_dsdb_load_partition_usn, METH_VARARGS,
598 "get uSNHighest and uSNUrgent from the partition @REPLCHANGED"},
599 { "samdb_ntds_invocation_id", (PyCFunction)py_samdb_ntds_invocation_id, METH_VARARGS,
600 "get the NTDS invocation ID GUID as a string"},
601 { "samdb_ntds_objectGUID", (PyCFunction)py_samdb_ntds_objectGUID, METH_VARARGS,
602 "get the NTDS objectGUID as a string"},
603 { "interface_ips", (PyCFunction)py_interface_ips, METH_VARARGS,
604 "get interface IP address list"},
612 debug_setup_talloc_log();
614 m = Py_InitModule3("glue", py_misc_methods,
615 "Python bindings for miscellaneous Samba functions.");
619 PyModule_AddObject(m, "version", PyString_FromString(SAMBA_VERSION_STRING));
621 /* one of the most annoying things about python scripts is
622 that they don't die when you hit control-C. This fixes that
623 sillyness. As we do all database operations using
624 transactions, this is also safe. In fact, not dying
625 immediately is unsafe as we could end up treating the
626 control-C exception as a different error and try to modify
627 as database incorrectly
629 signal(SIGINT, SIG_DFL);