LCOV - code coverage report
Current view: top level - libgpo - pygpo.c (source / functions) Hit Total Coverage
Test: coverage report for abartlet/fix-coverage dd10fb34 Lines: 144 248 58.1 %
Date: 2021-09-23 10:06:22 Functions: 11 15 73.3 %

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

Generated by: LCOV version 1.13