blob: 422ab033186fd2e8825a7e2ad808683240cad343 [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[] = {
30 {"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}
40};
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 = {
49 "spwd.struct_spwd",
50 struct_spwd__doc__,
51 struct_spwd_type_fields,
52 9,
53};
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) {
Victor Stinner97c18ab2010-05-07 16:34:53 +000063 PyObject *o = PyUnicode_DecodeFSDefault(val);
Martin v. Löwisb6a748b2009-05-29 15:23:17 +000064 PyStructSequence_SET_ITEM(v, i, o);
65 } else {
Martin v. Löwisc3001752005-01-23 09:27:24 +000066 PyStructSequence_SET_ITEM(v, i, Py_None);
67 Py_INCREF(Py_None);
68 }
69}
70
71static PyObject *mkspent(struct spwd *p)
72{
73 int setIndex = 0;
74 PyObject *v = PyStructSequence_New(&StructSpwdType);
75 if (v == NULL)
76 return NULL;
77
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
81 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);
90
91#undef SETS
92#undef SETI
93
94 if (PyErr_Occurred()) {
Thomas Wouters0e3f5912006-08-11 14:57:12 +000095 Py_DECREF(v);
Martin v. Löwisc3001752005-01-23 09:27:24 +000096 return NULL;
97 }
98
99 return v;
100}
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{
115 char *name;
116 struct spwd *p;
Martin v. Löwisb6a748b2009-05-29 15:23:17 +0000117 PyObject *arg, *bytes, *retval = NULL;
118
119 if (!PyArg_ParseTuple(args, "U:getspnam", &arg))
Martin v. Löwisc3001752005-01-23 09:27:24 +0000120 return NULL;
Martin v. Löwisb6a748b2009-05-29 15:23:17 +0000121 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;
Martin v. Löwisc3001752005-01-23 09:27:24 +0000127 if ((p = getspnam(name)) == NULL) {
128 PyErr_SetString(PyExc_KeyError, "getspnam(): name not found");
Martin v. Löwisb6a748b2009-05-29 15:23:17 +0000129 goto out;
Martin v. Löwisc3001752005-01-23 09:27:24 +0000130 }
Martin v. Löwisb6a748b2009-05-29 15:23:17 +0000131 retval = mkspent(p);
132out:
133 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{
150 PyObject *d;
151 struct spwd *p;
Martin v. Löwisc3001752005-01-23 09:27:24 +0000152 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;
167}
168
169#endif /* HAVE_GETSPENT */
170
171static PyMethodDef spwd_methods[] = {
172#ifdef HAVE_GETSPNAM
173 {"getspnam", spwd_getspnam, METH_VARARGS, spwd_getspnam__doc__},
174#endif
175#ifdef HAVE_GETSPENT
176 {"getspall", spwd_getspall, METH_NOARGS, spwd_getspall__doc__},
177#endif
178 {NULL, NULL} /* sentinel */
179};
180
181
Martin v. Löwis1a214512008-06-11 05:26:20 +0000182
183static struct PyModuleDef spwdmodule = {
184 PyModuleDef_HEAD_INIT,
185 "spwd",
186 spwd__doc__,
187 -1,
188 spwd_methods,
189 NULL,
190 NULL,
191 NULL,
192 NULL
193};
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{
198 PyObject *m;
Martin v. Löwis1a214512008-06-11 05:26:20 +0000199 m=PyModule_Create(&spwdmodule);
Neal Norwitz1ac754f2006-01-19 06:09:39 +0000200 if (m == NULL)
Martin v. Löwis1a214512008-06-11 05:26:20 +0000201 return NULL;
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000202 if (!initialized)
203 PyStructSequence_InitType(&StructSpwdType,
204 &struct_spwd_type_desc);
Martin v. Löwisc3001752005-01-23 09:27:24 +0000205 Py_INCREF((PyObject *) &StructSpwdType);
206 PyModule_AddObject(m, "struct_spwd", (PyObject *) &StructSpwdType);
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000207 initialized = 1;
Martin v. Löwis1a214512008-06-11 05:26:20 +0000208 return m;
Martin v. Löwisc3001752005-01-23 09:27:24 +0000209}