py_security: Fix comparison between two dom_sid objects
[samba.git] / source4 / librpc / ndr / py_security.c
1 /* 
2    Unix SMB/CIFS implementation.
3    Samba utility functions
4
5    Copyright (C) Jelmer Vernooij <jelmer@samba.org> 2008-2010
6    
7    This program is free software; you can redistribute it and/or modify
8    it under the terms of the GNU General Public License as published by
9    the Free Software Foundation; either version 3 of the License, or
10    (at your option) any later version.
11    
12    This program is distributed in the hope that it will be useful,
13    but WITHOUT ANY WARRANTY; without even the implied warranty of
14    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15    GNU General Public License for more details.
16    
17    You should have received a copy of the GNU General Public License
18    along with this program.  If not, see <http://www.gnu.org/licenses/>.
19 */
20 #include <Python.h>
21 #include "libcli/security/security.h"
22
23 #ifndef Py_RETURN_NONE
24 #define Py_RETURN_NONE return Py_INCREF(Py_None), Py_None
25 #endif
26
27 static void PyType_AddMethods(PyTypeObject *type, PyMethodDef *methods)
28 {
29         PyObject *dict;
30         int i;
31         if (type->tp_dict == NULL)
32                 type->tp_dict = PyDict_New();
33         dict = type->tp_dict;
34         for (i = 0; methods[i].ml_name; i++) {
35                 PyObject *descr;
36                 if (methods[i].ml_flags & METH_CLASS) 
37                         descr = PyCFunction_New(&methods[i], (PyObject *)type);
38                 else 
39                         descr = PyDescr_NewMethod(type, &methods[i]);
40                 PyDict_SetItemString(dict, methods[i].ml_name, 
41                                      descr);
42         }
43 }
44
45 static PyObject *py_dom_sid_split(PyObject *py_self, PyObject *args)
46 {
47         struct dom_sid *self = pytalloc_get_ptr(py_self);
48         struct dom_sid *domain_sid;
49         TALLOC_CTX *mem_ctx;
50         uint32_t rid;
51         NTSTATUS status;
52         PyObject *py_domain_sid;
53
54         mem_ctx = talloc_new(NULL);
55         if (mem_ctx == NULL) {
56                 PyErr_NoMemory();
57                 return NULL;
58         }
59
60         status = dom_sid_split_rid(mem_ctx, self, &domain_sid, &rid);
61         if (!NT_STATUS_IS_OK(status)) {
62                 PyErr_SetString(PyExc_RuntimeError, "dom_sid_split_rid failed");
63                 talloc_free(mem_ctx);
64                 return NULL;
65         }
66
67         py_domain_sid = pytalloc_steal(&dom_sid_Type, domain_sid);
68         talloc_free(mem_ctx);
69         return Py_BuildValue("(OI)", py_domain_sid, rid);
70 }
71
72 static int py_dom_sid_cmp(PyObject *py_self, PyObject *py_other)
73 {
74         struct dom_sid *self = pytalloc_get_ptr(py_self), *other;
75         int val;
76
77         other = pytalloc_get_ptr(py_other);
78         if (other == NULL)
79                 return -1;
80
81         val =  dom_sid_compare(self, other);
82         if (val > 0) {
83                 return 1;
84         } else if (val < 0) {
85                 return -1;
86         }
87         return 0;
88 }
89
90 static PyObject *py_dom_sid_str(PyObject *py_self)
91 {
92         struct dom_sid *self = pytalloc_get_ptr(py_self);
93         char *str = dom_sid_string(NULL, self);
94         PyObject *ret = PyString_FromString(str);
95         talloc_free(str);
96         return ret;
97 }
98
99 static PyObject *py_dom_sid_repr(PyObject *py_self)
100 {
101         struct dom_sid *self = pytalloc_get_ptr(py_self);
102         char *str = dom_sid_string(NULL, self);
103         PyObject *ret = PyString_FromFormat("dom_sid('%s')", str);
104         talloc_free(str);
105         return ret;
106 }
107
108 static int py_dom_sid_init(PyObject *self, PyObject *args, PyObject *kwargs)
109 {
110         char *str = NULL;
111         struct dom_sid *sid = pytalloc_get_ptr(self);
112         const char *kwnames[] = { "str", NULL };
113
114         if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|s", discard_const_p(char *, kwnames), &str))
115                 return -1;
116
117         if (str != NULL && !dom_sid_parse(str, sid)) {
118                 PyErr_SetString(PyExc_TypeError, "Unable to parse string");
119                 return -1;
120         }
121
122         return 0;
123 }
124
125 static PyMethodDef py_dom_sid_extra_methods[] = {
126         { "split", (PyCFunction)py_dom_sid_split, METH_NOARGS,
127                 "S.split() -> (domain_sid, rid)\n"
128                 "Split a domain sid" },
129         { NULL }
130 };
131
132
133 static void py_dom_sid_patch(PyTypeObject *type)
134 {
135         type->tp_init = py_dom_sid_init;
136         type->tp_str = py_dom_sid_str;
137         type->tp_repr = py_dom_sid_repr;
138         type->tp_compare = py_dom_sid_cmp;
139         PyType_AddMethods(type, py_dom_sid_extra_methods);
140 }
141
142 #define PY_DOM_SID_PATCH py_dom_sid_patch
143
144 static PyObject *py_descriptor_sacl_add(PyObject *self, PyObject *args)
145 {
146         struct security_descriptor *desc = pytalloc_get_ptr(self);
147         NTSTATUS status;
148         struct security_ace *ace;
149         PyObject *py_ace;
150
151         if (!PyArg_ParseTuple(args, "O", &py_ace))
152                 return NULL;
153
154         ace = pytalloc_get_ptr(py_ace);
155         status = security_descriptor_sacl_add(desc, ace);
156         PyErr_NTSTATUS_IS_ERR_RAISE(status);
157         Py_RETURN_NONE;
158 }
159
160 static PyObject *py_descriptor_dacl_add(PyObject *self, PyObject *args)
161 {
162         struct security_descriptor *desc = pytalloc_get_ptr(self);
163         NTSTATUS status;
164         struct security_ace *ace;
165         PyObject *py_ace;
166
167         if (!PyArg_ParseTuple(args, "O", &py_ace))
168                 return NULL;
169
170         ace = pytalloc_get_ptr(py_ace);
171
172         status = security_descriptor_dacl_add(desc, ace);
173         PyErr_NTSTATUS_IS_ERR_RAISE(status);
174         Py_RETURN_NONE;
175 }
176
177 static PyObject *py_descriptor_dacl_del(PyObject *self, PyObject *args)
178 {
179         struct security_descriptor *desc = pytalloc_get_ptr(self);
180         NTSTATUS status;
181         struct dom_sid *sid;
182         PyObject *py_sid;
183
184         if (!PyArg_ParseTuple(args, "O", &py_sid))
185                 return NULL;
186
187         sid = pytalloc_get_ptr(py_sid);
188         status = security_descriptor_dacl_del(desc, sid);
189         PyErr_NTSTATUS_IS_ERR_RAISE(status);
190         Py_RETURN_NONE;
191 }
192
193 static PyObject *py_descriptor_sacl_del(PyObject *self, PyObject *args)
194 {
195         struct security_descriptor *desc = pytalloc_get_ptr(self);
196         NTSTATUS status;
197         struct dom_sid *sid;
198         PyObject *py_sid;
199
200         if (!PyArg_ParseTuple(args, "O", &py_sid))
201                 return NULL;
202
203         sid = pytalloc_get_ptr(py_sid);
204         status = security_descriptor_sacl_del(desc, sid);
205         PyErr_NTSTATUS_IS_ERR_RAISE(status);
206         Py_RETURN_NONE;
207 }
208
209 static PyObject *py_descriptor_new(PyTypeObject *self, PyObject *args, PyObject *kwargs)
210 {
211         return pytalloc_steal(self, security_descriptor_initialise(NULL));
212 }
213
214 static PyObject *py_descriptor_from_sddl(PyObject *self, PyObject *args)
215 {
216         struct security_descriptor *secdesc;
217         char *sddl;
218         PyObject *py_sid;
219         struct dom_sid *sid;
220
221         if (!PyArg_ParseTuple(args, "sO!", &sddl, &dom_sid_Type, &py_sid))
222                 return NULL;
223
224         sid = pytalloc_get_ptr(py_sid);
225
226         secdesc = sddl_decode(NULL, sddl, sid);
227         if (secdesc == NULL) {
228                 PyErr_SetString(PyExc_TypeError, "Unable to parse SDDL");
229                 return NULL;
230         }
231
232         return pytalloc_steal((PyTypeObject *)self, secdesc);
233 }
234
235 static PyObject *py_descriptor_as_sddl(PyObject *self, PyObject *args)
236 {
237         struct dom_sid *sid;
238         PyObject *py_sid = Py_None;
239         struct security_descriptor *desc = pytalloc_get_ptr(self);
240         char *text;
241         PyObject *ret;
242
243         if (!PyArg_ParseTuple(args, "|O!", &dom_sid_Type, &py_sid))
244                 return NULL;
245
246         if (py_sid != Py_None)
247                 sid = pytalloc_get_ptr(py_sid);
248         else
249                 sid = NULL;
250
251         text = sddl_encode(NULL, desc, sid);
252
253         ret = PyString_FromString(text);
254
255         talloc_free(text);
256
257         return ret;
258 }
259
260 static PyMethodDef py_descriptor_extra_methods[] = {
261         { "sacl_add", (PyCFunction)py_descriptor_sacl_add, METH_VARARGS,
262                 "S.sacl_add(ace) -> None\n"
263                 "Add a security ace to this security descriptor" },
264         { "dacl_add", (PyCFunction)py_descriptor_dacl_add, METH_VARARGS,
265                 NULL },
266         { "dacl_del", (PyCFunction)py_descriptor_dacl_del, METH_VARARGS,
267                 NULL },
268         { "sacl_del", (PyCFunction)py_descriptor_sacl_del, METH_VARARGS,
269                 NULL },
270         { "from_sddl", (PyCFunction)py_descriptor_from_sddl, METH_VARARGS|METH_CLASS, 
271                 NULL },
272         { "as_sddl", (PyCFunction)py_descriptor_as_sddl, METH_VARARGS,
273                 NULL },
274         { NULL }
275 };
276
277 static void py_descriptor_patch(PyTypeObject *type)
278 {
279         type->tp_new = py_descriptor_new;
280         PyType_AddMethods(type, py_descriptor_extra_methods);
281 }
282
283 #define PY_DESCRIPTOR_PATCH py_descriptor_patch
284
285 static PyObject *py_token_is_sid(PyObject *self, PyObject *args)
286 {
287         PyObject *py_sid;
288         struct dom_sid *sid;
289         struct security_token *token = pytalloc_get_ptr(self);
290         if (!PyArg_ParseTuple(args, "O", &py_sid))
291                 return NULL;
292
293         sid = pytalloc_get_ptr(py_sid);
294
295         return PyBool_FromLong(security_token_is_sid(token, sid));
296 }
297
298 static PyObject *py_token_has_sid(PyObject *self, PyObject *args)
299 {
300         PyObject *py_sid;
301         struct dom_sid *sid;
302         struct security_token *token = pytalloc_get_ptr(self);
303         if (!PyArg_ParseTuple(args, "O", &py_sid))
304                 return NULL;
305
306         sid = pytalloc_get_ptr(py_sid);
307
308         return PyBool_FromLong(security_token_has_sid(token, sid));
309 }
310
311 static PyObject *py_token_is_anonymous(PyObject *self)
312 {
313         struct security_token *token = pytalloc_get_ptr(self);
314         
315         return PyBool_FromLong(security_token_is_anonymous(token));
316 }
317
318 static PyObject *py_token_is_system(PyObject *self)
319 {
320         struct security_token *token = pytalloc_get_ptr(self);
321         
322         return PyBool_FromLong(security_token_is_system(token));
323 }
324
325 static PyObject *py_token_has_builtin_administrators(PyObject *self)
326 {
327         struct security_token *token = pytalloc_get_ptr(self);
328         
329         return PyBool_FromLong(security_token_has_builtin_administrators(token));
330 }
331
332 static PyObject *py_token_has_nt_authenticated_users(PyObject *self)
333 {
334         struct security_token *token = pytalloc_get_ptr(self);
335         
336         return PyBool_FromLong(security_token_has_nt_authenticated_users(token));
337 }
338
339 static PyObject *py_token_has_privilege(PyObject *self, PyObject *args)
340 {
341         int priv;
342         struct security_token *token = pytalloc_get_ptr(self);
343
344         if (!PyArg_ParseTuple(args, "i", &priv))
345                 return NULL;
346
347         return PyBool_FromLong(security_token_has_privilege(token, priv));
348 }
349
350 static PyObject *py_token_set_privilege(PyObject *self, PyObject *args)
351 {
352         int priv;
353         struct security_token *token = pytalloc_get_ptr(self);
354
355         if (!PyArg_ParseTuple(args, "i", &priv))
356                 return NULL;
357
358         security_token_set_privilege(token, priv);
359         Py_RETURN_NONE;
360 }
361
362 static PyObject *py_token_new(PyTypeObject *self, PyObject *args, PyObject *kwargs)
363 {
364         return pytalloc_steal(self, security_token_initialise(NULL));
365 }       
366
367 static PyMethodDef py_token_extra_methods[] = {
368         { "is_sid", (PyCFunction)py_token_is_sid, METH_VARARGS,
369                 "S.is_sid(sid) -> bool\n"
370                 "Check whether this token is of the specified SID." },
371         { "has_sid", (PyCFunction)py_token_has_sid, METH_VARARGS,
372                 NULL },
373         { "is_anonymous", (PyCFunction)py_token_is_anonymous, METH_NOARGS,
374                 "S.is_anonymus() -> bool\n"
375                 "Check whether this is an anonymous token." },
376         { "is_system", (PyCFunction)py_token_is_system, METH_NOARGS,
377                 NULL },
378         { "has_builtin_administrators", (PyCFunction)py_token_has_builtin_administrators, METH_NOARGS,
379                 NULL },
380         { "has_nt_authenticated_users", (PyCFunction)py_token_has_nt_authenticated_users, METH_NOARGS,
381                 NULL },
382         { "has_privilege", (PyCFunction)py_token_has_privilege, METH_VARARGS,
383                 NULL },
384         { "set_privilege", (PyCFunction)py_token_set_privilege, METH_VARARGS,
385                 NULL },
386         { NULL }
387 };
388
389 #define PY_TOKEN_PATCH py_token_patch
390 static void py_token_patch(PyTypeObject *type)
391 {
392         type->tp_new = py_token_new;
393         PyType_AddMethods(type, py_token_extra_methods);
394 }
395
396 static PyObject *py_privilege_name(PyObject *self, PyObject *args)
397 {
398         int priv;
399         if (!PyArg_ParseTuple(args, "i", &priv))
400                 return NULL;
401
402         return PyString_FromString(sec_privilege_name(priv));
403 }
404
405 static PyObject *py_privilege_id(PyObject *self, PyObject *args)
406 {
407         char *name;
408
409         if (!PyArg_ParseTuple(args, "s", &name))
410                 return NULL;
411
412         return PyInt_FromLong(sec_privilege_id(name));
413 }
414
415 static PyObject *py_random_sid(PyObject *self)
416 {
417         struct dom_sid *sid;
418         PyObject *ret;
419         char *str = talloc_asprintf(NULL, "S-1-5-21-%u-%u-%u", 
420                         (unsigned)generate_random(), 
421                         (unsigned)generate_random(), 
422                         (unsigned)generate_random());
423
424         sid = dom_sid_parse_talloc(NULL, str);
425         talloc_free(str);
426         ret = pytalloc_steal(&dom_sid_Type, sid);
427         return ret;
428 }
429
430 static PyMethodDef py_mod_security_extra_methods[] = {
431         { "random_sid", (PyCFunction)py_random_sid, METH_NOARGS, NULL },
432         { "privilege_id", (PyCFunction)py_privilege_id, METH_VARARGS, NULL },
433         { "privilege_name", (PyCFunction)py_privilege_name, METH_VARARGS, NULL },
434         { NULL }
435 };
436
437 static void py_mod_security_patch(PyObject *m)
438 {
439         int i;
440         for (i = 0; py_mod_security_extra_methods[i].ml_name; i++) {
441                 PyObject *descr = PyCFunction_New(&py_mod_security_extra_methods[i], NULL);
442                 PyModule_AddObject(m, py_mod_security_extra_methods[i].ml_name,
443                                    descr);
444         }
445 }
446
447 #define PY_MOD_SECURITY_PATCH py_mod_security_patch