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_utf8_casefold(PyObject *self, PyObject *args)
144 struct ldb_context *ldb;
146 if (!PyArg_ParseTuple(args, "O", &py_ldb))
149 PyErr_LDB_OR_RAISE(py_ldb, ldb);
151 ldb_set_utf8_fns(ldb, NULL, wrap_casefold);
156 static PyObject *py_samdb_set_domain_sid(PyLdbObject *self, PyObject *args)
158 PyObject *py_ldb, *py_sid;
159 struct ldb_context *ldb;
163 if (!PyArg_ParseTuple(args, "OO", &py_ldb, &py_sid))
166 PyErr_LDB_OR_RAISE(py_ldb, ldb);
168 sid = dom_sid_parse_talloc(NULL, PyString_AsString(py_sid));
170 ret = samdb_set_domain_sid(ldb, sid);
172 PyErr_SetString(PyExc_RuntimeError, "set_domain_sid failed");
178 static PyObject *py_samdb_get_domain_sid(PyLdbObject *self, PyObject *args)
181 struct ldb_context *ldb;
182 const struct dom_sid *sid;
186 if (!PyArg_ParseTuple(args, "O", &py_ldb))
189 PyErr_LDB_OR_RAISE(py_ldb, ldb);
191 sid = samdb_domain_sid(ldb);
193 PyErr_SetString(PyExc_RuntimeError, "samdb_domain_sid failed");
196 retstr = dom_sid_string(NULL, sid);
197 ret = PyString_FromString(retstr);
202 static PyObject *py_ldb_register_samba_handlers(PyObject *self, PyObject *args)
205 struct ldb_context *ldb;
208 if (!PyArg_ParseTuple(args, "O", &py_ldb))
211 PyErr_LDB_OR_RAISE(py_ldb, ldb);
212 ret = ldb_register_samba_handlers(ldb);
214 PyErr_LDB_ERROR_IS_ERR_RAISE(py_ldb_get_exception(), ret, ldb);
218 static PyObject *py_dsdb_set_ntds_invocation_id(PyObject *self, PyObject *args)
220 PyObject *py_ldb, *py_guid;
223 struct ldb_context *ldb;
224 if (!PyArg_ParseTuple(args, "OO", &py_ldb, &py_guid))
227 PyErr_LDB_OR_RAISE(py_ldb, ldb);
228 GUID_from_string(PyString_AsString(py_guid), &guid);
230 ret = samdb_set_ntds_invocation_id(ldb, &guid);
232 PyErr_SetString(PyExc_RuntimeError, "set_ntds_invocation_id failed");
238 static PyObject *py_dsdb_set_global_schema(PyObject *self, PyObject *args)
241 struct ldb_context *ldb;
243 if (!PyArg_ParseTuple(args, "O", &py_ldb))
246 PyErr_LDB_OR_RAISE(py_ldb, ldb);
248 ret = dsdb_set_global_schema(ldb);
249 PyErr_LDB_ERROR_IS_ERR_RAISE(py_ldb_get_exception(), ret, ldb);
254 static PyObject *py_dsdb_set_schema_from_ldif(PyObject *self, PyObject *args)
259 struct ldb_context *ldb;
261 if (!PyArg_ParseTuple(args, "Oss", &py_ldb, &pf, &df))
264 PyErr_LDB_OR_RAISE(py_ldb, ldb);
266 result = dsdb_set_schema_from_ldif(ldb, pf, df);
267 PyErr_WERROR_IS_ERR_RAISE(result);
272 static PyObject *py_dsdb_write_prefixes_from_schema_to_ldb(PyObject *self, PyObject *args)
275 struct ldb_context *ldb;
277 struct dsdb_schema *schema;
279 if (!PyArg_ParseTuple(args, "O", &py_ldb))
282 PyErr_LDB_OR_RAISE(py_ldb, ldb);
284 schema = dsdb_get_schema(ldb, NULL);
286 PyErr_SetString(PyExc_RuntimeError, "Failed to set find a schema on ldb!\n");
290 result = dsdb_write_prefixes_from_schema_to_ldb(NULL, ldb, schema);
291 PyErr_WERROR_IS_ERR_RAISE(result);
296 static PyObject *py_dsdb_set_schema_from_ldb(PyObject *self, PyObject *args)
299 struct ldb_context *ldb;
300 PyObject *py_from_ldb;
301 struct ldb_context *from_ldb;
302 struct dsdb_schema *schema;
304 if (!PyArg_ParseTuple(args, "OO", &py_ldb, &py_from_ldb))
307 PyErr_LDB_OR_RAISE(py_ldb, ldb);
309 PyErr_LDB_OR_RAISE(py_from_ldb, from_ldb);
311 schema = dsdb_get_schema(from_ldb, NULL);
313 PyErr_SetString(PyExc_RuntimeError, "Failed to set find a schema on 'from' ldb!\n");
317 ret = dsdb_reference_schema(ldb, schema, true);
318 PyErr_LDB_ERROR_IS_ERR_RAISE(py_ldb_get_exception(), ret, ldb);
323 static PyObject *py_dsdb_load_partition_usn(PyObject *self, PyObject *args)
325 PyObject *py_dn, *py_ldb, *result;
327 uint64_t highest_uSN, urgent_uSN;
328 struct ldb_context *ldb;
332 mem_ctx = talloc_new(NULL);
333 if (mem_ctx == NULL) {
338 if (!PyArg_ParseTuple(args, "OO", &py_ldb, &py_dn)) {
339 talloc_free(mem_ctx);
343 PyErr_LDB_OR_RAISE(py_ldb, ldb);
345 if (!PyObject_AsDn(mem_ctx, py_dn, ldb, &dn)) {
346 talloc_free(mem_ctx);
350 ret = dsdb_load_partition_usn(ldb, dn, &highest_uSN, &urgent_uSN);
351 if (ret != LDB_SUCCESS) {
352 char *errstr = talloc_asprintf(mem_ctx, "Failed to load partition uSN - %s", ldb_errstring(ldb));
353 PyErr_SetString(PyExc_RuntimeError, errstr);
354 talloc_free(mem_ctx);
358 talloc_free(mem_ctx);
360 result = PyDict_New();
362 PyDict_SetItemString(result, "uSNHighest", PyInt_FromLong((uint64_t)highest_uSN));
363 PyDict_SetItemString(result, "uSNUrgent", PyInt_FromLong((uint64_t)urgent_uSN));
369 static PyObject *py_samdb_ntds_invocation_id(PyObject *self, PyObject *args)
371 PyObject *py_ldb, *result;
372 struct ldb_context *ldb;
374 const struct GUID *guid;
376 mem_ctx = talloc_new(NULL);
377 if (mem_ctx == NULL) {
382 if (!PyArg_ParseTuple(args, "O", &py_ldb)) {
383 talloc_free(mem_ctx);
387 PyErr_LDB_OR_RAISE(py_ldb, ldb);
389 guid = samdb_ntds_invocation_id(ldb);
391 PyErr_SetString(PyExc_RuntimeError, "Failed to find NTDS invocation ID");
392 talloc_free(mem_ctx);
396 result = PyString_FromString(GUID_string(mem_ctx, guid));
397 talloc_free(mem_ctx);
402 static PyObject *py_samdb_ntds_objectGUID(PyObject *self, PyObject *args)
404 PyObject *py_ldb, *result;
405 struct ldb_context *ldb;
407 const struct GUID *guid;
409 mem_ctx = talloc_new(NULL);
410 if (mem_ctx == NULL) {
415 if (!PyArg_ParseTuple(args, "O", &py_ldb)) {
416 talloc_free(mem_ctx);
420 PyErr_LDB_OR_RAISE(py_ldb, ldb);
422 guid = samdb_ntds_objectGUID(ldb);
424 PyErr_SetString(PyExc_RuntimeError, "Failed to find NTDS GUID");
425 talloc_free(mem_ctx);
429 result = PyString_FromString(GUID_string(mem_ctx, guid));
430 talloc_free(mem_ctx);
436 return the list of interface IPs we have configured
437 takes an loadparm context, returns a list of IPs in string form
439 Does not return addresses on 127.0.0.0/8
441 static PyObject *py_interface_ips(PyObject *self, PyObject *args)
447 struct loadparm_context *lp_ctx;
448 struct interface *ifaces;
452 if (!PyArg_ParseTuple(args, "Oi", &py_lp_ctx, &all_interfaces))
455 lp_ctx = lp_from_py_object(py_lp_ctx);
456 if (lp_ctx == NULL) {
457 PyErr_SetString(PyExc_TypeError, "Expected loadparm object");
461 tmp_ctx = talloc_new(NULL);
463 load_interfaces(tmp_ctx, lp_interfaces(lp_ctx), &ifaces);
465 count = iface_count(ifaces);
467 /* first count how many are not loopback addresses */
468 for (ifcount = i = 0; i<count; i++) {
469 const char *ip = iface_n_ip(ifaces, i);
470 if (!(!all_interfaces && iface_same_net(ip, "127.0.0.1", "255.0.0.0"))) {
475 pylist = PyList_New(ifcount);
476 for (ifcount = i = 0; i<count; i++) {
477 const char *ip = iface_n_ip(ifaces, i);
478 if (!(!all_interfaces && iface_same_net(ip, "127.0.0.1", "255.0.0.0"))) {
479 PyList_SetItem(pylist, ifcount, PyString_FromString(ip));
483 talloc_free(tmp_ctx);
488 static PyMethodDef py_misc_methods[] = {
489 { "generate_random_str", (PyCFunction)py_generate_random_str, METH_VARARGS,
490 "generate_random_str(len) -> string\n"
491 "Generate random string with specified length." },
492 { "generate_random_password", (PyCFunction)py_generate_random_password, METH_VARARGS,
493 "generate_random_password(min, max) -> string\n"
494 "Generate random password with a length >= min and <= max." },
495 { "unix2nttime", (PyCFunction)py_unix2nttime, METH_VARARGS,
496 "unix2nttime(timestamp) -> nttime" },
497 { "ldb_set_session_info", (PyCFunction)py_ldb_set_session_info, METH_VARARGS,
498 "ldb_set_session_info(ldb, session_info)\n"
499 "Set session info to use when connecting." },
500 { "samdb_set_domain_sid", (PyCFunction)py_samdb_set_domain_sid, METH_VARARGS,
501 "samdb_set_domain_sid(samdb, sid)\n"
502 "Set SID of domain to use." },
503 { "samdb_get_domain_sid", (PyCFunction)py_samdb_get_domain_sid, METH_VARARGS,
504 "samdb_get_domain_sid(samdb)\n"
505 "Get SID of domain in use." },
506 { "ldb_register_samba_handlers", (PyCFunction)py_ldb_register_samba_handlers, METH_VARARGS,
507 "ldb_register_samba_handlers(ldb)\n"
508 "Register Samba-specific LDB modules and schemas." },
509 { "ldb_set_utf8_casefold", (PyCFunction)py_ldb_set_utf8_casefold, METH_VARARGS,
510 "ldb_set_utf8_casefold(ldb)\n"
511 "Set the right Samba casefolding function for UTF8 charset." },
512 { "dsdb_set_ntds_invocation_id", (PyCFunction)py_dsdb_set_ntds_invocation_id, METH_VARARGS,
514 { "dsdb_set_global_schema", (PyCFunction)py_dsdb_set_global_schema, METH_VARARGS,
516 { "dsdb_set_schema_from_ldif", (PyCFunction)py_dsdb_set_schema_from_ldif, METH_VARARGS,
518 { "dsdb_write_prefixes_from_schema_to_ldb", (PyCFunction)py_dsdb_write_prefixes_from_schema_to_ldb, METH_VARARGS,
520 { "dsdb_set_schema_from_ldb", (PyCFunction)py_dsdb_set_schema_from_ldb, METH_VARARGS,
522 { "set_debug_level", (PyCFunction)py_set_debug_level, METH_VARARGS,
524 { "dsdb_load_partition_usn", (PyCFunction)py_dsdb_load_partition_usn, METH_VARARGS,
525 "get uSNHighest and uSNUrgent from the partition @REPLCHANGED"},
526 { "samdb_ntds_invocation_id", (PyCFunction)py_samdb_ntds_invocation_id, METH_VARARGS,
527 "get the NTDS invocation ID GUID as a string"},
528 { "samdb_ntds_objectGUID", (PyCFunction)py_samdb_ntds_objectGUID, METH_VARARGS,
529 "get the NTDS objectGUID as a string"},
530 { "interface_ips", (PyCFunction)py_interface_ips, METH_VARARGS,
531 "get interface IP address list"},
539 debug_setup_talloc_log();
541 m = Py_InitModule3("glue", py_misc_methods,
542 "Python bindings for miscellaneous Samba functions.");
546 PyModule_AddObject(m, "version", PyString_FromString(SAMBA_VERSION_STRING));
548 /* one of the most annoying things about python scripts is
549 that they don't die when you hit control-C. This fixes that
550 sillyness. As we do all database operations using
551 transactions, this is also safe. In fact, not dying
552 immediately is unsafe as we could end up treating the
553 control-C exception as a different error and try to modify
554 as database incorrectly
556 signal(SIGINT, SIG_DFL);