s4-python: Move samdb_ntds_objectGUID to pydsdb.
[metze/samba/wip.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_dsdb_set_global_schema(PyObject *self, PyObject *args)
121 {
122         PyObject *py_ldb;
123         struct ldb_context *ldb;
124         int ret;
125         if (!PyArg_ParseTuple(args, "O", &py_ldb))
126                 return NULL;
127
128         PyErr_LDB_OR_RAISE(py_ldb, ldb);
129
130         ret = dsdb_set_global_schema(ldb);
131         PyErr_LDB_ERROR_IS_ERR_RAISE(py_ldb_get_exception(), ret, ldb);
132
133         Py_RETURN_NONE;
134 }
135
136 static PyObject *py_dsdb_set_schema_from_ldif(PyObject *self, PyObject *args)
137 {
138         WERROR result;
139         char *pf, *df;
140         PyObject *py_ldb;
141         struct ldb_context *ldb;
142
143         if (!PyArg_ParseTuple(args, "Oss", &py_ldb, &pf, &df))
144                 return NULL;
145
146         PyErr_LDB_OR_RAISE(py_ldb, ldb);
147
148         result = dsdb_set_schema_from_ldif(ldb, pf, df);
149         PyErr_WERROR_IS_ERR_RAISE(result);
150
151         Py_RETURN_NONE;
152 }
153
154 static PyObject *py_dsdb_write_prefixes_from_schema_to_ldb(PyObject *self, PyObject *args)
155 {
156         PyObject *py_ldb;
157         struct ldb_context *ldb;
158         WERROR result;
159         struct dsdb_schema *schema;
160
161         if (!PyArg_ParseTuple(args, "O", &py_ldb))
162                 return NULL;
163
164         PyErr_LDB_OR_RAISE(py_ldb, ldb);
165
166         schema = dsdb_get_schema(ldb, NULL);
167         if (!schema) {
168                 PyErr_SetString(PyExc_RuntimeError, "Failed to set find a schema on ldb!\n");
169                 return NULL;
170         }
171
172         result = dsdb_write_prefixes_from_schema_to_ldb(NULL, ldb, schema);
173         PyErr_WERROR_IS_ERR_RAISE(result);
174
175         Py_RETURN_NONE;
176 }
177
178 static PyObject *py_dsdb_set_schema_from_ldb(PyObject *self, PyObject *args)
179 {
180         PyObject *py_ldb;
181         struct ldb_context *ldb;
182         PyObject *py_from_ldb;
183         struct ldb_context *from_ldb;
184         struct dsdb_schema *schema;
185         int ret;
186         if (!PyArg_ParseTuple(args, "OO", &py_ldb, &py_from_ldb))
187                 return NULL;
188
189         PyErr_LDB_OR_RAISE(py_ldb, ldb);
190
191         PyErr_LDB_OR_RAISE(py_from_ldb, from_ldb);
192
193         schema = dsdb_get_schema(from_ldb, NULL);
194         if (!schema) {
195                 PyErr_SetString(PyExc_RuntimeError, "Failed to set find a schema on 'from' ldb!\n");
196                 return NULL;
197         }
198
199         ret = dsdb_reference_schema(ldb, schema, true);
200         PyErr_LDB_ERROR_IS_ERR_RAISE(py_ldb_get_exception(), ret, ldb);
201
202         Py_RETURN_NONE;
203 }
204
205 static PyObject *py_dsdb_load_partition_usn(PyObject *self, PyObject *args)
206 {
207         PyObject *py_dn, *py_ldb, *result;
208         struct ldb_dn *dn;
209         uint64_t highest_uSN, urgent_uSN;
210         struct ldb_context *ldb;
211         TALLOC_CTX *mem_ctx;
212         int ret;
213
214         mem_ctx = talloc_new(NULL);
215         if (mem_ctx == NULL) {
216            PyErr_NoMemory();
217            return NULL;
218         }
219
220         if (!PyArg_ParseTuple(args, "OO", &py_ldb, &py_dn)) {
221            talloc_free(mem_ctx);
222            return NULL;
223         }
224
225         PyErr_LDB_OR_RAISE(py_ldb, ldb);
226
227         if (!PyObject_AsDn(mem_ctx, py_dn, ldb, &dn)) {
228            talloc_free(mem_ctx);
229            return NULL;
230         }
231
232         ret = dsdb_load_partition_usn(ldb, dn, &highest_uSN, &urgent_uSN);
233         if (ret != LDB_SUCCESS) {
234            char *errstr = talloc_asprintf(mem_ctx, "Failed to load partition uSN - %s", ldb_errstring(ldb));
235            PyErr_SetString(PyExc_RuntimeError, errstr);
236            talloc_free(mem_ctx);
237            return NULL;
238         }
239
240         talloc_free(mem_ctx);
241
242         result = PyDict_New();
243
244         PyDict_SetItemString(result, "uSNHighest", PyInt_FromLong((uint64_t)highest_uSN));
245         PyDict_SetItemString(result, "uSNUrgent", PyInt_FromLong((uint64_t)urgent_uSN));
246
247
248         return result;
249 }
250
251 /*
252   return the list of interface IPs we have configured
253   takes an loadparm context, returns a list of IPs in string form
254
255   Does not return addresses on 127.0.0.0/8
256  */
257 static PyObject *py_interface_ips(PyObject *self, PyObject *args)
258 {
259         PyObject *pylist;
260         int count;
261         TALLOC_CTX *tmp_ctx;
262         PyObject *py_lp_ctx;
263         struct loadparm_context *lp_ctx;
264         struct interface *ifaces;
265         int i, ifcount;
266         int all_interfaces;
267
268         if (!PyArg_ParseTuple(args, "Oi", &py_lp_ctx, &all_interfaces))
269                 return NULL;
270
271         lp_ctx = lp_from_py_object(py_lp_ctx);
272         if (lp_ctx == NULL) {
273                 PyErr_SetString(PyExc_TypeError, "Expected loadparm object");
274                 return NULL;
275         }
276
277         tmp_ctx = talloc_new(NULL);
278
279         load_interfaces(tmp_ctx, lp_interfaces(lp_ctx), &ifaces);
280
281         count = iface_count(ifaces);
282
283         /* first count how many are not loopback addresses */
284         for (ifcount = i = 0; i<count; i++) {
285                 const char *ip = iface_n_ip(ifaces, i);
286                 if (!(!all_interfaces && iface_same_net(ip, "127.0.0.1", "255.0.0.0"))) {
287                         ifcount++;
288                 }
289         }
290
291         pylist = PyList_New(ifcount);
292         for (ifcount = i = 0; i<count; i++) {
293                 const char *ip = iface_n_ip(ifaces, i);
294                 if (!(!all_interfaces && iface_same_net(ip, "127.0.0.1", "255.0.0.0"))) {
295                         PyList_SetItem(pylist, ifcount, PyString_FromString(ip));
296                         ifcount++;
297                 }
298         }
299         talloc_free(tmp_ctx);
300         return pylist;
301 }
302
303
304 static PyMethodDef py_misc_methods[] = {
305         { "generate_random_str", (PyCFunction)py_generate_random_str, METH_VARARGS,
306                 "generate_random_str(len) -> string\n"
307                 "Generate random string with specified length." },
308         { "generate_random_password", (PyCFunction)py_generate_random_password, METH_VARARGS,
309                 "generate_random_password(min, max) -> string\n"
310                 "Generate random password with a length >= min and <= max." },
311         { "unix2nttime", (PyCFunction)py_unix2nttime, METH_VARARGS,
312                 "unix2nttime(timestamp) -> nttime" },
313         { "dsdb_set_global_schema", (PyCFunction)py_dsdb_set_global_schema, METH_VARARGS,
314                 NULL },
315         { "dsdb_set_schema_from_ldif", (PyCFunction)py_dsdb_set_schema_from_ldif, METH_VARARGS,
316                 NULL },
317         { "dsdb_write_prefixes_from_schema_to_ldb", (PyCFunction)py_dsdb_write_prefixes_from_schema_to_ldb, METH_VARARGS,
318                 NULL },
319         { "dsdb_set_schema_from_ldb", (PyCFunction)py_dsdb_set_schema_from_ldb, METH_VARARGS,
320                 NULL },
321         { "set_debug_level", (PyCFunction)py_set_debug_level, METH_VARARGS,
322                 "set debug level" },
323         { "dsdb_load_partition_usn", (PyCFunction)py_dsdb_load_partition_usn, METH_VARARGS,
324                 "get uSNHighest and uSNUrgent from the partition @REPLCHANGED"},
325         { "interface_ips", (PyCFunction)py_interface_ips, METH_VARARGS,
326                 "get interface IP address list"},
327         { NULL }
328 };
329
330 void initglue(void)
331 {
332         PyObject *m;
333
334         debug_setup_talloc_log();
335
336         m = Py_InitModule3("glue", py_misc_methods, 
337                            "Python bindings for miscellaneous Samba functions.");
338         if (m == NULL)
339                 return;
340
341         PyModule_AddObject(m, "version", PyString_FromString(SAMBA_VERSION_STRING));
342
343         /* one of the most annoying things about python scripts is
344            that they don't die when you hit control-C. This fixes that
345            sillyness. As we do all database operations using
346            transactions, this is also safe. In fact, not dying
347            immediately is unsafe as we could end up treating the
348            control-C exception as a different error and try to modify
349            as database incorrectly 
350         */
351         signal(SIGINT, SIG_DFL);
352 }
353