LCOV - code coverage report
Current view: top level - libgpo - pygpo.c (source / functions) Hit Total Coverage
Test: coverage report for v4-17-test 1498b464 Lines: 12 256 4.7 %
Date: 2024-06-13 04:01:37 Functions: 1 15 6.7 %

          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 <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             : 
      34             : /* A Python C API module to use LIBGPO */
      35             : 
      36             : #define GPO_getter(ATTR) \
      37             : static PyObject* GPO_get_##ATTR(PyObject *self, void *closure) \
      38             : { \
      39             :         struct GROUP_POLICY_OBJECT *gpo_ptr \
      40             :                 = pytalloc_get_ptr(self); \
      41             :         \
      42             :         if (gpo_ptr->ATTR) \
      43             :                 return PyUnicode_FromString(gpo_ptr->ATTR); \
      44             :         else \
      45             :                 Py_RETURN_NONE; \
      46             : }
      47           0 : GPO_getter(ds_path)
      48           0 : GPO_getter(file_sys_path)
      49           0 : GPO_getter(display_name)
      50           0 : GPO_getter(name)
      51           0 : GPO_getter(link)
      52           0 : GPO_getter(user_extensions)
      53           0 : GPO_getter(machine_extensions)
      54             : 
      55             : static PyGetSetDef GPO_setters[] = {
      56             :         {discard_const_p(char, "ds_path"), (getter)GPO_get_ds_path, NULL, NULL,
      57             :                 NULL},
      58             :         {discard_const_p(char, "file_sys_path"), (getter)GPO_get_file_sys_path,
      59             :                 NULL, NULL, NULL},
      60             :         {discard_const_p(char, "display_name"), (getter)GPO_get_display_name,
      61             :                 NULL, NULL, NULL},
      62             :         {discard_const_p(char, "name"), (getter)GPO_get_name, NULL, NULL,
      63             :                 NULL},
      64             :         {discard_const_p(char, "link"), (getter)GPO_get_link, NULL, NULL,
      65             :                 NULL},
      66             :         {discard_const_p(char, "user_extensions"),
      67             :                 (getter)GPO_get_user_extensions,
      68             :                 NULL, NULL, NULL},
      69             :         {discard_const_p(char, "machine_extensions"),
      70             :                 (getter)GPO_get_machine_extensions, NULL, NULL, NULL},
      71             :         {0}
      72             : };
      73             : 
      74           0 : static PyObject *py_gpo_get_unix_path(PyObject *self, PyObject *args,
      75             :                                       PyObject *kwds)
      76             : {
      77             :         NTSTATUS status;
      78           0 :         const char *cache_dir = NULL;
      79           0 :         PyObject *ret = NULL;
      80           0 :         char *unix_path = NULL;
      81           0 :         TALLOC_CTX *frame = NULL;
      82             :         static const char *kwlist[] = {"cache_dir", NULL};
      83           0 :         struct GROUP_POLICY_OBJECT *gpo_ptr \
      84           0 :                 = (struct GROUP_POLICY_OBJECT *)pytalloc_get_ptr(self);
      85             : 
      86           0 :         frame = talloc_stackframe();
      87             : 
      88           0 :         if (!PyArg_ParseTupleAndKeywords(args, kwds, "|s",
      89             :                                          discard_const_p(char *, kwlist),
      90             :                                          &cache_dir)) {
      91           0 :                 goto out;
      92             :         }
      93             : 
      94           0 :         if (!cache_dir) {
      95           0 :                 cache_dir = cache_path(talloc_tos(), GPO_CACHE_DIR);
      96           0 :                 if (!cache_dir) {
      97           0 :                         PyErr_SetString(PyExc_MemoryError,
      98             :                                         "Failed to determine gpo cache dir");
      99           0 :                         goto out;
     100             :                 }
     101             :         }
     102             : 
     103           0 :         status = gpo_get_unix_path(frame, cache_dir, gpo_ptr, &unix_path);
     104             : 
     105           0 :         if (!NT_STATUS_IS_OK(status)) {
     106           0 :                 PyErr_Format(PyExc_RuntimeError,
     107             :                                 "Failed to determine gpo unix path: %s",
     108             :                                 get_friendly_nt_error_msg(status));
     109           0 :                 goto out;
     110             :         }
     111             : 
     112           0 :         ret = PyUnicode_FromString(unix_path);
     113             : 
     114           0 : out:
     115           0 :         TALLOC_FREE(frame);
     116           0 :         return ret;
     117             : }
     118             : 
     119             : static PyMethodDef GPO_methods[] = {
     120             :         {"get_unix_path", PY_DISCARD_FUNC_SIG(PyCFunction,
     121             :                                               py_gpo_get_unix_path),
     122             :                 METH_VARARGS | METH_KEYWORDS,
     123             :                 NULL },
     124             :         {0}
     125             : };
     126             : 
     127             : static PyTypeObject GPOType = {
     128             :         PyVarObject_HEAD_INIT(NULL, 0)
     129             :         .tp_name = "gpo.GROUP_POLICY_OBJECT",
     130             :         .tp_doc = "GROUP_POLICY_OBJECT",
     131             :         .tp_getset = GPO_setters,
     132             :         .tp_methods = GPO_methods,
     133             :         .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
     134             : };
     135             : 
     136             : typedef struct {
     137             :         PyObject_HEAD
     138             :         ADS_STRUCT *ads_ptr;
     139             :         PyObject *py_creds;
     140             :         struct cli_credentials *cli_creds;
     141             : } ADS;
     142             : 
     143           0 : static void py_ads_dealloc(ADS* self)
     144             : {
     145           0 :         TALLOC_FREE(self->ads_ptr);
     146           0 :         Py_CLEAR(self->py_creds);
     147           0 :         Py_TYPE(self)->tp_free((PyObject*)self);
     148           0 : }
     149             : 
     150             : static PyObject* py_ads_connect(ADS *self, PyObject *Py_UNUSED(ignored));
     151           0 : static int py_ads_init(ADS *self, PyObject *args, PyObject *kwds)
     152             : {
     153           0 :         const char *realm = NULL;
     154           0 :         const char *workgroup = NULL;
     155           0 :         const char *ldap_server = NULL;
     156           0 :         PyObject *lp_obj = NULL;
     157           0 :         PyObject *py_creds = NULL;
     158           0 :         struct loadparm_context *lp_ctx = NULL;
     159           0 :         bool ok = false;
     160             : 
     161             :         static const char *kwlist[] = {
     162             :                 "ldap_server", "loadparm_context", "credentials", NULL
     163             :         };
     164           0 :         if (!PyArg_ParseTupleAndKeywords(args, kwds, "sO|O",
     165             :                                          discard_const_p(char *, kwlist),
     166             :                                          &ldap_server, &lp_obj, &py_creds)) {
     167           0 :                 return -1;
     168             :         }
     169             :         /* keep reference to the credentials. Clear any earlier ones */
     170           0 :         Py_CLEAR(self->py_creds);
     171           0 :         self->cli_creds = NULL;
     172           0 :         self->py_creds = py_creds;
     173           0 :         Py_XINCREF(self->py_creds);
     174             : 
     175           0 :         if (self->py_creds) {
     176           0 :                 ok = py_check_dcerpc_type(self->py_creds, "samba.credentials",
     177             :                                           "Credentials");
     178           0 :                 if (!ok) {
     179           0 :                         return -1;
     180             :                 }
     181             :                 self->cli_creds
     182           0 :                         = PyCredentials_AsCliCredentials(self->py_creds);
     183             :         }
     184             : 
     185           0 :         ok = py_check_dcerpc_type(lp_obj, "samba.param", "LoadParm");
     186           0 :         if (!ok) {
     187           0 :                 return -1;
     188             :         }
     189           0 :         lp_ctx = pytalloc_get_type(lp_obj, struct loadparm_context);
     190           0 :         if (lp_ctx == NULL) {
     191           0 :                 return -1;
     192             :         }
     193           0 :         ok = lp_load_initial_only(lp_ctx->szConfigFile);
     194           0 :         if (!ok) {
     195           0 :                 PyErr_Format(PyExc_RuntimeError, "Could not load config file '%s'",
     196             :                                 lp_ctx->szConfigFile);
     197           0 :                 return -1;
     198             :         }
     199             : 
     200           0 :         if (self->cli_creds) {
     201           0 :                 realm = cli_credentials_get_realm(self->cli_creds);
     202           0 :                 workgroup = cli_credentials_get_domain(self->cli_creds);
     203             :         } else {
     204           0 :                 realm = lp_realm();
     205           0 :                 workgroup = lp_workgroup();
     206             :         }
     207             : 
     208             :         /* in case __init__ is called more than once */
     209           0 :         if (self->ads_ptr) {
     210           0 :                 TALLOC_FREE(self->ads_ptr);
     211             :         }
     212             :         /* always succeeds or crashes */
     213           0 :         self->ads_ptr = ads_init(pytalloc_get_mem_ctx(args),
     214             :                                  realm,
     215             :                                  workgroup,
     216             :                                  ldap_server,
     217             :                                  ADS_SASL_PLAIN);
     218             :         
     219           0 :         return 0;
     220             : }
     221             : 
     222             : /* connect.  Failure to connect results in an Exception */
     223           0 : static PyObject* py_ads_connect(ADS *self,
     224             :                 PyObject *Py_UNUSED(ignored))
     225             : {
     226             :         ADS_STATUS status;
     227           0 :         TALLOC_CTX *frame = talloc_stackframe();
     228           0 :         if (!self->ads_ptr) {
     229           0 :                 PyErr_SetString(PyExc_RuntimeError, "Uninitialized");
     230           0 :                 return NULL;
     231             :         }
     232           0 :         TALLOC_FREE(self->ads_ptr->auth.user_name);
     233           0 :         TALLOC_FREE(self->ads_ptr->auth.password);
     234           0 :         TALLOC_FREE(self->ads_ptr->auth.realm);
     235           0 :         if (self->cli_creds) {
     236           0 :                 self->ads_ptr->auth.user_name = talloc_strdup(self->ads_ptr,
     237             :                         cli_credentials_get_username(self->cli_creds));
     238           0 :                 if (self->ads_ptr->auth.user_name == NULL) {
     239           0 :                         PyErr_NoMemory();
     240           0 :                         goto err;
     241             :                 }
     242           0 :                 self->ads_ptr->auth.password = talloc_strdup(self->ads_ptr,
     243             :                         cli_credentials_get_password(self->cli_creds));
     244           0 :                 if (self->ads_ptr->auth.password == NULL) {
     245           0 :                         PyErr_NoMemory();
     246           0 :                         goto err;
     247             :                 }
     248           0 :                 self->ads_ptr->auth.realm = talloc_strdup(self->ads_ptr,
     249             :                         cli_credentials_get_realm(self->cli_creds));
     250           0 :                 if (self->ads_ptr->auth.realm == NULL) {
     251           0 :                         PyErr_NoMemory();
     252           0 :                         goto err;
     253             :                 }
     254           0 :                 self->ads_ptr->auth.flags |= ADS_AUTH_USER_CREDS;
     255           0 :                 status = ads_connect_user_creds(self->ads_ptr);
     256             :         } else {
     257           0 :                 char *passwd = NULL;
     258             : 
     259           0 :                 if (!secrets_init()) {
     260           0 :                         PyErr_SetString(PyExc_RuntimeError,
     261             :                                         "secrets_init() failed");
     262           0 :                         goto err;
     263             :                 }
     264             : 
     265           0 :                 self->ads_ptr->auth.user_name = talloc_asprintf(self->ads_ptr,
     266             :                                                         "%s$",
     267             :                                                         lp_netbios_name());
     268           0 :                 if (self->ads_ptr->auth.user_name == NULL) {
     269           0 :                         PyErr_NoMemory();
     270           0 :                         goto err;
     271             :                 }
     272             : 
     273           0 :                 passwd = secrets_fetch_machine_password(
     274           0 :                         self->ads_ptr->server.workgroup, NULL, NULL);
     275           0 :                 if (passwd == NULL) {
     276           0 :                         PyErr_SetString(PyExc_RuntimeError,
     277             :                                         "Failed to fetch the machine account "
     278             :                                         "password");
     279           0 :                         goto err;
     280             :                 }
     281             : 
     282           0 :                 self->ads_ptr->auth.password = talloc_strdup(self->ads_ptr,
     283             :                                                              passwd);
     284           0 :                 SAFE_FREE(passwd);
     285           0 :                 if (self->ads_ptr->auth.password == NULL) {
     286           0 :                         PyErr_NoMemory();
     287           0 :                         goto err;
     288             :                 }
     289           0 :                 self->ads_ptr->auth.realm = talloc_asprintf_strupper_m(
     290           0 :                         self->ads_ptr, "%s", self->ads_ptr->server.realm);
     291           0 :                 if (self->ads_ptr->auth.realm == NULL) {
     292           0 :                         PyErr_NoMemory();
     293           0 :                         goto err;
     294             :                 }
     295           0 :                 self->ads_ptr->auth.flags |= ADS_AUTH_USER_CREDS;
     296           0 :                 status = ads_connect(self->ads_ptr);
     297             :         }
     298           0 :         if (!ADS_ERR_OK(status)) {
     299           0 :                 PyErr_Format(PyExc_RuntimeError,
     300             :                                 "ads_connect() failed: %s",
     301             :                                 ads_errstr(status));
     302           0 :                 goto err;
     303             :         }
     304             : 
     305           0 :         TALLOC_FREE(frame);
     306           0 :         Py_RETURN_TRUE;
     307             : 
     308           0 : err:
     309           0 :         TALLOC_FREE(frame);
     310           0 :         return NULL;
     311             : }
     312             : 
     313             : /* Parameter mapping and functions for the GP_EXT struct */
     314             : void initgpo(void);
     315             : 
     316             : /* Global methods aka do not need a special pyobject type */
     317           0 : static PyObject *py_gpo_get_sysvol_gpt_version(PyObject * self,
     318             :                                                PyObject * args)
     319             : {
     320           0 :         TALLOC_CTX *tmp_ctx = NULL;
     321             :         char *unix_path;
     322           0 :         char *display_name = NULL;
     323           0 :         uint32_t sysvol_version = 0;
     324             :         PyObject *result;
     325             :         NTSTATUS status;
     326             : 
     327           0 :         if (!PyArg_ParseTuple(args, "s", &unix_path)) {
     328           0 :                 return NULL;
     329             :         }
     330           0 :         tmp_ctx = talloc_new(NULL);
     331           0 :         if (!tmp_ctx) {
     332           0 :                 return PyErr_NoMemory();
     333             :         }
     334           0 :         status = gpo_get_sysvol_gpt_version(tmp_ctx, unix_path,
     335             :                                             &sysvol_version,
     336             :                                             &display_name);
     337           0 :         if (!NT_STATUS_IS_OK(status)) {
     338           0 :                 PyErr_SetNTSTATUS(status);
     339           0 :                 TALLOC_FREE(tmp_ctx);
     340           0 :                 return NULL;
     341             :         }
     342             : 
     343           0 :         result = Py_BuildValue("[s,i]", display_name, sysvol_version);
     344           0 :         talloc_free(tmp_ctx);
     345           0 :         return result;
     346             : }
     347             : 
     348             : #ifdef HAVE_ADS
     349           0 : static ADS_STATUS find_samaccount(ADS_STRUCT *ads, TALLOC_CTX *mem_ctx,
     350             :                                   const char *samaccountname,
     351             :                                   uint32_t *uac_ret, const char **dn_ret)
     352             : {
     353             :         ADS_STATUS status;
     354           0 :         const char *attrs[] = { "userAccountControl", NULL };
     355             :         const char *filter;
     356           0 :         LDAPMessage *res = NULL;
     357           0 :         char *dn = NULL;
     358           0 :         uint32_t uac = 0;
     359             : 
     360           0 :         filter = talloc_asprintf(mem_ctx, "(sAMAccountName=%s)",
     361             :                                  samaccountname);
     362           0 :         if (filter == NULL) {
     363           0 :                 status = ADS_ERROR_NT(NT_STATUS_NO_MEMORY);
     364           0 :                 goto out;
     365             :         }
     366             : 
     367           0 :         status = ads_do_search_all(ads, ads->config.bind_path,
     368             :                                    LDAP_SCOPE_SUBTREE, filter, attrs, &res);
     369             : 
     370           0 :         if (!ADS_ERR_OK(status)) {
     371           0 :                 goto out;
     372             :         }
     373             : 
     374           0 :         if (ads_count_replies(ads, res) != 1) {
     375           0 :                 status = ADS_ERROR(LDAP_NO_RESULTS_RETURNED);
     376           0 :                 goto out;
     377             :         }
     378             : 
     379           0 :         dn = ads_get_dn(ads, talloc_tos(), res);
     380           0 :         if (dn == NULL) {
     381           0 :                 status = ADS_ERROR(LDAP_NO_MEMORY);
     382           0 :                 goto out;
     383             :         }
     384             : 
     385           0 :         if (!ads_pull_uint32(ads, res, "userAccountControl", &uac)) {
     386           0 :                 status = ADS_ERROR(LDAP_NO_SUCH_ATTRIBUTE);
     387           0 :                 goto out;
     388             :         }
     389             : 
     390           0 :         if (uac_ret) {
     391           0 :                 *uac_ret = uac;
     392             :         }
     393             : 
     394           0 :         if (dn_ret) {
     395           0 :                 *dn_ret = talloc_strdup(mem_ctx, dn);
     396           0 :                 if (*dn_ret == NULL) {
     397           0 :                         status = ADS_ERROR(LDAP_NO_MEMORY);
     398           0 :                         goto out;
     399             :                 }
     400             :         }
     401           0 : out:
     402           0 :         TALLOC_FREE(dn);
     403           0 :         ads_msgfree(ads, res);
     404             : 
     405           0 :         return status;
     406             : }
     407             : 
     408           0 : static PyObject *py_ads_get_gpo_list(ADS *self, PyObject *args, PyObject *kwds)
     409             : {
     410           0 :         TALLOC_CTX *frame = NULL;
     411           0 :         struct GROUP_POLICY_OBJECT *gpo = NULL, *gpo_list = NULL;
     412             :         ADS_STATUS status;
     413           0 :         const char *samaccountname = NULL;
     414           0 :         const char *dn = NULL;
     415           0 :         uint32_t uac = 0;
     416           0 :         uint32_t flags = 0;
     417           0 :         struct security_token *token = NULL;
     418           0 :         PyObject *ret = NULL;
     419           0 :         TALLOC_CTX *gpo_ctx = NULL;
     420             :         size_t list_size;
     421             :         size_t i;
     422             : 
     423             :         static const char *kwlist[] = {"samaccountname", NULL};
     424           0 :         if (!PyArg_ParseTupleAndKeywords(args, kwds, "s",
     425             :                                          discard_const_p(char *, kwlist),
     426             :                                          &samaccountname)) {
     427           0 :                 return NULL;
     428             :         }
     429           0 :         if (!self->ads_ptr) {
     430           0 :                 PyErr_SetString(PyExc_RuntimeError, "Uninitialized");
     431           0 :                 return NULL;
     432             :         }
     433             : 
     434           0 :         frame = talloc_stackframe();
     435             : 
     436           0 :         status = find_samaccount(self->ads_ptr, frame,
     437             :                                  samaccountname, &uac, &dn);
     438           0 :         if (!ADS_ERR_OK(status)) {
     439           0 :                 PyErr_Format(PyExc_RuntimeError,
     440             :                                 "Failed to find samAccountName '%s': %s",
     441             :                                 samaccountname, ads_errstr(status));
     442           0 :                 goto out;
     443             :         }
     444             : 
     445           0 :         if (uac & UF_WORKSTATION_TRUST_ACCOUNT ||
     446           0 :             uac & UF_SERVER_TRUST_ACCOUNT) {
     447           0 :                 flags |= GPO_LIST_FLAG_MACHINE;
     448           0 :                 status = gp_get_machine_token(self->ads_ptr, frame, dn,
     449             :                                               &token);
     450           0 :                 if (!ADS_ERR_OK(status)) {
     451           0 :                         PyErr_Format(PyExc_RuntimeError,
     452             :                                 "Failed to get machine token for '%s'(%s): %s",
     453             :                                 samaccountname, dn, ads_errstr(status));
     454           0 :                         goto out;
     455             :                 }
     456             :         } else {
     457           0 :                 status = ads_get_sid_token(self->ads_ptr, frame, dn, &token);
     458           0 :                 if (!ADS_ERR_OK(status)) {
     459           0 :                         PyErr_Format(PyExc_RuntimeError,
     460             :                                 "Failed to get sid token for '%s'(%s): %s",
     461             :                                 samaccountname, dn, ads_errstr(status));
     462           0 :                         goto out;
     463             :                 }
     464             :         }
     465             : 
     466           0 :         gpo_ctx = talloc_new(frame);
     467           0 :         if (!gpo_ctx) {
     468           0 :                 PyErr_NoMemory();
     469           0 :                 goto out;
     470             :         }
     471           0 :         status = ads_get_gpo_list(self->ads_ptr, gpo_ctx, dn, flags, token,
     472             :                                   &gpo_list);
     473           0 :         if (!ADS_ERR_OK(status)) {
     474           0 :                 PyErr_Format(PyExc_RuntimeError,
     475             :                         "Failed to fetch GPO list: %s",
     476             :                         ads_errstr(status));
     477           0 :                 goto out;
     478             :         }
     479             : 
     480             :         /* Convert the C linked list into a python list */
     481           0 :         list_size = 0;
     482           0 :         for (gpo = gpo_list; gpo != NULL; gpo = gpo->next) {
     483           0 :                 list_size++;
     484             :         }
     485             : 
     486           0 :         i = 0;
     487           0 :         ret = PyList_New(list_size);
     488           0 :         if (ret == NULL) {
     489           0 :                 goto out;
     490             :         }
     491             : 
     492           0 :         for (gpo = gpo_list; gpo != NULL; gpo = gpo->next) {
     493           0 :                 PyObject *obj = pytalloc_reference_ex(&GPOType,
     494             :                                                       gpo_ctx, gpo);
     495           0 :                 if (obj == NULL) {
     496           0 :                         Py_CLEAR(ret);
     497           0 :                         goto out;
     498             :                 }
     499             : 
     500           0 :                 PyList_SetItem(ret, i, obj);
     501           0 :                 i++;
     502             :         }
     503             : 
     504           0 : out:
     505           0 :         TALLOC_FREE(frame);
     506           0 :         return ret;
     507             : }
     508             : 
     509             : #endif
     510             : 
     511             : static PyMethodDef ADS_methods[] = {
     512             :         { "connect", (PyCFunction)py_ads_connect, METH_NOARGS,
     513             :                 "Connect to the LDAP server" },
     514             : #ifdef HAVE_ADS
     515             :         { "get_gpo_list", PY_DISCARD_FUNC_SIG(PyCFunction, py_ads_get_gpo_list),
     516             :                 METH_VARARGS | METH_KEYWORDS,
     517             :                 NULL },
     518             : #endif
     519             :         {0}
     520             : };
     521             : 
     522             : static PyTypeObject ads_ADSType = {
     523             :         .tp_name = "gpo.ADS_STRUCT",
     524             :         .tp_basicsize = sizeof(ADS),
     525             :         .tp_new = PyType_GenericNew,
     526             :         .tp_dealloc = (destructor)py_ads_dealloc,
     527             :         .tp_flags = Py_TPFLAGS_DEFAULT,
     528             :         .tp_doc = "ADS struct",
     529             :         .tp_methods = ADS_methods,
     530             :         .tp_init = (initproc)py_ads_init,
     531             : };
     532             : 
     533             : static PyMethodDef py_gpo_methods[] = {
     534             :         {"gpo_get_sysvol_gpt_version",
     535             :                 (PyCFunction)py_gpo_get_sysvol_gpt_version,
     536             :                 METH_VARARGS, NULL},
     537             :         {0}
     538             : };
     539             : 
     540             : static struct PyModuleDef moduledef = {
     541             :         PyModuleDef_HEAD_INIT,
     542             :         .m_name = "gpo",
     543             :         .m_doc = "libgpo python bindings",
     544             :         .m_size = -1,
     545             :         .m_methods = py_gpo_methods,
     546             : };
     547             : 
     548             : /* Will be called by python when loading this module */
     549             : void initgpo(void);
     550             : 
     551          77 : MODULE_INIT_FUNC(gpo)
     552             : {
     553             :         PyObject *m;
     554             : 
     555          77 :         debug_setup_talloc_log();
     556             : 
     557             :         /* Instantiate the types */
     558          77 :         m = PyModule_Create(&moduledef);
     559          77 :         if (m == NULL) {
     560           0 :                 goto err;
     561             :         }
     562             : 
     563          77 :         if (PyModule_AddObject(m, "version",
     564             :                            PyUnicode_FromString(SAMBA_VERSION_STRING)) ) {
     565           0 :                 goto err;
     566             :         }
     567             : 
     568          77 :         if (pytalloc_BaseObject_PyType_Ready(&ads_ADSType) < 0) {
     569           0 :                 goto err;
     570             :         }
     571             : 
     572          77 :         Py_INCREF(&ads_ADSType);
     573          77 :         if (PyModule_AddObject(m, "ADS_STRUCT", (PyObject *)&ads_ADSType)) {
     574           0 :                 goto err;
     575             :         }
     576             : 
     577          77 :         if (pytalloc_BaseObject_PyType_Ready(&GPOType) < 0) {
     578           0 :                 goto err;
     579             :         }
     580             : 
     581          77 :         Py_INCREF((PyObject *)(void *)&GPOType);
     582          77 :         if (PyModule_AddObject(m, "GROUP_POLICY_OBJECT",
     583             :                            (PyObject *)&GPOType)) {
     584           0 :                 goto err;
     585             :         }
     586          77 :         return m;
     587             : 
     588           0 : err:
     589           0 :         Py_CLEAR(m);
     590           0 :         return NULL;
     591             : }

Generated by: LCOV version 1.13