s4-python: Move set_session_info to PySambaLdb.
[kamenim/samba.git] / source4 / scripting / python / pyglue.c
1 /* 
2    Unix SMB/CIFS implementation.
3    Copyright (C) Jelmer Vernooij <jelmer@samba.org> 2007
4    Copyright (C) Matthias Dieter Wallnöfer          2009
5    
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.
10    
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.
15    
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/>.
18 */
19
20 #include <Python.h>
21 #include "includes.h"
22 #include "ldb.h"
23 #include "ldb_errors.h"
24 #include "ldb_wrap.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"
30 #include "version.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"
39
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"); \
45                 return NULL; \
46         } */\
47         ldb = PyLdb_AsLdbContext(py_ldb);
48
49 static void PyErr_SetLdbError(PyObject *error, int ret, struct ldb_context *ldb_ctx)
50 {
51         if (ret == LDB_ERR_PYTHON_EXCEPTION)
52                 return; /* Python exception should already be set, just keep that */
53
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)));
57 }
58
59 static PyObject *py_ldb_get_exception(void)
60 {
61         PyObject *mod = PyImport_ImportModule("ldb");
62         if (mod == NULL)
63                 return NULL;
64
65         return PyObject_GetAttrString(mod, "LdbError");
66 }
67
68 static PyObject *py_generate_random_str(PyObject *self, PyObject *args)
69 {
70         int len;
71         PyObject *ret;
72         char *retstr;
73         if (!PyArg_ParseTuple(args, "i", &len))
74                 return NULL;
75
76         retstr = generate_random_str(NULL, len);
77         ret = PyString_FromString(retstr);
78         talloc_free(retstr);
79         return ret;
80 }
81
82 static PyObject *py_generate_random_password(PyObject *self, PyObject *args)
83 {
84         int min, max;
85         PyObject *ret;
86         char *retstr;
87         if (!PyArg_ParseTuple(args, "ii", &min, &max))
88                 return NULL;
89
90         retstr = generate_random_password(NULL, min, max);
91         if (retstr == NULL) {
92                 return NULL;
93         }
94         ret = PyString_FromString(retstr);
95         talloc_free(retstr);
96         return ret;
97 }
98
99 static PyObject *py_unix2nttime(PyObject *self, PyObject *args)
100 {
101         time_t t;
102         NTTIME nt;
103         if (!PyArg_ParseTuple(args, "I", &t))
104                 return NULL;
105
106         unix_to_nt_time(&nt, t);
107
108         return PyInt_FromLong((uint64_t)nt);
109 }
110
111 static PyObject *py_set_debug_level(PyObject *self, PyObject *args)
112 {
113         unsigned level;
114         if (!PyArg_ParseTuple(args, "I", &level))
115                 return NULL;
116         (DEBUGLEVEL) = level;
117         Py_RETURN_NONE;
118 }
119
120 static PyObject *py_samdb_set_domain_sid(PyLdbObject *self, PyObject *args)
121
122         PyObject *py_ldb, *py_sid;
123         struct ldb_context *ldb;
124         struct dom_sid *sid;
125         bool ret;
126
127         if (!PyArg_ParseTuple(args, "OO", &py_ldb, &py_sid))
128                 return NULL;
129         
130         PyErr_LDB_OR_RAISE(py_ldb, ldb);
131
132         sid = dom_sid_parse_talloc(NULL, PyString_AsString(py_sid));
133
134         ret = samdb_set_domain_sid(ldb, sid);
135         if (!ret) {
136                 PyErr_SetString(PyExc_RuntimeError, "set_domain_sid failed");
137                 return NULL;
138         } 
139         Py_RETURN_NONE;
140 }
141
142 static PyObject *py_samdb_get_domain_sid(PyLdbObject *self, PyObject *args)
143
144         PyObject *py_ldb;
145         struct ldb_context *ldb;
146         const struct dom_sid *sid;
147         PyObject *ret;
148         char *retstr;
149
150         if (!PyArg_ParseTuple(args, "O", &py_ldb))
151                 return NULL;
152         
153         PyErr_LDB_OR_RAISE(py_ldb, ldb);
154
155         sid = samdb_domain_sid(ldb);
156         if (!sid) {
157                 PyErr_SetString(PyExc_RuntimeError, "samdb_domain_sid failed");
158                 return NULL;
159         } 
160         retstr = dom_sid_string(NULL, sid);
161         ret = PyString_FromString(retstr);
162         talloc_free(retstr);
163         return ret;
164 }
165
166 static PyObject *py_dsdb_set_ntds_invocation_id(PyObject *self, PyObject *args)
167 {
168         PyObject *py_ldb, *py_guid;
169         bool ret;
170         struct GUID guid;
171         struct ldb_context *ldb;
172         if (!PyArg_ParseTuple(args, "OO", &py_ldb, &py_guid))
173                 return NULL;
174
175         PyErr_LDB_OR_RAISE(py_ldb, ldb);
176         GUID_from_string(PyString_AsString(py_guid), &guid);
177
178         ret = samdb_set_ntds_invocation_id(ldb, &guid);
179         if (!ret) {
180                 PyErr_SetString(PyExc_RuntimeError, "set_ntds_invocation_id failed");
181                 return NULL;
182         }
183         Py_RETURN_NONE;
184 }
185
186 static PyObject *py_dsdb_set_global_schema(PyObject *self, PyObject *args)
187 {
188         PyObject *py_ldb;
189         struct ldb_context *ldb;
190         int ret;
191         if (!PyArg_ParseTuple(args, "O", &py_ldb))
192                 return NULL;
193
194         PyErr_LDB_OR_RAISE(py_ldb, ldb);
195
196         ret = dsdb_set_global_schema(ldb);
197         PyErr_LDB_ERROR_IS_ERR_RAISE(py_ldb_get_exception(), ret, ldb);
198
199         Py_RETURN_NONE;
200 }
201
202 static PyObject *py_dsdb_set_schema_from_ldif(PyObject *self, PyObject *args)
203 {
204         WERROR result;
205         char *pf, *df;
206         PyObject *py_ldb;
207         struct ldb_context *ldb;
208
209         if (!PyArg_ParseTuple(args, "Oss", &py_ldb, &pf, &df))
210                 return NULL;
211
212         PyErr_LDB_OR_RAISE(py_ldb, ldb);
213
214         result = dsdb_set_schema_from_ldif(ldb, pf, df);
215         PyErr_WERROR_IS_ERR_RAISE(result);
216
217         Py_RETURN_NONE;
218 }
219
220 static PyObject *py_dsdb_write_prefixes_from_schema_to_ldb(PyObject *self, PyObject *args)
221 {
222         PyObject *py_ldb;
223         struct ldb_context *ldb;
224         WERROR result;
225         struct dsdb_schema *schema;
226
227         if (!PyArg_ParseTuple(args, "O", &py_ldb))
228                 return NULL;
229
230         PyErr_LDB_OR_RAISE(py_ldb, ldb);
231
232         schema = dsdb_get_schema(ldb, NULL);
233         if (!schema) {
234                 PyErr_SetString(PyExc_RuntimeError, "Failed to set find a schema on ldb!\n");
235                 return NULL;
236         }
237
238         result = dsdb_write_prefixes_from_schema_to_ldb(NULL, ldb, schema);
239         PyErr_WERROR_IS_ERR_RAISE(result);
240
241         Py_RETURN_NONE;
242 }
243
244 static PyObject *py_dsdb_set_schema_from_ldb(PyObject *self, PyObject *args)
245 {
246         PyObject *py_ldb;
247         struct ldb_context *ldb;
248         PyObject *py_from_ldb;
249         struct ldb_context *from_ldb;
250         struct dsdb_schema *schema;
251         int ret;
252         if (!PyArg_ParseTuple(args, "OO", &py_ldb, &py_from_ldb))
253                 return NULL;
254
255         PyErr_LDB_OR_RAISE(py_ldb, ldb);
256
257         PyErr_LDB_OR_RAISE(py_from_ldb, from_ldb);
258
259         schema = dsdb_get_schema(from_ldb, NULL);
260         if (!schema) {
261                 PyErr_SetString(PyExc_RuntimeError, "Failed to set find a schema on 'from' ldb!\n");
262                 return NULL;
263         }
264
265         ret = dsdb_reference_schema(ldb, schema, true);
266         PyErr_LDB_ERROR_IS_ERR_RAISE(py_ldb_get_exception(), ret, ldb);
267
268         Py_RETURN_NONE;
269 }
270
271 static PyObject *py_dsdb_load_partition_usn(PyObject *self, PyObject *args)
272 {
273         PyObject *py_dn, *py_ldb, *result;
274         struct ldb_dn *dn;
275         uint64_t highest_uSN, urgent_uSN;
276         struct ldb_context *ldb;
277         TALLOC_CTX *mem_ctx;
278         int ret;
279
280         mem_ctx = talloc_new(NULL);
281         if (mem_ctx == NULL) {
282            PyErr_NoMemory();
283            return NULL;
284         }
285
286         if (!PyArg_ParseTuple(args, "OO", &py_ldb, &py_dn)) {
287            talloc_free(mem_ctx);
288            return NULL;
289         }
290
291         PyErr_LDB_OR_RAISE(py_ldb, ldb);
292
293         if (!PyObject_AsDn(mem_ctx, py_dn, ldb, &dn)) {
294            talloc_free(mem_ctx);
295            return NULL;
296         }
297
298         ret = dsdb_load_partition_usn(ldb, dn, &highest_uSN, &urgent_uSN);
299         if (ret != LDB_SUCCESS) {
300            char *errstr = talloc_asprintf(mem_ctx, "Failed to load partition uSN - %s", ldb_errstring(ldb));
301            PyErr_SetString(PyExc_RuntimeError, errstr);
302            talloc_free(mem_ctx);
303            return NULL;
304         }
305
306         talloc_free(mem_ctx);
307
308         result = PyDict_New();
309
310         PyDict_SetItemString(result, "uSNHighest", PyInt_FromLong((uint64_t)highest_uSN));
311         PyDict_SetItemString(result, "uSNUrgent", PyInt_FromLong((uint64_t)urgent_uSN));
312
313
314         return result;
315 }
316
317 static PyObject *py_samdb_ntds_invocation_id(PyObject *self, PyObject *args)
318 {
319         PyObject *py_ldb, *result;
320         struct ldb_context *ldb;
321         TALLOC_CTX *mem_ctx;
322         const struct GUID *guid;
323
324         mem_ctx = talloc_new(NULL);
325         if (mem_ctx == NULL) {
326                 PyErr_NoMemory();
327                 return NULL;
328         }
329
330         if (!PyArg_ParseTuple(args, "O", &py_ldb)) {
331                 talloc_free(mem_ctx);
332                 return NULL;
333         }
334
335         PyErr_LDB_OR_RAISE(py_ldb, ldb);
336
337         guid = samdb_ntds_invocation_id(ldb);
338         if (guid == NULL) {
339                 PyErr_SetString(PyExc_RuntimeError, "Failed to find NTDS invocation ID");
340                 talloc_free(mem_ctx);
341                 return NULL;
342         }
343
344         result = PyString_FromString(GUID_string(mem_ctx, guid));
345         talloc_free(mem_ctx);
346         return result;
347 }
348
349
350 static PyObject *py_samdb_ntds_objectGUID(PyObject *self, PyObject *args)
351 {
352         PyObject *py_ldb, *result;
353         struct ldb_context *ldb;
354         TALLOC_CTX *mem_ctx;
355         const struct GUID *guid;
356
357         mem_ctx = talloc_new(NULL);
358         if (mem_ctx == NULL) {
359                 PyErr_NoMemory();
360                 return NULL;
361         }
362
363         if (!PyArg_ParseTuple(args, "O", &py_ldb)) {
364                 talloc_free(mem_ctx);
365                 return NULL;
366         }
367
368         PyErr_LDB_OR_RAISE(py_ldb, ldb);
369
370         guid = samdb_ntds_objectGUID(ldb);
371         if (guid == NULL) {
372                 PyErr_SetString(PyExc_RuntimeError, "Failed to find NTDS GUID");
373                 talloc_free(mem_ctx);
374                 return NULL;
375         }
376
377         result = PyString_FromString(GUID_string(mem_ctx, guid));
378         talloc_free(mem_ctx);
379         return result;
380 }
381
382
383 /*
384   return the list of interface IPs we have configured
385   takes an loadparm context, returns a list of IPs in string form
386
387   Does not return addresses on 127.0.0.0/8
388  */
389 static PyObject *py_interface_ips(PyObject *self, PyObject *args)
390 {
391         PyObject *pylist;
392         int count;
393         TALLOC_CTX *tmp_ctx;
394         PyObject *py_lp_ctx;
395         struct loadparm_context *lp_ctx;
396         struct interface *ifaces;
397         int i, ifcount;
398         int all_interfaces;
399
400         if (!PyArg_ParseTuple(args, "Oi", &py_lp_ctx, &all_interfaces))
401                 return NULL;
402
403         lp_ctx = lp_from_py_object(py_lp_ctx);
404         if (lp_ctx == NULL) {
405                 PyErr_SetString(PyExc_TypeError, "Expected loadparm object");
406                 return NULL;
407         }
408
409         tmp_ctx = talloc_new(NULL);
410
411         load_interfaces(tmp_ctx, lp_interfaces(lp_ctx), &ifaces);
412
413         count = iface_count(ifaces);
414
415         /* first count how many are not loopback addresses */
416         for (ifcount = i = 0; i<count; i++) {
417                 const char *ip = iface_n_ip(ifaces, i);
418                 if (!(!all_interfaces && iface_same_net(ip, "127.0.0.1", "255.0.0.0"))) {
419                         ifcount++;
420                 }
421         }
422
423         pylist = PyList_New(ifcount);
424         for (ifcount = i = 0; i<count; i++) {
425                 const char *ip = iface_n_ip(ifaces, i);
426                 if (!(!all_interfaces && iface_same_net(ip, "127.0.0.1", "255.0.0.0"))) {
427                         PyList_SetItem(pylist, ifcount, PyString_FromString(ip));
428                         ifcount++;
429                 }
430         }
431         talloc_free(tmp_ctx);
432         return pylist;
433 }
434
435
436 static PyMethodDef py_misc_methods[] = {
437         { "generate_random_str", (PyCFunction)py_generate_random_str, METH_VARARGS,
438                 "generate_random_str(len) -> string\n"
439                 "Generate random string with specified length." },
440         { "generate_random_password", (PyCFunction)py_generate_random_password, METH_VARARGS,
441                 "generate_random_password(min, max) -> string\n"
442                 "Generate random password with a length >= min and <= max." },
443         { "unix2nttime", (PyCFunction)py_unix2nttime, METH_VARARGS,
444                 "unix2nttime(timestamp) -> nttime" },
445         { "samdb_set_domain_sid", (PyCFunction)py_samdb_set_domain_sid, METH_VARARGS,
446                 "samdb_set_domain_sid(samdb, sid)\n"
447                 "Set SID of domain to use." },
448         { "samdb_get_domain_sid", (PyCFunction)py_samdb_get_domain_sid, METH_VARARGS,
449                 "samdb_get_domain_sid(samdb)\n"
450                 "Get SID of domain in use." },
451         { "dsdb_set_ntds_invocation_id", (PyCFunction)py_dsdb_set_ntds_invocation_id, METH_VARARGS,
452                 NULL },
453         { "dsdb_set_global_schema", (PyCFunction)py_dsdb_set_global_schema, METH_VARARGS,
454                 NULL },
455         { "dsdb_set_schema_from_ldif", (PyCFunction)py_dsdb_set_schema_from_ldif, METH_VARARGS,
456                 NULL },
457         { "dsdb_write_prefixes_from_schema_to_ldb", (PyCFunction)py_dsdb_write_prefixes_from_schema_to_ldb, METH_VARARGS,
458                 NULL },
459         { "dsdb_set_schema_from_ldb", (PyCFunction)py_dsdb_set_schema_from_ldb, METH_VARARGS,
460                 NULL },
461         { "set_debug_level", (PyCFunction)py_set_debug_level, METH_VARARGS,
462                 "set debug level" },
463         { "dsdb_load_partition_usn", (PyCFunction)py_dsdb_load_partition_usn, METH_VARARGS,
464                 "get uSNHighest and uSNUrgent from the partition @REPLCHANGED"},
465         { "samdb_ntds_invocation_id", (PyCFunction)py_samdb_ntds_invocation_id, METH_VARARGS,
466                 "get the NTDS invocation ID GUID as a string"},
467         { "samdb_ntds_objectGUID", (PyCFunction)py_samdb_ntds_objectGUID, METH_VARARGS,
468                 "get the NTDS objectGUID as a string"},
469         { "interface_ips", (PyCFunction)py_interface_ips, METH_VARARGS,
470                 "get interface IP address list"},
471         { NULL }
472 };
473
474 void initglue(void)
475 {
476         PyObject *m;
477
478         debug_setup_talloc_log();
479
480         m = Py_InitModule3("glue", py_misc_methods, 
481                            "Python bindings for miscellaneous Samba functions.");
482         if (m == NULL)
483                 return;
484
485         PyModule_AddObject(m, "version", PyString_FromString(SAMBA_VERSION_STRING));
486
487         /* one of the most annoying things about python scripts is
488            that they don't die when you hit control-C. This fixes that
489            sillyness. As we do all database operations using
490            transactions, this is also safe. In fact, not dying
491            immediately is unsafe as we could end up treating the
492            control-C exception as a different error and try to modify
493            as database incorrectly 
494         */
495         signal(SIGINT, SIG_DFL);
496 }
497