LCOV - code coverage report
Current view: top level - libgpo - pygpo.c (source / functions) Hit Total Coverage
Test: coverage report for master 98b443d9 Lines: 181 300 60.3 %
Date: 2024-05-31 13:13:24 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 :         if (self->cli_creds) {
     394           2 :                 status = ads_connect_creds(self->ads_ptr, self->cli_creds);
     395           2 :                 if (!ADS_ERR_OK(status)) {
     396           0 :                         PyErr_Format(PyExc_RuntimeError,
     397             :                                         "ads_connect_creds() failed: %s",
     398             :                                         ads_errstr(status));
     399           0 :                         goto err;
     400             :                 }
     401             :         } else {
     402           0 :                 status = ads_connect_machine(self->ads_ptr);
     403           0 :                 if (!ADS_ERR_OK(status)) {
     404           0 :                         PyErr_Format(PyExc_RuntimeError,
     405             :                                         "ads_connect_machine() failed: %s",
     406             :                                         ads_errstr(status));
     407           0 :                         goto err;
     408             :                 }
     409             :         }
     410             : 
     411           2 :         TALLOC_FREE(frame);
     412           2 :         Py_RETURN_TRUE;
     413             : 
     414           0 : err:
     415           0 :         TALLOC_FREE(frame);
     416           0 :         return NULL;
     417             : }
     418             : 
     419             : /* Parameter mapping and functions for the GP_EXT struct */
     420             : void initgpo(void);
     421             : 
     422             : /* Global methods aka do not need a special pyobject type */
     423          46 : static PyObject *py_gpo_get_sysvol_gpt_version(PyObject * self,
     424             :                                                PyObject * args)
     425             : {
     426          46 :         TALLOC_CTX *tmp_ctx = NULL;
     427           0 :         char *unix_path;
     428          46 :         char *display_name = NULL;
     429          46 :         uint32_t sysvol_version = 0;
     430           0 :         PyObject *result;
     431           0 :         NTSTATUS status;
     432             : 
     433          46 :         if (!PyArg_ParseTuple(args, "s", &unix_path)) {
     434           0 :                 return NULL;
     435             :         }
     436          46 :         tmp_ctx = talloc_new(NULL);
     437          46 :         if (!tmp_ctx) {
     438           0 :                 return PyErr_NoMemory();
     439             :         }
     440          46 :         status = gpo_get_sysvol_gpt_version(tmp_ctx, unix_path,
     441             :                                             &sysvol_version,
     442             :                                             &display_name);
     443          46 :         if (!NT_STATUS_IS_OK(status)) {
     444           0 :                 PyErr_SetNTSTATUS(status);
     445           0 :                 TALLOC_FREE(tmp_ctx);
     446           0 :                 return NULL;
     447             :         }
     448             : 
     449          46 :         result = Py_BuildValue("[s,i]", display_name, sysvol_version);
     450          46 :         talloc_free(tmp_ctx);
     451          46 :         return result;
     452             : }
     453             : 
     454             : #ifdef HAVE_ADS
     455           2 : static ADS_STATUS find_samaccount(ADS_STRUCT *ads, TALLOC_CTX *mem_ctx,
     456             :                                   const char *samaccountname,
     457             :                                   uint32_t *uac_ret, const char **dn_ret)
     458             : {
     459           0 :         ADS_STATUS status;
     460           2 :         const char *attrs[] = { "userAccountControl", NULL };
     461           0 :         const char *filter;
     462           2 :         LDAPMessage *res = NULL;
     463           2 :         char *dn = NULL;
     464           2 :         uint32_t uac = 0;
     465             : 
     466           2 :         filter = talloc_asprintf(mem_ctx, "(sAMAccountName=%s)",
     467             :                                  samaccountname);
     468           2 :         if (filter == NULL) {
     469           0 :                 status = ADS_ERROR_NT(NT_STATUS_NO_MEMORY);
     470           0 :                 goto out;
     471             :         }
     472             : 
     473           2 :         status = ads_do_search_all(ads, ads->config.bind_path,
     474             :                                    LDAP_SCOPE_SUBTREE, filter, attrs, &res);
     475             : 
     476           2 :         if (!ADS_ERR_OK(status)) {
     477           0 :                 goto out;
     478             :         }
     479             : 
     480           2 :         if (ads_count_replies(ads, res) != 1) {
     481           0 :                 status = ADS_ERROR(LDAP_NO_RESULTS_RETURNED);
     482           0 :                 goto out;
     483             :         }
     484             : 
     485           2 :         dn = ads_get_dn(ads, talloc_tos(), res);
     486           2 :         if (dn == NULL) {
     487           0 :                 status = ADS_ERROR(LDAP_NO_MEMORY);
     488           0 :                 goto out;
     489             :         }
     490             : 
     491           2 :         if (!ads_pull_uint32(ads, res, "userAccountControl", &uac)) {
     492           0 :                 status = ADS_ERROR(LDAP_NO_SUCH_ATTRIBUTE);
     493           0 :                 goto out;
     494             :         }
     495             : 
     496           2 :         if (uac_ret) {
     497           2 :                 *uac_ret = uac;
     498             :         }
     499             : 
     500           2 :         if (dn_ret) {
     501           2 :                 *dn_ret = talloc_strdup(mem_ctx, dn);
     502           2 :                 if (*dn_ret == NULL) {
     503           0 :                         status = ADS_ERROR(LDAP_NO_MEMORY);
     504           0 :                         goto out;
     505             :                 }
     506             :         }
     507           2 : out:
     508           2 :         TALLOC_FREE(dn);
     509           2 :         ads_msgfree(ads, res);
     510             : 
     511           2 :         return status;
     512             : }
     513             : 
     514           2 : static PyObject *py_ads_get_gpo_list(ADS *self, PyObject *args, PyObject *kwds)
     515             : {
     516           2 :         TALLOC_CTX *frame = NULL;
     517           2 :         struct GROUP_POLICY_OBJECT *gpo = NULL, *gpo_list = NULL;
     518           0 :         ADS_STATUS status;
     519           2 :         const char *samaccountname = NULL;
     520           2 :         const char *dn = NULL;
     521           2 :         uint32_t uac = 0;
     522           2 :         uint32_t flags = 0;
     523           2 :         struct security_token *token = NULL;
     524           2 :         PyObject *ret = NULL;
     525           2 :         TALLOC_CTX *gpo_ctx = NULL;
     526           0 :         size_t list_size;
     527           0 :         size_t i;
     528             : 
     529           0 :         static const char *kwlist[] = {"samaccountname", NULL};
     530             : 
     531           2 :         PyErr_WarnEx(PyExc_DeprecationWarning, "The get_gpo_list function"
     532             :                                 " is deprecated as of Samba 4.19. Please use "
     533             :                                 "the samba.gp module instead.", 2);
     534             : 
     535           2 :         if (!PyArg_ParseTupleAndKeywords(args, kwds, "s",
     536             :                                          discard_const_p(char *, kwlist),
     537             :                                          &samaccountname)) {
     538           0 :                 return NULL;
     539             :         }
     540           2 :         if (!self->ads_ptr) {
     541           0 :                 PyErr_SetString(PyExc_RuntimeError, "Uninitialized");
     542           0 :                 return NULL;
     543             :         }
     544             : 
     545           2 :         frame = talloc_stackframe();
     546             : 
     547           2 :         status = find_samaccount(self->ads_ptr, frame,
     548             :                                  samaccountname, &uac, &dn);
     549           2 :         if (!ADS_ERR_OK(status)) {
     550           0 :                 PyErr_Format(PyExc_RuntimeError,
     551             :                                 "Failed to find samAccountName '%s': %s",
     552             :                                 samaccountname, ads_errstr(status));
     553           0 :                 goto out;
     554             :         }
     555             : 
     556           2 :         if (uac & UF_WORKSTATION_TRUST_ACCOUNT ||
     557           2 :             uac & UF_SERVER_TRUST_ACCOUNT) {
     558           2 :                 flags |= GPO_LIST_FLAG_MACHINE;
     559           2 :                 status = gp_get_machine_token(self->ads_ptr, frame, dn,
     560             :                                               &token);
     561           2 :                 if (!ADS_ERR_OK(status)) {
     562           0 :                         PyErr_Format(PyExc_RuntimeError,
     563             :                                 "Failed to get machine token for '%s'(%s): %s",
     564             :                                 samaccountname, dn, ads_errstr(status));
     565           0 :                         goto out;
     566             :                 }
     567             :         } else {
     568           0 :                 status = ads_get_sid_token(self->ads_ptr, frame, dn, &token);
     569           0 :                 if (!ADS_ERR_OK(status)) {
     570           0 :                         PyErr_Format(PyExc_RuntimeError,
     571             :                                 "Failed to get sid token for '%s'(%s): %s",
     572             :                                 samaccountname, dn, ads_errstr(status));
     573           0 :                         goto out;
     574             :                 }
     575             :         }
     576             : 
     577           2 :         gpo_ctx = talloc_new(frame);
     578           2 :         if (!gpo_ctx) {
     579           0 :                 PyErr_NoMemory();
     580           0 :                 goto out;
     581             :         }
     582           2 :         status = ads_get_gpo_list(self->ads_ptr, gpo_ctx, dn, flags, token,
     583             :                                   &gpo_list);
     584           2 :         if (!ADS_ERR_OK(status)) {
     585           0 :                 PyErr_Format(PyExc_RuntimeError,
     586             :                         "Failed to fetch GPO list: %s",
     587             :                         ads_errstr(status));
     588           0 :                 goto out;
     589             :         }
     590             : 
     591             :         /* Convert the C linked list into a python list */
     592           2 :         list_size = 0;
     593           8 :         for (gpo = gpo_list; gpo != NULL; gpo = gpo->next) {
     594           6 :                 list_size++;
     595             :         }
     596             : 
     597           2 :         i = 0;
     598           2 :         ret = PyList_New(list_size);
     599           2 :         if (ret == NULL) {
     600           0 :                 goto out;
     601             :         }
     602             : 
     603           8 :         for (gpo = gpo_list; gpo != NULL; gpo = gpo->next) {
     604           6 :                 PyObject *obj = pytalloc_reference_ex(&GPOType,
     605             :                                                       gpo_ctx, gpo);
     606           6 :                 if (obj == NULL) {
     607           0 :                         Py_CLEAR(ret);
     608           0 :                         goto out;
     609             :                 }
     610             : 
     611           6 :                 PyList_SetItem(ret, i, obj);
     612           6 :                 i++;
     613             :         }
     614             : 
     615           2 : out:
     616           2 :         TALLOC_FREE(frame);
     617           2 :         return ret;
     618             : }
     619             : 
     620             : #endif
     621             : 
     622             : static PyMethodDef ADS_methods[] = {
     623             :         { "connect", (PyCFunction)py_ads_connect, METH_NOARGS,
     624             :                 "Connect to the LDAP server" },
     625             : #ifdef HAVE_ADS
     626             :         { "get_gpo_list", PY_DISCARD_FUNC_SIG(PyCFunction, py_ads_get_gpo_list),
     627             :                 METH_VARARGS | METH_KEYWORDS,
     628             :                 NULL },
     629             : #endif
     630             :         {0}
     631             : };
     632             : 
     633             : static PyTypeObject ads_ADSType = {
     634             :         .tp_name = "gpo.ADS_STRUCT",
     635             :         .tp_basicsize = sizeof(ADS),
     636             :         .tp_new = PyType_GenericNew,
     637             :         .tp_dealloc = (destructor)py_ads_dealloc,
     638             :         .tp_flags = Py_TPFLAGS_DEFAULT,
     639             :         .tp_doc = "ADS struct",
     640             :         .tp_methods = ADS_methods,
     641             :         .tp_init = (initproc)py_ads_init,
     642             : };
     643             : 
     644             : static PyMethodDef py_gpo_methods[] = {
     645             :         {"gpo_get_sysvol_gpt_version",
     646             :                 (PyCFunction)py_gpo_get_sysvol_gpt_version,
     647             :                 METH_VARARGS, NULL},
     648             :         {0}
     649             : };
     650             : 
     651             : static struct PyModuleDef moduledef = {
     652             :         PyModuleDef_HEAD_INIT,
     653             :         .m_name = "gpo",
     654             :         .m_doc = "libgpo python bindings",
     655             :         .m_size = -1,
     656             :         .m_methods = py_gpo_methods,
     657             : };
     658             : 
     659             : /* Will be called by python when loading this module */
     660             : void initgpo(void);
     661             : 
     662         338 : MODULE_INIT_FUNC(gpo)
     663             : {
     664           1 :         PyObject *m;
     665             : 
     666         338 :         debug_setup_talloc_log();
     667             : 
     668             :         /* Instantiate the types */
     669         338 :         m = PyModule_Create(&moduledef);
     670         338 :         if (m == NULL) {
     671           0 :                 goto err;
     672             :         }
     673             : 
     674         338 :         if (PyModule_AddObject(m, "version",
     675             :                            PyUnicode_FromString(SAMBA_VERSION_STRING)) ) {
     676           0 :                 goto err;
     677             :         }
     678             : 
     679         338 :         if (pytalloc_BaseObject_PyType_Ready(&ads_ADSType) < 0) {
     680           0 :                 goto err;
     681             :         }
     682             : 
     683         283 :         Py_INCREF(&ads_ADSType);
     684         338 :         if (PyModule_AddObject(m, "ADS_STRUCT", (PyObject *)&ads_ADSType)) {
     685           0 :                 goto err;
     686             :         }
     687             : 
     688         338 :         if (pytalloc_BaseObject_PyType_Ready(&GPOType) < 0) {
     689           0 :                 goto err;
     690             :         }
     691             : 
     692         283 :         Py_INCREF((PyObject *)(void *)&GPOType);
     693         338 :         if (PyModule_AddObject(m, "GROUP_POLICY_OBJECT",
     694             :                            (PyObject *)&GPOType)) {
     695           0 :                 goto err;
     696             :         }
     697             : 
     698             : #define ADD_FLAGS(val)  PyModule_AddObject(m, #val, PyLong_FromLong(val))
     699             : 
     700         338 :         ADD_FLAGS(GP_LINK_UNKOWN);
     701         338 :         ADD_FLAGS(GP_LINK_MACHINE);
     702         338 :         ADD_FLAGS(GP_LINK_SITE);
     703         338 :         ADD_FLAGS(GP_LINK_DOMAIN);
     704         338 :         ADD_FLAGS(GP_LINK_OU);
     705         338 :         ADD_FLAGS(GP_LINK_LOCAL);
     706             : 
     707         338 :         return m;
     708             : 
     709           0 : err:
     710           0 :         Py_CLEAR(m);
     711           0 :         return NULL;
     712             : }

Generated by: LCOV version 1.14