s4/dsdb: Set schemaInfo attribute value during provisioning
[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_schema_info_reset(PyObject *self, PyObject *args)
163 {
164         PyObject *py_ldb;
165         struct ldb_context *ldb;
166         WERROR result;
167         struct dsdb_schema *schema;
168
169         if (!PyArg_ParseTuple(args, "O", &py_ldb))
170                 return NULL;
171
172         PyErr_LDB_OR_RAISE(py_ldb, ldb);
173
174         schema = dsdb_get_schema(ldb, NULL);
175         if (!schema) {
176                 PyErr_SetString(PyExc_RuntimeError, "Failed to set find a schema on ldb!\n");
177                 return NULL;
178         }
179
180         result = dsdb_schema_info_reset(ldb, schema);
181         PyErr_WERROR_IS_ERR_RAISE(result);
182
183         Py_RETURN_NONE;
184 }
185
186 static PyObject *py_dsdb_set_schema_from_ldb(PyObject *self, PyObject *args)
187 {
188         PyObject *py_ldb;
189         struct ldb_context *ldb;
190         PyObject *py_from_ldb;
191         struct ldb_context *from_ldb;
192         struct dsdb_schema *schema;
193         int ret;
194         if (!PyArg_ParseTuple(args, "OO", &py_ldb, &py_from_ldb))
195                 return NULL;
196
197         PyErr_LDB_OR_RAISE(py_ldb, ldb);
198
199         PyErr_LDB_OR_RAISE(py_from_ldb, from_ldb);
200
201         schema = dsdb_get_schema(from_ldb, NULL);
202         if (!schema) {
203                 PyErr_SetString(PyExc_RuntimeError, "Failed to set find a schema on 'from' ldb!\n");
204                 return NULL;
205         }
206
207         ret = dsdb_reference_schema(ldb, schema, true);
208         PyErr_LDB_ERROR_IS_ERR_RAISE(py_ldb_get_exception(), ret, ldb);
209
210         Py_RETURN_NONE;
211 }
212
213 /*
214   return the list of interface IPs we have configured
215   takes an loadparm context, returns a list of IPs in string form
216
217   Does not return addresses on 127.0.0.0/8
218  */
219 static PyObject *py_interface_ips(PyObject *self, PyObject *args)
220 {
221         PyObject *pylist;
222         int count;
223         TALLOC_CTX *tmp_ctx;
224         PyObject *py_lp_ctx;
225         struct loadparm_context *lp_ctx;
226         struct interface *ifaces;
227         int i, ifcount;
228         int all_interfaces;
229
230         if (!PyArg_ParseTuple(args, "Oi", &py_lp_ctx, &all_interfaces))
231                 return NULL;
232
233         tmp_ctx = talloc_new(NULL);
234
235         lp_ctx = lp_from_py_object(NULL, py_lp_ctx); /* FIXME: leaky */
236         if (lp_ctx == NULL) {
237                 PyErr_SetString(PyExc_TypeError, "Expected loadparm object");
238                 talloc_free(tmp_ctx);
239                 return NULL;
240         }
241
242         load_interfaces(tmp_ctx, lp_interfaces(lp_ctx), &ifaces);
243
244         count = iface_count(ifaces);
245
246         /* first count how many are not loopback addresses */
247         for (ifcount = i = 0; i<count; i++) {
248                 const char *ip = iface_n_ip(ifaces, i);
249                 if (!(!all_interfaces && iface_same_net(ip, "127.0.0.1", "255.0.0.0"))) {
250                         ifcount++;
251                 }
252         }
253
254         pylist = PyList_New(ifcount);
255         for (ifcount = i = 0; i<count; i++) {
256                 const char *ip = iface_n_ip(ifaces, i);
257                 if (!(!all_interfaces && iface_same_net(ip, "127.0.0.1", "255.0.0.0"))) {
258                         PyList_SetItem(pylist, ifcount, PyString_FromString(ip));
259                         ifcount++;
260                 }
261         }
262         talloc_free(tmp_ctx);
263         return pylist;
264 }
265
266
267 static PyMethodDef py_misc_methods[] = {
268         { "generate_random_str", (PyCFunction)py_generate_random_str, METH_VARARGS,
269                 "generate_random_str(len) -> string\n"
270                 "Generate random string with specified length." },
271         { "generate_random_password", (PyCFunction)py_generate_random_password, METH_VARARGS,
272                 "generate_random_password(min, max) -> string\n"
273                 "Generate random password with a length >= min and <= max." },
274         { "unix2nttime", (PyCFunction)py_unix2nttime, METH_VARARGS,
275                 "unix2nttime(timestamp) -> nttime" },
276         { "dsdb_set_schema_from_ldif", (PyCFunction)py_dsdb_set_schema_from_ldif, METH_VARARGS,
277                 NULL },
278         { "dsdb_write_prefixes_from_schema_to_ldb", (PyCFunction)py_dsdb_write_prefixes_from_schema_to_ldb, METH_VARARGS,
279                 NULL },
280         { "dsdb_schema_info_reset", (PyCFunction)py_dsdb_schema_info_reset, METH_VARARGS,
281                 "Reset schemaInfo value to default for a new Forest" },
282         { "dsdb_set_schema_from_ldb", (PyCFunction)py_dsdb_set_schema_from_ldb, METH_VARARGS,
283                 NULL },
284         { "set_debug_level", (PyCFunction)py_set_debug_level, METH_VARARGS,
285                 "set debug level" },
286         { "interface_ips", (PyCFunction)py_interface_ips, METH_VARARGS,
287                 "get interface IP address list"},
288         { NULL }
289 };
290
291 void init_glue(void)
292 {
293         PyObject *m;
294
295         debug_setup_talloc_log();
296
297         m = Py_InitModule3("_glue", py_misc_methods, 
298                            "Python bindings for miscellaneous Samba functions.");
299         if (m == NULL)
300                 return;
301
302         PyModule_AddObject(m, "version", PyString_FromString(SAMBA_VERSION_STRING));
303
304         /* one of the most annoying things about python scripts is
305            that they don't die when you hit control-C. This fixes that
306            sillyness. As we do all database operations using
307            transactions, this is also safe. In fact, not dying
308            immediately is unsafe as we could end up treating the
309            control-C exception as a different error and try to modify
310            as database incorrectly 
311         */
312         signal(SIGINT, SIG_DFL);
313 }
314