blob: 6ef4a7d265e4b6d5b905a4313853cfccf48e8fb0 [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
Brett Cannon20cf6dd2014-08-22 13:59:24 -040013/*[clinic input]
14output preset file
15module spwd
16[clinic start generated code]*/
17/*[clinic end generated code: output=da39a3ee5e6b4b0d input=b3464a3667278fae]*/
Martin v. Löwisc3001752005-01-23 09:27:24 +000018
19PyDoc_STRVAR(spwd__doc__,
20"This module provides access to the Unix shadow password database.\n\
21It is available on various Unix versions.\n\
22\n\
23Shadow password database entries are reported as 9-tuples of type struct_spwd,\n\
24containing the following items from the password database (see `<shadow.h>'):\n\
25sp_namp, sp_pwdp, sp_lstchg, sp_min, sp_max, sp_warn, sp_inact, sp_expire, sp_flag.\n\
26The sp_namp and sp_pwdp are strings, the rest are integers.\n\
27An exception is raised if the entry asked for cannot be found.\n\
28You have to be root to be able to use this module.");
29
30
31#if defined(HAVE_GETSPNAM) || defined(HAVE_GETSPENT)
32
33static PyStructSequence_Field struct_spwd_type_fields[] = {
R David Murraybd90d092013-11-03 19:54:05 -050034 {"sp_namp", "login name"},
35 {"sp_pwdp", "encrypted password"},
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000036 {"sp_lstchg", "date of last change"},
37 {"sp_min", "min #days between changes"},
38 {"sp_max", "max #days between changes"},
39 {"sp_warn", "#days before pw expires to warn user about it"},
R David Murraybd90d092013-11-03 19:54:05 -050040 {"sp_inact", "#days after pw expires until account is disabled"},
41 {"sp_expire", "#days since 1970-01-01 when account expires"},
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000042 {"sp_flag", "reserved"},
R David Murraybd90d092013-11-03 19:54:05 -050043 {"sp_nam", "login name; deprecated"}, /* Backward compatibility */
44 {"sp_pwd", "encrypted password; deprecated"}, /* Backward compatibility */
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000045 {0}
Martin v. Löwisc3001752005-01-23 09:27:24 +000046};
47
48PyDoc_STRVAR(struct_spwd__doc__,
49"spwd.struct_spwd: Results from getsp*() routines.\n\n\
50This object may be accessed either as a 9-tuple of\n\
R David Murraybd90d092013-11-03 19:54:05 -050051 (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 +000052or via the object attributes as named in the above tuple.");
53
54static PyStructSequence_Desc struct_spwd_type_desc = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000055 "spwd.struct_spwd",
56 struct_spwd__doc__,
57 struct_spwd_type_fields,
58 9,
Martin v. Löwisc3001752005-01-23 09:27:24 +000059};
60
Thomas Wouters49fd7fa2006-04-21 10:40:58 +000061static int initialized;
Martin v. Löwisc3001752005-01-23 09:27:24 +000062static PyTypeObject StructSpwdType;
63
64
65static void
Neal Norwitzeb8b3a62007-08-24 23:26:23 +000066sets(PyObject *v, int i, const char* val)
Martin v. Löwisc3001752005-01-23 09:27:24 +000067{
Martin v. Löwisb6a748b2009-05-29 15:23:17 +000068 if (val) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000069 PyObject *o = PyUnicode_DecodeFSDefault(val);
70 PyStructSequence_SET_ITEM(v, i, o);
Martin v. Löwisb6a748b2009-05-29 15:23:17 +000071 } else {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000072 PyStructSequence_SET_ITEM(v, i, Py_None);
73 Py_INCREF(Py_None);
Martin v. Löwisc3001752005-01-23 09:27:24 +000074 }
75}
76
77static PyObject *mkspent(struct spwd *p)
78{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000079 int setIndex = 0;
80 PyObject *v = PyStructSequence_New(&StructSpwdType);
81 if (v == NULL)
82 return NULL;
Martin v. Löwisc3001752005-01-23 09:27:24 +000083
Christian Heimes217cfd12007-12-02 14:31:20 +000084#define SETI(i,val) PyStructSequence_SET_ITEM(v, i, PyLong_FromLong((long) val))
Martin v. Löwisc3001752005-01-23 09:27:24 +000085#define SETS(i,val) sets(v, i, val)
86
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000087 SETS(setIndex++, p->sp_namp);
88 SETS(setIndex++, p->sp_pwdp);
89 SETI(setIndex++, p->sp_lstchg);
90 SETI(setIndex++, p->sp_min);
91 SETI(setIndex++, p->sp_max);
92 SETI(setIndex++, p->sp_warn);
93 SETI(setIndex++, p->sp_inact);
94 SETI(setIndex++, p->sp_expire);
95 SETI(setIndex++, p->sp_flag);
R David Murraybd90d092013-11-03 19:54:05 -050096 SETS(setIndex++, p->sp_namp); /* Backward compatibility for sp_nam */
97 SETS(setIndex++, p->sp_pwdp); /* Backward compatibility for sp_pwd */
Martin v. Löwisc3001752005-01-23 09:27:24 +000098
99#undef SETS
100#undef SETI
101
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000102 if (PyErr_Occurred()) {
103 Py_DECREF(v);
104 return NULL;
105 }
Martin v. Löwisc3001752005-01-23 09:27:24 +0000106
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000107 return v;
Martin v. Löwisc3001752005-01-23 09:27:24 +0000108}
109
110#endif /* HAVE_GETSPNAM || HAVE_GETSPENT */
111
112
113#ifdef HAVE_GETSPNAM
114
Brett Cannon20cf6dd2014-08-22 13:59:24 -0400115/*[clinic input]
116spwd.getspnam
Martin v. Löwisc3001752005-01-23 09:27:24 +0000117
Brett Cannon20cf6dd2014-08-22 13:59:24 -0400118 arg: unicode
119 /
120
121Return the shadow password database entry for the given user name.
122
123See `help(spwd)` for more on shadow password database entries.
124[clinic start generated code]*/
125
126static PyObject *
127spwd_getspnam_impl(PyModuleDef *module, PyObject *arg)
128/*[clinic end generated code: output=9f6bbe51a4eb3b21 input=dd89429e6167a00f]*/
Martin v. Löwisc3001752005-01-23 09:27:24 +0000129{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000130 char *name;
131 struct spwd *p;
Brett Cannon20cf6dd2014-08-22 13:59:24 -0400132 PyObject *bytes, *retval = NULL;
Martin v. Löwisb6a748b2009-05-29 15:23:17 +0000133
Victor Stinnerae6265f2010-05-15 16:27:27 +0000134 if ((bytes = PyUnicode_EncodeFSDefault(arg)) == NULL)
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000135 return NULL;
136 if (PyBytes_AsStringAndSize(bytes, &name, NULL) == -1)
137 goto out;
138 if ((p = getspnam(name)) == NULL) {
139 PyErr_SetString(PyExc_KeyError, "getspnam(): name not found");
140 goto out;
141 }
142 retval = mkspent(p);
Martin v. Löwisb6a748b2009-05-29 15:23:17 +0000143out:
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000144 Py_DECREF(bytes);
145 return retval;
Martin v. Löwisc3001752005-01-23 09:27:24 +0000146}
147
Neal Norwitz62679962005-01-24 23:33:50 +0000148#endif /* HAVE_GETSPNAM */
149
150#ifdef HAVE_GETSPENT
151
Brett Cannon20cf6dd2014-08-22 13:59:24 -0400152/*[clinic input]
153spwd.getspall
154
155Return a list of all available shadow password database entries, in arbitrary order.
156
157See `help(spwd)` for more on shadow password database entries.
158[clinic start generated code]*/
Martin v. Löwisc3001752005-01-23 09:27:24 +0000159
Martin v. Löwisc3001752005-01-23 09:27:24 +0000160static PyObject *
Brett Cannon20cf6dd2014-08-22 13:59:24 -0400161spwd_getspall_impl(PyModuleDef *module)
162/*[clinic end generated code: output=b12d8ec7bdb29612 input=b2c84b7857d622bd]*/
Martin v. Löwisc3001752005-01-23 09:27:24 +0000163{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000164 PyObject *d;
165 struct spwd *p;
166 if ((d = PyList_New(0)) == NULL)
167 return NULL;
168 setspent();
169 while ((p = getspent()) != NULL) {
170 PyObject *v = mkspent(p);
171 if (v == NULL || PyList_Append(d, v) != 0) {
172 Py_XDECREF(v);
173 Py_DECREF(d);
174 endspent();
175 return NULL;
176 }
177 Py_DECREF(v);
178 }
179 endspent();
180 return d;
Martin v. Löwisc3001752005-01-23 09:27:24 +0000181}
182
183#endif /* HAVE_GETSPENT */
184
185static PyMethodDef spwd_methods[] = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000186#ifdef HAVE_GETSPNAM
Brett Cannon20cf6dd2014-08-22 13:59:24 -0400187 SPWD_GETSPNAM_METHODDEF
Martin v. Löwisc3001752005-01-23 09:27:24 +0000188#endif
189#ifdef HAVE_GETSPENT
Brett Cannon20cf6dd2014-08-22 13:59:24 -0400190 SPWD_GETSPALL_METHODDEF
Martin v. Löwisc3001752005-01-23 09:27:24 +0000191#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000192 {NULL, NULL} /* sentinel */
Martin v. Löwisc3001752005-01-23 09:27:24 +0000193};
194
195
Martin v. Löwis1a214512008-06-11 05:26:20 +0000196
197static struct PyModuleDef spwdmodule = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000198 PyModuleDef_HEAD_INIT,
199 "spwd",
200 spwd__doc__,
201 -1,
202 spwd_methods,
203 NULL,
204 NULL,
205 NULL,
206 NULL
Martin v. Löwis1a214512008-06-11 05:26:20 +0000207};
208
Martin v. Löwisc3001752005-01-23 09:27:24 +0000209PyMODINIT_FUNC
Martin v. Löwis1a214512008-06-11 05:26:20 +0000210PyInit_spwd(void)
Martin v. Löwisc3001752005-01-23 09:27:24 +0000211{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000212 PyObject *m;
213 m=PyModule_Create(&spwdmodule);
214 if (m == NULL)
215 return NULL;
Victor Stinner1c8f0592013-07-22 22:24:54 +0200216 if (!initialized) {
217 if (PyStructSequence_InitType2(&StructSpwdType,
218 &struct_spwd_type_desc) < 0)
219 return NULL;
220 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000221 Py_INCREF((PyObject *) &StructSpwdType);
222 PyModule_AddObject(m, "struct_spwd", (PyObject *) &StructSpwdType);
223 initialized = 1;
224 return m;
Martin v. Löwisc3001752005-01-23 09:27:24 +0000225}