LCOV - code coverage report
Current view: | top level - Modules - spwdmodule.c (source / functions) |  |  | Hit | Total | Coverage
Test: | CPython 3.12 LCOV report [commit 5e6661bce9] |  | Lines: | 21 | 80 | 26.2 %
Date: | 2023-03-20 08:15:36 |  | Functions: | 6 | 10 | 60.0 %
|  |  | Branches: | 7 | 34 | 20.6 %

               Branch data     Line data    Source code
           1                 :            :
           2                 :            : /* UNIX shadow password file access module */
           3                 :            : /* A lot of code has been taken from pwdmodule.c */
           4                 :            : /* For info also see http://www.unixpapa.com/incnote/passwd.html */
           5                 :            :
           6                 :            : #include "Python.h"
           7                 :            :
           8                 :            : #include <sys/types.h>
           9                 :            : #ifdef HAVE_SHADOW_H
          10                 :            : #include <shadow.h>
          11                 :            : #endif
          12                 :            :
          13                 :            : #include "clinic/spwdmodule.c.h"
          14                 :            :
          15                 :            : /*[clinic input]
          16                 :            : module spwd
          17                 :            : [clinic start generated code]*/
          18                 :            : /*[clinic end generated code: output=da39a3ee5e6b4b0d input=c0b841b90a6a07ce]*/
          19                 :            :
          20                 :            : PyDoc_STRVAR(spwd__doc__,
          21                 :            : "This module provides access to the Unix shadow password database.\n\
          22                 :            : It is available on various Unix versions.\n\
          23                 :            : \n\
          24                 :            : Shadow password database entries are reported as 9-tuples of type struct_spwd,\n\
          25                 :            : containing the following items from the password database (see `<shadow.h>'):\n\
          26                 :            : sp_namp, sp_pwdp, sp_lstchg, sp_min, sp_max, sp_warn, sp_inact, sp_expire, sp_flag.\n\
          27                 :            : The sp_namp and sp_pwdp are strings, the rest are integers.\n\
          28                 :            : An exception is raised if the entry asked for cannot be found.\n\
          29                 :            : You have to be root to be able to use this module.");
          30                 :            :
          31                 :            :
          32                 :            : #if defined(HAVE_GETSPNAM) || defined(HAVE_GETSPENT)
          33                 :            :
          34                 :            : static PyStructSequence_Field struct_spwd_type_fields[] = {
          35                 :            :     {"sp_namp", "login name"},
          36                 :            :     {"sp_pwdp", "encrypted password"},
          37                 :            :     {"sp_lstchg", "date of last change"},
          38                 :            :     {"sp_min", "min #days between changes"},
          39                 :            :     {"sp_max", "max #days between changes"},
          40                 :            :     {"sp_warn", "#days before pw expires to warn user about it"},
          41                 :            :     {"sp_inact", "#days after pw expires until account is disabled"},
          42                 :            :     {"sp_expire", "#days since 1970-01-01 when account expires"},
          43                 :            :     {"sp_flag", "reserved"},
          44                 :            :     {"sp_nam", "login name; deprecated"}, /* Backward compatibility */
          45                 :            :     {"sp_pwd", "encrypted password; deprecated"}, /* Backward compatibility */
          46                 :            :     {0}
          47                 :            : };
          48                 :            :
          49                 :            : PyDoc_STRVAR(struct_spwd__doc__,
          50                 :            : "spwd.struct_spwd: Results from getsp*() routines.\n\n\
          51                 :            : This object may be accessed either as a 9-tuple of\n\
          52                 :            :   (sp_namp,sp_pwdp,sp_lstchg,sp_min,sp_max,sp_warn,sp_inact,sp_expire,sp_flag)\n\
          53                 :            : or via the object attributes as named in the above tuple.");
          54                 :            :
          55                 :            : static PyStructSequence_Desc struct_spwd_type_desc = {
          56                 :            :     "spwd.struct_spwd",
          57                 :            :     struct_spwd__doc__,
          58                 :            :     struct_spwd_type_fields,
          59                 :            :     9,
          60                 :            : };
          61                 :            :
          62                 :            : typedef struct {
          63                 :            :     PyTypeObject *StructSpwdType;
          64                 :            : } spwdmodulestate;
          65                 :            :
          66                 :            : static inline spwdmodulestate*
          67                 :         15 : get_spwd_state(PyObject *module)
          68                 :            : {
          69                 :         15 :     void *state = PyModule_GetState(module);
          70                 :            :     assert(state != NULL);
          71                 :         15 :     return (spwdmodulestate *)state;
          72                 :            : }
          73                 :            :
          74                 :            : static struct PyModuleDef spwdmodule;
          75                 :            :
          76                 :            : static void
          77                 :          0 : sets(PyObject *v, int i, const char* val)
          78                 :            : {
          79         [ #  # ]:          0 :   if (val) {
          80                 :          0 :       PyObject *o = PyUnicode_DecodeFSDefault(val);
          81                 :          0 :       PyStructSequence_SET_ITEM(v, i, o);
          82                 :            :   } else {
          83                 :          0 :       PyStructSequence_SET_ITEM(v, i, Py_None);
          84                 :          0 :       Py_INCREF(Py_None);
          85                 :            :   }
          86                 :          0 : }
          87                 :            :
          88                 :          0 : static PyObject *mkspent(PyObject *module, struct spwd *p)
          89                 :            : {
          90                 :          0 :     int setIndex = 0;
          91                 :          0 :     PyObject *v = PyStructSequence_New(get_spwd_state(module)->StructSpwdType);
          92         [ #  # ]:          0 :     if (v == NULL)
          93                 :          0 :         return NULL;
          94                 :            :
          95                 :            : #define SETI(i,val) PyStructSequence_SET_ITEM(v, i, PyLong_FromLong((long) val))
          96                 :            : #define SETS(i,val) sets(v, i, val)
          97                 :            :
          98                 :          0 :     SETS(setIndex++, p->sp_namp);
          99                 :          0 :     SETS(setIndex++, p->sp_pwdp);
         100                 :          0 :     SETI(setIndex++, p->sp_lstchg);
         101                 :          0 :     SETI(setIndex++, p->sp_min);
         102                 :          0 :     SETI(setIndex++, p->sp_max);
         103                 :          0 :     SETI(setIndex++, p->sp_warn);
         104                 :          0 :     SETI(setIndex++, p->sp_inact);
         105                 :          0 :     SETI(setIndex++, p->sp_expire);
         106                 :          0 :     SETI(setIndex++, p->sp_flag);
         107                 :          0 :     SETS(setIndex++, p->sp_namp); /* Backward compatibility for sp_nam */
         108                 :          0 :     SETS(setIndex++, p->sp_pwdp); /* Backward compatibility for sp_pwd */
         109                 :            :
         110                 :            : #undef SETS
         111                 :            : #undef SETI
         112                 :            :
         113         [ #  # ]:          0 :     if (PyErr_Occurred()) {
         114                 :          0 :         Py_DECREF(v);
         115                 :          0 :         return NULL;
         116                 :            :     }
         117                 :            :
         118                 :          0 :     return v;
         119                 :            : }
         120                 :            :
         121                 :            : #endif  /* HAVE_GETSPNAM || HAVE_GETSPENT */
         122                 :            :
         123                 :            :
         124                 :            : #ifdef HAVE_GETSPNAM
         125                 :            :
         126                 :            : /*[clinic input]
         127                 :            : spwd.getspnam
         128                 :            :
         129                 :            :     arg: unicode
         130                 :            :     /
         131                 :            :
         132                 :            : Return the shadow password database entry for the given user name.
         133                 :            :
         134                 :            : See `help(spwd)` for more on shadow password database entries.
         135                 :            : [clinic start generated code]*/
         136                 :            :
         137                 :            : static PyObject *
         138                 :          0 : spwd_getspnam_impl(PyObject *module, PyObject *arg)
         139                 :            : /*[clinic end generated code: output=701250cf57dc6ebe input=dd89429e6167a00f]*/
         140                 :            : {
         141                 :            :     char *name;
         142                 :            :     struct spwd *p;
         143                 :          0 :     PyObject *bytes, *retval = NULL;
         144                 :            :
         145         [ #  # ]:          0 :     if ((bytes = PyUnicode_EncodeFSDefault(arg)) == NULL)
         146                 :          0 :         return NULL;
         147                 :            :     /* check for embedded null bytes */
         148         [ #  # ]:          0 :     if (PyBytes_AsStringAndSize(bytes, &name, NULL) == -1)
         149                 :          0 :         goto out;
         150         [ #  # ]:          0 :     if ((p = getspnam(name)) == NULL) {
         151         [ #  # ]:          0 :         if (errno != 0)
         152                 :          0 :             PyErr_SetFromErrno(PyExc_OSError);
         153                 :            :         else
         154                 :          0 :             PyErr_SetString(PyExc_KeyError, "getspnam(): name not found");
         155                 :          0 :         goto out;
         156                 :            :     }
         157                 :          0 :     retval = mkspent(module, p);
         158                 :          0 : out:
         159                 :          0 :     Py_DECREF(bytes);
         160                 :          0 :     return retval;
         161                 :            : }
         162                 :            :
         163                 :            : #endif /* HAVE_GETSPNAM */
         164                 :            :
         165                 :            : #ifdef HAVE_GETSPENT
         166                 :            :
         167                 :            : /*[clinic input]
         168                 :            : spwd.getspall
         169                 :            :
         170                 :            : Return a list of all available shadow password database entries, in arbitrary order.
         171                 :            :
         172                 :            : See `help(spwd)` for more on shadow password database entries.
         173                 :            : [clinic start generated code]*/
         174                 :            :
         175                 :            : static PyObject *
         176                 :          0 : spwd_getspall_impl(PyObject *module)
         177                 :            : /*[clinic end generated code: output=4fda298d6bf6d057 input=b2c84b7857d622bd]*/
         178                 :            : {
         179                 :            :     PyObject *d;
         180                 :            :     struct spwd *p;
         181         [ #  # ]:          0 :     if ((d = PyList_New(0)) == NULL)
         182                 :          0 :         return NULL;
         183                 :          0 :     setspent();
         184         [ #  # ]:          0 :     while ((p = getspent()) != NULL) {
         185                 :          0 :         PyObject *v = mkspent(module, p);
         186   [ #  #  #  # ]:          0 :         if (v == NULL || PyList_Append(d, v) != 0) {
         187                 :          0 :             Py_XDECREF(v);
         188                 :          0 :             Py_DECREF(d);
         189                 :          0 :             endspent();
         190                 :          0 :             return NULL;
         191                 :            :         }
         192                 :          0 :         Py_DECREF(v);
         193                 :            :     }
         194                 :          0 :     endspent();
         195                 :          0 :     return d;
         196                 :            : }
         197                 :            :
         198                 :            : #endif /* HAVE_GETSPENT */
         199                 :            :
         200                 :            : static PyMethodDef spwd_methods[] = {
         201                 :            : #ifdef HAVE_GETSPNAM
         202                 :            :     SPWD_GETSPNAM_METHODDEF
         203                 :            : #endif
         204                 :            : #ifdef HAVE_GETSPENT
         205                 :            :     SPWD_GETSPALL_METHODDEF
         206                 :            : #endif
         207                 :            :     {NULL,              NULL}           /* sentinel */
         208                 :            : };
         209                 :            :
         210                 :            : static int
         211                 :          1 : spwdmodule_exec(PyObject *module)
         212                 :            : {
         213                 :          1 :     spwdmodulestate *state = get_spwd_state(module);
         214                 :            :
         215                 :          1 :     state->StructSpwdType = PyStructSequence_NewType(&struct_spwd_type_desc);
         216         [ -  + ]:          1 :     if (state->StructSpwdType == NULL) {
         217                 :          0 :         return -1;
         218                 :            :     }
         219         [ -  + ]:          1 :     if (PyModule_AddType(module, state->StructSpwdType) < 0) {
         220                 :          0 :         return -1;
         221                 :            :     }
         222                 :          1 :     return 0;
         223                 :            : }
         224                 :            :
         225                 :            : static PyModuleDef_Slot spwdmodule_slots[] = {
         226                 :            :     {Py_mod_exec, spwdmodule_exec},
         227                 :            :     {0, NULL}
         228                 :            : };
         229                 :            :
         230                 :          6 : static int spwdmodule_traverse(PyObject *m, visitproc visit, void *arg) {
         231   [ +  -  -  + ]:          6 :     Py_VISIT(get_spwd_state(m)->StructSpwdType);
         232                 :          6 :     return 0;
         233                 :            : }
         234                 :            :
         235                 :          2 : static int spwdmodule_clear(PyObject *m) {
         236         [ +  + ]:          2 :     Py_CLEAR(get_spwd_state(m)->StructSpwdType);
         237                 :          2 :     return 0;
         238                 :            : }
         239                 :            :
         240                 :          1 : static void spwdmodule_free(void *m) {
         241                 :          1 :     spwdmodule_clear((PyObject *)m);
         242                 :          1 : }
         243                 :            :
         244                 :            : static struct PyModuleDef spwdmodule = {
         245                 :            :     PyModuleDef_HEAD_INIT,
         246                 :            :     .m_name = "spwd",
         247                 :            :     .m_doc = spwd__doc__,
         248                 :            :     .m_size = sizeof(spwdmodulestate),
         249                 :            :     .m_methods = spwd_methods,
         250                 :            :     .m_slots = spwdmodule_slots,
         251                 :            :     .m_traverse = spwdmodule_traverse,
         252                 :            :     .m_clear = spwdmodule_clear,
         253                 :            :     .m_free = spwdmodule_free,
         254                 :            : };
         255                 :            :
         256                 :            : PyMODINIT_FUNC
         257                 :          1 : PyInit_spwd(void)
         258                 :            : {
         259         [ -  + ]:          1 :     if (PyErr_WarnEx(PyExc_DeprecationWarning,
         260                 :            :                      "'spwd' is deprecated and slated for removal in "
         261                 :            :                      "Python 3.13",
         262                 :            :                      7)) {
         263                 :          0 :         return NULL;
         264                 :            :     }
         265                 :            :
         266                 :          1 :     return PyModuleDef_Init(&spwdmodule);
         267                 :            : }

Generated by: LCOV version 1.14