blob: 194ae196ba7c515b8445c8b223662909fea0aad5 [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"
Martin v. Löwisc3001752005-01-23 09:27:24 +00007
8#include <sys/types.h>
9#ifdef HAVE_SHADOW_H
10#include <shadow.h>
11#endif
12
13
14PyDoc_STRVAR(spwd__doc__,
15"This module provides access to the Unix shadow password database.\n\
16It is available on various Unix versions.\n\
17\n\
18Shadow password database entries are reported as 9-tuples of type struct_spwd,\n\
19containing the following items from the password database (see `<shadow.h>'):\n\
20sp_namp, sp_pwdp, sp_lstchg, sp_min, sp_max, sp_warn, sp_inact, sp_expire, sp_flag.\n\
21The sp_namp and sp_pwdp are strings, the rest are integers.\n\
22An exception is raised if the entry asked for cannot be found.\n\
23You have to be root to be able to use this module.");
24
25
26#if defined(HAVE_GETSPNAM) || defined(HAVE_GETSPENT)
27
28static PyStructSequence_Field struct_spwd_type_fields[] = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000029 {"sp_nam", "login name"},
30 {"sp_pwd", "encrypted password"},
31 {"sp_lstchg", "date of last change"},
32 {"sp_min", "min #days between changes"},
33 {"sp_max", "max #days between changes"},
34 {"sp_warn", "#days before pw expires to warn user about it"},
35 {"sp_inact", "#days after pw expires until account is blocked"},
36 {"sp_expire", "#days since 1970-01-01 until account is disabled"},
37 {"sp_flag", "reserved"},
38 {0}
Martin v. Löwisc3001752005-01-23 09:27:24 +000039};
40
41PyDoc_STRVAR(struct_spwd__doc__,
42"spwd.struct_spwd: Results from getsp*() routines.\n\n\
43This object may be accessed either as a 9-tuple of\n\
44 (sp_nam,sp_pwd,sp_lstchg,sp_min,sp_max,sp_warn,sp_inact,sp_expire,sp_flag)\n\
45or via the object attributes as named in the above tuple.");
46
47static PyStructSequence_Desc struct_spwd_type_desc = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000048 "spwd.struct_spwd",
49 struct_spwd__doc__,
50 struct_spwd_type_fields,
51 9,
Martin v. Löwisc3001752005-01-23 09:27:24 +000052};
53
Thomas Wouters49fd7fa2006-04-21 10:40:58 +000054static int initialized;
Martin v. Löwisc3001752005-01-23 09:27:24 +000055static PyTypeObject StructSpwdType;
56
57
58static void
Neal Norwitzeb8b3a62007-08-24 23:26:23 +000059sets(PyObject *v, int i, const char* val)
Martin v. Löwisc3001752005-01-23 09:27:24 +000060{
Martin v. Löwisb6a748b2009-05-29 15:23:17 +000061 if (val) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000062 PyObject *o = PyUnicode_DecodeFSDefault(val);
63 PyStructSequence_SET_ITEM(v, i, o);
Martin v. Löwisb6a748b2009-05-29 15:23:17 +000064 } else {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000065 PyStructSequence_SET_ITEM(v, i, Py_None);
66 Py_INCREF(Py_None);
Martin v. Löwisc3001752005-01-23 09:27:24 +000067 }
68}
69
70static PyObject *mkspent(struct spwd *p)
71{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000072 int setIndex = 0;
73 PyObject *v = PyStructSequence_New(&StructSpwdType);
74 if (v == NULL)
75 return NULL;
Martin v. Löwisc3001752005-01-23 09:27:24 +000076
Christian Heimes217cfd12007-12-02 14:31:20 +000077#define SETI(i,val) PyStructSequence_SET_ITEM(v, i, PyLong_FromLong((long) val))
Martin v. Löwisc3001752005-01-23 09:27:24 +000078#define SETS(i,val) sets(v, i, val)
79
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000080 SETS(setIndex++, p->sp_namp);
81 SETS(setIndex++, p->sp_pwdp);
82 SETI(setIndex++, p->sp_lstchg);
83 SETI(setIndex++, p->sp_min);
84 SETI(setIndex++, p->sp_max);
85 SETI(setIndex++, p->sp_warn);
86 SETI(setIndex++, p->sp_inact);
87 SETI(setIndex++, p->sp_expire);
88 SETI(setIndex++, p->sp_flag);
Martin v. Löwisc3001752005-01-23 09:27:24 +000089
90#undef SETS
91#undef SETI
92
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000093 if (PyErr_Occurred()) {
94 Py_DECREF(v);
95 return NULL;
96 }
Martin v. Löwisc3001752005-01-23 09:27:24 +000097
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000098 return v;
Martin v. Löwisc3001752005-01-23 09:27:24 +000099}
100
101#endif /* HAVE_GETSPNAM || HAVE_GETSPENT */
102
103
104#ifdef HAVE_GETSPNAM
105
106PyDoc_STRVAR(spwd_getspnam__doc__,
107"getspnam(name) -> (sp_namp, sp_pwdp, sp_lstchg, sp_min, sp_max,\n\
108 sp_warn, sp_inact, sp_expire, sp_flag)\n\
109Return the shadow password database entry for the given user name.\n\
110See spwd.__doc__ for more on shadow password database entries.");
111
112static PyObject* spwd_getspnam(PyObject *self, PyObject *args)
113{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000114 char *name;
115 struct spwd *p;
116 PyObject *arg, *bytes, *retval = NULL;
Martin v. Löwisb6a748b2009-05-29 15:23:17 +0000117
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000118 if (!PyArg_ParseTuple(args, "U:getspnam", &arg))
119 return NULL;
Victor Stinnerae6265f2010-05-15 16:27:27 +0000120 if ((bytes = PyUnicode_EncodeFSDefault(arg)) == NULL)
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000121 return NULL;
122 if (PyBytes_AsStringAndSize(bytes, &name, NULL) == -1)
123 goto out;
124 if ((p = getspnam(name)) == NULL) {
125 PyErr_SetString(PyExc_KeyError, "getspnam(): name not found");
126 goto out;
127 }
128 retval = mkspent(p);
Martin v. Löwisb6a748b2009-05-29 15:23:17 +0000129out:
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000130 Py_DECREF(bytes);
131 return retval;
Martin v. Löwisc3001752005-01-23 09:27:24 +0000132}
133
Neal Norwitz62679962005-01-24 23:33:50 +0000134#endif /* HAVE_GETSPNAM */
135
136#ifdef HAVE_GETSPENT
137
Martin v. Löwisc3001752005-01-23 09:27:24 +0000138PyDoc_STRVAR(spwd_getspall__doc__,
139"getspall() -> list_of_entries\n\
140Return a list of all available shadow password database entries, \
141in arbitrary order.\n\
142See spwd.__doc__ for more on shadow password database entries.");
143
Martin v. Löwisc3001752005-01-23 09:27:24 +0000144static PyObject *
145spwd_getspall(PyObject *self, PyObject *args)
146{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000147 PyObject *d;
148 struct spwd *p;
149 if ((d = PyList_New(0)) == NULL)
150 return NULL;
151 setspent();
152 while ((p = getspent()) != NULL) {
153 PyObject *v = mkspent(p);
154 if (v == NULL || PyList_Append(d, v) != 0) {
155 Py_XDECREF(v);
156 Py_DECREF(d);
157 endspent();
158 return NULL;
159 }
160 Py_DECREF(v);
161 }
162 endspent();
163 return d;
Martin v. Löwisc3001752005-01-23 09:27:24 +0000164}
165
166#endif /* HAVE_GETSPENT */
167
168static PyMethodDef spwd_methods[] = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000169#ifdef HAVE_GETSPNAM
170 {"getspnam", spwd_getspnam, METH_VARARGS, spwd_getspnam__doc__},
Martin v. Löwisc3001752005-01-23 09:27:24 +0000171#endif
172#ifdef HAVE_GETSPENT
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000173 {"getspall", spwd_getspall, METH_NOARGS, spwd_getspall__doc__},
Martin v. Löwisc3001752005-01-23 09:27:24 +0000174#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000175 {NULL, NULL} /* sentinel */
Martin v. Löwisc3001752005-01-23 09:27:24 +0000176};
177
178
Martin v. Löwis1a214512008-06-11 05:26:20 +0000179
180static struct PyModuleDef spwdmodule = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000181 PyModuleDef_HEAD_INIT,
182 "spwd",
183 spwd__doc__,
184 -1,
185 spwd_methods,
186 NULL,
187 NULL,
188 NULL,
189 NULL
Martin v. Löwis1a214512008-06-11 05:26:20 +0000190};
191
Martin v. Löwisc3001752005-01-23 09:27:24 +0000192PyMODINIT_FUNC
Martin v. Löwis1a214512008-06-11 05:26:20 +0000193PyInit_spwd(void)
Martin v. Löwisc3001752005-01-23 09:27:24 +0000194{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000195 PyObject *m;
196 m=PyModule_Create(&spwdmodule);
197 if (m == NULL)
198 return NULL;
199 if (!initialized)
200 PyStructSequence_InitType(&StructSpwdType,
201 &struct_spwd_type_desc);
202 Py_INCREF((PyObject *) &StructSpwdType);
203 PyModule_AddObject(m, "struct_spwd", (PyObject *) &StructSpwdType);
204 initialized = 1;
205 return m;
Martin v. Löwisc3001752005-01-23 09:27:24 +0000206}