Line data Source code
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 "py3compat.h"
22 : #include "libcli/security/security.h"
23 :
24 10686 : static void PyType_AddMethods(PyTypeObject *type, PyMethodDef *methods)
25 : {
26 : PyObject *dict;
27 : int i;
28 10686 : if (type->tp_dict == NULL)
29 0 : type->tp_dict = PyDict_New();
30 10686 : dict = type->tp_dict;
31 71240 : for (i = 0; methods[i].ml_name; i++) {
32 : PyObject *descr;
33 60554 : if (methods[i].ml_flags & METH_CLASS)
34 3562 : descr = PyCFunction_New(&methods[i], (PyObject *)type);
35 : else
36 56992 : descr = PyDescr_NewMethod(type, &methods[i]);
37 60554 : PyDict_SetItemString(dict, methods[i].ml_name,
38 : descr);
39 60554 : Py_CLEAR(descr);
40 : }
41 10686 : }
42 :
43 1887 : static PyObject *py_dom_sid_split(PyObject *py_self, PyObject *args)
44 : {
45 1887 : struct dom_sid *self = pytalloc_get_ptr(py_self);
46 : struct dom_sid *domain_sid;
47 : TALLOC_CTX *mem_ctx;
48 : uint32_t rid;
49 : NTSTATUS status;
50 : PyObject *py_domain_sid;
51 :
52 1887 : mem_ctx = talloc_new(NULL);
53 1887 : if (mem_ctx == NULL) {
54 0 : PyErr_NoMemory();
55 0 : return NULL;
56 : }
57 :
58 1887 : status = dom_sid_split_rid(mem_ctx, self, &domain_sid, &rid);
59 1887 : if (!NT_STATUS_IS_OK(status)) {
60 0 : PyErr_SetString(PyExc_RuntimeError, "dom_sid_split_rid failed");
61 0 : talloc_free(mem_ctx);
62 0 : return NULL;
63 : }
64 :
65 1887 : py_domain_sid = pytalloc_steal(&dom_sid_Type, domain_sid);
66 1887 : talloc_free(mem_ctx);
67 1887 : return Py_BuildValue("(OI)", py_domain_sid, rid);
68 : }
69 :
70 : #if PY_MAJOR_VERSION >= 3
71 4209 : static PyObject *py_dom_sid_richcmp(PyObject *py_self, PyObject *py_other, int op)
72 : {
73 4209 : struct dom_sid *self = pytalloc_get_ptr(py_self), *other;
74 : int val;
75 :
76 4209 : other = pytalloc_get_ptr(py_other);
77 4209 : if (other == NULL) {
78 0 : Py_INCREF(Py_NotImplemented);
79 0 : return Py_NotImplemented;
80 : }
81 :
82 4209 : val = dom_sid_compare(self, other);
83 :
84 4209 : switch (op) {
85 4092 : case Py_EQ: if (val == 0) Py_RETURN_TRUE; else Py_RETURN_FALSE;
86 117 : case Py_NE: if (val != 0) Py_RETURN_TRUE; else Py_RETURN_FALSE;
87 0 : case Py_LT: if (val < 0) Py_RETURN_TRUE; else Py_RETURN_FALSE;
88 0 : case Py_GT: if (val > 0) Py_RETURN_TRUE; else Py_RETURN_FALSE;
89 0 : case Py_LE: if (val <= 0) Py_RETURN_TRUE; else Py_RETURN_FALSE;
90 0 : case Py_GE: if (val >= 0) Py_RETURN_TRUE; else Py_RETURN_FALSE;
91 : }
92 0 : Py_INCREF(Py_NotImplemented);
93 0 : return Py_NotImplemented;
94 : }
95 : #else
96 : static int py_dom_sid_cmp(PyObject *py_self, PyObject *py_other)
97 : {
98 : struct dom_sid *self = pytalloc_get_ptr(py_self), *other;
99 : int val;
100 :
101 : other = pytalloc_get_ptr(py_other);
102 : if (other == NULL)
103 : return -1;
104 :
105 : val = dom_sid_compare(self, other);
106 : if (val > 0) {
107 : return 1;
108 : } else if (val < 0) {
109 : return -1;
110 : }
111 : return 0;
112 : }
113 : #endif
114 :
115 25021 : static PyObject *py_dom_sid_str(PyObject *py_self)
116 : {
117 25021 : struct dom_sid *self = pytalloc_get_ptr(py_self);
118 : struct dom_sid_buf buf;
119 25021 : PyObject *ret = PyUnicode_FromString(dom_sid_str_buf(self, &buf));
120 25021 : return ret;
121 : }
122 :
123 0 : static PyObject *py_dom_sid_repr(PyObject *py_self)
124 : {
125 0 : struct dom_sid *self = pytalloc_get_ptr(py_self);
126 : struct dom_sid_buf buf;
127 0 : PyObject *ret = PyUnicode_FromFormat(
128 : "dom_sid('%s')", dom_sid_str_buf(self, &buf));
129 0 : return ret;
130 : }
131 :
132 30043 : static int py_dom_sid_init(PyObject *self, PyObject *args, PyObject *kwargs)
133 : {
134 30043 : char *str = NULL;
135 30043 : struct dom_sid *sid = pytalloc_get_ptr(self);
136 30043 : const char *kwnames[] = { "str", NULL };
137 :
138 30043 : if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|s", discard_const_p(char *, kwnames), &str))
139 0 : return -1;
140 :
141 30043 : if (str != NULL && !dom_sid_parse(str, sid)) {
142 5892 : PyErr_SetString(PyExc_TypeError, "Unable to parse string");
143 5892 : return -1;
144 : }
145 :
146 24151 : return 0;
147 : }
148 :
149 : static PyMethodDef py_dom_sid_extra_methods[] = {
150 : { "split", (PyCFunction)py_dom_sid_split, METH_NOARGS,
151 : "S.split() -> (domain_sid, rid)\n"
152 : "Split a domain sid" },
153 : {0}
154 : };
155 :
156 :
157 3562 : static void py_dom_sid_patch(PyTypeObject *type)
158 : {
159 3562 : type->tp_init = py_dom_sid_init;
160 3562 : type->tp_str = py_dom_sid_str;
161 3562 : type->tp_repr = py_dom_sid_repr;
162 : #if PY_MAJOR_VERSION >= 3
163 3562 : type->tp_richcompare = py_dom_sid_richcmp;
164 : #else
165 : type->tp_compare = py_dom_sid_cmp;
166 : #endif
167 3562 : PyType_AddMethods(type, py_dom_sid_extra_methods);
168 3562 : }
169 :
170 : #define PY_DOM_SID_PATCH py_dom_sid_patch
171 :
172 3636 : static PyObject *py_descriptor_sacl_add(PyObject *self, PyObject *args)
173 : {
174 3636 : struct security_descriptor *desc = pytalloc_get_ptr(self);
175 : NTSTATUS status;
176 : struct security_ace *ace;
177 : PyObject *py_ace;
178 3636 : Py_ssize_t idx = -1;
179 :
180 3636 : if (!PyArg_ParseTuple(args, "O|n", &py_ace, &idx))
181 0 : return NULL;
182 :
183 3636 : ace = pytalloc_get_ptr(py_ace);
184 3636 : status = security_descriptor_sacl_insert(desc, ace, idx);
185 3636 : PyErr_NTSTATUS_IS_ERR_RAISE(status);
186 3636 : Py_RETURN_NONE;
187 : }
188 :
189 546936 : static PyObject *py_descriptor_dacl_add(PyObject *self, PyObject *args)
190 : {
191 546936 : struct security_descriptor *desc = pytalloc_get_ptr(self);
192 : NTSTATUS status;
193 : struct security_ace *ace;
194 : PyObject *py_ace;
195 546936 : Py_ssize_t idx = -1;
196 :
197 546936 : if (!PyArg_ParseTuple(args, "O|n", &py_ace, &idx))
198 0 : return NULL;
199 :
200 546936 : ace = pytalloc_get_ptr(py_ace);
201 :
202 546936 : status = security_descriptor_dacl_insert(desc, ace, idx);
203 546936 : PyErr_NTSTATUS_IS_ERR_RAISE(status);
204 546936 : Py_RETURN_NONE;
205 : }
206 :
207 0 : static PyObject *py_descriptor_dacl_del(PyObject *self, PyObject *args)
208 : {
209 0 : struct security_descriptor *desc = pytalloc_get_ptr(self);
210 : NTSTATUS status;
211 : struct dom_sid *sid;
212 : PyObject *py_sid;
213 :
214 0 : if (!PyArg_ParseTuple(args, "O", &py_sid))
215 0 : return NULL;
216 :
217 0 : sid = pytalloc_get_ptr(py_sid);
218 0 : status = security_descriptor_dacl_del(desc, sid);
219 0 : PyErr_NTSTATUS_IS_ERR_RAISE(status);
220 0 : Py_RETURN_NONE;
221 : }
222 :
223 0 : static PyObject *py_descriptor_sacl_del(PyObject *self, PyObject *args)
224 : {
225 0 : struct security_descriptor *desc = pytalloc_get_ptr(self);
226 : NTSTATUS status;
227 : struct dom_sid *sid;
228 : PyObject *py_sid;
229 :
230 0 : if (!PyArg_ParseTuple(args, "O", &py_sid))
231 0 : return NULL;
232 :
233 0 : sid = pytalloc_get_ptr(py_sid);
234 0 : status = security_descriptor_sacl_del(desc, sid);
235 0 : PyErr_NTSTATUS_IS_ERR_RAISE(status);
236 0 : Py_RETURN_NONE;
237 : }
238 :
239 64575 : static PyObject *py_descriptor_dacl_del_ace(PyObject *self, PyObject *args)
240 : {
241 64575 : struct security_descriptor *desc = pytalloc_get_ptr(self);
242 : NTSTATUS status;
243 64575 : struct security_ace *ace = NULL;
244 64575 : PyObject *py_ace = Py_None;
245 :
246 64575 : if (!PyArg_ParseTuple(args, "O!", &security_ace_Type, &py_ace))
247 0 : return NULL;
248 :
249 64575 : if (!PyObject_TypeCheck(py_ace, &security_ace_Type)) {
250 0 : PyErr_SetString(PyExc_TypeError,
251 : "expected security.security_ace "
252 : "for first argument to .dacl_del_ace");
253 0 : return NULL;
254 : }
255 :
256 64575 : ace = pytalloc_get_ptr(py_ace);
257 64575 : status = security_descriptor_dacl_del_ace(desc, ace);
258 64575 : PyErr_NTSTATUS_IS_ERR_RAISE(status);
259 27578 : Py_RETURN_NONE;
260 : }
261 :
262 0 : static PyObject *py_descriptor_sacl_del_ace(PyObject *self, PyObject *args)
263 : {
264 0 : struct security_descriptor *desc = pytalloc_get_ptr(self);
265 : NTSTATUS status;
266 0 : struct security_ace *ace = NULL;
267 0 : PyObject *py_ace = Py_None;
268 :
269 0 : if (!PyArg_ParseTuple(args, "O!", &security_ace_Type, &py_ace))
270 0 : return NULL;
271 :
272 0 : if (!PyObject_TypeCheck(py_ace, &security_ace_Type)) {
273 0 : PyErr_SetString(PyExc_TypeError,
274 : "expected security.security_ace "
275 : "for first argument to .sacl_del_ace");
276 0 : return NULL;
277 : }
278 :
279 0 : ace = pytalloc_get_ptr(py_ace);
280 0 : status = security_descriptor_sacl_del_ace(desc, ace);
281 0 : PyErr_NTSTATUS_IS_ERR_RAISE(status);
282 0 : Py_RETURN_NONE;
283 : }
284 :
285 643228 : static PyObject *py_descriptor_new(PyTypeObject *self, PyObject *args, PyObject *kwargs)
286 : {
287 643228 : return pytalloc_steal(self, security_descriptor_initialise(NULL));
288 : }
289 :
290 30064 : static PyObject *py_descriptor_from_sddl(PyObject *self, PyObject *args)
291 : {
292 : struct security_descriptor *secdesc;
293 : char *sddl;
294 : PyObject *py_sid;
295 : struct dom_sid *sid;
296 :
297 30064 : if (!PyArg_ParseTuple(args, "sO!", &sddl, &dom_sid_Type, &py_sid))
298 0 : return NULL;
299 :
300 30064 : if (!PyObject_TypeCheck(py_sid, &dom_sid_Type)) {
301 0 : PyErr_SetString(PyExc_TypeError,
302 : "expected security.dom_sid "
303 : "for second argument to .from_sddl");
304 0 : return NULL;
305 : }
306 :
307 30064 : sid = pytalloc_get_ptr(py_sid);
308 :
309 30064 : secdesc = sddl_decode(NULL, sddl, sid);
310 30064 : if (secdesc == NULL) {
311 0 : PyErr_SetString(PyExc_TypeError, "Unable to parse SDDL");
312 0 : return NULL;
313 : }
314 :
315 30064 : return pytalloc_steal((PyTypeObject *)self, secdesc);
316 : }
317 :
318 72052 : static PyObject *py_descriptor_as_sddl(PyObject *self, PyObject *args)
319 : {
320 : struct dom_sid *sid;
321 72052 : PyObject *py_sid = Py_None;
322 72052 : struct security_descriptor *desc = pytalloc_get_ptr(self);
323 : char *text;
324 : PyObject *ret;
325 :
326 72052 : if (!PyArg_ParseTuple(args, "|O!", &dom_sid_Type, &py_sid))
327 0 : return NULL;
328 :
329 72052 : if (py_sid != Py_None)
330 71768 : sid = pytalloc_get_ptr(py_sid);
331 : else
332 284 : sid = NULL;
333 :
334 72052 : text = sddl_encode(NULL, desc, sid);
335 :
336 72052 : ret = PyUnicode_FromString(text);
337 :
338 72052 : talloc_free(text);
339 :
340 72052 : return ret;
341 : }
342 :
343 : static PyMethodDef py_descriptor_extra_methods[] = {
344 : { "sacl_add", (PyCFunction)py_descriptor_sacl_add, METH_VARARGS,
345 : "S.sacl_add(ace) -> None\n"
346 : "Add a security ace to this security descriptor" },
347 : { "dacl_add", (PyCFunction)py_descriptor_dacl_add, METH_VARARGS,
348 : NULL },
349 : { "dacl_del", (PyCFunction)py_descriptor_dacl_del, METH_VARARGS,
350 : NULL },
351 : { "sacl_del", (PyCFunction)py_descriptor_sacl_del, METH_VARARGS,
352 : NULL },
353 : { "dacl_del_ace", (PyCFunction)py_descriptor_dacl_del_ace, METH_VARARGS,
354 : NULL },
355 : { "sacl_del_ace", (PyCFunction)py_descriptor_sacl_del_ace, METH_VARARGS,
356 : NULL },
357 : { "from_sddl", (PyCFunction)py_descriptor_from_sddl, METH_VARARGS|METH_CLASS,
358 : NULL },
359 : { "as_sddl", (PyCFunction)py_descriptor_as_sddl, METH_VARARGS,
360 : NULL },
361 : {0}
362 : };
363 :
364 0 : static PyObject *py_descriptor_richcmp(
365 : PyObject *py_self, PyObject *py_other, int op)
366 : {
367 0 : struct security_descriptor *self = pytalloc_get_ptr(py_self);
368 0 : struct security_descriptor *other = pytalloc_get_ptr(py_other);
369 : bool eq;
370 :
371 0 : if (other == NULL) {
372 0 : Py_INCREF(Py_NotImplemented);
373 0 : return Py_NotImplemented;
374 : }
375 :
376 0 : eq = security_descriptor_equal(self, other);
377 :
378 0 : switch(op) {
379 0 : case Py_EQ:
380 0 : if (eq) {
381 0 : Py_RETURN_TRUE;
382 : } else {
383 0 : Py_RETURN_FALSE;
384 : }
385 : break;
386 0 : case Py_NE:
387 0 : if (eq) {
388 0 : Py_RETURN_FALSE;
389 : } else {
390 0 : Py_RETURN_TRUE;
391 : }
392 : break;
393 0 : default:
394 0 : break;
395 : }
396 :
397 0 : Py_RETURN_NOTIMPLEMENTED;
398 : }
399 :
400 3562 : static void py_descriptor_patch(PyTypeObject *type)
401 : {
402 3562 : type->tp_new = py_descriptor_new;
403 3562 : type->tp_richcompare = py_descriptor_richcmp;
404 3562 : PyType_AddMethods(type, py_descriptor_extra_methods);
405 3562 : }
406 :
407 : #define PY_DESCRIPTOR_PATCH py_descriptor_patch
408 :
409 0 : static PyObject *py_token_is_sid(PyObject *self, PyObject *args)
410 : {
411 : PyObject *py_sid;
412 : struct dom_sid *sid;
413 0 : struct security_token *token = pytalloc_get_ptr(self);
414 0 : if (!PyArg_ParseTuple(args, "O", &py_sid))
415 0 : return NULL;
416 :
417 0 : sid = pytalloc_get_ptr(py_sid);
418 :
419 0 : return PyBool_FromLong(security_token_is_sid(token, sid));
420 : }
421 :
422 0 : static PyObject *py_token_has_sid(PyObject *self, PyObject *args)
423 : {
424 : PyObject *py_sid;
425 : struct dom_sid *sid;
426 0 : struct security_token *token = pytalloc_get_ptr(self);
427 0 : if (!PyArg_ParseTuple(args, "O", &py_sid))
428 0 : return NULL;
429 :
430 0 : sid = pytalloc_get_ptr(py_sid);
431 :
432 0 : return PyBool_FromLong(security_token_has_sid(token, sid));
433 : }
434 :
435 2 : static PyObject *py_token_is_anonymous(PyObject *self,
436 : PyObject *Py_UNUSED(ignored))
437 : {
438 2 : struct security_token *token = pytalloc_get_ptr(self);
439 :
440 2 : return PyBool_FromLong(security_token_is_anonymous(token));
441 : }
442 :
443 2 : static PyObject *py_token_is_system(PyObject *self,
444 : PyObject *Py_UNUSED(ignored))
445 : {
446 2 : struct security_token *token = pytalloc_get_ptr(self);
447 :
448 2 : return PyBool_FromLong(security_token_is_system(token));
449 : }
450 :
451 1 : static PyObject *py_token_has_builtin_administrators(PyObject *self,
452 : PyObject *Py_UNUSED(ignored))
453 : {
454 1 : struct security_token *token = pytalloc_get_ptr(self);
455 :
456 1 : return PyBool_FromLong(security_token_has_builtin_administrators(token));
457 : }
458 :
459 0 : static PyObject *py_token_has_nt_authenticated_users(PyObject *self,
460 : PyObject *Py_UNUSED(ignored))
461 : {
462 0 : struct security_token *token = pytalloc_get_ptr(self);
463 :
464 0 : return PyBool_FromLong(security_token_has_nt_authenticated_users(token));
465 : }
466 :
467 0 : static PyObject *py_token_has_privilege(PyObject *self, PyObject *args)
468 : {
469 : int priv;
470 0 : struct security_token *token = pytalloc_get_ptr(self);
471 :
472 0 : if (!PyArg_ParseTuple(args, "i", &priv))
473 0 : return NULL;
474 :
475 0 : return PyBool_FromLong(security_token_has_privilege(token, priv));
476 : }
477 :
478 0 : static PyObject *py_token_set_privilege(PyObject *self, PyObject *args)
479 : {
480 : int priv;
481 0 : struct security_token *token = pytalloc_get_ptr(self);
482 :
483 0 : if (!PyArg_ParseTuple(args, "i", &priv))
484 0 : return NULL;
485 :
486 0 : security_token_set_privilege(token, priv);
487 0 : Py_RETURN_NONE;
488 : }
489 :
490 0 : static PyObject *py_token_new(PyTypeObject *self, PyObject *args, PyObject *kwargs)
491 : {
492 0 : return pytalloc_steal(self, security_token_initialise(NULL));
493 : }
494 :
495 : static PyMethodDef py_token_extra_methods[] = {
496 : { "is_sid", (PyCFunction)py_token_is_sid, METH_VARARGS,
497 : "S.is_sid(sid) -> bool\n"
498 : "Check whether this token is of the specified SID." },
499 : { "has_sid", (PyCFunction)py_token_has_sid, METH_VARARGS,
500 : NULL },
501 : { "is_anonymous", (PyCFunction)py_token_is_anonymous, METH_NOARGS,
502 : "S.is_anonymous() -> bool\n"
503 : "Check whether this is an anonymous token." },
504 : { "is_system", (PyCFunction)py_token_is_system, METH_NOARGS,
505 : NULL },
506 : { "has_builtin_administrators", (PyCFunction)py_token_has_builtin_administrators, METH_NOARGS,
507 : NULL },
508 : { "has_nt_authenticated_users", (PyCFunction)py_token_has_nt_authenticated_users, METH_NOARGS,
509 : NULL },
510 : { "has_privilege", (PyCFunction)py_token_has_privilege, METH_VARARGS,
511 : NULL },
512 : { "set_privilege", (PyCFunction)py_token_set_privilege, METH_VARARGS,
513 : NULL },
514 : {0}
515 : };
516 :
517 : #define PY_TOKEN_PATCH py_token_patch
518 3562 : static void py_token_patch(PyTypeObject *type)
519 : {
520 3562 : type->tp_new = py_token_new;
521 3562 : PyType_AddMethods(type, py_token_extra_methods);
522 3562 : }
523 :
524 0 : static PyObject *py_privilege_name(PyObject *self, PyObject *args)
525 : {
526 : int priv;
527 0 : const char *name = NULL;
528 0 : if (!PyArg_ParseTuple(args, "i", &priv)) {
529 0 : return NULL;
530 : }
531 0 : name = sec_privilege_name(priv);
532 0 : if (name == NULL) {
533 0 : PyErr_Format(PyExc_ValueError,
534 : "Invalid privilege LUID: %d", priv);
535 0 : return NULL;
536 : }
537 :
538 0 : return PyUnicode_FromString(name);
539 : }
540 :
541 0 : static PyObject *py_privilege_id(PyObject *self, PyObject *args)
542 : {
543 : char *name;
544 :
545 0 : if (!PyArg_ParseTuple(args, "s", &name))
546 0 : return NULL;
547 :
548 0 : return PyLong_FromLong(sec_privilege_id(name));
549 : }
550 :
551 97 : static PyObject *py_random_sid(PyObject *self,
552 : PyObject *Py_UNUSED(ignored))
553 : {
554 : struct dom_sid *sid;
555 : PyObject *ret;
556 97 : char *str = talloc_asprintf(
557 : NULL,
558 : "S-1-5-21-%"PRIu32"-%"PRIu32"-%"PRIu32,
559 : generate_random(),
560 : generate_random(),
561 : generate_random());
562 :
563 97 : sid = dom_sid_parse_talloc(NULL, str);
564 97 : talloc_free(str);
565 97 : ret = pytalloc_steal(&dom_sid_Type, sid);
566 97 : return ret;
567 : }
568 :
569 : static PyMethodDef py_mod_security_extra_methods[] = {
570 : { "random_sid", (PyCFunction)py_random_sid, METH_NOARGS, NULL },
571 : { "privilege_id", (PyCFunction)py_privilege_id, METH_VARARGS, NULL },
572 : { "privilege_name", (PyCFunction)py_privilege_name, METH_VARARGS, NULL },
573 : {0}
574 : };
575 :
576 3562 : static void py_mod_security_patch(PyObject *m)
577 : {
578 : int i;
579 14248 : for (i = 0; py_mod_security_extra_methods[i].ml_name; i++) {
580 10686 : PyObject *descr = PyCFunction_New(&py_mod_security_extra_methods[i], NULL);
581 10686 : PyModule_AddObject(m, py_mod_security_extra_methods[i].ml_name,
582 : descr);
583 : }
584 3562 : }
585 :
586 : #define PY_MOD_SECURITY_PATCH py_mod_security_patch
|