Revert "s4/dsdb: Set schemaInfo attribute value during provisioning"
[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_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         tmp_ctx = talloc_new(NULL);
210
211         lp_ctx = lp_from_py_object(NULL, py_lp_ctx); /* FIXME: leaky */
212         if (lp_ctx == NULL) {
213                 PyErr_SetString(PyExc_TypeError, "Expected loadparm object");
214                 talloc_free(tmp_ctx);
215                 return NULL;
216         }
217
218         load_interfaces(tmp_ctx, lp_interfaces(lp_ctx), &ifaces);
219
220         count = iface_count(ifaces);
221
222         /* first count how many are not loopback addresses */
223         for (ifcount = i = 0; i<count; i++) {
224                 const char *ip = iface_n_ip(ifaces, i);
225                 if (!(!all_interfaces && iface_same_net(ip, "127.0.0.1", "255.0.0.0"))) {
226                         ifcount++;
227                 }
228         }
229
230         pylist = PyList_New(ifcount);
231         for (ifcount = i = 0; i<count; i++) {
232                 const char *ip = iface_n_ip(ifaces, i);
233                 if (!(!all_interfaces && iface_same_net(ip, "127.0.0.1", "255.0.0.0"))) {
234                         PyList_SetItem(pylist, ifcount, PyString_FromString(ip));
235                         ifcount++;
236                 }
237         }
238         talloc_free(tmp_ctx);
239         return pylist;
240 }
241
242
243 static PyMethodDef py_misc_methods[] = {
244         { "generate_random_str", (PyCFunction)py_generate_random_str, METH_VARARGS,
245                 "generate_random_str(len) -> string\n"
246                 "Generate random string with specified length." },
247         { "generate_random_password", (PyCFunction)py_generate_random_password, METH_VARARGS,
248                 "generate_random_password(min, max) -> string\n"
249                 "Generate random password with a length >= min and <= max." },
250         { "unix2nttime", (PyCFunction)py_unix2nttime, METH_VARARGS,
251                 "unix2nttime(timestamp) -> nttime" },
252         { "dsdb_set_schema_from_ldif", (PyCFunction)py_dsdb_set_schema_from_ldif, METH_VARARGS,
253                 NULL },
254         { "dsdb_write_prefixes_from_schema_to_ldb", (PyCFunction)py_dsdb_write_prefixes_from_schema_to_ldb, METH_VARARGS,
255                 NULL },
256         { "dsdb_set_schema_from_ldb", (PyCFunction)py_dsdb_set_schema_from_ldb, METH_VARARGS,
257                 NULL },
258         { "set_debug_level", (PyCFunction)py_set_debug_level, METH_VARARGS,
259                 "set debug level" },
260         { "interface_ips", (PyCFunction)py_interface_ips, METH_VARARGS,
261                 "get interface IP address list"},
262         { NULL }
263 };
264
265 void init_glue(void)
266 {
267         PyObject *m;
268
269         debug_setup_talloc_log();
270
271         m = Py_InitModule3("_glue", py_misc_methods, 
272                            "Python bindings for miscellaneous Samba functions.");
273         if (m == NULL)
274                 return;
275
276         PyModule_AddObject(m, "version", PyString_FromString(SAMBA_VERSION_STRING));
277
278         /* one of the most annoying things about python scripts is
279            that they don't die when you hit control-C. This fixes that
280            sillyness. As we do all database operations using
281            transactions, this is also safe. In fact, not dying
282            immediately is unsafe as we could end up treating the
283            control-C exception as a different error and try to modify
284            as database incorrectly 
285         */
286         signal(SIGINT, SIG_DFL);
287 }
288