s4:schema Provide a way to reference a loaded schema between ldbs
[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    
5    This program is free software; you can redistribute it and/or modify
6    it under the terms of the GNU General Public License as published by
7    the Free Software Foundation; either version 3 of the License, or
8    (at your option) any later version.
9    
10    This program is distributed in the hope that it will be useful,
11    but WITHOUT ANY WARRANTY; without even the implied warranty of
12    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13    GNU General Public License for more details.
14    
15    You should have received a copy of the GNU General Public License
16    along with this program.  If not, see <http://www.gnu.org/licenses/>.
17 */
18
19 #include "includes.h"
20 #include "ldb.h"
21 #include "ldb_errors.h"
22 #include "param/param.h"
23 #include "auth/credentials/credentials.h"
24 #include "dsdb/samdb/samdb.h"
25 #include "lib/ldb-samba/ldif_handlers.h"
26 #include "librpc/ndr/libndr.h"
27 #include "version.h"
28 #include <Python.h>
29 #include "lib/ldb/pyldb.h"
30 #include "libcli/util/pyerrors.h"
31 #include "libcli/security/security.h"
32 #include "auth/pyauth.h"
33 #include "param/pyparam.h"
34 #include "auth/credentials/pycredentials.h"
35
36 #ifndef Py_RETURN_NONE
37 #define Py_RETURN_NONE return Py_INCREF(Py_None), Py_None
38 #endif
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_unix2nttime(PyObject *self, PyObject *args)
83 {
84         time_t t;
85         NTTIME nt;
86         if (!PyArg_ParseTuple(args, "I", &t))
87                 return NULL;
88
89         unix_to_nt_time(&nt, t);
90
91         return PyInt_FromLong((uint64_t)nt);
92 }
93
94 static PyObject *py_ldb_set_credentials(PyObject *self, PyObject *args)
95 {
96         PyObject *py_creds, *py_ldb;
97         struct cli_credentials *creds;
98         struct ldb_context *ldb;
99         if (!PyArg_ParseTuple(args, "OO", &py_ldb, &py_creds))
100                 return NULL;
101
102         PyErr_LDB_OR_RAISE(py_ldb, ldb);
103         
104         creds = cli_credentials_from_py_object(py_creds);
105         if (creds == NULL) {
106                 PyErr_SetString(PyExc_TypeError, "Expected credentials object");
107                 return NULL;
108         }
109
110         ldb_set_opaque(ldb, "credentials", creds);
111
112         Py_RETURN_NONE;
113 }
114
115 static PyObject *py_ldb_set_loadparm(PyObject *self, PyObject *args)
116 {
117         PyObject *py_lp_ctx, *py_ldb;
118         struct loadparm_context *lp_ctx;
119         struct ldb_context *ldb;
120         if (!PyArg_ParseTuple(args, "OO", &py_ldb, &py_lp_ctx))
121                 return NULL;
122
123         PyErr_LDB_OR_RAISE(py_ldb, ldb);
124
125         lp_ctx = lp_from_py_object(py_lp_ctx);
126         if (lp_ctx == NULL) {
127                 PyErr_SetString(PyExc_TypeError, "Expected loadparm object");
128                 return NULL;
129         }
130
131         ldb_set_opaque(ldb, "loadparm", lp_ctx);
132
133         Py_RETURN_NONE;
134 }
135
136
137 static PyObject *py_ldb_set_session_info(PyObject *self, PyObject *args)
138 {
139         PyObject *py_session_info, *py_ldb;
140         struct auth_session_info *info;
141         struct ldb_context *ldb;
142         if (!PyArg_ParseTuple(args, "OO", &py_ldb, &py_session_info))
143                 return NULL;
144
145         PyErr_LDB_OR_RAISE(py_ldb, ldb);
146         /*if (!PyAuthSession_Check(py_session_info)) {
147                 PyErr_SetString(PyExc_TypeError, "Expected session info object");
148                 return NULL;
149         }*/
150
151         info = PyAuthSession_AsSession(py_session_info);
152
153         ldb_set_opaque(ldb, "sessionInfo", info);
154
155         Py_RETURN_NONE;
156 }
157
158 static PyObject *py_samdb_set_domain_sid(PyLdbObject *self, PyObject *args)
159
160         PyObject *py_ldb, *py_sid;
161         struct ldb_context *ldb;
162         struct dom_sid *sid;
163         bool ret;
164
165         if (!PyArg_ParseTuple(args, "OO", &py_ldb, &py_sid))
166                 return NULL;
167         
168         PyErr_LDB_OR_RAISE(py_ldb, ldb);
169
170         sid = dom_sid_parse_talloc(NULL, PyString_AsString(py_sid));
171
172         ret = samdb_set_domain_sid(ldb, sid);
173         if (!ret) {
174                 PyErr_SetString(PyExc_RuntimeError, "set_domain_sid failed");
175                 return NULL;
176         } 
177         Py_RETURN_NONE;
178 }
179
180 static PyObject *py_ldb_register_samba_handlers(PyObject *self, PyObject *args)
181 {
182         PyObject *py_ldb;
183         struct ldb_context *ldb;
184         int ret;
185
186         if (!PyArg_ParseTuple(args, "O", &py_ldb))
187                 return NULL;
188
189         PyErr_LDB_OR_RAISE(py_ldb, ldb);
190         ret = ldb_register_samba_handlers(ldb);
191
192         PyErr_LDB_ERROR_IS_ERR_RAISE(py_ldb_get_exception(), ret, ldb);
193         Py_RETURN_NONE;
194 }
195
196 static PyObject *py_dsdb_set_ntds_invocation_id(PyObject *self, PyObject *args)
197 {
198         PyObject *py_ldb, *py_guid;
199         bool ret;
200         struct GUID guid;
201         struct ldb_context *ldb;
202         if (!PyArg_ParseTuple(args, "OO", &py_ldb, &py_guid))
203                 return NULL;
204
205         PyErr_LDB_OR_RAISE(py_ldb, ldb);
206         GUID_from_string(PyString_AsString(py_guid), &guid);
207
208         ret = samdb_set_ntds_invocation_id(ldb, &guid);
209         if (!ret) {
210                 PyErr_SetString(PyExc_RuntimeError, "set_ntds_invocation_id failed");
211                 return NULL;
212         }
213         Py_RETURN_NONE;
214 }
215
216 static PyObject *py_dsdb_set_opaque_integer(PyObject *self, PyObject *args)
217 {
218         PyObject *py_ldb;
219         int value;
220         int *old_val, *new_val;
221         char *py_opaque_name, *opaque_name_talloc;
222         struct ldb_context *ldb;
223         TALLOC_CTX *tmp_ctx;
224
225         if (!PyArg_ParseTuple(args, "Osi", &py_ldb, &py_opaque_name, &value))
226                 return NULL;
227
228         PyErr_LDB_OR_RAISE(py_ldb, ldb);
229
230         /* see if we have a cached copy */
231         old_val = (int *)ldb_get_opaque(ldb, 
232                                         py_opaque_name);
233
234         if (old_val) {
235                 *old_val = value;
236                 Py_RETURN_NONE;
237         } 
238
239         tmp_ctx = talloc_new(ldb);
240         if (tmp_ctx == NULL) {
241                 goto failed;
242         }
243         
244         new_val = talloc(tmp_ctx, int);
245         if (!new_val) {
246                 goto failed;
247         }
248         
249         opaque_name_talloc = talloc_strdup(tmp_ctx, py_opaque_name);
250         if (!opaque_name_talloc) {
251                 goto failed;
252         }
253         
254         *new_val = value;
255
256         /* cache the domain_sid in the ldb */
257         if (ldb_set_opaque(ldb, opaque_name_talloc, new_val) != LDB_SUCCESS) {
258                 goto failed;
259         }
260
261         talloc_steal(ldb, new_val);
262         talloc_steal(ldb, opaque_name_talloc);
263         talloc_free(tmp_ctx);
264
265         Py_RETURN_NONE;
266
267 failed:
268         talloc_free(tmp_ctx);
269         PyErr_SetString(PyExc_RuntimeError, "Failed to set opaque integer into the ldb!\n");
270         return NULL;
271 }
272
273 static PyObject *py_dsdb_set_global_schema(PyObject *self, PyObject *args)
274 {
275         PyObject *py_ldb;
276         struct ldb_context *ldb;
277         int ret;
278         if (!PyArg_ParseTuple(args, "O", &py_ldb))
279                 return NULL;
280
281         PyErr_LDB_OR_RAISE(py_ldb, ldb);
282
283         ret = dsdb_set_global_schema(ldb);
284         PyErr_LDB_ERROR_IS_ERR_RAISE(py_ldb_get_exception(), ret, ldb);
285
286         Py_RETURN_NONE;
287 }
288
289 static PyObject *py_dsdb_set_schema_from_ldif(PyObject *self, PyObject *args)
290 {
291         WERROR result;
292         char *pf, *df;
293         PyObject *py_ldb;
294         struct ldb_context *ldb;
295
296         if (!PyArg_ParseTuple(args, "Oss", &py_ldb, &pf, &df))
297                 return NULL;
298
299         PyErr_LDB_OR_RAISE(py_ldb, ldb);
300
301         result = dsdb_set_schema_from_ldif(ldb, pf, df);
302         PyErr_WERROR_IS_ERR_RAISE(result);
303
304         Py_RETURN_NONE;
305 }
306
307 static PyObject *py_dsdb_convert_schema_to_openldap(PyObject *self, PyObject *args)
308 {
309         char *target_str, *mapping;
310         PyObject *py_ldb;
311         struct ldb_context *ldb;
312         PyObject *ret;
313         char *retstr;
314
315         if (!PyArg_ParseTuple(args, "Oss", &py_ldb, &target_str, &mapping))
316                 return NULL;
317
318         PyErr_LDB_OR_RAISE(py_ldb, ldb);
319
320         retstr = dsdb_convert_schema_to_openldap(ldb, target_str, mapping);
321         if (!retstr) {
322                 PyErr_SetString(PyExc_RuntimeError, "dsdb_convert_schema_to_openldap failed");
323                 return NULL;
324         } 
325         ret = PyString_FromString(retstr);
326         talloc_free(retstr);
327         return ret;
328 }
329
330 static PyObject *py_dsdb_set_schema_from_ldb(PyObject *self, PyObject *args)
331 {
332         PyObject *py_ldb;
333         struct ldb_context *ldb;
334         PyObject *py_from_ldb;
335         struct ldb_context *from_ldb;
336         struct dsdb_schema *schema;
337         int ret;
338         if (!PyArg_ParseTuple(args, "OO", &py_ldb, &py_from_ldb))
339                 return NULL;
340
341         PyErr_LDB_OR_RAISE(py_ldb, ldb);
342
343         PyErr_LDB_OR_RAISE(py_from_ldb, from_ldb);
344
345         schema = dsdb_get_schema(from_ldb);
346         if (!schema) {
347                 PyErr_SetString(PyExc_RuntimeError, "Failed to set find a schema on 'from' ldb!\n");
348                 return NULL;
349         }
350
351         ret = dsdb_reference_schema(ldb, schema);
352         PyErr_LDB_ERROR_IS_ERR_RAISE(py_ldb_get_exception(), ret, ldb);
353
354         Py_RETURN_NONE;
355 }
356
357 static PyObject *py_dom_sid_to_rid(PyLdbObject *self, PyObject *args)
358 {
359         PyObject *py_sid;
360         struct dom_sid *sid;
361         uint32_t rid;
362         NTSTATUS status;
363         
364         if(!PyArg_ParseTuple(args, "O", &py_sid))
365                 return NULL;
366
367         sid = dom_sid_parse_talloc(NULL, PyString_AsString(py_sid));
368
369         status = dom_sid_split_rid(NULL, sid, NULL, &rid);
370         if (!NT_STATUS_IS_OK(status)) {
371                 PyErr_SetString(PyExc_RuntimeError, "dom_sid_split_rid failed");
372                 return NULL;
373         }
374
375         return PyInt_FromLong(rid);
376 }
377
378 static PyMethodDef py_misc_methods[] = {
379         { "generate_random_str", (PyCFunction)py_generate_random_str, METH_VARARGS,
380                 "random_password(len) -> string\n"
381                 "Generate random password with specified length." },
382         { "unix2nttime", (PyCFunction)py_unix2nttime, METH_VARARGS,
383                 "unix2nttime(timestamp) -> nttime" },
384         { "ldb_set_credentials", (PyCFunction)py_ldb_set_credentials, METH_VARARGS, 
385                 "ldb_set_credentials(ldb, credentials) -> None\n"
386                 "Set credentials to use when connecting." },
387         { "ldb_set_session_info", (PyCFunction)py_ldb_set_session_info, METH_VARARGS,
388                 "ldb_set_session_info(ldb, session_info)\n"
389                 "Set session info to use when connecting." },
390         { "ldb_set_loadparm", (PyCFunction)py_ldb_set_loadparm, METH_VARARGS,
391                 "ldb_set_loadparm(ldb, session_info)\n"
392                 "Set loadparm context to use when connecting." },
393         { "samdb_set_domain_sid", (PyCFunction)py_samdb_set_domain_sid, METH_VARARGS,
394                 "samdb_set_domain_sid(samdb, sid)\n"
395                 "Set SID of domain to use." },
396         { "ldb_register_samba_handlers", (PyCFunction)py_ldb_register_samba_handlers, METH_VARARGS,
397                 "ldb_register_samba_handlers(ldb)\n"
398                 "Register Samba-specific LDB modules and schemas." },
399         { "dsdb_set_ntds_invocation_id", (PyCFunction)py_dsdb_set_ntds_invocation_id, METH_VARARGS,
400                 NULL },
401         { "dsdb_set_opaque_integer", (PyCFunction)py_dsdb_set_opaque_integer, METH_VARARGS,
402                 NULL },
403         { "dsdb_set_global_schema", (PyCFunction)py_dsdb_set_global_schema, METH_VARARGS,
404                 NULL },
405         { "dsdb_set_schema_from_ldif", (PyCFunction)py_dsdb_set_schema_from_ldif, METH_VARARGS,
406                 NULL },
407         { "dsdb_set_schema_from_ldb", (PyCFunction)py_dsdb_set_schema_from_ldb, METH_VARARGS,
408                 NULL },
409         { "dsdb_convert_schema_to_openldap", (PyCFunction)py_dsdb_convert_schema_to_openldap, METH_VARARGS,
410                 NULL },
411         { "dom_sid_to_rid", (PyCFunction)py_dom_sid_to_rid, METH_VARARGS,
412                 NULL },
413         { NULL }
414 };
415
416 void initglue(void)
417 {
418         PyObject *m;
419
420         m = Py_InitModule3("glue", py_misc_methods, 
421                            "Python bindings for miscellaneous Samba functions.");
422         if (m == NULL)
423                 return;
424
425         PyModule_AddObject(m, "version", PyString_FromString(SAMBA_VERSION_STRING));
426
427         PyModule_AddObject(m, "DS_BEHAVIOR_WIN2000", PyInt_FromLong(DS_BEHAVIOR_WIN2000));
428         PyModule_AddObject(m, "DS_BEHAVIOR_WIN2003_INTERIM", PyInt_FromLong(DS_BEHAVIOR_WIN2003_INTERIM));
429         PyModule_AddObject(m, "DS_BEHAVIOR_WIN2003", PyInt_FromLong(DS_BEHAVIOR_WIN2003));
430         PyModule_AddObject(m, "DS_BEHAVIOR_WIN2008", PyInt_FromLong(DS_BEHAVIOR_WIN2008));
431
432 }
433