LCOV - code coverage report
Current view: top level - libgpo - pygpo.c (source / functions) Hit Total Coverage
Test: coverage report for master 2f515e9b Lines: 191 337 56.7 %
Date: 2024-04-21 15:09:00 Functions: 25 32 78.1 %

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

Generated by: LCOV version 1.14