| |
| /* UNIX shadow password file access module */ |
| /* A lot of code has been taken from pwdmodule.c */ |
| /* For info also see http://www.unixpapa.com/incnote/passwd.html */ |
| |
| #include "Python.h" |
| |
| #include <sys/types.h> |
| #ifdef HAVE_SHADOW_H |
| #include <shadow.h> |
| #endif |
| |
| |
| PyDoc_STRVAR(spwd__doc__, |
| "This module provides access to the Unix shadow password database.\n\ |
| It is available on various Unix versions.\n\ |
| \n\ |
| Shadow password database entries are reported as 9-tuples of type struct_spwd,\n\ |
| containing the following items from the password database (see `<shadow.h>'):\n\ |
| sp_namp, sp_pwdp, sp_lstchg, sp_min, sp_max, sp_warn, sp_inact, sp_expire, sp_flag.\n\ |
| The sp_namp and sp_pwdp are strings, the rest are integers.\n\ |
| An exception is raised if the entry asked for cannot be found.\n\ |
| You have to be root to be able to use this module."); |
| |
| |
| #if defined(HAVE_GETSPNAM) || defined(HAVE_GETSPENT) |
| |
| static PyStructSequence_Field struct_spwd_type_fields[] = { |
| {"sp_nam", "login name"}, |
| {"sp_pwd", "encrypted password"}, |
| {"sp_lstchg", "date of last change"}, |
| {"sp_min", "min #days between changes"}, |
| {"sp_max", "max #days between changes"}, |
| {"sp_warn", "#days before pw expires to warn user about it"}, |
| {"sp_inact", "#days after pw expires until account is blocked"}, |
| {"sp_expire", "#days since 1970-01-01 until account is disabled"}, |
| {"sp_flag", "reserved"}, |
| {0} |
| }; |
| |
| PyDoc_STRVAR(struct_spwd__doc__, |
| "spwd.struct_spwd: Results from getsp*() routines.\n\n\ |
| This object may be accessed either as a 9-tuple of\n\ |
| (sp_nam,sp_pwd,sp_lstchg,sp_min,sp_max,sp_warn,sp_inact,sp_expire,sp_flag)\n\ |
| or via the object attributes as named in the above tuple."); |
| |
| static PyStructSequence_Desc struct_spwd_type_desc = { |
| "spwd.struct_spwd", |
| struct_spwd__doc__, |
| struct_spwd_type_fields, |
| 9, |
| }; |
| |
| static int initialized; |
| static PyTypeObject StructSpwdType; |
| |
| |
| static void |
| sets(PyObject *v, int i, const char* val) |
| { |
| if (val) { |
| PyObject *o = PyUnicode_DecodeFSDefault(val); |
| PyStructSequence_SET_ITEM(v, i, o); |
| } else { |
| PyStructSequence_SET_ITEM(v, i, Py_None); |
| Py_INCREF(Py_None); |
| } |
| } |
| |
| static PyObject *mkspent(struct spwd *p) |
| { |
| int setIndex = 0; |
| PyObject *v = PyStructSequence_New(&StructSpwdType); |
| if (v == NULL) |
| return NULL; |
| |
| #define SETI(i,val) PyStructSequence_SET_ITEM(v, i, PyLong_FromLong((long) val)) |
| #define SETS(i,val) sets(v, i, val) |
| |
| SETS(setIndex++, p->sp_namp); |
| SETS(setIndex++, p->sp_pwdp); |
| SETI(setIndex++, p->sp_lstchg); |
| SETI(setIndex++, p->sp_min); |
| SETI(setIndex++, p->sp_max); |
| SETI(setIndex++, p->sp_warn); |
| SETI(setIndex++, p->sp_inact); |
| SETI(setIndex++, p->sp_expire); |
| SETI(setIndex++, p->sp_flag); |
| |
| #undef SETS |
| #undef SETI |
| |
| if (PyErr_Occurred()) { |
| Py_DECREF(v); |
| return NULL; |
| } |
| |
| return v; |
| } |
| |
| #endif /* HAVE_GETSPNAM || HAVE_GETSPENT */ |
| |
| |
| #ifdef HAVE_GETSPNAM |
| |
| PyDoc_STRVAR(spwd_getspnam__doc__, |
| "getspnam(name) -> (sp_namp, sp_pwdp, sp_lstchg, sp_min, sp_max,\n\ |
| sp_warn, sp_inact, sp_expire, sp_flag)\n\ |
| Return the shadow password database entry for the given user name.\n\ |
| See spwd.__doc__ for more on shadow password database entries."); |
| |
| static PyObject* spwd_getspnam(PyObject *self, PyObject *args) |
| { |
| char *name; |
| struct spwd *p; |
| PyObject *arg, *bytes, *retval = NULL; |
| |
| if (!PyArg_ParseTuple(args, "U:getspnam", &arg)) |
| return NULL; |
| if ((bytes = PyUnicode_EncodeFSDefault(arg)) == NULL) |
| return NULL; |
| if (PyBytes_AsStringAndSize(bytes, &name, NULL) == -1) |
| goto out; |
| if ((p = getspnam(name)) == NULL) { |
| PyErr_SetString(PyExc_KeyError, "getspnam(): name not found"); |
| goto out; |
| } |
| retval = mkspent(p); |
| out: |
| Py_DECREF(bytes); |
| return retval; |
| } |
| |
| #endif /* HAVE_GETSPNAM */ |
| |
| #ifdef HAVE_GETSPENT |
| |
| PyDoc_STRVAR(spwd_getspall__doc__, |
| "getspall() -> list_of_entries\n\ |
| Return a list of all available shadow password database entries, \ |
| in arbitrary order.\n\ |
| See spwd.__doc__ for more on shadow password database entries."); |
| |
| static PyObject * |
| spwd_getspall(PyObject *self, PyObject *args) |
| { |
| PyObject *d; |
| struct spwd *p; |
| if ((d = PyList_New(0)) == NULL) |
| return NULL; |
| setspent(); |
| while ((p = getspent()) != NULL) { |
| PyObject *v = mkspent(p); |
| if (v == NULL || PyList_Append(d, v) != 0) { |
| Py_XDECREF(v); |
| Py_DECREF(d); |
| endspent(); |
| return NULL; |
| } |
| Py_DECREF(v); |
| } |
| endspent(); |
| return d; |
| } |
| |
| #endif /* HAVE_GETSPENT */ |
| |
| static PyMethodDef spwd_methods[] = { |
| #ifdef HAVE_GETSPNAM |
| {"getspnam", spwd_getspnam, METH_VARARGS, spwd_getspnam__doc__}, |
| #endif |
| #ifdef HAVE_GETSPENT |
| {"getspall", spwd_getspall, METH_NOARGS, spwd_getspall__doc__}, |
| #endif |
| {NULL, NULL} /* sentinel */ |
| }; |
| |
| |
| |
| static struct PyModuleDef spwdmodule = { |
| PyModuleDef_HEAD_INIT, |
| "spwd", |
| spwd__doc__, |
| -1, |
| spwd_methods, |
| NULL, |
| NULL, |
| NULL, |
| NULL |
| }; |
| |
| PyMODINIT_FUNC |
| PyInit_spwd(void) |
| { |
| PyObject *m; |
| m=PyModule_Create(&spwdmodule); |
| if (m == NULL) |
| return NULL; |
| if (!initialized) |
| PyStructSequence_InitType(&StructSpwdType, |
| &struct_spwd_type_desc); |
| Py_INCREF((PyObject *) &StructSpwdType); |
| PyModule_AddObject(m, "struct_spwd", (PyObject *) &StructSpwdType); |
| initialized = 1; |
| return m; |
| } |