blob: da452e9ff0fcec6597d01532681ba479f1f9c88b [file] [log] [blame]
Martin v. Löwisc3001752005-01-23 09:27:24 +00001
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#include "structseq.h"
8
9#include <sys/types.h>
10#ifdef HAVE_SHADOW_H
11#include <shadow.h>
12#endif
13
14
15PyDoc_STRVAR(spwd__doc__,
16"This module provides access to the Unix shadow password database.\n\
17It is available on various Unix versions.\n\
18\n\
19Shadow password database entries are reported as 9-tuples of type struct_spwd,\n\
20containing the following items from the password database (see `<shadow.h>'):\n\
21sp_namp, sp_pwdp, sp_lstchg, sp_min, sp_max, sp_warn, sp_inact, sp_expire, sp_flag.\n\
22The sp_namp and sp_pwdp are strings, the rest are integers.\n\
23An exception is raised if the entry asked for cannot be found.\n\
24You have to be root to be able to use this module.");
25
26
27#if defined(HAVE_GETSPNAM) || defined(HAVE_GETSPENT)
28
29static PyStructSequence_Field struct_spwd_type_fields[] = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000030 {"sp_nam", "login name"},
31 {"sp_pwd", "encrypted password"},
32 {"sp_lstchg", "date of last change"},
33 {"sp_min", "min #days between changes"},
34 {"sp_max", "max #days between changes"},
35 {"sp_warn", "#days before pw expires to warn user about it"},
36 {"sp_inact", "#days after pw expires until account is blocked"},
37 {"sp_expire", "#days since 1970-01-01 until account is disabled"},
38 {"sp_flag", "reserved"},
39 {0}
Martin v. Löwisc3001752005-01-23 09:27:24 +000040};
41
42PyDoc_STRVAR(struct_spwd__doc__,
43"spwd.struct_spwd: Results from getsp*() routines.\n\n\
44This object may be accessed either as a 9-tuple of\n\
45 (sp_nam,sp_pwd,sp_lstchg,sp_min,sp_max,sp_warn,sp_inact,sp_expire,sp_flag)\n\
46or via the object attributes as named in the above tuple.");
47
48static PyStructSequence_Desc struct_spwd_type_desc = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000049 "spwd.struct_spwd",
50 struct_spwd__doc__,
51 struct_spwd_type_fields,
52 9,
Martin v. Löwisc3001752005-01-23 09:27:24 +000053};
54
Thomas Wouters49fd7fa2006-04-21 10:40:58 +000055static int initialized;
Martin v. Löwisc3001752005-01-23 09:27:24 +000056static PyTypeObject StructSpwdType;
57
58
59static void
Neal Norwitzeb8b3a62007-08-24 23:26:23 +000060sets(PyObject *v, int i, const char* val)
Martin v. Löwisc3001752005-01-23 09:27:24 +000061{
Martin v. Löwisb6a748b2009-05-29 15:23:17 +000062 if (val) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000063 PyObject *o = PyUnicode_DecodeFSDefault(val);
64 PyStructSequence_SET_ITEM(v, i, o);
Martin v. Löwisb6a748b2009-05-29 15:23:17 +000065 } else {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000066 PyStructSequence_SET_ITEM(v, i, Py_None);
67 Py_INCREF(Py_None);
Martin v. Löwisc3001752005-01-23 09:27:24 +000068 }
69}
70
71static PyObject *mkspent(struct spwd *p)
72{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000073 int setIndex = 0;
74 PyObject *v = PyStructSequence_New(&StructSpwdType);
75 if (v == NULL)
76 return NULL;
Martin v. Löwisc3001752005-01-23 09:27:24 +000077
Christian Heimes217cfd12007-12-02 14:31:20 +000078#define SETI(i,val) PyStructSequence_SET_ITEM(v, i, PyLong_FromLong((long) val))
Martin v. Löwisc3001752005-01-23 09:27:24 +000079#define SETS(i,val) sets(v, i, val)
80
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000081 SETS(setIndex++, p->sp_namp);
82 SETS(setIndex++, p->sp_pwdp);
83 SETI(setIndex++, p->sp_lstchg);
84 SETI(setIndex++, p->sp_min);
85 SETI(setIndex++, p->sp_max);
86 SETI(setIndex++, p->sp_warn);
87 SETI(setIndex++, p->sp_inact);
88 SETI(setIndex++, p->sp_expire);
89 SETI(setIndex++, p->sp_flag);
Martin v. Löwisc3001752005-01-23 09:27:24 +000090
91#undef SETS
92#undef SETI
93
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000094 if (PyErr_Occurred()) {
95 Py_DECREF(v);
96 return NULL;
97 }
Martin v. Löwisc3001752005-01-23 09:27:24 +000098
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000099 return v;
Martin v. Löwisc3001752005-01-23 09:27:24 +0000100}
101
102#endif /* HAVE_GETSPNAM || HAVE_GETSPENT */
103
104
105#ifdef HAVE_GETSPNAM
106
107PyDoc_STRVAR(spwd_getspnam__doc__,
108"getspnam(name) -> (sp_namp, sp_pwdp, sp_lstchg, sp_min, sp_max,\n\
109 sp_warn, sp_inact, sp_expire, sp_flag)\n\
110Return the shadow password database entry for the given user name.\n\
111See spwd.__doc__ for more on shadow password database entries.");
112
113static PyObject* spwd_getspnam(PyObject *self, PyObject *args)
114{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000115 char *name;
116 struct spwd *p;
117 PyObject *arg, *bytes, *retval = NULL;
Martin v. Löwisb6a748b2009-05-29 15:23:17 +0000118
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000119 if (!PyArg_ParseTuple(args, "U:getspnam", &arg))
120 return NULL;
121 if ((bytes = PyUnicode_AsEncodedString(arg,
122 Py_FileSystemDefaultEncoding,
123 "surrogateescape")) == NULL)
124 return NULL;
125 if (PyBytes_AsStringAndSize(bytes, &name, NULL) == -1)
126 goto out;
127 if ((p = getspnam(name)) == NULL) {
128 PyErr_SetString(PyExc_KeyError, "getspnam(): name not found");
129 goto out;
130 }
131 retval = mkspent(p);
Martin v. Löwisb6a748b2009-05-29 15:23:17 +0000132out:
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000133 Py_DECREF(bytes);
134 return retval;
Martin v. Löwisc3001752005-01-23 09:27:24 +0000135}
136
Neal Norwitz62679962005-01-24 23:33:50 +0000137#endif /* HAVE_GETSPNAM */
138
139#ifdef HAVE_GETSPENT
140
Martin v. Löwisc3001752005-01-23 09:27:24 +0000141PyDoc_STRVAR(spwd_getspall__doc__,
142"getspall() -> list_of_entries\n\
143Return a list of all available shadow password database entries, \
144in arbitrary order.\n\
145See spwd.__doc__ for more on shadow password database entries.");
146
Martin v. Löwisc3001752005-01-23 09:27:24 +0000147static PyObject *
148spwd_getspall(PyObject *self, PyObject *args)
149{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000150 PyObject *d;
151 struct spwd *p;
152 if ((d = PyList_New(0)) == NULL)
153 return NULL;
154 setspent();
155 while ((p = getspent()) != NULL) {
156 PyObject *v = mkspent(p);
157 if (v == NULL || PyList_Append(d, v) != 0) {
158 Py_XDECREF(v);
159 Py_DECREF(d);
160 endspent();
161 return NULL;
162 }
163 Py_DECREF(v);
164 }
165 endspent();
166 return d;
Martin v. Löwisc3001752005-01-23 09:27:24 +0000167}
168
169#endif /* HAVE_GETSPENT */
170
171static PyMethodDef spwd_methods[] = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000172#ifdef HAVE_GETSPNAM
173 {"getspnam", spwd_getspnam, METH_VARARGS, spwd_getspnam__doc__},
Martin v. Löwisc3001752005-01-23 09:27:24 +0000174#endif
175#ifdef HAVE_GETSPENT
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000176 {"getspall", spwd_getspall, METH_NOARGS, spwd_getspall__doc__},
Martin v. Löwisc3001752005-01-23 09:27:24 +0000177#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000178 {NULL, NULL} /* sentinel */
Martin v. Löwisc3001752005-01-23 09:27:24 +0000179};
180
181
Martin v. Löwis1a214512008-06-11 05:26:20 +0000182
183static struct PyModuleDef spwdmodule = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000184 PyModuleDef_HEAD_INIT,
185 "spwd",
186 spwd__doc__,
187 -1,
188 spwd_methods,
189 NULL,
190 NULL,
191 NULL,
192 NULL
Martin v. Löwis1a214512008-06-11 05:26:20 +0000193};
194
Martin v. Löwisc3001752005-01-23 09:27:24 +0000195PyMODINIT_FUNC
Martin v. Löwis1a214512008-06-11 05:26:20 +0000196PyInit_spwd(void)
Martin v. Löwisc3001752005-01-23 09:27:24 +0000197{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000198 PyObject *m;
199 m=PyModule_Create(&spwdmodule);
200 if (m == NULL)
201 return NULL;
202 if (!initialized)
203 PyStructSequence_InitType(&StructSpwdType,
204 &struct_spwd_type_desc);
205 Py_INCREF((PyObject *) &StructSpwdType);
206 PyModule_AddObject(m, "struct_spwd", (PyObject *) &StructSpwdType);
207 initialized = 1;
208 return m;
Martin v. Löwisc3001752005-01-23 09:27:24 +0000209}