blob: 013cb1156e083979403815d8bdd14d91bb2d4fef [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 Cannon52d67ef2014-08-22 14:01:56 -040013#include "clinic/spwdmodule.c.h"
14
Brett Cannon20cf6dd2014-08-22 13:59:24 -040015/*[clinic input]
16output preset file
17module spwd
18[clinic start generated code]*/
19/*[clinic end generated code: output=da39a3ee5e6b4b0d input=b3464a3667278fae]*/
Martin v. Löwisc3001752005-01-23 09:27:24 +000020
21PyDoc_STRVAR(spwd__doc__,
22"This module provides access to the Unix shadow password database.\n\
23It is available on various Unix versions.\n\
24\n\
25Shadow password database entries are reported as 9-tuples of type struct_spwd,\n\
26containing the following items from the password database (see `<shadow.h>'):\n\
27sp_namp, sp_pwdp, sp_lstchg, sp_min, sp_max, sp_warn, sp_inact, sp_expire, sp_flag.\n\
28The sp_namp and sp_pwdp are strings, the rest are integers.\n\
29An exception is raised if the entry asked for cannot be found.\n\
30You have to be root to be able to use this module.");
31
32
33#if defined(HAVE_GETSPNAM) || defined(HAVE_GETSPENT)
34
35static PyStructSequence_Field struct_spwd_type_fields[] = {
R David Murraybd90d092013-11-03 19:54:05 -050036 {"sp_namp", "login name"},
37 {"sp_pwdp", "encrypted password"},
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000038 {"sp_lstchg", "date of last change"},
39 {"sp_min", "min #days between changes"},
40 {"sp_max", "max #days between changes"},
41 {"sp_warn", "#days before pw expires to warn user about it"},
R David Murraybd90d092013-11-03 19:54:05 -050042 {"sp_inact", "#days after pw expires until account is disabled"},
43 {"sp_expire", "#days since 1970-01-01 when account expires"},
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000044 {"sp_flag", "reserved"},
R David Murraybd90d092013-11-03 19:54:05 -050045 {"sp_nam", "login name; deprecated"}, /* Backward compatibility */
46 {"sp_pwd", "encrypted password; deprecated"}, /* Backward compatibility */
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000047 {0}
Martin v. Löwisc3001752005-01-23 09:27:24 +000048};
49
50PyDoc_STRVAR(struct_spwd__doc__,
51"spwd.struct_spwd: Results from getsp*() routines.\n\n\
52This object may be accessed either as a 9-tuple of\n\
R David Murraybd90d092013-11-03 19:54:05 -050053 (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 +000054or via the object attributes as named in the above tuple.");
55
56static PyStructSequence_Desc struct_spwd_type_desc = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000057 "spwd.struct_spwd",
58 struct_spwd__doc__,
59 struct_spwd_type_fields,
60 9,
Martin v. Löwisc3001752005-01-23 09:27:24 +000061};
62
Thomas Wouters49fd7fa2006-04-21 10:40:58 +000063static int initialized;
Martin v. Löwisc3001752005-01-23 09:27:24 +000064static PyTypeObject StructSpwdType;
65
66
67static void
Neal Norwitzeb8b3a62007-08-24 23:26:23 +000068sets(PyObject *v, int i, const char* val)
Martin v. Löwisc3001752005-01-23 09:27:24 +000069{
Martin v. Löwisb6a748b2009-05-29 15:23:17 +000070 if (val) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000071 PyObject *o = PyUnicode_DecodeFSDefault(val);
72 PyStructSequence_SET_ITEM(v, i, o);
Martin v. Löwisb6a748b2009-05-29 15:23:17 +000073 } else {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000074 PyStructSequence_SET_ITEM(v, i, Py_None);
75 Py_INCREF(Py_None);
Martin v. Löwisc3001752005-01-23 09:27:24 +000076 }
77}
78
79static PyObject *mkspent(struct spwd *p)
80{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000081 int setIndex = 0;
82 PyObject *v = PyStructSequence_New(&StructSpwdType);
83 if (v == NULL)
84 return NULL;
Martin v. Löwisc3001752005-01-23 09:27:24 +000085
Christian Heimes217cfd12007-12-02 14:31:20 +000086#define SETI(i,val) PyStructSequence_SET_ITEM(v, i, PyLong_FromLong((long) val))
Martin v. Löwisc3001752005-01-23 09:27:24 +000087#define SETS(i,val) sets(v, i, val)
88
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000089 SETS(setIndex++, p->sp_namp);
90 SETS(setIndex++, p->sp_pwdp);
91 SETI(setIndex++, p->sp_lstchg);
92 SETI(setIndex++, p->sp_min);
93 SETI(setIndex++, p->sp_max);
94 SETI(setIndex++, p->sp_warn);
95 SETI(setIndex++, p->sp_inact);
96 SETI(setIndex++, p->sp_expire);
97 SETI(setIndex++, p->sp_flag);
R David Murraybd90d092013-11-03 19:54:05 -050098 SETS(setIndex++, p->sp_namp); /* Backward compatibility for sp_nam */
99 SETS(setIndex++, p->sp_pwdp); /* Backward compatibility for sp_pwd */
Martin v. Löwisc3001752005-01-23 09:27:24 +0000100
101#undef SETS
102#undef SETI
103
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000104 if (PyErr_Occurred()) {
105 Py_DECREF(v);
106 return NULL;
107 }
Martin v. Löwisc3001752005-01-23 09:27:24 +0000108
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000109 return v;
Martin v. Löwisc3001752005-01-23 09:27:24 +0000110}
111
112#endif /* HAVE_GETSPNAM || HAVE_GETSPENT */
113
114
115#ifdef HAVE_GETSPNAM
116
Brett Cannon20cf6dd2014-08-22 13:59:24 -0400117/*[clinic input]
118spwd.getspnam
Martin v. Löwisc3001752005-01-23 09:27:24 +0000119
Brett Cannon20cf6dd2014-08-22 13:59:24 -0400120 arg: unicode
121 /
122
123Return the shadow password database entry for the given user name.
124
125See `help(spwd)` for more on shadow password database entries.
126[clinic start generated code]*/
127
128static PyObject *
129spwd_getspnam_impl(PyModuleDef *module, PyObject *arg)
130/*[clinic end generated code: output=9f6bbe51a4eb3b21 input=dd89429e6167a00f]*/
Martin v. Löwisc3001752005-01-23 09:27:24 +0000131{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000132 char *name;
133 struct spwd *p;
Brett Cannon20cf6dd2014-08-22 13:59:24 -0400134 PyObject *bytes, *retval = NULL;
Martin v. Löwisb6a748b2009-05-29 15:23:17 +0000135
Victor Stinnerae6265f2010-05-15 16:27:27 +0000136 if ((bytes = PyUnicode_EncodeFSDefault(arg)) == NULL)
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000137 return NULL;
138 if (PyBytes_AsStringAndSize(bytes, &name, NULL) == -1)
139 goto out;
140 if ((p = getspnam(name)) == NULL) {
141 PyErr_SetString(PyExc_KeyError, "getspnam(): name not found");
142 goto out;
143 }
144 retval = mkspent(p);
Martin v. Löwisb6a748b2009-05-29 15:23:17 +0000145out:
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000146 Py_DECREF(bytes);
147 return retval;
Martin v. Löwisc3001752005-01-23 09:27:24 +0000148}
149
Neal Norwitz62679962005-01-24 23:33:50 +0000150#endif /* HAVE_GETSPNAM */
151
152#ifdef HAVE_GETSPENT
153
Brett Cannon20cf6dd2014-08-22 13:59:24 -0400154/*[clinic input]
155spwd.getspall
156
157Return a list of all available shadow password database entries, in arbitrary order.
158
159See `help(spwd)` for more on shadow password database entries.
160[clinic start generated code]*/
Martin v. Löwisc3001752005-01-23 09:27:24 +0000161
Martin v. Löwisc3001752005-01-23 09:27:24 +0000162static PyObject *
Brett Cannon20cf6dd2014-08-22 13:59:24 -0400163spwd_getspall_impl(PyModuleDef *module)
164/*[clinic end generated code: output=b12d8ec7bdb29612 input=b2c84b7857d622bd]*/
Martin v. Löwisc3001752005-01-23 09:27:24 +0000165{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000166 PyObject *d;
167 struct spwd *p;
168 if ((d = PyList_New(0)) == NULL)
169 return NULL;
170 setspent();
171 while ((p = getspent()) != NULL) {
172 PyObject *v = mkspent(p);
173 if (v == NULL || PyList_Append(d, v) != 0) {
174 Py_XDECREF(v);
175 Py_DECREF(d);
176 endspent();
177 return NULL;
178 }
179 Py_DECREF(v);
180 }
181 endspent();
182 return d;
Martin v. Löwisc3001752005-01-23 09:27:24 +0000183}
184
185#endif /* HAVE_GETSPENT */
186
187static PyMethodDef spwd_methods[] = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000188#ifdef HAVE_GETSPNAM
Brett Cannon20cf6dd2014-08-22 13:59:24 -0400189 SPWD_GETSPNAM_METHODDEF
Martin v. Löwisc3001752005-01-23 09:27:24 +0000190#endif
191#ifdef HAVE_GETSPENT
Brett Cannon20cf6dd2014-08-22 13:59:24 -0400192 SPWD_GETSPALL_METHODDEF
Martin v. Löwisc3001752005-01-23 09:27:24 +0000193#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000194 {NULL, NULL} /* sentinel */
Martin v. Löwisc3001752005-01-23 09:27:24 +0000195};
196
197
Martin v. Löwis1a214512008-06-11 05:26:20 +0000198
199static struct PyModuleDef spwdmodule = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000200 PyModuleDef_HEAD_INIT,
201 "spwd",
202 spwd__doc__,
203 -1,
204 spwd_methods,
205 NULL,
206 NULL,
207 NULL,
208 NULL
Martin v. Löwis1a214512008-06-11 05:26:20 +0000209};
210
Martin v. Löwisc3001752005-01-23 09:27:24 +0000211PyMODINIT_FUNC
Martin v. Löwis1a214512008-06-11 05:26:20 +0000212PyInit_spwd(void)
Martin v. Löwisc3001752005-01-23 09:27:24 +0000213{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000214 PyObject *m;
215 m=PyModule_Create(&spwdmodule);
216 if (m == NULL)
217 return NULL;
Victor Stinner1c8f0592013-07-22 22:24:54 +0200218 if (!initialized) {
219 if (PyStructSequence_InitType2(&StructSpwdType,
220 &struct_spwd_type_desc) < 0)
221 return NULL;
222 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000223 Py_INCREF((PyObject *) &StructSpwdType);
224 PyModule_AddObject(m, "struct_spwd", (PyObject *) &StructSpwdType);
225 initialized = 1;
226 return m;
Martin v. Löwisc3001752005-01-23 09:27:24 +0000227}