blob: 96707b4ada829e7c78e8d10cf0599fa62671a723 [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;
Victor Stinnerae6265f2010-05-15 16:27:27 +0000121 if ((bytes = PyUnicode_EncodeFSDefault(arg)) == NULL)
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000122 return NULL;
123 if (PyBytes_AsStringAndSize(bytes, &name, NULL) == -1)
124 goto out;
125 if ((p = getspnam(name)) == NULL) {
126 PyErr_SetString(PyExc_KeyError, "getspnam(): name not found");
127 goto out;
128 }
129 retval = mkspent(p);
Martin v. Löwisb6a748b2009-05-29 15:23:17 +0000130out:
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000131 Py_DECREF(bytes);
132 return retval;
Martin v. Löwisc3001752005-01-23 09:27:24 +0000133}
134
Neal Norwitz62679962005-01-24 23:33:50 +0000135#endif /* HAVE_GETSPNAM */
136
137#ifdef HAVE_GETSPENT
138
Martin v. Löwisc3001752005-01-23 09:27:24 +0000139PyDoc_STRVAR(spwd_getspall__doc__,
140"getspall() -> list_of_entries\n\
141Return a list of all available shadow password database entries, \
142in arbitrary order.\n\
143See spwd.__doc__ for more on shadow password database entries.");
144
Martin v. Löwisc3001752005-01-23 09:27:24 +0000145static PyObject *
146spwd_getspall(PyObject *self, PyObject *args)
147{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000148 PyObject *d;
149 struct spwd *p;
150 if ((d = PyList_New(0)) == NULL)
151 return NULL;
152 setspent();
153 while ((p = getspent()) != NULL) {
154 PyObject *v = mkspent(p);
155 if (v == NULL || PyList_Append(d, v) != 0) {
156 Py_XDECREF(v);
157 Py_DECREF(d);
158 endspent();
159 return NULL;
160 }
161 Py_DECREF(v);
162 }
163 endspent();
164 return d;
Martin v. Löwisc3001752005-01-23 09:27:24 +0000165}
166
167#endif /* HAVE_GETSPENT */
168
169static PyMethodDef spwd_methods[] = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000170#ifdef HAVE_GETSPNAM
171 {"getspnam", spwd_getspnam, METH_VARARGS, spwd_getspnam__doc__},
Martin v. Löwisc3001752005-01-23 09:27:24 +0000172#endif
173#ifdef HAVE_GETSPENT
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000174 {"getspall", spwd_getspall, METH_NOARGS, spwd_getspall__doc__},
Martin v. Löwisc3001752005-01-23 09:27:24 +0000175#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000176 {NULL, NULL} /* sentinel */
Martin v. Löwisc3001752005-01-23 09:27:24 +0000177};
178
179
Martin v. Löwis1a214512008-06-11 05:26:20 +0000180
181static struct PyModuleDef spwdmodule = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000182 PyModuleDef_HEAD_INIT,
183 "spwd",
184 spwd__doc__,
185 -1,
186 spwd_methods,
187 NULL,
188 NULL,
189 NULL,
190 NULL
Martin v. Löwis1a214512008-06-11 05:26:20 +0000191};
192
Martin v. Löwisc3001752005-01-23 09:27:24 +0000193PyMODINIT_FUNC
Martin v. Löwis1a214512008-06-11 05:26:20 +0000194PyInit_spwd(void)
Martin v. Löwisc3001752005-01-23 09:27:24 +0000195{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000196 PyObject *m;
197 m=PyModule_Create(&spwdmodule);
198 if (m == NULL)
199 return NULL;
200 if (!initialized)
201 PyStructSequence_InitType(&StructSpwdType,
202 &struct_spwd_type_desc);
203 Py_INCREF((PyObject *) &StructSpwdType);
204 PyModule_AddObject(m, "struct_spwd", (PyObject *) &StructSpwdType);
205 initialized = 1;
206 return m;
Martin v. Löwisc3001752005-01-23 09:27:24 +0000207}