blob: 68ea1b5ea4af2de24643b5b7bf1c1bef8d831004 [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[] = {
R David Murraybd90d092013-11-03 19:54:05 -050029 {"sp_namp", "login name"},
30 {"sp_pwdp", "encrypted password"},
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000031 {"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"},
R David Murraybd90d092013-11-03 19:54:05 -050035 {"sp_inact", "#days after pw expires until account is disabled"},
36 {"sp_expire", "#days since 1970-01-01 when account expires"},
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000037 {"sp_flag", "reserved"},
R David Murraybd90d092013-11-03 19:54:05 -050038 {"sp_nam", "login name; deprecated"}, /* Backward compatibility */
39 {"sp_pwd", "encrypted password; deprecated"}, /* Backward compatibility */
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000040 {0}
Martin v. Löwisc3001752005-01-23 09:27:24 +000041};
42
43PyDoc_STRVAR(struct_spwd__doc__,
44"spwd.struct_spwd: Results from getsp*() routines.\n\n\
45This object may be accessed either as a 9-tuple of\n\
R David Murraybd90d092013-11-03 19:54:05 -050046 (sp_namp,sp_pwdp,sp_lstchg,sp_min,sp_max,sp_warn,sp_inact,sp_expire,sp_flag)\n\
Martin v. Löwisc3001752005-01-23 09:27:24 +000047or via the object attributes as named in the above tuple.");
48
49static PyStructSequence_Desc struct_spwd_type_desc = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000050 "spwd.struct_spwd",
51 struct_spwd__doc__,
52 struct_spwd_type_fields,
53 9,
Martin v. Löwisc3001752005-01-23 09:27:24 +000054};
55
Thomas Wouters49fd7fa2006-04-21 10:40:58 +000056static int initialized;
Martin v. Löwisc3001752005-01-23 09:27:24 +000057static PyTypeObject StructSpwdType;
58
59
60static void
Neal Norwitzeb8b3a62007-08-24 23:26:23 +000061sets(PyObject *v, int i, const char* val)
Martin v. Löwisc3001752005-01-23 09:27:24 +000062{
Martin v. Löwisb6a748b2009-05-29 15:23:17 +000063 if (val) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000064 PyObject *o = PyUnicode_DecodeFSDefault(val);
65 PyStructSequence_SET_ITEM(v, i, o);
Martin v. Löwisb6a748b2009-05-29 15:23:17 +000066 } else {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000067 PyStructSequence_SET_ITEM(v, i, Py_None);
68 Py_INCREF(Py_None);
Martin v. Löwisc3001752005-01-23 09:27:24 +000069 }
70}
71
72static PyObject *mkspent(struct spwd *p)
73{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000074 int setIndex = 0;
75 PyObject *v = PyStructSequence_New(&StructSpwdType);
76 if (v == NULL)
77 return NULL;
Martin v. Löwisc3001752005-01-23 09:27:24 +000078
Christian Heimes217cfd12007-12-02 14:31:20 +000079#define SETI(i,val) PyStructSequence_SET_ITEM(v, i, PyLong_FromLong((long) val))
Martin v. Löwisc3001752005-01-23 09:27:24 +000080#define SETS(i,val) sets(v, i, val)
81
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000082 SETS(setIndex++, p->sp_namp);
83 SETS(setIndex++, p->sp_pwdp);
84 SETI(setIndex++, p->sp_lstchg);
85 SETI(setIndex++, p->sp_min);
86 SETI(setIndex++, p->sp_max);
87 SETI(setIndex++, p->sp_warn);
88 SETI(setIndex++, p->sp_inact);
89 SETI(setIndex++, p->sp_expire);
90 SETI(setIndex++, p->sp_flag);
R David Murraybd90d092013-11-03 19:54:05 -050091 SETS(setIndex++, p->sp_namp); /* Backward compatibility for sp_nam */
92 SETS(setIndex++, p->sp_pwdp); /* Backward compatibility for sp_pwd */
Martin v. Löwisc3001752005-01-23 09:27:24 +000093
94#undef SETS
95#undef SETI
96
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000097 if (PyErr_Occurred()) {
98 Py_DECREF(v);
99 return NULL;
100 }
Martin v. Löwisc3001752005-01-23 09:27:24 +0000101
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000102 return v;
Martin v. Löwisc3001752005-01-23 09:27:24 +0000103}
104
105#endif /* HAVE_GETSPNAM || HAVE_GETSPENT */
106
107
108#ifdef HAVE_GETSPNAM
109
110PyDoc_STRVAR(spwd_getspnam__doc__,
111"getspnam(name) -> (sp_namp, sp_pwdp, sp_lstchg, sp_min, sp_max,\n\
112 sp_warn, sp_inact, sp_expire, sp_flag)\n\
113Return the shadow password database entry for the given user name.\n\
114See spwd.__doc__ for more on shadow password database entries.");
115
116static PyObject* spwd_getspnam(PyObject *self, PyObject *args)
117{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000118 char *name;
119 struct spwd *p;
120 PyObject *arg, *bytes, *retval = NULL;
Martin v. Löwisb6a748b2009-05-29 15:23:17 +0000121
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000122 if (!PyArg_ParseTuple(args, "U:getspnam", &arg))
123 return NULL;
Victor Stinnerae6265f2010-05-15 16:27:27 +0000124 if ((bytes = PyUnicode_EncodeFSDefault(arg)) == NULL)
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000125 return NULL;
126 if (PyBytes_AsStringAndSize(bytes, &name, NULL) == -1)
127 goto out;
128 if ((p = getspnam(name)) == NULL) {
129 PyErr_SetString(PyExc_KeyError, "getspnam(): name not found");
130 goto out;
131 }
132 retval = mkspent(p);
Martin v. Löwisb6a748b2009-05-29 15:23:17 +0000133out:
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000134 Py_DECREF(bytes);
135 return retval;
Martin v. Löwisc3001752005-01-23 09:27:24 +0000136}
137
Neal Norwitz62679962005-01-24 23:33:50 +0000138#endif /* HAVE_GETSPNAM */
139
140#ifdef HAVE_GETSPENT
141
Martin v. Löwisc3001752005-01-23 09:27:24 +0000142PyDoc_STRVAR(spwd_getspall__doc__,
143"getspall() -> list_of_entries\n\
144Return a list of all available shadow password database entries, \
145in arbitrary order.\n\
146See spwd.__doc__ for more on shadow password database entries.");
147
Martin v. Löwisc3001752005-01-23 09:27:24 +0000148static PyObject *
149spwd_getspall(PyObject *self, PyObject *args)
150{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000151 PyObject *d;
152 struct spwd *p;
153 if ((d = PyList_New(0)) == NULL)
154 return NULL;
155 setspent();
156 while ((p = getspent()) != NULL) {
157 PyObject *v = mkspent(p);
158 if (v == NULL || PyList_Append(d, v) != 0) {
159 Py_XDECREF(v);
160 Py_DECREF(d);
161 endspent();
162 return NULL;
163 }
164 Py_DECREF(v);
165 }
166 endspent();
167 return d;
Martin v. Löwisc3001752005-01-23 09:27:24 +0000168}
169
170#endif /* HAVE_GETSPENT */
171
172static PyMethodDef spwd_methods[] = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000173#ifdef HAVE_GETSPNAM
174 {"getspnam", spwd_getspnam, METH_VARARGS, spwd_getspnam__doc__},
Martin v. Löwisc3001752005-01-23 09:27:24 +0000175#endif
176#ifdef HAVE_GETSPENT
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000177 {"getspall", spwd_getspall, METH_NOARGS, spwd_getspall__doc__},
Martin v. Löwisc3001752005-01-23 09:27:24 +0000178#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000179 {NULL, NULL} /* sentinel */
Martin v. Löwisc3001752005-01-23 09:27:24 +0000180};
181
182
Martin v. Löwis1a214512008-06-11 05:26:20 +0000183
184static struct PyModuleDef spwdmodule = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000185 PyModuleDef_HEAD_INIT,
186 "spwd",
187 spwd__doc__,
188 -1,
189 spwd_methods,
190 NULL,
191 NULL,
192 NULL,
193 NULL
Martin v. Löwis1a214512008-06-11 05:26:20 +0000194};
195
Martin v. Löwisc3001752005-01-23 09:27:24 +0000196PyMODINIT_FUNC
Martin v. Löwis1a214512008-06-11 05:26:20 +0000197PyInit_spwd(void)
Martin v. Löwisc3001752005-01-23 09:27:24 +0000198{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000199 PyObject *m;
200 m=PyModule_Create(&spwdmodule);
201 if (m == NULL)
202 return NULL;
Victor Stinner1c8f0592013-07-22 22:24:54 +0200203 if (!initialized) {
204 if (PyStructSequence_InitType2(&StructSpwdType,
205 &struct_spwd_type_desc) < 0)
206 return NULL;
207 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000208 Py_INCREF((PyObject *) &StructSpwdType);
209 PyModule_AddObject(m, "struct_spwd", (PyObject *) &StructSpwdType);
210 initialized = 1;
211 return m;
Martin v. Löwisc3001752005-01-23 09:27:24 +0000212}