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