Line data Source code
1 : /*
2 : Unix SMB/CIFS implementation.
3 : Copyright (C) Luke Morrison <luc785@hotmail.com> 2013
4 :
5 : This program is free software; you can redistribute it and/or modify
6 : it under the terms of the GNU General Public License as published by
7 : the Free Software Foundation; either version 3 of the License, or
8 : (at your option) any later version.
9 :
10 : This program is distributed in the hope that it will be useful,
11 : but WITHOUT ANY WARRANTY; without even the implied warranty of
12 : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 : GNU General Public License for more details.
14 :
15 : You should have received a copy of the GNU General Public License
16 : along with this program. If not, see <http://www.gnu.org/licenses/>.
17 : */
18 :
19 : #include "lib/replace/system/python.h"
20 : #include "includes.h"
21 : #include "version.h"
22 : #include "param/pyparam.h"
23 : #include "gpo.h"
24 : #include "ads.h"
25 : #include "secrets.h"
26 : #include "../libds/common/flags.h"
27 : #include "librpc/rpc/pyrpc_util.h"
28 : #include "auth/credentials/pycredentials.h"
29 : #include "libcli/util/pyerrors.h"
30 : #include "python/py3compat.h"
31 : #include "python/modules.h"
32 : #include <pytalloc.h>
33 : #include "../libcli/security/security.h"
34 :
35 : /* A Python C API module to use LIBGPO */
36 :
37 : #define GPO_getter(ATTR) \
38 : static PyObject* GPO_get_##ATTR(PyObject *self, void *closure) \
39 : { \
40 : struct GROUP_POLICY_OBJECT *gpo_ptr \
41 : = pytalloc_get_ptr(self); \
42 : \
43 : if (gpo_ptr->ATTR) \
44 : return PyUnicode_FromString(gpo_ptr->ATTR); \
45 : else \
46 : Py_RETURN_NONE; \
47 : }
48 8 : GPO_getter(ds_path)
49 9530 : GPO_getter(file_sys_path)
50 420 : GPO_getter(display_name)
51 1112 : GPO_getter(name)
52 0 : GPO_getter(link)
53 0 : GPO_getter(user_extensions)
54 0 : GPO_getter(machine_extensions)
55 : #define GPO_setter(ATTR) \
56 : static int GPO_set_##ATTR(PyObject *self, PyObject *val, void *closure) \
57 : { \
58 : struct GROUP_POLICY_OBJECT *gpo_ptr \
59 : = pytalloc_get_ptr(self); \
60 : \
61 : if (!PyUnicode_Check(val)) { \
62 : PyErr_Format(PyExc_TypeError, \
63 : "Cannot convert input to string"); \
64 : return -1; \
65 : } \
66 : if (val != Py_None) { \
67 : gpo_ptr->ATTR = talloc_strdup(gpo_ptr, \
68 : _PyUnicode_AsString(val)); \
69 : } else { \
70 : gpo_ptr->ATTR = NULL; \
71 : } \
72 : return 0; \
73 : }
74 304 : GPO_setter(ds_path)
75 304 : GPO_setter(file_sys_path)
76 304 : GPO_setter(display_name)
77 304 : GPO_setter(name)
78 304 : GPO_setter(link)
79 154 : GPO_setter(user_extensions)
80 304 : GPO_setter(machine_extensions)
81 : #define GPO_int_getter(ATTR) \
82 : static PyObject* GPO_get_##ATTR(PyObject *self, void *closure) \
83 : { \
84 : struct GROUP_POLICY_OBJECT *gpo_ptr \
85 : = pytalloc_get_ptr(self); \
86 : \
87 : return PyLong_FromLong(gpo_ptr->ATTR); \
88 : }
89 0 : GPO_int_getter(options)
90 0 : GPO_int_getter(version)
91 0 : GPO_int_getter(link_type)
92 : #define GPO_int_setter(ATTR) \
93 : static int GPO_set_##ATTR(PyObject *self, PyObject *val, void *closure) \
94 : { \
95 : struct GROUP_POLICY_OBJECT *gpo_ptr \
96 : = pytalloc_get_ptr(self); \
97 : \
98 : if (!PyLong_Check(val)) { \
99 : PyErr_Format(PyExc_TypeError, \
100 : "Cannot convert input to int"); \
101 : return -1; \
102 : } else { \
103 : gpo_ptr->ATTR = PyLong_AsLong(val); \
104 : } \
105 : return 0; \
106 : }
107 304 : GPO_int_setter(options)
108 304 : GPO_int_setter(version)
109 304 : GPO_int_setter(link_type)
110 :
111 304 : static PyObject *GPO_marshall_get_sec_desc_buf(PyObject *self, PyObject *args,
112 : PyObject *kwds)
113 : {
114 304 : struct GROUP_POLICY_OBJECT *gpo_ptr = pytalloc_get_ptr(self);
115 0 : NTSTATUS status;
116 304 : uint8_t *data = NULL;
117 304 : size_t len = 0;
118 :
119 304 : status = marshall_sec_desc(gpo_ptr, gpo_ptr->security_descriptor,
120 : &data, &len);
121 304 : if (!NT_STATUS_IS_OK(status)) {
122 0 : PyErr_Format(PyExc_BufferError,
123 : "marshall_sec_desc_buf failed: %s",
124 : nt_errstr(status));
125 0 : return NULL;
126 : }
127 :
128 304 : return PyBytes_FromStringAndSize((char *)data, len);
129 : }
130 :
131 304 : static PyObject *GPO_unmarshall_set_sec_desc(PyObject *self, PyObject *args,
132 : PyObject *kwds)
133 : {
134 304 : struct GROUP_POLICY_OBJECT *gpo_ptr = pytalloc_get_ptr(self);
135 304 : char *bytes = NULL;
136 304 : size_t length = 0;
137 0 : NTSTATUS status;
138 :
139 304 : if (!PyArg_ParseTuple(args, "s#", &bytes, &length)) {
140 0 : PyErr_Format(PyExc_TypeError,
141 : "Cannot convert input to bytes");
142 0 : return NULL;
143 : }
144 :
145 304 : gpo_ptr->security_descriptor = talloc_zero(gpo_ptr,
146 : struct security_descriptor);
147 304 : status = unmarshall_sec_desc(gpo_ptr, (uint8_t *)bytes, length,
148 : &gpo_ptr->security_descriptor);
149 304 : if (!NT_STATUS_IS_OK(status)) {
150 0 : PyErr_Format(PyExc_BufferError,
151 : "unmarshall_sec_desc failed: %s",
152 : nt_errstr(status));
153 0 : return NULL;
154 : }
155 :
156 304 : return Py_None;
157 : }
158 :
159 : static PyGetSetDef GPO_setters[] = {
160 : {discard_const_p(char, "options"), (getter)GPO_get_options,
161 : (setter)GPO_set_options, NULL, NULL},
162 : {discard_const_p(char, "version"), (getter)GPO_get_version,
163 : (setter)GPO_set_version, NULL, NULL},
164 : {discard_const_p(char, "ds_path"), (getter)GPO_get_ds_path,
165 : (setter)GPO_set_ds_path, NULL, NULL},
166 : {discard_const_p(char, "file_sys_path"), (getter)GPO_get_file_sys_path,
167 : (setter)GPO_set_file_sys_path, NULL, NULL},
168 : {discard_const_p(char, "display_name"), (getter)GPO_get_display_name,
169 : (setter)GPO_set_display_name, NULL, NULL},
170 : {discard_const_p(char, "name"), (getter)GPO_get_name,
171 : (setter)GPO_set_name, NULL, NULL},
172 : {discard_const_p(char, "link"), (getter)GPO_get_link,
173 : (setter)GPO_set_link, NULL, NULL},
174 : {discard_const_p(char, "link_type"), (getter)GPO_get_link_type,
175 : (setter)GPO_set_link_type, NULL, NULL},
176 : {discard_const_p(char, "user_extensions"),
177 : (getter)GPO_get_user_extensions,
178 : (setter)GPO_set_user_extensions, NULL, NULL},
179 : {discard_const_p(char, "machine_extensions"),
180 : (getter)GPO_get_machine_extensions,
181 : (setter)GPO_set_machine_extensions, NULL, NULL},
182 : {0}
183 : };
184 :
185 0 : static PyObject *py_gpo_get_unix_path(PyObject *self, PyObject *args,
186 : PyObject *kwds)
187 : {
188 0 : NTSTATUS status;
189 0 : const char *cache_dir = NULL;
190 0 : PyObject *ret = NULL;
191 0 : char *unix_path = NULL;
192 0 : TALLOC_CTX *frame = NULL;
193 0 : static const char *kwlist[] = {"cache_dir", NULL};
194 0 : struct GROUP_POLICY_OBJECT *gpo_ptr \
195 0 : = (struct GROUP_POLICY_OBJECT *)pytalloc_get_ptr(self);
196 :
197 0 : frame = talloc_stackframe();
198 :
199 0 : if (!PyArg_ParseTupleAndKeywords(args, kwds, "|s",
200 : discard_const_p(char *, kwlist),
201 : &cache_dir)) {
202 0 : goto out;
203 : }
204 :
205 0 : if (!cache_dir) {
206 0 : cache_dir = cache_path(talloc_tos(), GPO_CACHE_DIR);
207 0 : if (!cache_dir) {
208 0 : PyErr_SetString(PyExc_MemoryError,
209 : "Failed to determine gpo cache dir");
210 0 : goto out;
211 : }
212 : }
213 :
214 0 : status = gpo_get_unix_path(frame, cache_dir, gpo_ptr, &unix_path);
215 :
216 0 : if (!NT_STATUS_IS_OK(status)) {
217 0 : PyErr_Format(PyExc_RuntimeError,
218 : "Failed to determine gpo unix path: %s",
219 : get_friendly_nt_error_msg(status));
220 0 : goto out;
221 : }
222 :
223 0 : ret = PyUnicode_FromString(unix_path);
224 :
225 0 : out:
226 0 : TALLOC_FREE(frame);
227 0 : return ret;
228 : }
229 :
230 : static PyMethodDef GPO_methods[] = {
231 : {"get_unix_path", PY_DISCARD_FUNC_SIG(PyCFunction,
232 : py_gpo_get_unix_path),
233 : METH_VARARGS | METH_KEYWORDS,
234 : NULL },
235 : {"set_sec_desc", PY_DISCARD_FUNC_SIG(PyCFunction,
236 : GPO_unmarshall_set_sec_desc),
237 : METH_VARARGS, NULL },
238 : {"get_sec_desc_buf", PY_DISCARD_FUNC_SIG(PyCFunction,
239 : GPO_marshall_get_sec_desc_buf),
240 : METH_NOARGS, NULL },
241 : {0}
242 : };
243 :
244 458 : static int py_gpo_init(PyObject *self, PyObject *args, PyObject *kwds)
245 : {
246 458 : struct GROUP_POLICY_OBJECT *gpo_ptr = pytalloc_get_ptr(self);
247 458 : const char *name = NULL;
248 458 : const char *display_name = NULL;
249 458 : enum GPO_LINK_TYPE link_type = GP_LINK_UNKOWN;
250 458 : const char *file_sys_path = NULL;
251 :
252 0 : static const char *kwlist[] = {
253 : "name", "display_name", "link_type", "file_sys_path", NULL
254 : };
255 458 : if (!PyArg_ParseTupleAndKeywords(args, kwds, "|ssIs",
256 : discard_const_p(char *, kwlist),
257 : &name, &display_name, &link_type,
258 : &file_sys_path)) {
259 0 : return -1;
260 : }
261 :
262 458 : if (name) {
263 154 : gpo_ptr->name = talloc_strdup(gpo_ptr, name);
264 : }
265 458 : if (display_name) {
266 154 : gpo_ptr->display_name = talloc_strdup(gpo_ptr, display_name);
267 : }
268 458 : gpo_ptr->link_type = link_type;
269 458 : if (file_sys_path) {
270 0 : gpo_ptr->file_sys_path = talloc_strdup(gpo_ptr, file_sys_path);
271 : }
272 :
273 458 : return 0;
274 : }
275 :
276 458 : static PyObject *py_gpo_new(PyTypeObject *type, PyObject *args, PyObject *kwargs)
277 : {
278 458 : return pytalloc_new(struct GROUP_POLICY_OBJECT, type);
279 : }
280 :
281 : static PyTypeObject GPOType = {
282 : PyVarObject_HEAD_INIT(NULL, 0)
283 : .tp_name = "gpo.GROUP_POLICY_OBJECT",
284 : .tp_doc = "GROUP_POLICY_OBJECT",
285 : .tp_getset = GPO_setters,
286 : .tp_methods = GPO_methods,
287 : .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
288 : .tp_new = py_gpo_new,
289 : .tp_init = (initproc)py_gpo_init,
290 : };
291 :
292 : typedef struct {
293 : PyObject_HEAD
294 : ADS_STRUCT *ads_ptr;
295 : PyObject *py_creds;
296 : struct cli_credentials *cli_creds;
297 : } ADS;
298 :
299 2 : static void py_ads_dealloc(ADS* self)
300 : {
301 2 : TALLOC_FREE(self->ads_ptr);
302 2 : Py_CLEAR(self->py_creds);
303 2 : Py_TYPE(self)->tp_free((PyObject*)self);
304 2 : }
305 :
306 : static PyObject* py_ads_connect(ADS *self, PyObject *Py_UNUSED(ignored));
307 2 : static int py_ads_init(ADS *self, PyObject *args, PyObject *kwds)
308 : {
309 2 : const char *realm = NULL;
310 2 : const char *workgroup = NULL;
311 2 : const char *ldap_server = NULL;
312 2 : PyObject *lp_obj = NULL;
313 2 : PyObject *py_creds = NULL;
314 2 : struct loadparm_context *lp_ctx = NULL;
315 2 : bool ok = false;
316 :
317 0 : static const char *kwlist[] = {
318 : "ldap_server", "loadparm_context", "credentials", NULL
319 : };
320 2 : if (!PyArg_ParseTupleAndKeywords(args, kwds, "sO|O",
321 : discard_const_p(char *, kwlist),
322 : &ldap_server, &lp_obj, &py_creds)) {
323 0 : return -1;
324 : }
325 : /* keep reference to the credentials. Clear any earlier ones */
326 2 : Py_CLEAR(self->py_creds);
327 2 : self->cli_creds = NULL;
328 2 : self->py_creds = py_creds;
329 2 : Py_XINCREF(self->py_creds);
330 :
331 2 : if (self->py_creds) {
332 2 : ok = py_check_dcerpc_type(self->py_creds, "samba.credentials",
333 : "Credentials");
334 2 : if (!ok) {
335 0 : return -1;
336 : }
337 0 : self->cli_creds
338 2 : = PyCredentials_AsCliCredentials(self->py_creds);
339 : }
340 :
341 2 : ok = py_check_dcerpc_type(lp_obj, "samba.param", "LoadParm");
342 2 : if (!ok) {
343 0 : return -1;
344 : }
345 2 : lp_ctx = pytalloc_get_type(lp_obj, struct loadparm_context);
346 2 : if (lp_ctx == NULL) {
347 0 : return -1;
348 : }
349 2 : ok = lp_load_initial_only(lp_ctx->szConfigFile);
350 2 : if (!ok) {
351 0 : PyErr_Format(PyExc_RuntimeError, "Could not load config file '%s'",
352 : lp_ctx->szConfigFile);
353 0 : return -1;
354 : }
355 :
356 2 : if (self->cli_creds) {
357 2 : realm = cli_credentials_get_realm(self->cli_creds);
358 2 : workgroup = cli_credentials_get_domain(self->cli_creds);
359 : } else {
360 0 : realm = lp_realm();
361 0 : workgroup = lp_workgroup();
362 : }
363 :
364 : /* in case __init__ is called more than once */
365 2 : if (self->ads_ptr) {
366 0 : TALLOC_FREE(self->ads_ptr);
367 : }
368 : /* always succeeds or crashes */
369 2 : self->ads_ptr = ads_init(pytalloc_get_mem_ctx(args),
370 : realm,
371 : workgroup,
372 : ldap_server,
373 : ADS_SASL_PLAIN);
374 :
375 2 : return 0;
376 : }
377 :
378 : /* connect. Failure to connect results in an Exception */
379 2 : static PyObject* py_ads_connect(ADS *self,
380 : PyObject *Py_UNUSED(ignored))
381 : {
382 0 : ADS_STATUS status;
383 2 : TALLOC_CTX *frame = talloc_stackframe();
384 2 : if (!self->ads_ptr) {
385 0 : PyErr_SetString(PyExc_RuntimeError, "Uninitialized");
386 0 : return NULL;
387 : }
388 2 : ADS_TALLOC_CONST_FREE(self->ads_ptr->auth.user_name);
389 2 : ADS_TALLOC_CONST_FREE(self->ads_ptr->auth.password);
390 2 : ADS_TALLOC_CONST_FREE(self->ads_ptr->auth.realm);
391 2 : if (self->cli_creds) {
392 2 : self->ads_ptr->auth.user_name = talloc_strdup(self->ads_ptr,
393 : cli_credentials_get_username(self->cli_creds));
394 2 : if (self->ads_ptr->auth.user_name == NULL) {
395 0 : PyErr_NoMemory();
396 0 : goto err;
397 : }
398 2 : self->ads_ptr->auth.password = talloc_strdup(self->ads_ptr,
399 : cli_credentials_get_password(self->cli_creds));
400 2 : if (self->ads_ptr->auth.password == NULL) {
401 0 : PyErr_NoMemory();
402 0 : goto err;
403 : }
404 2 : self->ads_ptr->auth.realm = talloc_strdup(self->ads_ptr,
405 : cli_credentials_get_realm(self->cli_creds));
406 2 : if (self->ads_ptr->auth.realm == NULL) {
407 0 : PyErr_NoMemory();
408 0 : goto err;
409 : }
410 2 : self->ads_ptr->auth.flags |= ADS_AUTH_USER_CREDS;
411 2 : status = ads_connect_user_creds(self->ads_ptr);
412 : } else {
413 0 : char *passwd = NULL;
414 :
415 0 : if (!secrets_init()) {
416 0 : PyErr_SetString(PyExc_RuntimeError,
417 : "secrets_init() failed");
418 0 : goto err;
419 : }
420 :
421 0 : self->ads_ptr->auth.user_name = talloc_asprintf(self->ads_ptr,
422 : "%s$",
423 : lp_netbios_name());
424 0 : if (self->ads_ptr->auth.user_name == NULL) {
425 0 : PyErr_NoMemory();
426 0 : goto err;
427 : }
428 :
429 0 : passwd = secrets_fetch_machine_password(
430 0 : self->ads_ptr->server.workgroup, NULL, NULL);
431 0 : if (passwd == NULL) {
432 0 : PyErr_SetString(PyExc_RuntimeError,
433 : "Failed to fetch the machine account "
434 : "password");
435 0 : goto err;
436 : }
437 :
438 0 : self->ads_ptr->auth.password = talloc_strdup(self->ads_ptr,
439 : passwd);
440 0 : SAFE_FREE(passwd);
441 0 : if (self->ads_ptr->auth.password == NULL) {
442 0 : PyErr_NoMemory();
443 0 : goto err;
444 : }
445 0 : self->ads_ptr->auth.realm = talloc_asprintf_strupper_m(
446 0 : self->ads_ptr, "%s", self->ads_ptr->server.realm);
447 0 : if (self->ads_ptr->auth.realm == NULL) {
448 0 : PyErr_NoMemory();
449 0 : goto err;
450 : }
451 0 : self->ads_ptr->auth.flags |= ADS_AUTH_USER_CREDS;
452 0 : status = ads_connect(self->ads_ptr);
453 : }
454 2 : if (!ADS_ERR_OK(status)) {
455 0 : PyErr_Format(PyExc_RuntimeError,
456 : "ads_connect() failed: %s",
457 : ads_errstr(status));
458 0 : goto err;
459 : }
460 :
461 2 : TALLOC_FREE(frame);
462 2 : Py_RETURN_TRUE;
463 :
464 0 : err:
465 0 : TALLOC_FREE(frame);
466 0 : return NULL;
467 : }
468 :
469 : /* Parameter mapping and functions for the GP_EXT struct */
470 : void initgpo(void);
471 :
472 : /* Global methods aka do not need a special pyobject type */
473 46 : static PyObject *py_gpo_get_sysvol_gpt_version(PyObject * self,
474 : PyObject * args)
475 : {
476 46 : TALLOC_CTX *tmp_ctx = NULL;
477 0 : char *unix_path;
478 46 : char *display_name = NULL;
479 46 : uint32_t sysvol_version = 0;
480 0 : PyObject *result;
481 0 : NTSTATUS status;
482 :
483 46 : if (!PyArg_ParseTuple(args, "s", &unix_path)) {
484 0 : return NULL;
485 : }
486 46 : tmp_ctx = talloc_new(NULL);
487 46 : if (!tmp_ctx) {
488 0 : return PyErr_NoMemory();
489 : }
490 46 : status = gpo_get_sysvol_gpt_version(tmp_ctx, unix_path,
491 : &sysvol_version,
492 : &display_name);
493 46 : if (!NT_STATUS_IS_OK(status)) {
494 0 : PyErr_SetNTSTATUS(status);
495 0 : TALLOC_FREE(tmp_ctx);
496 0 : return NULL;
497 : }
498 :
499 46 : result = Py_BuildValue("[s,i]", display_name, sysvol_version);
500 46 : talloc_free(tmp_ctx);
501 46 : return result;
502 : }
503 :
504 : #ifdef HAVE_ADS
505 2 : static ADS_STATUS find_samaccount(ADS_STRUCT *ads, TALLOC_CTX *mem_ctx,
506 : const char *samaccountname,
507 : uint32_t *uac_ret, const char **dn_ret)
508 : {
509 0 : ADS_STATUS status;
510 2 : const char *attrs[] = { "userAccountControl", NULL };
511 0 : const char *filter;
512 2 : LDAPMessage *res = NULL;
513 2 : char *dn = NULL;
514 2 : uint32_t uac = 0;
515 :
516 2 : filter = talloc_asprintf(mem_ctx, "(sAMAccountName=%s)",
517 : samaccountname);
518 2 : if (filter == NULL) {
519 0 : status = ADS_ERROR_NT(NT_STATUS_NO_MEMORY);
520 0 : goto out;
521 : }
522 :
523 2 : status = ads_do_search_all(ads, ads->config.bind_path,
524 : LDAP_SCOPE_SUBTREE, filter, attrs, &res);
525 :
526 2 : if (!ADS_ERR_OK(status)) {
527 0 : goto out;
528 : }
529 :
530 2 : if (ads_count_replies(ads, res) != 1) {
531 0 : status = ADS_ERROR(LDAP_NO_RESULTS_RETURNED);
532 0 : goto out;
533 : }
534 :
535 2 : dn = ads_get_dn(ads, talloc_tos(), res);
536 2 : if (dn == NULL) {
537 0 : status = ADS_ERROR(LDAP_NO_MEMORY);
538 0 : goto out;
539 : }
540 :
541 2 : if (!ads_pull_uint32(ads, res, "userAccountControl", &uac)) {
542 0 : status = ADS_ERROR(LDAP_NO_SUCH_ATTRIBUTE);
543 0 : goto out;
544 : }
545 :
546 2 : if (uac_ret) {
547 2 : *uac_ret = uac;
548 : }
549 :
550 2 : if (dn_ret) {
551 2 : *dn_ret = talloc_strdup(mem_ctx, dn);
552 2 : if (*dn_ret == NULL) {
553 0 : status = ADS_ERROR(LDAP_NO_MEMORY);
554 0 : goto out;
555 : }
556 : }
557 2 : out:
558 2 : TALLOC_FREE(dn);
559 2 : ads_msgfree(ads, res);
560 :
561 2 : return status;
562 : }
563 :
564 2 : static PyObject *py_ads_get_gpo_list(ADS *self, PyObject *args, PyObject *kwds)
565 : {
566 2 : TALLOC_CTX *frame = NULL;
567 2 : struct GROUP_POLICY_OBJECT *gpo = NULL, *gpo_list = NULL;
568 0 : ADS_STATUS status;
569 2 : const char *samaccountname = NULL;
570 2 : const char *dn = NULL;
571 2 : uint32_t uac = 0;
572 2 : uint32_t flags = 0;
573 2 : struct security_token *token = NULL;
574 2 : PyObject *ret = NULL;
575 2 : TALLOC_CTX *gpo_ctx = NULL;
576 0 : size_t list_size;
577 0 : size_t i;
578 :
579 0 : static const char *kwlist[] = {"samaccountname", NULL};
580 :
581 2 : PyErr_WarnEx(PyExc_DeprecationWarning, "The get_gpo_list function"
582 : " is deprecated as of Samba 4.19. Please use "
583 : "the samba.gp module instead.", 2);
584 :
585 2 : if (!PyArg_ParseTupleAndKeywords(args, kwds, "s",
586 : discard_const_p(char *, kwlist),
587 : &samaccountname)) {
588 0 : return NULL;
589 : }
590 2 : if (!self->ads_ptr) {
591 0 : PyErr_SetString(PyExc_RuntimeError, "Uninitialized");
592 0 : return NULL;
593 : }
594 :
595 2 : frame = talloc_stackframe();
596 :
597 2 : status = find_samaccount(self->ads_ptr, frame,
598 : samaccountname, &uac, &dn);
599 2 : if (!ADS_ERR_OK(status)) {
600 0 : PyErr_Format(PyExc_RuntimeError,
601 : "Failed to find samAccountName '%s': %s",
602 : samaccountname, ads_errstr(status));
603 0 : goto out;
604 : }
605 :
606 2 : if (uac & UF_WORKSTATION_TRUST_ACCOUNT ||
607 2 : uac & UF_SERVER_TRUST_ACCOUNT) {
608 2 : flags |= GPO_LIST_FLAG_MACHINE;
609 2 : status = gp_get_machine_token(self->ads_ptr, frame, dn,
610 : &token);
611 2 : if (!ADS_ERR_OK(status)) {
612 0 : PyErr_Format(PyExc_RuntimeError,
613 : "Failed to get machine token for '%s'(%s): %s",
614 : samaccountname, dn, ads_errstr(status));
615 0 : goto out;
616 : }
617 : } else {
618 0 : status = ads_get_sid_token(self->ads_ptr, frame, dn, &token);
619 0 : if (!ADS_ERR_OK(status)) {
620 0 : PyErr_Format(PyExc_RuntimeError,
621 : "Failed to get sid token for '%s'(%s): %s",
622 : samaccountname, dn, ads_errstr(status));
623 0 : goto out;
624 : }
625 : }
626 :
627 2 : gpo_ctx = talloc_new(frame);
628 2 : if (!gpo_ctx) {
629 0 : PyErr_NoMemory();
630 0 : goto out;
631 : }
632 2 : status = ads_get_gpo_list(self->ads_ptr, gpo_ctx, dn, flags, token,
633 : &gpo_list);
634 2 : if (!ADS_ERR_OK(status)) {
635 0 : PyErr_Format(PyExc_RuntimeError,
636 : "Failed to fetch GPO list: %s",
637 : ads_errstr(status));
638 0 : goto out;
639 : }
640 :
641 : /* Convert the C linked list into a python list */
642 2 : list_size = 0;
643 8 : for (gpo = gpo_list; gpo != NULL; gpo = gpo->next) {
644 6 : list_size++;
645 : }
646 :
647 2 : i = 0;
648 2 : ret = PyList_New(list_size);
649 2 : if (ret == NULL) {
650 0 : goto out;
651 : }
652 :
653 8 : for (gpo = gpo_list; gpo != NULL; gpo = gpo->next) {
654 6 : PyObject *obj = pytalloc_reference_ex(&GPOType,
655 : gpo_ctx, gpo);
656 6 : if (obj == NULL) {
657 0 : Py_CLEAR(ret);
658 0 : goto out;
659 : }
660 :
661 6 : PyList_SetItem(ret, i, obj);
662 6 : i++;
663 : }
664 :
665 2 : out:
666 2 : TALLOC_FREE(frame);
667 2 : return ret;
668 : }
669 :
670 : #endif
671 :
672 : static PyMethodDef ADS_methods[] = {
673 : { "connect", (PyCFunction)py_ads_connect, METH_NOARGS,
674 : "Connect to the LDAP server" },
675 : #ifdef HAVE_ADS
676 : { "get_gpo_list", PY_DISCARD_FUNC_SIG(PyCFunction, py_ads_get_gpo_list),
677 : METH_VARARGS | METH_KEYWORDS,
678 : NULL },
679 : #endif
680 : {0}
681 : };
682 :
683 : static PyTypeObject ads_ADSType = {
684 : .tp_name = "gpo.ADS_STRUCT",
685 : .tp_basicsize = sizeof(ADS),
686 : .tp_new = PyType_GenericNew,
687 : .tp_dealloc = (destructor)py_ads_dealloc,
688 : .tp_flags = Py_TPFLAGS_DEFAULT,
689 : .tp_doc = "ADS struct",
690 : .tp_methods = ADS_methods,
691 : .tp_init = (initproc)py_ads_init,
692 : };
693 :
694 : static PyMethodDef py_gpo_methods[] = {
695 : {"gpo_get_sysvol_gpt_version",
696 : (PyCFunction)py_gpo_get_sysvol_gpt_version,
697 : METH_VARARGS, NULL},
698 : {0}
699 : };
700 :
701 : static struct PyModuleDef moduledef = {
702 : PyModuleDef_HEAD_INIT,
703 : .m_name = "gpo",
704 : .m_doc = "libgpo python bindings",
705 : .m_size = -1,
706 : .m_methods = py_gpo_methods,
707 : };
708 :
709 : /* Will be called by python when loading this module */
710 : void initgpo(void);
711 :
712 338 : MODULE_INIT_FUNC(gpo)
713 : {
714 1 : PyObject *m;
715 :
716 338 : debug_setup_talloc_log();
717 :
718 : /* Instantiate the types */
719 338 : m = PyModule_Create(&moduledef);
720 338 : if (m == NULL) {
721 0 : goto err;
722 : }
723 :
724 338 : if (PyModule_AddObject(m, "version",
725 : PyUnicode_FromString(SAMBA_VERSION_STRING)) ) {
726 0 : goto err;
727 : }
728 :
729 338 : if (pytalloc_BaseObject_PyType_Ready(&ads_ADSType) < 0) {
730 0 : goto err;
731 : }
732 :
733 283 : Py_INCREF(&ads_ADSType);
734 338 : if (PyModule_AddObject(m, "ADS_STRUCT", (PyObject *)&ads_ADSType)) {
735 0 : goto err;
736 : }
737 :
738 338 : if (pytalloc_BaseObject_PyType_Ready(&GPOType) < 0) {
739 0 : goto err;
740 : }
741 :
742 283 : Py_INCREF((PyObject *)(void *)&GPOType);
743 338 : if (PyModule_AddObject(m, "GROUP_POLICY_OBJECT",
744 : (PyObject *)&GPOType)) {
745 0 : goto err;
746 : }
747 :
748 : #define ADD_FLAGS(val) PyModule_AddObject(m, #val, PyLong_FromLong(val))
749 :
750 338 : ADD_FLAGS(GP_LINK_UNKOWN);
751 338 : ADD_FLAGS(GP_LINK_MACHINE);
752 338 : ADD_FLAGS(GP_LINK_SITE);
753 338 : ADD_FLAGS(GP_LINK_DOMAIN);
754 338 : ADD_FLAGS(GP_LINK_OU);
755 338 : ADD_FLAGS(GP_LINK_LOCAL);
756 :
757 338 : return m;
758 :
759 0 : err:
760 0 : Py_CLEAR(m);
761 0 : return NULL;
762 : }
|