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 static int initialized; 63 static PyTypeObject StructSpwdType; 64 65 66 static void 67 sets(PyObject *v, int i, const char* val) 68 { 69 if (val) { 70 PyObject *o = PyUnicode_DecodeFSDefault(val); 71 PyStructSequence_SET_ITEM(v, i, o); 72 } else { 73 PyStructSequence_SET_ITEM(v, i, Py_None); 74 Py_INCREF(Py_None); 75 } 76 } 77 78 static PyObject *mkspent(struct spwd *p) 79 { 80 int setIndex = 0; 81 PyObject *v = PyStructSequence_New(&StructSpwdType); 82 if (v == NULL) 83 return NULL; 84 85 #define SETI(i,val) PyStructSequence_SET_ITEM(v, i, PyLong_FromLong((long) val)) 86 #define SETS(i,val) sets(v, i, val) 87 88 SETS(setIndex++, p->sp_namp); 89 SETS(setIndex++, p->sp_pwdp); 90 SETI(setIndex++, p->sp_lstchg); 91 SETI(setIndex++, p->sp_min); 92 SETI(setIndex++, p->sp_max); 93 SETI(setIndex++, p->sp_warn); 94 SETI(setIndex++, p->sp_inact); 95 SETI(setIndex++, p->sp_expire); 96 SETI(setIndex++, p->sp_flag); 97 SETS(setIndex++, p->sp_namp); /* Backward compatibility for sp_nam */ 98 SETS(setIndex++, p->sp_pwdp); /* Backward compatibility for sp_pwd */ 99 100 #undef SETS 101 #undef SETI 102 103 if (PyErr_Occurred()) { 104 Py_DECREF(v); 105 return NULL; 106 } 107 108 return v; 109 } 110 111 #endif /* HAVE_GETSPNAM || HAVE_GETSPENT */ 112 113 114 #ifdef HAVE_GETSPNAM 115 116 /*[clinic input] 117 spwd.getspnam 118 119 arg: unicode 120 / 121 122 Return the shadow password database entry for the given user name. 123 124 See `help(spwd)` for more on shadow password database entries. 125 [clinic start generated code]*/ 126 127 static PyObject * 128 spwd_getspnam_impl(PyObject *module, PyObject *arg) 129 /*[clinic end generated code: output=701250cf57dc6ebe input=dd89429e6167a00f]*/ 130 { 131 char *name; 132 struct spwd *p; 133 PyObject *bytes, *retval = NULL; 134 135 if ((bytes = PyUnicode_EncodeFSDefault(arg)) == NULL) 136 return NULL; 137 if (PyBytes_AsStringAndSize(bytes, &name, NULL) == -1) 138 goto out; 139 if ((p = getspnam(name)) == NULL) { 140 if (errno != 0) 141 PyErr_SetFromErrno(PyExc_OSError); 142 else 143 PyErr_SetString(PyExc_KeyError, "getspnam(): name not found"); 144 goto out; 145 } 146 retval = mkspent(p); 147 out: 148 Py_DECREF(bytes); 149 return retval; 150 } 151 152 #endif /* HAVE_GETSPNAM */ 153 154 #ifdef HAVE_GETSPENT 155 156 /*[clinic input] 157 spwd.getspall 158 159 Return a list of all available shadow password database entries, in arbitrary order. 160 161 See `help(spwd)` for more on shadow password database entries. 162 [clinic start generated code]*/ 163 164 static PyObject * 165 spwd_getspall_impl(PyObject *module) 166 /*[clinic end generated code: output=4fda298d6bf6d057 input=b2c84b7857d622bd]*/ 167 { 168 PyObject *d; 169 struct spwd *p; 170 if ((d = PyList_New(0)) == NULL) 171 return NULL; 172 setspent(); 173 while ((p = getspent()) != NULL) { 174 PyObject *v = mkspent(p); 175 if (v == NULL || PyList_Append(d, v) != 0) { 176 Py_XDECREF(v); 177 Py_DECREF(d); 178 endspent(); 179 return NULL; 180 } 181 Py_DECREF(v); 182 } 183 endspent(); 184 return d; 185 } 186 187 #endif /* HAVE_GETSPENT */ 188 189 static PyMethodDef spwd_methods[] = { 190 #ifdef HAVE_GETSPNAM 191 SPWD_GETSPNAM_METHODDEF 192 #endif 193 #ifdef HAVE_GETSPENT 194 SPWD_GETSPALL_METHODDEF 195 #endif 196 {NULL, NULL} /* sentinel */ 197 }; 198 199 200 201 static struct PyModuleDef spwdmodule = { 202 PyModuleDef_HEAD_INIT, 203 "spwd", 204 spwd__doc__, 205 -1, 206 spwd_methods, 207 NULL, 208 NULL, 209 NULL, 210 NULL 211 }; 212 213 PyMODINIT_FUNC 214 PyInit_spwd(void) 215 { 216 PyObject *m; 217 m=PyModule_Create(&spwdmodule); 218 if (m == NULL) 219 return NULL; 220 if (!initialized) { 221 if (PyStructSequence_InitType2(&StructSpwdType, 222 &struct_spwd_type_desc) < 0) 223 return NULL; 224 } 225 Py_INCREF((PyObject *) &StructSpwdType); 226 PyModule_AddObject(m, "struct_spwd", (PyObject *) &StructSpwdType); 227 initialized = 1; 228 return m; 229 } 230