2 Unix SMB/CIFS implementation.
3 Samba utility functions
5 Copyright (C) Jelmer Vernooij <jelmer@samba.org> 2008-2010
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.
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.
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/>.
21 #include "py3compat.h"
22 #include "libcli/security/sddl.h"
23 #include "libcli/security/security.h"
25 static void PyType_AddMethods(PyTypeObject
*type
, PyMethodDef
*methods
)
29 if (type
->tp_dict
== NULL
)
30 type
->tp_dict
= PyDict_New();
32 for (i
= 0; methods
[i
].ml_name
; i
++) {
34 if (methods
[i
].ml_flags
& METH_CLASS
)
35 descr
= PyCFunction_New(&methods
[i
], (PyObject
*)type
);
37 descr
= PyDescr_NewMethod(type
, &methods
[i
]);
38 PyDict_SetItemString(dict
, methods
[i
].ml_name
,
44 static PyObject
*py_dom_sid_split(PyObject
*py_self
, PyObject
*args
)
46 struct dom_sid
*self
= pytalloc_get_ptr(py_self
);
47 struct dom_sid
*domain_sid
;
51 PyObject
*py_domain_sid
;
53 mem_ctx
= talloc_new(NULL
);
54 if (mem_ctx
== NULL
) {
59 status
= dom_sid_split_rid(mem_ctx
, self
, &domain_sid
, &rid
);
60 if (!NT_STATUS_IS_OK(status
)) {
61 PyErr_SetString(PyExc_RuntimeError
, "dom_sid_split_rid failed");
66 py_domain_sid
= pytalloc_steal(&dom_sid_Type
, domain_sid
);
68 return Py_BuildValue("(OI)", py_domain_sid
, rid
);
71 #if PY_MAJOR_VERSION >= 3
72 static PyObject
*py_dom_sid_richcmp(PyObject
*py_self
, PyObject
*py_other
, int op
)
74 struct dom_sid
*self
= pytalloc_get_ptr(py_self
), *other
;
77 other
= pytalloc_get_ptr(py_other
);
79 Py_INCREF(Py_NotImplemented
);
80 return Py_NotImplemented
;
83 val
= dom_sid_compare(self
, other
);
86 case Py_EQ
: if (val
== 0) Py_RETURN_TRUE
; else Py_RETURN_FALSE
;
87 case Py_NE
: if (val
!= 0) Py_RETURN_TRUE
; else Py_RETURN_FALSE
;
88 case Py_LT
: if (val
< 0) Py_RETURN_TRUE
; else Py_RETURN_FALSE
;
89 case Py_GT
: if (val
> 0) Py_RETURN_TRUE
; else Py_RETURN_FALSE
;
90 case Py_LE
: if (val
<= 0) Py_RETURN_TRUE
; else Py_RETURN_FALSE
;
91 case Py_GE
: if (val
>= 0) Py_RETURN_TRUE
; else Py_RETURN_FALSE
;
93 Py_INCREF(Py_NotImplemented
);
94 return Py_NotImplemented
;
97 static int py_dom_sid_cmp(PyObject
*py_self
, PyObject
*py_other
)
99 struct dom_sid
*self
= pytalloc_get_ptr(py_self
), *other
;
102 other
= pytalloc_get_ptr(py_other
);
106 val
= dom_sid_compare(self
, other
);
109 } else if (val
< 0) {
116 static PyObject
*py_dom_sid_str(PyObject
*py_self
)
118 struct dom_sid
*self
= pytalloc_get_ptr(py_self
);
119 struct dom_sid_buf buf
;
120 PyObject
*ret
= PyUnicode_FromString(dom_sid_str_buf(self
, &buf
));
124 static PyObject
*py_dom_sid_repr(PyObject
*py_self
)
126 struct dom_sid
*self
= pytalloc_get_ptr(py_self
);
127 struct dom_sid_buf buf
;
128 PyObject
*ret
= PyUnicode_FromFormat(
129 "dom_sid('%s')", dom_sid_str_buf(self
, &buf
));
133 static int py_dom_sid_init(PyObject
*self
, PyObject
*args
, PyObject
*kwargs
)
136 struct dom_sid
*sid
= pytalloc_get_ptr(self
);
137 const char *kwnames
[] = { "str", NULL
};
139 if (!PyArg_ParseTupleAndKeywords(args
, kwargs
, "|s", discard_const_p(char *, kwnames
), &str
))
142 if (str
!= NULL
&& !dom_sid_parse(str
, sid
)) {
143 PyErr_SetString(PyExc_TypeError
, "Unable to parse string");
150 static PyMethodDef py_dom_sid_extra_methods
[] = {
151 { "split", (PyCFunction
)py_dom_sid_split
, METH_NOARGS
,
152 "S.split() -> (domain_sid, rid)\n"
153 "Split a domain sid" },
158 static void py_dom_sid_patch(PyTypeObject
*type
)
160 type
->tp_init
= py_dom_sid_init
;
161 type
->tp_str
= py_dom_sid_str
;
162 type
->tp_repr
= py_dom_sid_repr
;
163 #if PY_MAJOR_VERSION >= 3
164 type
->tp_richcompare
= py_dom_sid_richcmp
;
166 type
->tp_compare
= py_dom_sid_cmp
;
168 PyType_AddMethods(type
, py_dom_sid_extra_methods
);
171 #define PY_DOM_SID_PATCH py_dom_sid_patch
173 static PyObject
*py_descriptor_sacl_add(PyObject
*self
, PyObject
*args
)
175 struct security_descriptor
*desc
= pytalloc_get_ptr(self
);
177 struct security_ace
*ace
;
180 if (!PyArg_ParseTuple(args
, "O", &py_ace
))
183 ace
= pytalloc_get_ptr(py_ace
);
184 status
= security_descriptor_sacl_add(desc
, ace
);
185 PyErr_NTSTATUS_IS_ERR_RAISE(status
);
189 static PyObject
*py_descriptor_dacl_add(PyObject
*self
, PyObject
*args
)
191 struct security_descriptor
*desc
= pytalloc_get_ptr(self
);
193 struct security_ace
*ace
;
196 if (!PyArg_ParseTuple(args
, "O", &py_ace
))
199 ace
= pytalloc_get_ptr(py_ace
);
201 status
= security_descriptor_dacl_add(desc
, ace
);
202 PyErr_NTSTATUS_IS_ERR_RAISE(status
);
206 static PyObject
*py_descriptor_dacl_del(PyObject
*self
, PyObject
*args
)
208 struct security_descriptor
*desc
= pytalloc_get_ptr(self
);
213 if (!PyArg_ParseTuple(args
, "O", &py_sid
))
216 sid
= pytalloc_get_ptr(py_sid
);
217 status
= security_descriptor_dacl_del(desc
, sid
);
218 PyErr_NTSTATUS_IS_ERR_RAISE(status
);
222 static PyObject
*py_descriptor_sacl_del(PyObject
*self
, PyObject
*args
)
224 struct security_descriptor
*desc
= pytalloc_get_ptr(self
);
229 if (!PyArg_ParseTuple(args
, "O", &py_sid
))
232 sid
= pytalloc_get_ptr(py_sid
);
233 status
= security_descriptor_sacl_del(desc
, sid
);
234 PyErr_NTSTATUS_IS_ERR_RAISE(status
);
238 static PyObject
*py_descriptor_dacl_del_ace(PyObject
*self
, PyObject
*args
)
240 struct security_descriptor
*desc
= pytalloc_get_ptr(self
);
242 struct security_ace
*ace
= NULL
;
243 PyObject
*py_ace
= Py_None
;
245 if (!PyArg_ParseTuple(args
, "O!", &security_ace_Type
, &py_ace
))
248 if (!PyObject_TypeCheck(py_ace
, &security_ace_Type
)) {
249 PyErr_SetString(PyExc_TypeError
,
250 "expected security.security_ace "
251 "for first argument to .dacl_del_ace");
255 ace
= pytalloc_get_ptr(py_ace
);
256 status
= security_descriptor_dacl_del_ace(desc
, ace
);
257 PyErr_NTSTATUS_IS_ERR_RAISE(status
);
261 static PyObject
*py_descriptor_sacl_del_ace(PyObject
*self
, PyObject
*args
)
263 struct security_descriptor
*desc
= pytalloc_get_ptr(self
);
265 struct security_ace
*ace
= NULL
;
266 PyObject
*py_ace
= Py_None
;
268 if (!PyArg_ParseTuple(args
, "O!", &security_ace_Type
, &py_ace
))
271 if (!PyObject_TypeCheck(py_ace
, &security_ace_Type
)) {
272 PyErr_SetString(PyExc_TypeError
,
273 "expected security.security_ace "
274 "for first argument to .sacl_del_ace");
278 ace
= pytalloc_get_ptr(py_ace
);
279 status
= security_descriptor_sacl_del_ace(desc
, ace
);
280 PyErr_NTSTATUS_IS_ERR_RAISE(status
);
284 static PyObject
*py_descriptor_new(PyTypeObject
*self
, PyObject
*args
, PyObject
*kwargs
)
286 return pytalloc_steal(self
, security_descriptor_initialise(NULL
));
289 static PyObject
*py_descriptor_from_sddl(PyObject
*self
, PyObject
*args
)
291 struct security_descriptor
*secdesc
;
296 if (!PyArg_ParseTuple(args
, "sO!", &sddl
, &dom_sid_Type
, &py_sid
))
299 if (!PyObject_TypeCheck(py_sid
, &dom_sid_Type
)) {
300 PyErr_SetString(PyExc_TypeError
,
301 "expected security.dom_sid "
302 "for second argument to .from_sddl");
306 sid
= pytalloc_get_ptr(py_sid
);
308 secdesc
= sddl_decode(NULL
, sddl
, sid
);
309 if (secdesc
== NULL
) {
310 PyErr_SetString(PyExc_TypeError
, "Unable to parse SDDL");
314 return pytalloc_steal((PyTypeObject
*)self
, secdesc
);
317 static PyObject
*py_descriptor_as_sddl(PyObject
*self
, PyObject
*args
)
320 PyObject
*py_sid
= Py_None
;
321 struct security_descriptor
*desc
= pytalloc_get_ptr(self
);
325 if (!PyArg_ParseTuple(args
, "|O!", &dom_sid_Type
, &py_sid
))
328 if (py_sid
!= Py_None
)
329 sid
= pytalloc_get_ptr(py_sid
);
333 text
= sddl_encode(NULL
, desc
, sid
);
335 ret
= PyUnicode_FromString(text
);
342 static PyMethodDef py_descriptor_extra_methods
[] = {
343 { "sacl_add", (PyCFunction
)py_descriptor_sacl_add
, METH_VARARGS
,
344 "S.sacl_add(ace) -> None\n"
345 "Add a security ace to this security descriptor" },
346 { "dacl_add", (PyCFunction
)py_descriptor_dacl_add
, METH_VARARGS
,
348 { "dacl_del", (PyCFunction
)py_descriptor_dacl_del
, METH_VARARGS
,
350 { "sacl_del", (PyCFunction
)py_descriptor_sacl_del
, METH_VARARGS
,
352 { "dacl_del_ace", (PyCFunction
)py_descriptor_dacl_del_ace
, METH_VARARGS
,
354 { "sacl_del_ace", (PyCFunction
)py_descriptor_sacl_del_ace
, METH_VARARGS
,
356 { "from_sddl", (PyCFunction
)py_descriptor_from_sddl
, METH_VARARGS
|METH_CLASS
,
358 { "as_sddl", (PyCFunction
)py_descriptor_as_sddl
, METH_VARARGS
,
363 static PyObject
*py_descriptor_richcmp(
364 PyObject
*py_self
, PyObject
*py_other
, int op
)
366 struct security_descriptor
*self
= pytalloc_get_ptr(py_self
);
367 struct security_descriptor
*other
= pytalloc_get_ptr(py_other
);
371 Py_INCREF(Py_NotImplemented
);
372 return Py_NotImplemented
;
375 eq
= security_descriptor_equal(self
, other
);
396 Py_RETURN_NOTIMPLEMENTED
;
399 static void py_descriptor_patch(PyTypeObject
*type
)
401 type
->tp_new
= py_descriptor_new
;
402 type
->tp_richcompare
= py_descriptor_richcmp
;
403 PyType_AddMethods(type
, py_descriptor_extra_methods
);
406 #define PY_DESCRIPTOR_PATCH py_descriptor_patch
408 static PyObject
*py_token_is_sid(PyObject
*self
, PyObject
*args
)
412 struct security_token
*token
= pytalloc_get_ptr(self
);
413 if (!PyArg_ParseTuple(args
, "O", &py_sid
))
416 sid
= pytalloc_get_ptr(py_sid
);
418 return PyBool_FromLong(security_token_is_sid(token
, sid
));
421 static PyObject
*py_token_has_sid(PyObject
*self
, PyObject
*args
)
425 struct security_token
*token
= pytalloc_get_ptr(self
);
426 if (!PyArg_ParseTuple(args
, "O", &py_sid
))
429 sid
= pytalloc_get_ptr(py_sid
);
431 return PyBool_FromLong(security_token_has_sid(token
, sid
));
434 static PyObject
*py_token_is_anonymous(PyObject
*self
,
435 PyObject
*Py_UNUSED(ignored
))
437 struct security_token
*token
= pytalloc_get_ptr(self
);
439 return PyBool_FromLong(security_token_is_anonymous(token
));
442 static PyObject
*py_token_is_system(PyObject
*self
,
443 PyObject
*Py_UNUSED(ignored
))
445 struct security_token
*token
= pytalloc_get_ptr(self
);
447 return PyBool_FromLong(security_token_is_system(token
));
450 static PyObject
*py_token_has_builtin_administrators(PyObject
*self
,
451 PyObject
*Py_UNUSED(ignored
))
453 struct security_token
*token
= pytalloc_get_ptr(self
);
455 return PyBool_FromLong(security_token_has_builtin_administrators(token
));
458 static PyObject
*py_token_has_nt_authenticated_users(PyObject
*self
,
459 PyObject
*Py_UNUSED(ignored
))
461 struct security_token
*token
= pytalloc_get_ptr(self
);
463 return PyBool_FromLong(security_token_has_nt_authenticated_users(token
));
466 static PyObject
*py_token_has_privilege(PyObject
*self
, PyObject
*args
)
469 struct security_token
*token
= pytalloc_get_ptr(self
);
471 if (!PyArg_ParseTuple(args
, "i", &priv
))
474 return PyBool_FromLong(security_token_has_privilege(token
, priv
));
477 static PyObject
*py_token_set_privilege(PyObject
*self
, PyObject
*args
)
480 struct security_token
*token
= pytalloc_get_ptr(self
);
482 if (!PyArg_ParseTuple(args
, "i", &priv
))
485 security_token_set_privilege(token
, priv
);
489 static PyObject
*py_token_new(PyTypeObject
*self
, PyObject
*args
, PyObject
*kwargs
)
491 return pytalloc_steal(self
, security_token_initialise(NULL
));
494 static PyMethodDef py_token_extra_methods
[] = {
495 { "is_sid", (PyCFunction
)py_token_is_sid
, METH_VARARGS
,
496 "S.is_sid(sid) -> bool\n"
497 "Check whether this token is of the specified SID." },
498 { "has_sid", (PyCFunction
)py_token_has_sid
, METH_VARARGS
,
500 { "is_anonymous", (PyCFunction
)py_token_is_anonymous
, METH_NOARGS
,
501 "S.is_anonymous() -> bool\n"
502 "Check whether this is an anonymous token." },
503 { "is_system", (PyCFunction
)py_token_is_system
, METH_NOARGS
,
505 { "has_builtin_administrators", (PyCFunction
)py_token_has_builtin_administrators
, METH_NOARGS
,
507 { "has_nt_authenticated_users", (PyCFunction
)py_token_has_nt_authenticated_users
, METH_NOARGS
,
509 { "has_privilege", (PyCFunction
)py_token_has_privilege
, METH_VARARGS
,
511 { "set_privilege", (PyCFunction
)py_token_set_privilege
, METH_VARARGS
,
516 #define PY_TOKEN_PATCH py_token_patch
517 static void py_token_patch(PyTypeObject
*type
)
519 type
->tp_new
= py_token_new
;
520 PyType_AddMethods(type
, py_token_extra_methods
);
523 static PyObject
*py_privilege_name(PyObject
*self
, PyObject
*args
)
526 const char *name
= NULL
;
527 if (!PyArg_ParseTuple(args
, "i", &priv
)) {
530 name
= sec_privilege_name(priv
);
532 PyErr_Format(PyExc_ValueError
,
533 "Invalid privilege LUID: %d", priv
);
537 return PyUnicode_FromString(name
);
540 static PyObject
*py_privilege_id(PyObject
*self
, PyObject
*args
)
544 if (!PyArg_ParseTuple(args
, "s", &name
))
547 return PyLong_FromLong(sec_privilege_id(name
));
550 static PyObject
*py_random_sid(PyObject
*self
,
551 PyObject
*Py_UNUSED(ignored
))
555 char *str
= talloc_asprintf(
557 "S-1-5-21-%"PRIu32
"-%"PRIu32
"-%"PRIu32
,
562 sid
= dom_sid_parse_talloc(NULL
, str
);
564 ret
= pytalloc_steal(&dom_sid_Type
, sid
);
568 static PyMethodDef py_mod_security_extra_methods
[] = {
569 { "random_sid", (PyCFunction
)py_random_sid
, METH_NOARGS
, NULL
},
570 { "privilege_id", (PyCFunction
)py_privilege_id
, METH_VARARGS
, NULL
},
571 { "privilege_name", (PyCFunction
)py_privilege_name
, METH_VARARGS
, NULL
},
575 static void py_mod_security_patch(PyObject
*m
)
578 for (i
= 0; py_mod_security_extra_methods
[i
].ml_name
; i
++) {
579 PyObject
*descr
= PyCFunction_New(&py_mod_security_extra_methods
[i
], NULL
);
580 PyModule_AddObject(m
, py_mod_security_extra_methods
[i
].ml_name
,
585 #define PY_MOD_SECURITY_PATCH py_mod_security_patch
587 static PyObject
*py_security_ace_equal(PyObject
*py_self
, PyObject
*py_other
, int op
)
589 struct security_ace
*self
= pytalloc_get_ptr(py_self
);
590 struct security_ace
*other
= NULL
;
593 if (!PyObject_TypeCheck(py_other
, &security_ace_Type
)) {
596 other
= pytalloc_get_ptr(py_other
);
597 eq
= security_ace_equal(self
, other
);
619 Py_RETURN_NOTIMPLEMENTED
;
622 static PyObject
*py_security_ace_as_sddl(PyObject
*self
, PyObject
*args
)
624 struct security_ace
*ace
= pytalloc_get_ptr(self
);
625 PyObject
*py_sid
= Py_None
;
626 struct dom_sid
*sid
= NULL
;
628 PyObject
*ret
= Py_None
;
630 if (!PyArg_ParseTuple(args
, "O!", &dom_sid_Type
, &py_sid
))
633 if (!PyObject_TypeCheck(py_sid
, &dom_sid_Type
)) {
634 PyErr_SetString(PyExc_TypeError
,
635 "expected security.dom_sid "
636 "for second argument to .sddl_encode_ace");
640 sid
= pytalloc_get_ptr(py_sid
);
642 text
= sddl_encode_ace(NULL
, ace
, sid
);
646 ret
= PyUnicode_FromString(text
);
652 static PyMethodDef py_security_ace_extra_methods
[] = {
653 { "as_sddl", (PyCFunction
)py_security_ace_as_sddl
, METH_VARARGS
, NULL
},
657 #define PY_ACE_PATCH py_security_ace_patch
659 static void py_security_ace_patch(PyTypeObject
*type
)
661 type
->tp_richcompare
= py_security_ace_equal
;
662 PyType_AddMethods(type
, py_security_ace_extra_methods
);