LCOV - code coverage report
Current view: top level - libgpo - pygpo.c (source / functions) Hit Total Coverage
Test: coverage report for fix-15632 9995c5c2 Lines: 190 334 56.9 %
Date: 2024-04-13 12:30:31 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        9326 : GPO_getter(file_sys_path)
      50         410 : GPO_getter(display_name)
      51        1102 : 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         296 : GPO_setter(ds_path)
      75         296 : GPO_setter(file_sys_path)
      76         296 : GPO_setter(display_name)
      77         296 : GPO_setter(name)
      78         296 : GPO_setter(link)
      79         150 : GPO_setter(user_extensions)
      80         296 : 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         296 : GPO_int_setter(options)
     108         296 : GPO_int_setter(version)
     109         296 : GPO_int_setter(link_type)
     110             : 
     111         296 : static PyObject *GPO_marshall_get_sec_desc_buf(PyObject *self, PyObject *args,
     112             :                                                PyObject *kwds)
     113             : {
     114         296 :         struct GROUP_POLICY_OBJECT *gpo_ptr = pytalloc_get_ptr(self);
     115           0 :         NTSTATUS status;
     116         296 :         uint8_t *data = NULL;
     117         296 :         size_t len = 0;
     118             : 
     119         296 :         status = marshall_sec_desc(gpo_ptr, gpo_ptr->security_descriptor,
     120             :                                    &data, &len);
     121         296 :         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         296 :         return PyBytes_FromStringAndSize((char *)data, len);
     129             : }
     130             : 
     131         296 : static PyObject *GPO_unmarshall_set_sec_desc(PyObject *self, PyObject *args,
     132             :                                              PyObject *kwds)
     133             : {
     134         296 :         struct GROUP_POLICY_OBJECT *gpo_ptr = pytalloc_get_ptr(self);
     135         296 :         char *bytes = NULL;
     136         296 :         size_t length = 0;
     137           0 :         NTSTATUS status;
     138             : 
     139         296 :         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         296 :         gpo_ptr->security_descriptor = talloc_zero(gpo_ptr,
     146             :                                                    struct security_descriptor);
     147         296 :         status = unmarshall_sec_desc(gpo_ptr, (uint8_t *)bytes, length,
     148             :                                      &gpo_ptr->security_descriptor);
     149         296 :         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         296 :         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         446 : static int py_gpo_init(PyObject *self, PyObject *args, PyObject *kwds)
     245             : {
     246         446 :         struct GROUP_POLICY_OBJECT *gpo_ptr = pytalloc_get_ptr(self);
     247         446 :         const char *name = NULL;
     248         446 :         const char *display_name = NULL;
     249         446 :         enum GPO_LINK_TYPE link_type = GP_LINK_UNKOWN;
     250         446 :         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         446 :         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         446 :         if (name) {
     263         150 :                 gpo_ptr->name = talloc_strdup(gpo_ptr, name);
     264             :         }
     265         446 :         if (display_name) {
     266         150 :                 gpo_ptr->display_name = talloc_strdup(gpo_ptr, display_name);
     267             :         }
     268         446 :         gpo_ptr->link_type = link_type;
     269         446 :         if (file_sys_path) {
     270           0 :                 gpo_ptr->file_sys_path = talloc_strdup(gpo_ptr, file_sys_path);
     271             :         }
     272             : 
     273         446 :         return 0;
     274             : }
     275             : 
     276         446 : static PyObject *py_gpo_new(PyTypeObject *type, PyObject *args, PyObject *kwargs)
     277             : {
     278         446 :         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         336 : MODULE_INIT_FUNC(gpo)
     713             : {
     714           1 :         PyObject *m;
     715             : 
     716         336 :         debug_setup_talloc_log();
     717             : 
     718             :         /* Instantiate the types */
     719         336 :         m = PyModule_Create(&moduledef);
     720         336 :         if (m == NULL) {
     721           0 :                 goto err;
     722             :         }
     723             : 
     724         336 :         if (PyModule_AddObject(m, "version",
     725             :                            PyUnicode_FromString(SAMBA_VERSION_STRING)) ) {
     726           0 :                 goto err;
     727             :         }
     728             : 
     729         336 :         if (pytalloc_BaseObject_PyType_Ready(&ads_ADSType) < 0) {
     730           0 :                 goto err;
     731             :         }
     732             : 
     733         282 :         Py_INCREF(&ads_ADSType);
     734         336 :         if (PyModule_AddObject(m, "ADS_STRUCT", (PyObject *)&ads_ADSType)) {
     735           0 :                 goto err;
     736             :         }
     737             : 
     738         336 :         if (pytalloc_BaseObject_PyType_Ready(&GPOType) < 0) {
     739           0 :                 goto err;
     740             :         }
     741             : 
     742         282 :         Py_INCREF((PyObject *)(void *)&GPOType);
     743         336 :         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         336 :         ADD_FLAGS(GP_LINK_UNKOWN);
     751         336 :         ADD_FLAGS(GP_LINK_MACHINE);
     752         336 :         ADD_FLAGS(GP_LINK_SITE);
     753         336 :         ADD_FLAGS(GP_LINK_DOMAIN);
     754         336 :         ADD_FLAGS(GP_LINK_OU);
     755         336 :         ADD_FLAGS(GP_LINK_LOCAL);
     756             : 
     757         336 :         return m;
     758             : 
     759           0 : err:
     760           0 :         Py_CLEAR(m);
     761           0 :         return NULL;
     762             : }

Generated by: LCOV version 1.14