s4 python: Add a function to get the oid of an attribute when the attid is known
[kamenim/samba.git] / source4 / dsdb / pydsdb.c
1 /* 
2    Unix SMB/CIFS implementation.
3    Copyright (C) Jelmer Vernooij <jelmer@samba.org> 2007-2010
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 "libcli/util/pyerrors.h"
23 #include "dsdb/samdb/samdb.h"
24 #include "lib/ldb/pyldb.h"
25 #include "libcli/security/security.h"
26 #include "librpc/ndr/libndr.h"
27
28 /* FIXME: These should be in a header file somewhere, once we finish moving
29  * away from SWIG .. */
30 #define PyErr_LDB_OR_RAISE(py_ldb, ldb) \
31 /*      if (!PyLdb_Check(py_ldb)) { \
32                 PyErr_SetString(py_ldb_get_exception(), "Ldb connection object required"); \
33                 return NULL; \
34         } */\
35         ldb = PyLdb_AsLdbContext(py_ldb);
36
37 static PyObject *py_ldb_get_exception(void)
38 {
39         PyObject *mod = PyImport_ImportModule("ldb");
40         if (mod == NULL)
41                 return NULL;
42
43         return PyObject_GetAttrString(mod, "LdbError");
44 }
45
46 static void PyErr_SetLdbError(PyObject *error, int ret, struct ldb_context *ldb_ctx)
47 {
48         if (ret == LDB_ERR_PYTHON_EXCEPTION)
49                 return; /* Python exception should already be set, just keep that */
50
51         PyErr_SetObject(error, 
52                         Py_BuildValue(discard_const_p(char, "(i,s)"), ret,
53                         ldb_ctx == NULL?ldb_strerror(ret):ldb_errstring(ldb_ctx)));
54 }
55
56 static PyObject *py_samdb_server_site_name(PyObject *self, PyObject *args)
57 {
58         PyObject *py_ldb, *result;
59         struct ldb_context *ldb;
60         const char *site;
61         TALLOC_CTX *mem_ctx;
62
63         if (!PyArg_ParseTuple(args, "O", &py_ldb))
64                 return NULL;
65
66         PyErr_LDB_OR_RAISE(py_ldb, ldb);
67
68         mem_ctx = talloc_new(NULL);
69
70         site = samdb_server_site_name(ldb, mem_ctx);
71         if (site == NULL) {
72                 PyErr_SetString(PyExc_RuntimeError, "Failed to find server site");
73                 talloc_free(mem_ctx);
74                 return NULL;
75         }
76
77         result = PyString_FromString(site);
78         talloc_free(mem_ctx);
79         return result;
80 }
81
82 static PyObject *py_dsdb_convert_schema_to_openldap(PyObject *self,
83                                                                                                         PyObject *args)
84 {
85         char *target_str, *mapping;
86         PyObject *py_ldb;
87         struct ldb_context *ldb;
88         PyObject *ret;
89         char *retstr;
90
91         if (!PyArg_ParseTuple(args, "Oss", &py_ldb, &target_str, &mapping))
92                 return NULL;
93
94         PyErr_LDB_OR_RAISE(py_ldb, ldb);
95
96         retstr = dsdb_convert_schema_to_openldap(ldb, target_str, mapping);
97         if (retstr == NULL) {
98                 PyErr_SetString(PyExc_RuntimeError,
99                                                 "dsdb_convert_schema_to_openldap failed");
100                 return NULL;
101         } 
102
103         ret = PyString_FromString(retstr);
104         talloc_free(retstr);
105         return ret;
106 }
107
108 static PyObject *py_samdb_set_domain_sid(PyLdbObject *self, PyObject *args)
109
110         PyObject *py_ldb, *py_sid;
111         struct ldb_context *ldb;
112         struct dom_sid *sid;
113         bool ret;
114
115         if (!PyArg_ParseTuple(args, "OO", &py_ldb, &py_sid))
116                 return NULL;
117         
118         PyErr_LDB_OR_RAISE(py_ldb, ldb);
119
120         sid = dom_sid_parse_talloc(NULL, PyString_AsString(py_sid));
121
122         ret = samdb_set_domain_sid(ldb, sid);
123         if (!ret) {
124                 PyErr_SetString(PyExc_RuntimeError, "set_domain_sid failed");
125                 return NULL;
126         } 
127         Py_RETURN_NONE;
128 }
129
130 static PyObject *py_samdb_get_domain_sid(PyLdbObject *self, PyObject *args)
131
132         PyObject *py_ldb;
133         struct ldb_context *ldb;
134         const struct dom_sid *sid;
135         PyObject *ret;
136         char *retstr;
137
138         if (!PyArg_ParseTuple(args, "O", &py_ldb))
139                 return NULL;
140         
141         PyErr_LDB_OR_RAISE(py_ldb, ldb);
142
143         sid = samdb_domain_sid(ldb);
144         if (!sid) {
145                 PyErr_SetString(PyExc_RuntimeError, "samdb_domain_sid failed");
146                 return NULL;
147         } 
148         retstr = dom_sid_string(NULL, sid);
149         ret = PyString_FromString(retstr);
150         talloc_free(retstr);
151         return ret;
152 }
153
154 static PyObject *py_samdb_ntds_invocation_id(PyObject *self, PyObject *args)
155 {
156         PyObject *py_ldb, *result;
157         struct ldb_context *ldb;
158         TALLOC_CTX *mem_ctx;
159         const struct GUID *guid;
160
161         mem_ctx = talloc_new(NULL);
162         if (mem_ctx == NULL) {
163                 PyErr_NoMemory();
164                 return NULL;
165         }
166
167         if (!PyArg_ParseTuple(args, "O", &py_ldb)) {
168                 talloc_free(mem_ctx);
169                 return NULL;
170         }
171
172         PyErr_LDB_OR_RAISE(py_ldb, ldb);
173
174         guid = samdb_ntds_invocation_id(ldb);
175         if (guid == NULL) {
176                 PyErr_SetString(PyExc_RuntimeError,
177                                                 "Failed to find NTDS invocation ID");
178                 talloc_free(mem_ctx);
179                 return NULL;
180         }
181
182         result = PyString_FromString(GUID_string(mem_ctx, guid));
183         talloc_free(mem_ctx);
184         return result;
185 }
186
187 static PyObject *py_dsdb_get_oid_from_attid(PyObject *self, PyObject *args)
188 {
189         PyObject *py_ldb;
190         struct ldb_context *ldb;
191         uint32_t attid;
192         struct dsdb_schema *schema;
193         const char *oid;
194         TALLOC_CTX *mem_ctx;
195         WERROR status;
196
197         mem_ctx = talloc_new(NULL);
198         if (mem_ctx == NULL) {
199            PyErr_NoMemory();
200            return NULL;
201         }
202
203         if (!PyArg_ParseTuple(args, "Oi", &py_ldb, &attid))
204                 return NULL;
205
206         PyErr_LDB_OR_RAISE(py_ldb, ldb);
207
208         schema = dsdb_get_schema(ldb, NULL);
209
210         if (!schema) {
211                 PyErr_SetString(PyExc_RuntimeError, "Failed to find a schema from ldb \n");
212                 return NULL;
213         }
214         status = dsdb_schema_pfm_oid_from_attid(schema->prefixmap, attid,
215                                                         mem_ctx, &oid);
216         PyErr_WERROR_IS_ERR_RAISE(status);
217
218         return PyString_FromString(oid);
219 }
220
221 static PyObject *py_dsdb_set_ntds_invocation_id(PyObject *self, PyObject *args)
222 {
223         PyObject *py_ldb, *py_guid;
224         bool ret;
225         struct GUID guid;
226         struct ldb_context *ldb;
227         if (!PyArg_ParseTuple(args, "OO", &py_ldb, &py_guid))
228                 return NULL;
229
230         PyErr_LDB_OR_RAISE(py_ldb, ldb);
231         GUID_from_string(PyString_AsString(py_guid), &guid);
232
233         ret = samdb_set_ntds_invocation_id(ldb, &guid);
234         if (!ret) {
235                 PyErr_SetString(PyExc_RuntimeError, "set_ntds_invocation_id failed");
236                 return NULL;
237         }
238         Py_RETURN_NONE;
239 }
240
241 static PyObject *py_samdb_ntds_objectGUID(PyObject *self, PyObject *args)
242 {
243         PyObject *py_ldb, *result;
244         struct ldb_context *ldb;
245         TALLOC_CTX *mem_ctx;
246         const struct GUID *guid;
247
248         mem_ctx = talloc_new(NULL);
249         if (mem_ctx == NULL) {
250                 PyErr_NoMemory();
251                 return NULL;
252         }
253
254         if (!PyArg_ParseTuple(args, "O", &py_ldb)) {
255                 talloc_free(mem_ctx);
256                 return NULL;
257         }
258
259         PyErr_LDB_OR_RAISE(py_ldb, ldb);
260
261         guid = samdb_ntds_objectGUID(ldb);
262         if (guid == NULL) {
263                 PyErr_SetString(PyExc_RuntimeError, "Failed to find NTDS GUID");
264                 talloc_free(mem_ctx);
265                 return NULL;
266         }
267
268         result = PyString_FromString(GUID_string(mem_ctx, guid));
269         talloc_free(mem_ctx);
270         return result;
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_load_partition_usn(PyObject *self, PyObject *args)
290 {
291         PyObject *py_dn, *py_ldb, *result;
292         struct ldb_dn *dn;
293         uint64_t highest_uSN, urgent_uSN;
294         struct ldb_context *ldb;
295         TALLOC_CTX *mem_ctx;
296         int ret;
297
298         mem_ctx = talloc_new(NULL);
299         if (mem_ctx == NULL) {
300            PyErr_NoMemory();
301            return NULL;
302         }
303
304         if (!PyArg_ParseTuple(args, "OO", &py_ldb, &py_dn)) {
305            talloc_free(mem_ctx);
306            return NULL;
307         }
308
309         PyErr_LDB_OR_RAISE(py_ldb, ldb);
310
311         if (!PyObject_AsDn(mem_ctx, py_dn, ldb, &dn)) {
312            talloc_free(mem_ctx);
313            return NULL;
314         }
315
316         ret = dsdb_load_partition_usn(ldb, dn, &highest_uSN, &urgent_uSN);
317         if (ret != LDB_SUCCESS) {
318            char *errstr = talloc_asprintf(mem_ctx, "Failed to load partition uSN - %s", ldb_errstring(ldb));
319            PyErr_SetString(PyExc_RuntimeError, errstr);
320            talloc_free(mem_ctx);
321            return NULL;
322         }
323
324         talloc_free(mem_ctx);
325
326         result = PyDict_New();
327
328         PyDict_SetItemString(result, "uSNHighest", PyInt_FromLong((uint64_t)highest_uSN));
329         PyDict_SetItemString(result, "uSNUrgent", PyInt_FromLong((uint64_t)urgent_uSN));
330
331
332         return result;
333 }
334
335 static PyMethodDef py_dsdb_methods[] = {
336         { "samdb_server_site_name", (PyCFunction)py_samdb_server_site_name,
337                 METH_VARARGS, "Get the server site name as a string"},
338         { "dsdb_convert_schema_to_openldap",
339                 (PyCFunction)py_dsdb_convert_schema_to_openldap, METH_VARARGS, 
340                 "dsdb_convert_schema_to_openldap(ldb, target_str, mapping) -> str\n"
341                 "Create an OpenLDAP schema from a schema." },
342         { "samdb_set_domain_sid", (PyCFunction)py_samdb_set_domain_sid,
343                 METH_VARARGS,
344                 "samdb_set_domain_sid(samdb, sid)\n"
345                 "Set SID of domain to use." },
346         { "samdb_get_domain_sid", (PyCFunction)py_samdb_get_domain_sid,
347                 METH_VARARGS,
348                 "samdb_get_domain_sid(samdb)\n"
349                 "Get SID of domain in use." },
350         { "samdb_ntds_invocation_id", (PyCFunction)py_samdb_ntds_invocation_id,
351                 METH_VARARGS, "get the NTDS invocation ID GUID as a string"},
352         { "dsdb_get_oid_from_attid", (PyCFunction)py_dsdb_get_oid_from_attid, METH_VARARGS,
353                 NULL },
354         { "dsdb_set_ntds_invocation_id",
355                 (PyCFunction)py_dsdb_set_ntds_invocation_id, METH_VARARGS,
356                 NULL },
357         { "samdb_ntds_objectGUID", (PyCFunction)py_samdb_ntds_objectGUID,
358                 METH_VARARGS, "get the NTDS objectGUID as a string"},
359         { "dsdb_set_global_schema", (PyCFunction)py_dsdb_set_global_schema,
360                 METH_VARARGS, NULL },
361         { "dsdb_load_partition_usn", (PyCFunction)py_dsdb_load_partition_usn,
362                 METH_VARARGS,
363                 "get uSNHighest and uSNUrgent from the partition @REPLCHANGED"},
364         { NULL }
365 };
366
367 void initdsdb(void)
368 {
369         PyObject *m;
370
371         m = Py_InitModule3("dsdb", py_dsdb_methods, 
372                            "Python bindings for the directory service databases.");
373         if (m == NULL)
374                 return;
375
376         /* "userAccountControl" flags */
377         PyModule_AddObject(m, "UF_NORMAL_ACCOUNT",
378                                            PyInt_FromLong(UF_NORMAL_ACCOUNT));
379         PyModule_AddObject(m, "UF_TEMP_DUPLICATE_ACCOUNT",
380                                            PyInt_FromLong(UF_TEMP_DUPLICATE_ACCOUNT));
381         PyModule_AddObject(m, "UF_SERVER_TRUST_ACCOUNT",
382                                            PyInt_FromLong(UF_SERVER_TRUST_ACCOUNT));
383         PyModule_AddObject(m, "UF_WORKSTATION_TRUST_ACCOUNT",
384                                            PyInt_FromLong(UF_WORKSTATION_TRUST_ACCOUNT));
385         PyModule_AddObject(m, "UF_INTERDOMAIN_TRUST_ACCOUNT",
386                                            PyInt_FromLong(UF_INTERDOMAIN_TRUST_ACCOUNT));
387         PyModule_AddObject(m, "UF_PASSWD_NOTREQD",
388                                            PyInt_FromLong(UF_PASSWD_NOTREQD));
389         PyModule_AddObject(m, "UF_ACCOUNTDISABLE",
390                                            PyInt_FromLong(UF_ACCOUNTDISABLE));
391
392         /* "groupType" flags */
393         PyModule_AddObject(m, "GTYPE_SECURITY_BUILTIN_LOCAL_GROUP",
394                                            PyInt_FromLong(GTYPE_SECURITY_BUILTIN_LOCAL_GROUP));
395         PyModule_AddObject(m, "GTYPE_SECURITY_GLOBAL_GROUP",
396                                            PyInt_FromLong(GTYPE_SECURITY_GLOBAL_GROUP));
397         PyModule_AddObject(m, "GTYPE_SECURITY_DOMAIN_LOCAL_GROUP",
398                                            PyInt_FromLong(GTYPE_SECURITY_DOMAIN_LOCAL_GROUP));
399         PyModule_AddObject(m, "GTYPE_SECURITY_UNIVERSAL_GROUP",
400                                            PyInt_FromLong(GTYPE_SECURITY_UNIVERSAL_GROUP));
401         PyModule_AddObject(m, "GTYPE_DISTRIBUTION_GLOBAL_GROUP",
402                                            PyInt_FromLong(GTYPE_DISTRIBUTION_GLOBAL_GROUP));
403         PyModule_AddObject(m, "GTYPE_DISTRIBUTION_DOMAIN_LOCAL_GROUP",
404                                            PyInt_FromLong(GTYPE_DISTRIBUTION_DOMAIN_LOCAL_GROUP));
405         PyModule_AddObject(m, "GTYPE_DISTRIBUTION_UNIVERSAL_GROUP",
406                                            PyInt_FromLong(GTYPE_DISTRIBUTION_UNIVERSAL_GROUP));
407
408         /* "sAMAccountType" flags */
409         PyModule_AddObject(m, "ATYPE_NORMAL_ACCOUNT",
410                                            PyInt_FromLong(ATYPE_NORMAL_ACCOUNT));
411         PyModule_AddObject(m, "ATYPE_WORKSTATION_TRUST",
412                                            PyInt_FromLong(ATYPE_WORKSTATION_TRUST));
413         PyModule_AddObject(m, "ATYPE_INTERDOMAIN_TRUST",
414                                            PyInt_FromLong(ATYPE_INTERDOMAIN_TRUST));
415         PyModule_AddObject(m, "ATYPE_SECURITY_GLOBAL_GROUP",
416                                            PyInt_FromLong(ATYPE_SECURITY_GLOBAL_GROUP));
417         PyModule_AddObject(m, "ATYPE_SECURITY_LOCAL_GROUP",
418                                            PyInt_FromLong(ATYPE_SECURITY_LOCAL_GROUP));
419         PyModule_AddObject(m, "ATYPE_SECURITY_UNIVERSAL_GROUP",
420                                            PyInt_FromLong(ATYPE_SECURITY_UNIVERSAL_GROUP));
421         PyModule_AddObject(m, "ATYPE_DISTRIBUTION_GLOBAL_GROUP",
422                                            PyInt_FromLong(ATYPE_DISTRIBUTION_GLOBAL_GROUP));
423         PyModule_AddObject(m, "ATYPE_DISTRIBUTION_LOCAL_GROUP",
424                                            PyInt_FromLong(ATYPE_DISTRIBUTION_LOCAL_GROUP));
425         PyModule_AddObject(m, "ATYPE_DISTRIBUTION_UNIVERSAL_GROUP",
426                                            PyInt_FromLong(ATYPE_DISTRIBUTION_UNIVERSAL_GROUP));
427
428         /* "domainFunctionality", "forestFunctionality" flags in the rootDSE */
429         PyModule_AddObject(m, "DS_DOMAIN_FUNCTION_2000",
430                                            PyInt_FromLong(DS_DOMAIN_FUNCTION_2000));
431         PyModule_AddObject(m, "DS_DOMAIN_FUNCTION_2003_MIXED",
432                                            PyInt_FromLong(DS_DOMAIN_FUNCTION_2003_MIXED));
433         PyModule_AddObject(m, "DS_DOMAIN_FUNCTION_2003",
434                                            PyInt_FromLong(DS_DOMAIN_FUNCTION_2003));
435         PyModule_AddObject(m, "DS_DOMAIN_FUNCTION_2008",
436                                            PyInt_FromLong(DS_DOMAIN_FUNCTION_2008));
437         PyModule_AddObject(m, "DS_DOMAIN_FUNCTION_2008_R2",
438                                            PyInt_FromLong(DS_DOMAIN_FUNCTION_2008_R2));
439
440         /* "domainControllerFunctionality" flags in the rootDSE */
441         PyModule_AddObject(m, "DS_DC_FUNCTION_2000",
442                                            PyInt_FromLong(DS_DC_FUNCTION_2000));
443         PyModule_AddObject(m, "DS_DC_FUNCTION_2003",
444                                            PyInt_FromLong(DS_DC_FUNCTION_2003));
445         PyModule_AddObject(m, "DS_DC_FUNCTION_2008",
446                                            PyInt_FromLong(DS_DC_FUNCTION_2008));
447         PyModule_AddObject(m, "DS_DC_FUNCTION_2008_R2",
448                                            PyInt_FromLong(DS_DC_FUNCTION_2008_R2));
449 }