LCOV - code coverage report
Current view: top level - Modules - spwdmodule.c (source / functions) Hit Total Coverage
Test: CPython lcov report Lines: 33 81 40.7 %
Date: 2022-07-07 18:19:46 Functions: 7 10 70.0 %

          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          64 : get_spwd_state(PyObject *module)
      68             : {
      69          64 :     void *state = PyModule_GetState(module);
      70          64 :     assert(state != NULL);
      71          64 :     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           1 : 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           1 :     PyObject *bytes, *retval = NULL;
     144             : 
     145           1 :     if ((bytes = PyUnicode_EncodeFSDefault(arg)) == NULL)
     146           0 :         return NULL;
     147             :     /* check for embedded null bytes */
     148           1 :     if (PyBytes_AsStringAndSize(bytes, &name, NULL) == -1)
     149           0 :         goto out;
     150           1 :     if ((p = getspnam(name)) == NULL) {
     151           1 :         if (errno != 0)
     152           1 :             PyErr_SetFromErrno(PyExc_OSError);
     153             :         else
     154           0 :             PyErr_SetString(PyExc_KeyError, "getspnam(): name not found");
     155           1 :         goto out;
     156             :     }
     157           0 :     retval = mkspent(module, p);
     158           1 : out:
     159           1 :     Py_DECREF(bytes);
     160           1 :     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           2 : spwdmodule_exec(PyObject *module)
     212             : {
     213           2 :     spwdmodulestate *state = get_spwd_state(module);
     214             : 
     215           2 :     state->StructSpwdType = PyStructSequence_NewType(&struct_spwd_type_desc);
     216           2 :     if (state->StructSpwdType == NULL) {
     217           0 :         return -1;
     218             :     }
     219           2 :     if (PyModule_AddType(module, state->StructSpwdType) < 0) {
     220           0 :         return -1;
     221             :     }
     222           2 :     return 0;
     223             : }
     224             : 
     225             : static PyModuleDef_Slot spwdmodule_slots[] = {
     226             :     {Py_mod_exec, spwdmodule_exec},
     227             :     {0, NULL}
     228             : };
     229             : 
     230          28 : static int spwdmodule_traverse(PyObject *m, visitproc visit, void *arg) {
     231          28 :     Py_VISIT(get_spwd_state(m)->StructSpwdType);
     232          28 :     return 0;
     233             : }
     234             : 
     235           4 : static int spwdmodule_clear(PyObject *m) {
     236           4 :     Py_CLEAR(get_spwd_state(m)->StructSpwdType);
     237           4 :     return 0;
     238             : }
     239             : 
     240           2 : static void spwdmodule_free(void *m) {
     241           2 :     spwdmodule_clear((PyObject *)m);
     242           2 : }
     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           2 : PyInit_spwd(void)
     258             : {
     259           2 :     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           2 :     return PyModuleDef_Init(&spwdmodule);
     267             : }

Generated by: LCOV version 1.14