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_dsdb_set_schema_from_ldif(PyObject *self, PyObject *args)
125 struct ldb_context *ldb;
127 if (!PyArg_ParseTuple(args, "Oss", &py_ldb, &pf, &df))
130 PyErr_LDB_OR_RAISE(py_ldb, ldb);
132 result = dsdb_set_schema_from_ldif(ldb, pf, df);
133 PyErr_WERROR_IS_ERR_RAISE(result);
138 static PyObject *py_dsdb_write_prefixes_from_schema_to_ldb(PyObject *self, PyObject *args)
141 struct ldb_context *ldb;
143 struct dsdb_schema *schema;
145 if (!PyArg_ParseTuple(args, "O", &py_ldb))
148 PyErr_LDB_OR_RAISE(py_ldb, ldb);
150 schema = dsdb_get_schema(ldb, NULL);
152 PyErr_SetString(PyExc_RuntimeError, "Failed to set find a schema on ldb!\n");
156 result = dsdb_write_prefixes_from_schema_to_ldb(NULL, ldb, schema);
157 PyErr_WERROR_IS_ERR_RAISE(result);
162 static PyObject *py_dsdb_set_schema_from_ldb(PyObject *self, PyObject *args)
165 struct ldb_context *ldb;
166 PyObject *py_from_ldb;
167 struct ldb_context *from_ldb;
168 struct dsdb_schema *schema;
170 if (!PyArg_ParseTuple(args, "OO", &py_ldb, &py_from_ldb))
173 PyErr_LDB_OR_RAISE(py_ldb, ldb);
175 PyErr_LDB_OR_RAISE(py_from_ldb, from_ldb);
177 schema = dsdb_get_schema(from_ldb, NULL);
179 PyErr_SetString(PyExc_RuntimeError, "Failed to set find a schema on 'from' ldb!\n");
183 ret = dsdb_reference_schema(ldb, schema, true);
184 PyErr_LDB_ERROR_IS_ERR_RAISE(py_ldb_get_exception(), ret, ldb);
189 static PyObject *py_dsdb_load_partition_usn(PyObject *self, PyObject *args)
191 PyObject *py_dn, *py_ldb, *result;
193 uint64_t highest_uSN, urgent_uSN;
194 struct ldb_context *ldb;
198 mem_ctx = talloc_new(NULL);
199 if (mem_ctx == NULL) {
204 if (!PyArg_ParseTuple(args, "OO", &py_ldb, &py_dn)) {
205 talloc_free(mem_ctx);
209 PyErr_LDB_OR_RAISE(py_ldb, ldb);
211 if (!PyObject_AsDn(mem_ctx, py_dn, ldb, &dn)) {
212 talloc_free(mem_ctx);
216 ret = dsdb_load_partition_usn(ldb, dn, &highest_uSN, &urgent_uSN);
217 if (ret != LDB_SUCCESS) {
218 char *errstr = talloc_asprintf(mem_ctx, "Failed to load partition uSN - %s", ldb_errstring(ldb));
219 PyErr_SetString(PyExc_RuntimeError, errstr);
220 talloc_free(mem_ctx);
224 talloc_free(mem_ctx);
226 result = PyDict_New();
228 PyDict_SetItemString(result, "uSNHighest", PyInt_FromLong((uint64_t)highest_uSN));
229 PyDict_SetItemString(result, "uSNUrgent", PyInt_FromLong((uint64_t)urgent_uSN));
236 return the list of interface IPs we have configured
237 takes an loadparm context, returns a list of IPs in string form
239 Does not return addresses on 127.0.0.0/8
241 static PyObject *py_interface_ips(PyObject *self, PyObject *args)
247 struct loadparm_context *lp_ctx;
248 struct interface *ifaces;
252 if (!PyArg_ParseTuple(args, "Oi", &py_lp_ctx, &all_interfaces))
255 lp_ctx = lp_from_py_object(py_lp_ctx);
256 if (lp_ctx == NULL) {
257 PyErr_SetString(PyExc_TypeError, "Expected loadparm object");
261 tmp_ctx = talloc_new(NULL);
263 load_interfaces(tmp_ctx, lp_interfaces(lp_ctx), &ifaces);
265 count = iface_count(ifaces);
267 /* first count how many are not loopback addresses */
268 for (ifcount = i = 0; i<count; i++) {
269 const char *ip = iface_n_ip(ifaces, i);
270 if (!(!all_interfaces && iface_same_net(ip, "127.0.0.1", "255.0.0.0"))) {
275 pylist = PyList_New(ifcount);
276 for (ifcount = i = 0; i<count; i++) {
277 const char *ip = iface_n_ip(ifaces, i);
278 if (!(!all_interfaces && iface_same_net(ip, "127.0.0.1", "255.0.0.0"))) {
279 PyList_SetItem(pylist, ifcount, PyString_FromString(ip));
283 talloc_free(tmp_ctx);
288 static PyMethodDef py_misc_methods[] = {
289 { "generate_random_str", (PyCFunction)py_generate_random_str, METH_VARARGS,
290 "generate_random_str(len) -> string\n"
291 "Generate random string with specified length." },
292 { "generate_random_password", (PyCFunction)py_generate_random_password, METH_VARARGS,
293 "generate_random_password(min, max) -> string\n"
294 "Generate random password with a length >= min and <= max." },
295 { "unix2nttime", (PyCFunction)py_unix2nttime, METH_VARARGS,
296 "unix2nttime(timestamp) -> nttime" },
297 { "dsdb_set_schema_from_ldif", (PyCFunction)py_dsdb_set_schema_from_ldif, METH_VARARGS,
299 { "dsdb_write_prefixes_from_schema_to_ldb", (PyCFunction)py_dsdb_write_prefixes_from_schema_to_ldb, METH_VARARGS,
301 { "dsdb_set_schema_from_ldb", (PyCFunction)py_dsdb_set_schema_from_ldb, METH_VARARGS,
303 { "set_debug_level", (PyCFunction)py_set_debug_level, METH_VARARGS,
305 { "dsdb_load_partition_usn", (PyCFunction)py_dsdb_load_partition_usn, METH_VARARGS,
306 "get uSNHighest and uSNUrgent from the partition @REPLCHANGED"},
307 { "interface_ips", (PyCFunction)py_interface_ips, METH_VARARGS,
308 "get interface IP address list"},
316 debug_setup_talloc_log();
318 m = Py_InitModule3("_glue", py_misc_methods,
319 "Python bindings for miscellaneous Samba functions.");
323 PyModule_AddObject(m, "version", PyString_FromString(SAMBA_VERSION_STRING));
325 /* one of the most annoying things about python scripts is
326 that they don't die when you hit control-C. This fixes that
327 sillyness. As we do all database operations using
328 transactions, this is also safe. In fact, not dying
329 immediately is unsafe as we could end up treating the
330 control-C exception as a different error and try to modify
331 as database incorrectly
333 signal(SIGINT, SIG_DFL);