LCOV - code coverage report
Current view: top level - python - pyglue.c (source / functions) Hit Total Coverage
Test: coverage report for v4-17-test 1498b464 Lines: 127 203 62.6 %
Date: 2024-06-13 04:01:37 Functions: 17 22 77.3 %

          Line data    Source code
       1             : /* 
       2             :    Unix SMB/CIFS implementation.
       3             :    Copyright (C) Jelmer Vernooij <jelmer@samba.org> 2007
       4             :    Copyright (C) Matthias Dieter Wallnöfer          2009
       5             :    
       6             :    This program is free software; you can redistribute it and/or modify
       7             :    it under the terms of the GNU General Public License as published by
       8             :    the Free Software Foundation; either version 3 of the License, or
       9             :    (at your option) any later version.
      10             :    
      11             :    This program is distributed in the hope that it will be useful,
      12             :    but WITHOUT ANY WARRANTY; without even the implied warranty of
      13             :    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      14             :    GNU General Public License for more details.
      15             :    
      16             :    You should have received a copy of the GNU General Public License
      17             :    along with this program.  If not, see <http://www.gnu.org/licenses/>.
      18             : */
      19             : 
      20             : #include <Python.h>
      21             : #include "python/py3compat.h"
      22             : #include "includes.h"
      23             : #include "version.h"
      24             : #include "param/pyparam.h"
      25             : #include "lib/socket/netif.h"
      26             : #include "lib/util/debug.h"
      27             : #include "librpc/ndr/ndr_private.h"
      28             : 
      29             : void init_glue(void);
      30             : static PyObject *PyExc_NTSTATUSError;
      31             : static PyObject *PyExc_WERRORError;
      32             : static PyObject *PyExc_HRESULTError;
      33             : static PyObject *PyExc_DsExtendedError;
      34             : 
      35           0 : static PyObject *py_generate_random_str(PyObject *self, PyObject *args)
      36             : {
      37             :         int len;
      38             :         PyObject *ret;
      39             :         char *retstr;
      40           0 :         if (!PyArg_ParseTuple(args, "i", &len))
      41           0 :                 return NULL;
      42             : 
      43           0 :         retstr = generate_random_str(NULL, len);
      44           0 :         ret = PyUnicode_FromString(retstr);
      45           0 :         talloc_free(retstr);
      46           0 :         return ret;
      47             : }
      48             : 
      49        1053 : static PyObject *py_generate_random_password(PyObject *self, PyObject *args)
      50             : {
      51             :         int min, max;
      52             :         PyObject *ret;
      53             :         char *retstr;
      54        1053 :         if (!PyArg_ParseTuple(args, "ii", &min, &max))
      55           0 :                 return NULL;
      56             : 
      57        1053 :         retstr = generate_random_password(NULL, min, max);
      58        1053 :         if (retstr == NULL) {
      59           0 :                 return NULL;
      60             :         }
      61        1053 :         ret = PyUnicode_FromString(retstr);
      62        1053 :         talloc_free(retstr);
      63        1053 :         return ret;
      64             : }
      65             : 
      66         347 : static PyObject *py_generate_random_machine_password(PyObject *self, PyObject *args)
      67             : {
      68             :         int min, max;
      69             :         PyObject *ret;
      70             :         char *retstr;
      71         347 :         if (!PyArg_ParseTuple(args, "ii", &min, &max))
      72           0 :                 return NULL;
      73             : 
      74         347 :         retstr = generate_random_machine_password(NULL, min, max);
      75         347 :         if (retstr == NULL) {
      76           0 :                 return NULL;
      77             :         }
      78         347 :         ret = PyUnicode_FromString(retstr);
      79         347 :         talloc_free(retstr);
      80         347 :         return ret;
      81             : }
      82             : 
      83          44 : static PyObject *py_check_password_quality(PyObject *self, PyObject *args)
      84             : {
      85             :         char *pass;
      86             : 
      87          44 :         if (!PyArg_ParseTuple(args, "s", &pass)) {
      88           0 :                 return NULL;
      89             :         }
      90             : 
      91          44 :         return PyBool_FromLong(check_password_quality(pass));
      92             : }
      93             : 
      94        4805 : static PyObject *py_generate_random_bytes(PyObject *self, PyObject *args)
      95             : {
      96             :         int len;
      97             :         PyObject *ret;
      98        4805 :         uint8_t *bytes = NULL;
      99             : 
     100        4805 :         if (!PyArg_ParseTuple(args, "i", &len))
     101           0 :                 return NULL;
     102             : 
     103        4805 :         bytes = talloc_zero_size(NULL, len);
     104        4805 :         generate_random_buffer(bytes, len);
     105        4805 :         ret = PyBytes_FromStringAndSize((const char *)bytes, len);
     106        4805 :         talloc_free(bytes);
     107        4805 :         return ret;
     108             : }
     109             : 
     110         498 : static PyObject *py_unix2nttime(PyObject *self, PyObject *args)
     111             : {
     112             :         time_t t;
     113             :         unsigned int _t;
     114             :         NTTIME nt;
     115             : 
     116         498 :         if (!PyArg_ParseTuple(args, "I", &_t)) {
     117           0 :                 return NULL;
     118             :         }
     119         498 :         t = _t;
     120             : 
     121         498 :         unix_to_nt_time(&nt, t);
     122             : 
     123         498 :         return PyLong_FromLongLong((uint64_t)nt);
     124             : }
     125             : 
     126       66873 : static PyObject *py_nttime2unix(PyObject *self, PyObject *args)
     127             : {
     128             :         time_t t;
     129             :         NTTIME nt;
     130       66873 :         if (!PyArg_ParseTuple(args, "K", &nt))
     131           0 :                 return NULL;
     132             : 
     133       66873 :         t = nt_time_to_unix(nt);
     134             : 
     135       66873 :         return PyLong_FromLong((uint64_t)t);
     136             : }
     137             : 
     138           0 : static PyObject *py_float2nttime(PyObject *self, PyObject *args)
     139             : {
     140           0 :         double ft = 0;
     141           0 :         double ft_sec = 0;
     142           0 :         double ft_nsec = 0;
     143             :         struct timespec ts;
     144           0 :         NTTIME nt = 0;
     145             : 
     146           0 :         if (!PyArg_ParseTuple(args, "d", &ft)) {
     147           0 :                 return NULL;
     148             :         }
     149             : 
     150           0 :         ft_sec = (double)(int)ft;
     151           0 :         ft_nsec = (ft - ft_sec) * 1.0e+9;
     152             : 
     153           0 :         ts.tv_sec = (int)ft_sec;
     154           0 :         ts.tv_nsec = (int)ft_nsec;
     155             : 
     156           0 :         nt = full_timespec_to_nt_time(&ts);
     157             : 
     158           0 :         return PyLong_FromLongLong((uint64_t)nt);
     159             : }
     160             : 
     161          72 : static PyObject *py_nttime2float(PyObject *self, PyObject *args)
     162             : {
     163          72 :         double ft = 0;
     164             :         struct timespec ts;
     165          72 :         const struct timespec ts_zero = { .tv_sec = 0, };
     166          72 :         NTTIME nt = 0;
     167             : 
     168          72 :         if (!PyArg_ParseTuple(args, "K", &nt)) {
     169           0 :                 return NULL;
     170             :         }
     171             : 
     172          72 :         ts = nt_time_to_full_timespec(nt);
     173          72 :         if (is_omit_timespec(&ts)) {
     174           0 :                 return PyFloat_FromDouble(1.0);
     175             :         }
     176          72 :         ft = timespec_elapsed2(&ts_zero, &ts);
     177             : 
     178          72 :         return PyFloat_FromDouble(ft);
     179             : }
     180             : 
     181         154 : static PyObject *py_nttime2string(PyObject *self, PyObject *args)
     182             : {
     183             :         PyObject *ret;
     184             :         NTTIME nt;
     185             :         TALLOC_CTX *tmp_ctx;
     186             :         const char *string;
     187         154 :         if (!PyArg_ParseTuple(args, "K", &nt))
     188           0 :                 return NULL;
     189             : 
     190         154 :         tmp_ctx = talloc_new(NULL);
     191         154 :         if (tmp_ctx == NULL) {
     192           0 :                 PyErr_NoMemory();
     193           0 :                 return NULL;
     194             :         }
     195             : 
     196         154 :         string = nt_time_string(tmp_ctx, nt);
     197         154 :         ret =  PyUnicode_FromString(string);
     198             : 
     199         154 :         talloc_free(tmp_ctx);
     200             : 
     201         154 :         return ret;
     202             : }
     203             : 
     204        1989 : static PyObject *py_set_debug_level(PyObject *self, PyObject *args)
     205             : {
     206             :         unsigned level;
     207        1989 :         if (!PyArg_ParseTuple(args, "I", &level))
     208           0 :                 return NULL;
     209        1989 :         debuglevel_set(level);
     210        1989 :         Py_RETURN_NONE;
     211             : }
     212             : 
     213        2188 : static PyObject *py_get_debug_level(PyObject *self,
     214             :                 PyObject *Py_UNUSED(ignored))
     215             : {
     216        2188 :         return PyLong_FromLong(debuglevel_get());
     217             : }
     218             : 
     219       11256 : static PyObject *py_fault_setup(PyObject *self,
     220             :                 PyObject *Py_UNUSED(ignored))
     221             : {
     222             :         static bool done;
     223       11256 :         if (!done) {
     224        5297 :                 fault_setup();
     225        5297 :                 done = true;
     226             :         }
     227       11256 :         Py_RETURN_NONE;
     228             : }
     229             : 
     230        2240 : static PyObject *py_is_ntvfs_fileserver_built(PyObject *self,
     231             :                 PyObject *Py_UNUSED(ignored))
     232             : {
     233             : #ifdef WITH_NTVFS_FILESERVER
     234        2240 :         Py_RETURN_TRUE;
     235             : #else
     236             :         Py_RETURN_FALSE;
     237             : #endif
     238             : }
     239             : 
     240         164 : static PyObject *py_is_heimdal_built(PyObject *self,
     241             :                 PyObject *Py_UNUSED(ignored))
     242             : {
     243             : #ifdef SAMBA4_USES_HEIMDAL
     244         130 :         Py_RETURN_TRUE;
     245             : #else
     246          34 :         Py_RETURN_FALSE;
     247             : #endif
     248             : }
     249             : 
     250         592 : static PyObject *py_is_ad_dc_built(PyObject *self,
     251             :                 PyObject *Py_UNUSED(ignored))
     252             : {
     253             : #ifdef AD_DC_BUILD_IS_ENABLED
     254         592 :         Py_RETURN_TRUE;
     255             : #else
     256             :         Py_RETURN_FALSE;
     257             : #endif
     258             : }
     259             : 
     260         560 : static PyObject *py_is_selftest_enabled(PyObject *self,
     261             :                 PyObject *Py_UNUSED(ignored))
     262             : {
     263             : #ifdef ENABLE_SELFTEST
     264         560 :         Py_RETURN_TRUE;
     265             : #else
     266             :         Py_RETURN_FALSE;
     267             : #endif
     268             : }
     269             : 
     270           0 : static PyObject *py_ndr_token_max_list_size(PyObject *self,
     271             :                 PyObject *Py_UNUSED(ignored))
     272             : {
     273           0 :         return PyLong_FromLong(ndr_token_max_list_size());
     274             : }
     275             : 
     276             : /*
     277             :   return the list of interface IPs we have configured
     278             :   takes an loadparm context, returns a list of IPs in string form
     279             : 
     280             :   Does not return addresses on 127.0.0.0/8
     281             :  */
     282         397 : static PyObject *py_interface_ips(PyObject *self, PyObject *args)
     283             : {
     284             :         PyObject *pylist;
     285             :         int count;
     286             :         TALLOC_CTX *tmp_ctx;
     287             :         PyObject *py_lp_ctx;
     288             :         struct loadparm_context *lp_ctx;
     289             :         struct interface *ifaces;
     290             :         int i, ifcount;
     291         397 :         int all_interfaces = 1;
     292             : 
     293         397 :         if (!PyArg_ParseTuple(args, "O|i", &py_lp_ctx, &all_interfaces))
     294           0 :                 return NULL;
     295             : 
     296         397 :         tmp_ctx = talloc_new(NULL);
     297         397 :         if (tmp_ctx == NULL) {
     298           0 :                 PyErr_NoMemory();
     299           0 :                 return NULL;
     300             :         }
     301             : 
     302         397 :         lp_ctx = lpcfg_from_py_object(tmp_ctx, py_lp_ctx);
     303         397 :         if (lp_ctx == NULL) {
     304           0 :                 talloc_free(tmp_ctx);
     305           0 :                 return NULL;
     306             :         }
     307             : 
     308         397 :         load_interface_list(tmp_ctx, lp_ctx, &ifaces);
     309             : 
     310         397 :         count = iface_list_count(ifaces);
     311             : 
     312             :         /* first count how many are not loopback addresses */
     313        1856 :         for (ifcount = i = 0; i<count; i++) {
     314        1459 :                 const char *ip = iface_list_n_ip(ifaces, i);
     315             : 
     316        1459 :                 if (all_interfaces) {
     317         222 :                         ifcount++;
     318         222 :                         continue;
     319             :                 }
     320             : 
     321        1237 :                 if (iface_list_same_net(ip, "127.0.0.1", "255.0.0.0")) {
     322           0 :                         continue;
     323             :                 }
     324             : 
     325        1237 :                 if (iface_list_same_net(ip, "169.254.0.0", "255.255.0.0")) {
     326           0 :                         continue;
     327             :                 }
     328             : 
     329        1237 :                 if (iface_list_same_net(ip, "::1", "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff")) {
     330           0 :                         continue;
     331             :                 }
     332             : 
     333        1237 :                 if (iface_list_same_net(ip, "fe80::", "ffff:ffff:ffff:ffff::")) {
     334           0 :                         continue;
     335             :                 }
     336             : 
     337        1237 :                 ifcount++;
     338             :         }
     339             : 
     340         397 :         pylist = PyList_New(ifcount);
     341        1856 :         for (ifcount = i = 0; i<count; i++) {
     342        1459 :                 const char *ip = iface_list_n_ip(ifaces, i);
     343             : 
     344        1459 :                 if (all_interfaces) {
     345         222 :                         PyList_SetItem(pylist, ifcount, PyUnicode_FromString(ip));
     346         222 :                         ifcount++;
     347         222 :                         continue;
     348             :                 }
     349             : 
     350        1237 :                 if (iface_list_same_net(ip, "127.0.0.1", "255.0.0.0")) {
     351           0 :                         continue;
     352             :                 }
     353             : 
     354        1237 :                 if (iface_list_same_net(ip, "169.254.0.0", "255.255.0.0")) {
     355           0 :                         continue;
     356             :                 }
     357             : 
     358        1237 :                 if (iface_list_same_net(ip, "::1", "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff")) {
     359           0 :                         continue;
     360             :                 }
     361             : 
     362        1237 :                 if (iface_list_same_net(ip, "fe80::", "ffff:ffff:ffff:ffff::")) {
     363           0 :                         continue;
     364             :                 }
     365             : 
     366        1237 :                 PyList_SetItem(pylist, ifcount, PyUnicode_FromString(ip));
     367        1237 :                 ifcount++;
     368             :         }
     369         397 :         talloc_free(tmp_ctx);
     370         397 :         return pylist;
     371             : }
     372             : 
     373           0 : static PyObject *py_strcasecmp_m(PyObject *self, PyObject *args)
     374             : {
     375           0 :         const char *s1 = NULL;
     376           0 :         const char *s2 = NULL;
     377           0 :         long cmp_result = 0;
     378           0 :         if (!PyArg_ParseTuple(args, PYARG_STR_UNI
     379             :                               PYARG_STR_UNI,
     380             :                               "utf8", &s1, "utf8", &s2)) {
     381           0 :                 return NULL;
     382             :         }
     383             : 
     384           0 :         cmp_result = strcasecmp_m(s1, s2);
     385           0 :         PyMem_Free(discard_const_p(char, s1));
     386           0 :         PyMem_Free(discard_const_p(char, s2));
     387           0 :         return PyLong_FromLong(cmp_result);
     388             : }
     389             : 
     390           0 : static PyObject *py_strstr_m(PyObject *self, PyObject *args)
     391             : {
     392           0 :         const char *s1 = NULL;
     393           0 :         const char *s2 = NULL;
     394           0 :         char *strstr_ret = NULL;
     395           0 :         PyObject *result = NULL;
     396           0 :         if (!PyArg_ParseTuple(args, PYARG_STR_UNI
     397             :                               PYARG_STR_UNI,
     398             :                               "utf8", &s1, "utf8", &s2))
     399           0 :                 return NULL;
     400             : 
     401           0 :         strstr_ret = strstr_m(s1, s2);
     402           0 :         if (!strstr_ret) {
     403           0 :                 PyMem_Free(discard_const_p(char, s1));
     404           0 :                 PyMem_Free(discard_const_p(char, s2));
     405           0 :                 Py_RETURN_NONE;
     406             :         }
     407           0 :         result = PyUnicode_FromString(strstr_ret);
     408           0 :         PyMem_Free(discard_const_p(char, s1));
     409           0 :         PyMem_Free(discard_const_p(char, s2));
     410           0 :         return result;
     411             : }
     412             : 
     413             : static PyMethodDef py_misc_methods[] = {
     414             :         { "generate_random_str", (PyCFunction)py_generate_random_str, METH_VARARGS,
     415             :                 "generate_random_str(len) -> string\n"
     416             :                 "Generate random string with specified length." },
     417             :         { "generate_random_password", (PyCFunction)py_generate_random_password,
     418             :                 METH_VARARGS, "generate_random_password(min, max) -> string\n"
     419             :                 "Generate random password (based on printable ascii characters) "
     420             :                 "with a length >= min and <= max." },
     421             :         { "generate_random_machine_password", (PyCFunction)py_generate_random_machine_password,
     422             :                 METH_VARARGS, "generate_random_machine_password(min, max) -> string\n"
     423             :                 "Generate random password "
     424             :                 "(based on random utf16 characters converted to utf8 or "
     425             :                 "random ascii characters if 'unix charset' is not 'utf8')"
     426             :                 "with a length >= min (at least 14) and <= max (at most 255)." },
     427             :         { "check_password_quality", (PyCFunction)py_check_password_quality,
     428             :                 METH_VARARGS, "check_password_quality(pass) -> bool\n"
     429             :                 "Check password quality against Samba's check_password_quality,"
     430             :                 "the implementation of Microsoft's rules:"
     431             :                 "http://msdn.microsoft.com/en-us/subscriptions/cc786468%28v=ws.10%29.aspx"
     432             :         },
     433             :         { "unix2nttime", (PyCFunction)py_unix2nttime, METH_VARARGS,
     434             :                 "unix2nttime(timestamp) -> nttime" },
     435             :         { "nttime2unix", (PyCFunction)py_nttime2unix, METH_VARARGS,
     436             :                 "nttime2unix(nttime) -> timestamp" },
     437             :         { "float2nttime", (PyCFunction)py_float2nttime, METH_VARARGS,
     438             :                 "pytime2nttime(floattimestamp) -> nttime" },
     439             :         { "nttime2float", (PyCFunction)py_nttime2float, METH_VARARGS,
     440             :                 "nttime2pytime(nttime) -> floattimestamp" },
     441             :         { "nttime2string", (PyCFunction)py_nttime2string, METH_VARARGS,
     442             :                 "nttime2string(nttime) -> string" },
     443             :         { "set_debug_level", (PyCFunction)py_set_debug_level, METH_VARARGS,
     444             :                 "set debug level" },
     445             :         { "get_debug_level", (PyCFunction)py_get_debug_level, METH_NOARGS,
     446             :                 "get debug level" },
     447             :         { "fault_setup", (PyCFunction)py_fault_setup, METH_NOARGS,
     448             :                 "setup the default samba panic handler" },
     449             :         { "interface_ips", (PyCFunction)py_interface_ips, METH_VARARGS,
     450             :                 "interface_ips(lp_ctx[, all_interfaces) -> list_of_ifaces\n"
     451             :                 "\n"
     452             :                 "get interface IP address list"},
     453             :         { "strcasecmp_m", (PyCFunction)py_strcasecmp_m, METH_VARARGS,
     454             :                 "(for testing) compare two strings using Samba's strcasecmp_m()"},
     455             :         { "strstr_m", (PyCFunction)py_strstr_m, METH_VARARGS,
     456             :                 "(for testing) find one string in another with Samba's strstr_m()"},
     457             :         { "is_ntvfs_fileserver_built", (PyCFunction)py_is_ntvfs_fileserver_built, METH_NOARGS,
     458             :                 "is the NTVFS file server built in this installation?" },
     459             :         { "is_heimdal_built", (PyCFunction)py_is_heimdal_built, METH_NOARGS,
     460             :                 "is Samba built with Heimdal Kerberbos?" },
     461             :         { "generate_random_bytes",
     462             :                 (PyCFunction)py_generate_random_bytes,
     463             :                 METH_VARARGS,
     464             :                 "generate_random_bytes(len) -> bytes\n"
     465             :                 "Generate random bytes with specified length." },
     466             :         { "is_ad_dc_built", (PyCFunction)py_is_ad_dc_built, METH_NOARGS,
     467             :                 "is Samba built with AD DC?" },
     468             :         { "is_selftest_enabled", (PyCFunction)py_is_selftest_enabled,
     469             :                 METH_NOARGS, "is Samba built with selftest enabled?" },
     470             :         { "ndr_token_max_list_size", (PyCFunction)py_ndr_token_max_list_size,
     471             :                 METH_NOARGS, "How many NDR internal tokens is too many for this build?" },
     472             :         {0}
     473             : };
     474             : 
     475             : static struct PyModuleDef moduledef = {
     476             :     PyModuleDef_HEAD_INIT,
     477             :     .m_name = "_glue",
     478             :     .m_doc = "Python bindings for miscellaneous Samba functions.",
     479             :     .m_size = -1,
     480             :     .m_methods = py_misc_methods,
     481             : };
     482             : 
     483        7561 : MODULE_INIT_FUNC(_glue)
     484             : {
     485             :         PyObject *m;
     486             : 
     487        7561 :         debug_setup_talloc_log();
     488             : 
     489        7561 :         m = PyModule_Create(&moduledef);
     490        7561 :         if (m == NULL)
     491           0 :                 return NULL;
     492             : 
     493        7561 :         PyModule_AddObject(m, "version",
     494             :                                            PyUnicode_FromString(SAMBA_VERSION_STRING));
     495        7561 :         PyExc_NTSTATUSError = PyErr_NewException(discard_const_p(char, "samba.NTSTATUSError"), PyExc_RuntimeError, NULL);
     496        7561 :         if (PyExc_NTSTATUSError != NULL) {
     497        7561 :                 Py_INCREF(PyExc_NTSTATUSError);
     498        7561 :                 PyModule_AddObject(m, "NTSTATUSError", PyExc_NTSTATUSError);
     499             :         }
     500             : 
     501        7561 :         PyExc_WERRORError = PyErr_NewException(discard_const_p(char, "samba.WERRORError"), PyExc_RuntimeError, NULL);
     502        7561 :         if (PyExc_WERRORError != NULL) {
     503        7561 :                 Py_INCREF(PyExc_WERRORError);
     504        7561 :                 PyModule_AddObject(m, "WERRORError", PyExc_WERRORError);
     505             :         }
     506             : 
     507        7561 :         PyExc_HRESULTError = PyErr_NewException(discard_const_p(char, "samba.HRESULTError"), PyExc_RuntimeError, NULL);
     508        7561 :         if (PyExc_HRESULTError != NULL) {
     509        7561 :                 Py_INCREF(PyExc_HRESULTError);
     510        7561 :                 PyModule_AddObject(m, "HRESULTError", PyExc_HRESULTError);
     511             :         }
     512             : 
     513        7561 :         PyExc_DsExtendedError = PyErr_NewException(discard_const_p(char, "samba.DsExtendedError"), PyExc_RuntimeError, NULL);
     514        7561 :         if (PyExc_DsExtendedError != NULL) {
     515        7561 :                 Py_INCREF(PyExc_DsExtendedError);
     516        7561 :                 PyModule_AddObject(m, "DsExtendedError", PyExc_DsExtendedError);
     517             :         }
     518             : 
     519        7561 :         return m;
     520             : }
     521             : 

Generated by: LCOV version 1.13