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