blob: 1601ec0f2fc4e726c248498c2315c091f497f88e [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]
Brett Cannon20cf6dd2014-08-22 13:59:24 -040016module spwd
17[clinic start generated code]*/
Serhiy Storchaka1009bf12015-04-03 23:53:51 +030018/*[clinic end generated code: output=da39a3ee5e6b4b0d input=c0b841b90a6a07ce]*/
Martin v. Löwisc3001752005-01-23 09:27:24 +000019
20PyDoc_STRVAR(spwd__doc__,
21"This module provides access to the Unix shadow password database.\n\
22It is available on various Unix versions.\n\
23\n\
24Shadow password database entries are reported as 9-tuples of type struct_spwd,\n\
25containing the following items from the password database (see `<shadow.h>'):\n\
26sp_namp, sp_pwdp, sp_lstchg, sp_min, sp_max, sp_warn, sp_inact, sp_expire, sp_flag.\n\
27The sp_namp and sp_pwdp are strings, the rest are integers.\n\
28An exception is raised if the entry asked for cannot be found.\n\
29You have to be root to be able to use this module.");
30
31
32#if defined(HAVE_GETSPNAM) || defined(HAVE_GETSPENT)
33
34static PyStructSequence_Field struct_spwd_type_fields[] = {
R David Murraybd90d092013-11-03 19:54:05 -050035 {"sp_namp", "login name"},
36 {"sp_pwdp", "encrypted password"},
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000037 {"sp_lstchg", "date of last change"},
38 {"sp_min", "min #days between changes"},
39 {"sp_max", "max #days between changes"},
40 {"sp_warn", "#days before pw expires to warn user about it"},
R David Murraybd90d092013-11-03 19:54:05 -050041 {"sp_inact", "#days after pw expires until account is disabled"},
42 {"sp_expire", "#days since 1970-01-01 when account expires"},
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000043 {"sp_flag", "reserved"},
R David Murraybd90d092013-11-03 19:54:05 -050044 {"sp_nam", "login name; deprecated"}, /* Backward compatibility */
45 {"sp_pwd", "encrypted password; deprecated"}, /* Backward compatibility */
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000046 {0}
Martin v. Löwisc3001752005-01-23 09:27:24 +000047};
48
49PyDoc_STRVAR(struct_spwd__doc__,
50"spwd.struct_spwd: Results from getsp*() routines.\n\n\
51This object may be accessed either as a 9-tuple of\n\
R David Murraybd90d092013-11-03 19:54:05 -050052 (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 +000053or via the object attributes as named in the above tuple.");
54
55static PyStructSequence_Desc struct_spwd_type_desc = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000056 "spwd.struct_spwd",
57 struct_spwd__doc__,
58 struct_spwd_type_fields,
59 9,
Martin v. Löwisc3001752005-01-23 09:27:24 +000060};
61
Thomas Wouters49fd7fa2006-04-21 10:40:58 +000062static int initialized;
Martin v. Löwisc3001752005-01-23 09:27:24 +000063static PyTypeObject StructSpwdType;
64
65
66static void
Neal Norwitzeb8b3a62007-08-24 23:26:23 +000067sets(PyObject *v, int i, const char* val)
Martin v. Löwisc3001752005-01-23 09:27:24 +000068{
Martin v. Löwisb6a748b2009-05-29 15:23:17 +000069 if (val) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000070 PyObject *o = PyUnicode_DecodeFSDefault(val);
71 PyStructSequence_SET_ITEM(v, i, o);
Martin v. Löwisb6a748b2009-05-29 15:23:17 +000072 } else {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000073 PyStructSequence_SET_ITEM(v, i, Py_None);
74 Py_INCREF(Py_None);
Martin v. Löwisc3001752005-01-23 09:27:24 +000075 }
76}
77
78static PyObject *mkspent(struct spwd *p)
79{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000080 int setIndex = 0;
81 PyObject *v = PyStructSequence_New(&StructSpwdType);
82 if (v == NULL)
83 return NULL;
Martin v. Löwisc3001752005-01-23 09:27:24 +000084
Christian Heimes217cfd12007-12-02 14:31:20 +000085#define SETI(i,val) PyStructSequence_SET_ITEM(v, i, PyLong_FromLong((long) val))
Martin v. Löwisc3001752005-01-23 09:27:24 +000086#define SETS(i,val) sets(v, i, val)
87
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000088 SETS(setIndex++, p->sp_namp);
89 SETS(setIndex++, p->sp_pwdp);
90 SETI(setIndex++, p->sp_lstchg);
91 SETI(setIndex++, p->sp_min);
92 SETI(setIndex++, p->sp_max);
93 SETI(setIndex++, p->sp_warn);
94 SETI(setIndex++, p->sp_inact);
95 SETI(setIndex++, p->sp_expire);
96 SETI(setIndex++, p->sp_flag);
R David Murraybd90d092013-11-03 19:54:05 -050097 SETS(setIndex++, p->sp_namp); /* Backward compatibility for sp_nam */
98 SETS(setIndex++, p->sp_pwdp); /* Backward compatibility for sp_pwd */
Martin v. Löwisc3001752005-01-23 09:27:24 +000099
100#undef SETS
101#undef SETI
102
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000103 if (PyErr_Occurred()) {
104 Py_DECREF(v);
105 return NULL;
106 }
Martin v. Löwisc3001752005-01-23 09:27:24 +0000107
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000108 return v;
Martin v. Löwisc3001752005-01-23 09:27:24 +0000109}
110
111#endif /* HAVE_GETSPNAM || HAVE_GETSPENT */
112
113
114#ifdef HAVE_GETSPNAM
115
Brett Cannon20cf6dd2014-08-22 13:59:24 -0400116/*[clinic input]
117spwd.getspnam
Martin v. Löwisc3001752005-01-23 09:27:24 +0000118
Brett Cannon20cf6dd2014-08-22 13:59:24 -0400119 arg: unicode
120 /
121
122Return the shadow password database entry for the given user name.
123
124See `help(spwd)` for more on shadow password database entries.
125[clinic start generated code]*/
126
127static PyObject *
Serhiy Storchaka1a2b24f2016-07-07 17:35:15 +0300128spwd_getspnam_impl(PyObject *module, PyObject *arg)
129/*[clinic end generated code: output=701250cf57dc6ebe input=dd89429e6167a00f]*/
Martin v. Löwisc3001752005-01-23 09:27:24 +0000130{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000131 char *name;
132 struct spwd *p;
Brett Cannon20cf6dd2014-08-22 13:59:24 -0400133 PyObject *bytes, *retval = NULL;
Martin v. Löwisb6a748b2009-05-29 15:23:17 +0000134
Victor Stinnerae6265f2010-05-15 16:27:27 +0000135 if ((bytes = PyUnicode_EncodeFSDefault(arg)) == NULL)
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000136 return NULL;
Serhiy Storchakaf7eae0a2017-06-28 08:30:06 +0300137 /* check for embedded null bytes */
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000138 if (PyBytes_AsStringAndSize(bytes, &name, NULL) == -1)
139 goto out;
140 if ((p = getspnam(name)) == NULL) {
Berker Peksag3c3d7f42016-03-19 11:44:17 +0200141 if (errno != 0)
142 PyErr_SetFromErrno(PyExc_OSError);
143 else
144 PyErr_SetString(PyExc_KeyError, "getspnam(): name not found");
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000145 goto out;
146 }
147 retval = mkspent(p);
Martin v. Löwisb6a748b2009-05-29 15:23:17 +0000148out:
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000149 Py_DECREF(bytes);
150 return retval;
Martin v. Löwisc3001752005-01-23 09:27:24 +0000151}
152
Neal Norwitz62679962005-01-24 23:33:50 +0000153#endif /* HAVE_GETSPNAM */
154
155#ifdef HAVE_GETSPENT
156
Brett Cannon20cf6dd2014-08-22 13:59:24 -0400157/*[clinic input]
158spwd.getspall
159
160Return a list of all available shadow password database entries, in arbitrary order.
161
162See `help(spwd)` for more on shadow password database entries.
163[clinic start generated code]*/
Martin v. Löwisc3001752005-01-23 09:27:24 +0000164
Martin v. Löwisc3001752005-01-23 09:27:24 +0000165static PyObject *
Serhiy Storchaka1a2b24f2016-07-07 17:35:15 +0300166spwd_getspall_impl(PyObject *module)
167/*[clinic end generated code: output=4fda298d6bf6d057 input=b2c84b7857d622bd]*/
Martin v. Löwisc3001752005-01-23 09:27:24 +0000168{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000169 PyObject *d;
170 struct spwd *p;
171 if ((d = PyList_New(0)) == NULL)
172 return NULL;
173 setspent();
174 while ((p = getspent()) != NULL) {
175 PyObject *v = mkspent(p);
176 if (v == NULL || PyList_Append(d, v) != 0) {
177 Py_XDECREF(v);
178 Py_DECREF(d);
179 endspent();
180 return NULL;
181 }
182 Py_DECREF(v);
183 }
184 endspent();
185 return d;
Martin v. Löwisc3001752005-01-23 09:27:24 +0000186}
187
188#endif /* HAVE_GETSPENT */
189
190static PyMethodDef spwd_methods[] = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000191#ifdef HAVE_GETSPNAM
Brett Cannon20cf6dd2014-08-22 13:59:24 -0400192 SPWD_GETSPNAM_METHODDEF
Martin v. Löwisc3001752005-01-23 09:27:24 +0000193#endif
194#ifdef HAVE_GETSPENT
Brett Cannon20cf6dd2014-08-22 13:59:24 -0400195 SPWD_GETSPALL_METHODDEF
Martin v. Löwisc3001752005-01-23 09:27:24 +0000196#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000197 {NULL, NULL} /* sentinel */
Martin v. Löwisc3001752005-01-23 09:27:24 +0000198};
199
200
Martin v. Löwis1a214512008-06-11 05:26:20 +0000201
202static struct PyModuleDef spwdmodule = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000203 PyModuleDef_HEAD_INIT,
204 "spwd",
205 spwd__doc__,
206 -1,
207 spwd_methods,
208 NULL,
209 NULL,
210 NULL,
211 NULL
Martin v. Löwis1a214512008-06-11 05:26:20 +0000212};
213
Martin v. Löwisc3001752005-01-23 09:27:24 +0000214PyMODINIT_FUNC
Martin v. Löwis1a214512008-06-11 05:26:20 +0000215PyInit_spwd(void)
Martin v. Löwisc3001752005-01-23 09:27:24 +0000216{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000217 PyObject *m;
218 m=PyModule_Create(&spwdmodule);
219 if (m == NULL)
220 return NULL;
Victor Stinner1c8f0592013-07-22 22:24:54 +0200221 if (!initialized) {
222 if (PyStructSequence_InitType2(&StructSpwdType,
223 &struct_spwd_type_desc) < 0)
224 return NULL;
225 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000226 Py_INCREF((PyObject *) &StructSpwdType);
227 PyModule_AddObject(m, "struct_spwd", (PyObject *) &StructSpwdType);
228 initialized = 1;
229 return m;
Martin v. Löwisc3001752005-01-23 09:27:24 +0000230}