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 "lib/replace/system/python.h"
21 : #include "gen_ndr/conditional_ace.h"
22 : #include "py3compat.h"
23 : #include "libcli/security/sddl.h"
24 : #include "libcli/security/security.h"
25 :
26 :
27 : /* Set up in py_mod_security_patch() */
28 : static PyObject *PyExc_SDDLValueError = NULL;
29 :
30 :
31 30596 : static void PyType_AddMethods(PyTypeObject *type, PyMethodDef *methods)
32 : {
33 772 : PyObject *dict;
34 772 : int i;
35 30596 : if (type->tp_dict == NULL)
36 0 : type->tp_dict = PyDict_New();
37 30596 : dict = type->tp_dict;
38 168278 : for (i = 0; methods[i].ml_name; i++) {
39 3474 : PyObject *descr;
40 137682 : if (methods[i].ml_flags & METH_CLASS)
41 7649 : descr = PyCFunction_New(&methods[i], (PyObject *)type);
42 : else
43 130033 : descr = PyDescr_NewMethod(type, &methods[i]);
44 137682 : PyDict_SetItemString(dict, methods[i].ml_name,
45 : descr);
46 137682 : Py_CLEAR(descr);
47 : }
48 30596 : }
49 :
50 8870 : static PyObject *py_dom_sid_split(PyObject *py_self, PyObject *args)
51 : {
52 8870 : struct dom_sid *self = pytalloc_get_ptr(py_self);
53 71 : struct dom_sid *domain_sid;
54 71 : TALLOC_CTX *mem_ctx;
55 71 : uint32_t rid;
56 71 : NTSTATUS status;
57 71 : PyObject *py_domain_sid;
58 :
59 8870 : mem_ctx = talloc_new(NULL);
60 8870 : if (mem_ctx == NULL) {
61 0 : PyErr_NoMemory();
62 0 : return NULL;
63 : }
64 :
65 8870 : status = dom_sid_split_rid(mem_ctx, self, &domain_sid, &rid);
66 8870 : if (!NT_STATUS_IS_OK(status)) {
67 0 : PyErr_SetString(PyExc_RuntimeError, "dom_sid_split_rid failed");
68 0 : talloc_free(mem_ctx);
69 0 : return NULL;
70 : }
71 :
72 8870 : py_domain_sid = pytalloc_steal(&dom_sid_Type, domain_sid);
73 8870 : talloc_free(mem_ctx);
74 8870 : return Py_BuildValue("(OI)", py_domain_sid, rid);
75 : }
76 :
77 4699 : static PyObject *py_dom_sid_richcmp(PyObject *py_self, PyObject *py_other, int op)
78 : {
79 4699 : struct dom_sid *self = pytalloc_get_ptr(py_self), *other;
80 121 : int val;
81 :
82 4699 : other = pytalloc_get_ptr(py_other);
83 4699 : if (other == NULL) {
84 0 : Py_INCREF(Py_NotImplemented);
85 0 : return Py_NotImplemented;
86 : }
87 :
88 4699 : val = dom_sid_compare(self, other);
89 :
90 4699 : switch (op) {
91 4459 : case Py_EQ: if (val == 0) Py_RETURN_TRUE; else Py_RETURN_FALSE;
92 240 : case Py_NE: if (val != 0) Py_RETURN_TRUE; else Py_RETURN_FALSE;
93 0 : case Py_LT: if (val < 0) Py_RETURN_TRUE; else Py_RETURN_FALSE;
94 0 : case Py_GT: if (val > 0) Py_RETURN_TRUE; else Py_RETURN_FALSE;
95 0 : case Py_LE: if (val <= 0) Py_RETURN_TRUE; else Py_RETURN_FALSE;
96 0 : case Py_GE: if (val >= 0) Py_RETURN_TRUE; else Py_RETURN_FALSE;
97 : }
98 0 : Py_INCREF(Py_NotImplemented);
99 0 : return Py_NotImplemented;
100 : }
101 :
102 63840 : static PyObject *py_dom_sid_str(PyObject *py_self)
103 : {
104 63840 : struct dom_sid *self = pytalloc_get_ptr(py_self);
105 1572 : struct dom_sid_buf buf;
106 63840 : PyObject *ret = PyUnicode_FromString(dom_sid_str_buf(self, &buf));
107 63840 : return ret;
108 : }
109 :
110 1 : static PyObject *py_dom_sid_repr(PyObject *py_self)
111 : {
112 1 : struct dom_sid *self = pytalloc_get_ptr(py_self);
113 1 : struct dom_sid_buf buf;
114 1 : PyObject *ret = PyUnicode_FromFormat(
115 : "dom_sid('%s')", dom_sid_str_buf(self, &buf));
116 1 : return ret;
117 : }
118 :
119 123621 : static int py_dom_sid_init(PyObject *self, PyObject *args, PyObject *kwargs)
120 : {
121 123621 : char *str = NULL;
122 123621 : struct dom_sid *sid = pytalloc_get_ptr(self);
123 123621 : const char *kwnames[] = { "str", NULL };
124 :
125 123621 : if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|s", discard_const_p(char *, kwnames), &str))
126 0 : return -1;
127 :
128 123621 : if (str != NULL && !dom_sid_parse(str, sid)) {
129 6808 : PyErr_Format(PyExc_ValueError,
130 : "Unable to parse string: '%s'", str);
131 6808 : return -1;
132 : }
133 :
134 49596 : return 0;
135 : }
136 :
137 : static PyMethodDef py_dom_sid_extra_methods[] = {
138 : { "split", (PyCFunction)py_dom_sid_split, METH_NOARGS,
139 : "S.split() -> (domain_sid, rid)\n"
140 : "Split a domain sid" },
141 : {0}
142 : };
143 :
144 :
145 7649 : static void py_dom_sid_patch(PyTypeObject *type)
146 : {
147 7649 : type->tp_init = py_dom_sid_init;
148 7649 : type->tp_str = py_dom_sid_str;
149 7649 : type->tp_repr = py_dom_sid_repr;
150 7649 : type->tp_richcompare = py_dom_sid_richcmp;
151 7649 : PyType_AddMethods(type, py_dom_sid_extra_methods);
152 7456 : }
153 :
154 : #define PY_DOM_SID_PATCH py_dom_sid_patch
155 :
156 7335 : static PyObject *py_descriptor_sacl_add(PyObject *self, PyObject *args)
157 : {
158 7335 : struct security_descriptor *desc = pytalloc_get_ptr(self);
159 1495 : NTSTATUS status;
160 1495 : struct security_ace *ace;
161 1495 : PyObject *py_ace;
162 7335 : Py_ssize_t idx = -1;
163 :
164 7335 : if (!PyArg_ParseTuple(args, "O|n", &py_ace, &idx))
165 0 : return NULL;
166 :
167 7335 : ace = pytalloc_get_ptr(py_ace);
168 7335 : status = security_descriptor_sacl_insert(desc, ace, idx);
169 7335 : PyErr_NTSTATUS_IS_ERR_RAISE(status);
170 7335 : Py_RETURN_NONE;
171 : }
172 :
173 862192 : static PyObject *py_descriptor_dacl_add(PyObject *self, PyObject *args)
174 : {
175 862192 : struct security_descriptor *desc = pytalloc_get_ptr(self);
176 144095 : NTSTATUS status;
177 144095 : struct security_ace *ace;
178 144095 : PyObject *py_ace;
179 862192 : Py_ssize_t idx = -1;
180 :
181 862192 : if (!PyArg_ParseTuple(args, "O|n", &py_ace, &idx))
182 0 : return NULL;
183 :
184 862192 : ace = pytalloc_get_ptr(py_ace);
185 :
186 862192 : status = security_descriptor_dacl_insert(desc, ace, idx);
187 862192 : PyErr_NTSTATUS_IS_ERR_RAISE(status);
188 862192 : Py_RETURN_NONE;
189 : }
190 :
191 0 : static PyObject *py_descriptor_dacl_del(PyObject *self, PyObject *args)
192 : {
193 0 : struct security_descriptor *desc = pytalloc_get_ptr(self);
194 0 : NTSTATUS status;
195 0 : struct dom_sid *sid;
196 0 : PyObject *py_sid;
197 :
198 0 : if (!PyArg_ParseTuple(args, "O", &py_sid))
199 0 : return NULL;
200 :
201 0 : sid = pytalloc_get_ptr(py_sid);
202 0 : status = security_descriptor_dacl_del(desc, sid);
203 0 : PyErr_NTSTATUS_IS_ERR_RAISE(status);
204 0 : Py_RETURN_NONE;
205 : }
206 :
207 0 : static PyObject *py_descriptor_sacl_del(PyObject *self, PyObject *args)
208 : {
209 0 : struct security_descriptor *desc = pytalloc_get_ptr(self);
210 0 : NTSTATUS status;
211 0 : struct dom_sid *sid;
212 0 : 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_sacl_del(desc, sid);
219 0 : PyErr_NTSTATUS_IS_ERR_RAISE(status);
220 0 : Py_RETURN_NONE;
221 : }
222 :
223 110854 : static PyObject *py_descriptor_dacl_del_ace(PyObject *self, PyObject *args)
224 : {
225 110854 : struct security_descriptor *desc = pytalloc_get_ptr(self);
226 594 : NTSTATUS status;
227 110854 : struct security_ace *ace = NULL;
228 110854 : PyObject *py_ace = Py_None;
229 :
230 110854 : if (!PyArg_ParseTuple(args, "O!", &security_ace_Type, &py_ace))
231 0 : return NULL;
232 :
233 110854 : if (!PyObject_TypeCheck(py_ace, &security_ace_Type)) {
234 0 : PyErr_SetString(PyExc_TypeError,
235 : "expected security.security_ace "
236 : "for first argument to .dacl_del_ace");
237 0 : return NULL;
238 : }
239 :
240 110854 : ace = pytalloc_get_ptr(py_ace);
241 110854 : status = security_descriptor_dacl_del_ace(desc, ace);
242 110854 : PyErr_NTSTATUS_IS_ERR_RAISE(status);
243 110845 : Py_RETURN_NONE;
244 : }
245 :
246 0 : static PyObject *py_descriptor_sacl_del_ace(PyObject *self, PyObject *args)
247 : {
248 0 : struct security_descriptor *desc = pytalloc_get_ptr(self);
249 0 : NTSTATUS status;
250 0 : struct security_ace *ace = NULL;
251 0 : PyObject *py_ace = Py_None;
252 :
253 0 : if (!PyArg_ParseTuple(args, "O!", &security_ace_Type, &py_ace))
254 0 : return NULL;
255 :
256 0 : if (!PyObject_TypeCheck(py_ace, &security_ace_Type)) {
257 0 : PyErr_SetString(PyExc_TypeError,
258 : "expected security.security_ace "
259 : "for first argument to .sacl_del_ace");
260 0 : return NULL;
261 : }
262 :
263 0 : ace = pytalloc_get_ptr(py_ace);
264 0 : status = security_descriptor_sacl_del_ace(desc, ace);
265 0 : PyErr_NTSTATUS_IS_ERR_RAISE(status);
266 0 : Py_RETURN_NONE;
267 : }
268 :
269 1026051 : static PyObject *py_descriptor_new(PyTypeObject *self, PyObject *args, PyObject *kwargs)
270 : {
271 1026051 : return pytalloc_steal(self, security_descriptor_initialise(NULL));
272 : }
273 :
274 49611 : static PyObject *py_descriptor_from_sddl(PyObject *self, PyObject *args, PyObject *kwargs)
275 : {
276 49611 : TALLOC_CTX *tmp_ctx = NULL;
277 10118 : static const char *kwnames[] = { "", "", "allow_device_in_sddl", NULL };
278 10118 : struct security_descriptor *secdesc;
279 10118 : char *sddl;
280 10118 : PyObject *py_sid;
281 49611 : int allow_device_in_sddl = 1;
282 10118 : struct dom_sid *sid;
283 49611 : const char *err_msg = NULL;
284 49611 : size_t err_msg_offset = 0;
285 49611 : enum ace_condition_flags ace_condition_flags = 0;
286 :
287 49611 : if (!PyArg_ParseTupleAndKeywords(args,
288 : kwargs,
289 : "sO!|$p",
290 : discard_const_p(char *, kwnames),
291 : &sddl,
292 : &dom_sid_Type,
293 : &py_sid,
294 : &allow_device_in_sddl))
295 0 : return NULL;
296 :
297 49609 : if (!PyObject_TypeCheck(py_sid, &dom_sid_Type)) {
298 0 : PyErr_SetString(PyExc_TypeError,
299 : "expected security.dom_sid "
300 : "for second argument to .from_sddl");
301 0 : return NULL;
302 : }
303 :
304 49609 : sid = pytalloc_get_ptr(py_sid);
305 :
306 49609 : if (allow_device_in_sddl) {
307 49593 : ace_condition_flags |= ACE_CONDITION_FLAG_ALLOW_DEVICE;
308 : }
309 :
310 49609 : tmp_ctx = talloc_new(NULL);
311 49609 : if (tmp_ctx == NULL) {
312 0 : PyErr_NoMemory();
313 0 : return NULL;
314 : }
315 :
316 49609 : secdesc = sddl_decode_err_msg(tmp_ctx, sddl, sid,
317 : ace_condition_flags,
318 : &err_msg, &err_msg_offset);
319 49609 : if (secdesc == NULL) {
320 194 : PyObject *exc = NULL;
321 194 : if (err_msg == NULL) {
322 82 : err_msg = "unknown error";
323 : }
324 : /*
325 : * Some notes about this exception value:
326 : *
327 : * We don't want to add the offset first, so as not to
328 : * confuse those who are used to the integer error
329 : * code coming first.
330 : *
331 : * The errant sddl is added so that the exception can
332 : * be caught some distance away from the call and we
333 : * still know what the messages refer to.
334 : */
335 194 : exc = Py_BuildValue("(s, s, i, s)",
336 : "Unable to parse SDDL",
337 : err_msg,
338 : err_msg_offset,
339 : sddl);
340 194 : if (exc == NULL) {
341 0 : talloc_free(tmp_ctx);
342 : /* an exception was set by Py_BuildValue() */
343 0 : return NULL;
344 : }
345 194 : PyErr_SetObject(PyExc_SDDLValueError, exc);
346 157 : Py_DECREF(exc);
347 194 : talloc_free(tmp_ctx);
348 194 : return NULL;
349 : }
350 :
351 49415 : secdesc = talloc_steal(NULL, secdesc);
352 49415 : talloc_free(tmp_ctx);
353 :
354 49415 : return pytalloc_steal((PyTypeObject *)self, secdesc);
355 : }
356 :
357 76563 : static PyObject *py_descriptor_as_sddl(PyObject *self, PyObject *args)
358 : {
359 944 : struct dom_sid *sid;
360 76563 : PyObject *py_sid = Py_None;
361 76563 : struct security_descriptor *desc = pytalloc_get_ptr(self);
362 944 : char *text;
363 944 : PyObject *ret;
364 :
365 76563 : if (!PyArg_ParseTuple(args, "|O!", &dom_sid_Type, &py_sid))
366 0 : return NULL;
367 :
368 76562 : if (py_sid != Py_None)
369 75837 : sid = pytalloc_get_ptr(py_sid);
370 : else
371 683 : sid = NULL;
372 :
373 76562 : text = sddl_encode(NULL, desc, sid);
374 76562 : if (text == NULL) {
375 0 : PyErr_SetString(PyExc_ValueError, "Unable to encode SDDL");
376 0 : return NULL;
377 : }
378 :
379 76562 : ret = PyUnicode_FromString(text);
380 :
381 76562 : talloc_free(text);
382 :
383 76562 : return ret;
384 : }
385 :
386 : static PyMethodDef py_descriptor_extra_methods[] = {
387 : { "sacl_add", (PyCFunction)py_descriptor_sacl_add, METH_VARARGS,
388 : "S.sacl_add(ace) -> None\n"
389 : "Add a security ace to this security descriptor" },
390 : { "dacl_add", (PyCFunction)py_descriptor_dacl_add, METH_VARARGS,
391 : NULL },
392 : { "dacl_del", (PyCFunction)py_descriptor_dacl_del, METH_VARARGS,
393 : NULL },
394 : { "sacl_del", (PyCFunction)py_descriptor_sacl_del, METH_VARARGS,
395 : NULL },
396 : { "dacl_del_ace", (PyCFunction)py_descriptor_dacl_del_ace, METH_VARARGS,
397 : NULL },
398 : { "sacl_del_ace", (PyCFunction)py_descriptor_sacl_del_ace, METH_VARARGS,
399 : NULL },
400 : { "from_sddl", (PyCFunction)py_descriptor_from_sddl, METH_VARARGS|METH_KEYWORDS|METH_CLASS,
401 : NULL },
402 : { "as_sddl", (PyCFunction)py_descriptor_as_sddl, METH_VARARGS,
403 : NULL },
404 : {0}
405 : };
406 :
407 7876 : static PyObject *py_descriptor_richcmp(
408 : PyObject *py_self, PyObject *py_other, int op)
409 : {
410 7876 : struct security_descriptor *self = pytalloc_get_ptr(py_self);
411 7876 : struct security_descriptor *other = pytalloc_get_ptr(py_other);
412 7839 : bool eq;
413 :
414 7876 : if (other == NULL) {
415 22 : Py_INCREF(Py_NotImplemented);
416 22 : return Py_NotImplemented;
417 : }
418 :
419 7854 : eq = security_descriptor_equal(self, other);
420 :
421 7854 : switch(op) {
422 147 : case Py_EQ:
423 147 : if (eq) {
424 147 : Py_RETURN_TRUE;
425 : } else {
426 0 : Py_RETURN_FALSE;
427 : }
428 7696 : break;
429 7707 : case Py_NE:
430 7707 : if (eq) {
431 7581 : Py_RETURN_FALSE;
432 : } else {
433 126 : Py_RETURN_TRUE;
434 : }
435 0 : break;
436 0 : default:
437 0 : break;
438 : }
439 :
440 0 : Py_RETURN_NOTIMPLEMENTED;
441 : }
442 :
443 7649 : static void py_descriptor_patch(PyTypeObject *type)
444 : {
445 7649 : type->tp_new = py_descriptor_new;
446 7649 : type->tp_richcompare = py_descriptor_richcmp;
447 7649 : PyType_AddMethods(type, py_descriptor_extra_methods);
448 7456 : }
449 :
450 : #define PY_DESCRIPTOR_PATCH py_descriptor_patch
451 :
452 0 : static PyObject *py_token_is_sid(PyObject *self, PyObject *args)
453 : {
454 0 : PyObject *py_sid;
455 0 : struct dom_sid *sid;
456 0 : struct security_token *token = pytalloc_get_ptr(self);
457 0 : if (!PyArg_ParseTuple(args, "O", &py_sid))
458 0 : return NULL;
459 :
460 0 : sid = pytalloc_get_ptr(py_sid);
461 :
462 0 : return PyBool_FromLong(security_token_is_sid(token, sid));
463 : }
464 :
465 0 : static PyObject *py_token_has_sid(PyObject *self, PyObject *args)
466 : {
467 0 : PyObject *py_sid;
468 0 : struct dom_sid *sid;
469 0 : struct security_token *token = pytalloc_get_ptr(self);
470 0 : if (!PyArg_ParseTuple(args, "O", &py_sid))
471 0 : return NULL;
472 :
473 0 : sid = pytalloc_get_ptr(py_sid);
474 :
475 0 : return PyBool_FromLong(security_token_has_sid(token, sid));
476 : }
477 :
478 3 : static PyObject *py_token_is_anonymous(PyObject *self,
479 : PyObject *Py_UNUSED(ignored))
480 : {
481 3 : struct security_token *token = pytalloc_get_ptr(self);
482 :
483 3 : return PyBool_FromLong(security_token_is_anonymous(token));
484 : }
485 :
486 27 : static PyObject *py_token_is_system(PyObject *self,
487 : PyObject *Py_UNUSED(ignored))
488 : {
489 27 : struct security_token *token = pytalloc_get_ptr(self);
490 :
491 27 : return PyBool_FromLong(security_token_is_system(token));
492 : }
493 :
494 2 : static PyObject *py_token_has_builtin_administrators(PyObject *self,
495 : PyObject *Py_UNUSED(ignored))
496 : {
497 2 : struct security_token *token = pytalloc_get_ptr(self);
498 :
499 2 : return PyBool_FromLong(security_token_has_builtin_administrators(token));
500 : }
501 :
502 1 : static PyObject *py_token_has_nt_authenticated_users(PyObject *self,
503 : PyObject *Py_UNUSED(ignored))
504 : {
505 1 : struct security_token *token = pytalloc_get_ptr(self);
506 :
507 1 : return PyBool_FromLong(security_token_has_nt_authenticated_users(token));
508 : }
509 :
510 3 : static PyObject *py_token_has_privilege(PyObject *self, PyObject *args)
511 : {
512 3 : int priv;
513 3 : struct security_token *token = pytalloc_get_ptr(self);
514 :
515 3 : if (!PyArg_ParseTuple(args, "i", &priv))
516 0 : return NULL;
517 :
518 3 : return PyBool_FromLong(security_token_has_privilege(token, priv));
519 : }
520 :
521 1 : static PyObject *py_token_set_privilege(PyObject *self, PyObject *args)
522 : {
523 1 : int priv;
524 1 : struct security_token *token = pytalloc_get_ptr(self);
525 :
526 1 : if (!PyArg_ParseTuple(args, "i", &priv))
527 0 : return NULL;
528 :
529 1 : security_token_set_privilege(token, priv);
530 1 : Py_RETURN_NONE;
531 : }
532 :
533 107 : static PyObject *py_token_new(PyTypeObject *self, PyObject *args, PyObject *kwargs)
534 : {
535 107 : int evaluate_claims = CLAIMS_EVALUATION_INVALID_STATE;
536 107 : const char *kwnames[] = { "evaluate_claims", NULL };
537 :
538 107 : if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|i",
539 : discard_const_p(char *, kwnames),
540 : &evaluate_claims)) {
541 0 : return NULL;
542 : }
543 :
544 107 : return pytalloc_steal(self, security_token_initialise(NULL, evaluate_claims));
545 : }
546 :
547 : static PyMethodDef py_token_extra_methods[] = {
548 : { "is_sid", (PyCFunction)py_token_is_sid, METH_VARARGS,
549 : "S.is_sid(sid) -> bool\n"
550 : "Check whether this token is of the specified SID." },
551 : { "has_sid", (PyCFunction)py_token_has_sid, METH_VARARGS,
552 : NULL },
553 : { "is_anonymous", (PyCFunction)py_token_is_anonymous, METH_NOARGS,
554 : "S.is_anonymous() -> bool\n"
555 : "Check whether this is an anonymous token." },
556 : { "is_system", (PyCFunction)py_token_is_system, METH_NOARGS,
557 : NULL },
558 : { "has_builtin_administrators", (PyCFunction)py_token_has_builtin_administrators, METH_NOARGS,
559 : NULL },
560 : { "has_nt_authenticated_users", (PyCFunction)py_token_has_nt_authenticated_users, METH_NOARGS,
561 : NULL },
562 : { "has_privilege", (PyCFunction)py_token_has_privilege, METH_VARARGS,
563 : NULL },
564 : { "set_privilege", (PyCFunction)py_token_set_privilege, METH_VARARGS,
565 : NULL },
566 : {0}
567 : };
568 :
569 : #define PY_TOKEN_PATCH py_token_patch
570 7649 : static void py_token_patch(PyTypeObject *type)
571 : {
572 7649 : type->tp_new = py_token_new;
573 7649 : PyType_AddMethods(type, py_token_extra_methods);
574 7456 : }
575 :
576 1 : static PyObject *py_privilege_name(PyObject *self, PyObject *args)
577 : {
578 1 : int priv;
579 1 : const char *name = NULL;
580 1 : if (!PyArg_ParseTuple(args, "i", &priv)) {
581 0 : return NULL;
582 : }
583 1 : name = sec_privilege_name(priv);
584 1 : if (name == NULL) {
585 0 : PyErr_Format(PyExc_ValueError,
586 : "Invalid privilege LUID: %d", priv);
587 0 : return NULL;
588 : }
589 :
590 1 : return PyUnicode_FromString(name);
591 : }
592 :
593 1 : static PyObject *py_privilege_id(PyObject *self, PyObject *args)
594 : {
595 1 : char *name;
596 :
597 1 : if (!PyArg_ParseTuple(args, "s", &name))
598 0 : return NULL;
599 :
600 1 : return PyLong_FromLong(sec_privilege_id(name));
601 : }
602 :
603 143 : static PyObject *py_random_sid(PyObject *self,
604 : PyObject *Py_UNUSED(ignored))
605 : {
606 19 : struct dom_sid *sid;
607 19 : PyObject *ret;
608 143 : char *str = talloc_asprintf(
609 : NULL,
610 : "S-1-5-21-%"PRIu32"-%"PRIu32"-%"PRIu32,
611 : generate_random(),
612 : generate_random(),
613 : generate_random());
614 :
615 143 : sid = dom_sid_parse_talloc(NULL, str);
616 143 : talloc_free(str);
617 143 : ret = pytalloc_steal(&dom_sid_Type, sid);
618 143 : return ret;
619 : }
620 :
621 : static PyMethodDef py_mod_security_extra_methods[] = {
622 : { "random_sid", (PyCFunction)py_random_sid, METH_NOARGS, NULL },
623 : { "privilege_id", (PyCFunction)py_privilege_id, METH_VARARGS, NULL },
624 : { "privilege_name", (PyCFunction)py_privilege_name, METH_VARARGS, NULL },
625 : {0}
626 : };
627 :
628 7649 : static bool py_mod_security_patch(PyObject *m)
629 : {
630 193 : int ret;
631 193 : int i;
632 30596 : for (i = 0; py_mod_security_extra_methods[i].ml_name; i++) {
633 22947 : PyObject *descr = PyCFunction_New(&py_mod_security_extra_methods[i], NULL);
634 22947 : ret = PyModule_AddObject(m, py_mod_security_extra_methods[i].ml_name,
635 : descr);
636 22947 : if (ret != 0) {
637 0 : return false;
638 : }
639 : }
640 : /*
641 : * I wanted to make this a subclass of ValueError, but it
642 : * seems there isn't an easy way to do that using the API.
643 : * (c.f. SimpleExtendsException in cpython:Objects/exceptions.c)
644 : */
645 7649 : PyExc_SDDLValueError = PyErr_NewException("security.SDDLValueError",
646 : NULL, NULL);
647 :
648 7649 : if (PyExc_SDDLValueError == NULL) {
649 0 : return false;
650 : }
651 7649 : ret = PyModule_AddObject(m, "SDDLValueError", PyExc_SDDLValueError);
652 7649 : if (ret != 0) {
653 0 : return false;
654 : }
655 7456 : return true;
656 : }
657 :
658 : #define PY_MOD_SECURITY_PATCH(m) \
659 : do { \
660 : bool _ok = py_mod_security_patch(m); \
661 : if (! _ok) { \
662 : Py_XDECREF(m); \
663 : return NULL; \
664 : } \
665 : } while(0)
666 :
667 160047 : static PyObject *py_security_ace_equal(PyObject *py_self, PyObject *py_other, int op)
668 : {
669 160047 : struct security_ace *self = pytalloc_get_ptr(py_self);
670 160047 : struct security_ace *other = NULL;
671 14702 : bool eq;
672 :
673 160047 : if (!PyObject_TypeCheck(py_other, &security_ace_Type)) {
674 0 : eq = false;
675 : } else {
676 160047 : other = pytalloc_get_ptr(py_other);
677 160047 : eq = security_ace_equal(self, other);
678 : }
679 :
680 160047 : switch(op) {
681 160045 : case Py_EQ:
682 160045 : if (eq) {
683 1453 : Py_RETURN_TRUE;
684 : } else {
685 158592 : Py_RETURN_FALSE;
686 : }
687 2 : break;
688 2 : case Py_NE:
689 2 : if (eq) {
690 0 : Py_RETURN_FALSE;
691 : } else {
692 2 : Py_RETURN_TRUE;
693 : }
694 0 : break;
695 0 : default:
696 0 : break;
697 : }
698 :
699 0 : Py_RETURN_NOTIMPLEMENTED;
700 : }
701 :
702 13 : static PyObject *py_security_ace_as_sddl(PyObject *self, PyObject *args)
703 : {
704 13 : struct security_ace *ace = pytalloc_get_ptr(self);
705 13 : PyObject *py_sid = Py_None;
706 13 : struct dom_sid *sid = NULL;
707 13 : char *text = NULL;
708 13 : PyObject *ret = Py_None;
709 :
710 13 : if (!PyArg_ParseTuple(args, "O!", &dom_sid_Type, &py_sid))
711 0 : return NULL;
712 :
713 13 : if (!PyObject_TypeCheck(py_sid, &dom_sid_Type)) {
714 0 : PyErr_SetString(PyExc_TypeError,
715 : "expected security.dom_sid "
716 : "for second argument to .sddl_encode_ace");
717 0 : return NULL;
718 : }
719 :
720 13 : sid = pytalloc_get_ptr(py_sid);
721 :
722 13 : text = sddl_encode_ace(NULL, ace, sid);
723 13 : if (text == NULL) {
724 0 : return NULL;
725 : }
726 13 : ret = PyUnicode_FromString(text);
727 13 : talloc_free(text);
728 :
729 13 : return ret;
730 : }
731 :
732 : static PyMethodDef py_security_ace_extra_methods[] = {
733 : { "as_sddl", (PyCFunction)py_security_ace_as_sddl, METH_VARARGS, NULL },
734 : {0}
735 : };
736 :
737 : #define PY_ACE_PATCH py_security_ace_patch
738 :
739 7649 : static void py_security_ace_patch(PyTypeObject *type)
740 : {
741 7649 : type->tp_richcompare = py_security_ace_equal;
742 7649 : PyType_AddMethods(type, py_security_ace_extra_methods);
743 7456 : }
|