Skip to content

Commit f8a7b59

Browse files
author
loewis
committed
Patch #579435: Shadow Password Support Module
git-svn-id: http://svn.python.org/projects/python/trunk@38359 6015fed2-1504-0410-9fe1-9d1591cc4771
1 parent c8c449b commit f8a7b59

11 files changed

Lines changed: 466 additions & 429 deletions

File tree

Doc/Makefile.deps

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -164,6 +164,7 @@ LIBFILES= $(MANSTYLES) $(INDEXSTYLES) $(COMMONTEX) \
164164
lib/libposix.tex \
165165
lib/libposixpath.tex \
166166
lib/libpwd.tex \
167+
lib/libspwd.tex \
167168
lib/libgrp.tex \
168169
lib/libcrypt.tex \
169170
lib/libdbm.tex \

Doc/lib/lib.tex

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -193,6 +193,7 @@ \chapter*{Front Matter\label{front}}
193193
\input{libunix} % UNIX Specific Services
194194
\input{libposix}
195195
\input{libpwd}
196+
\input{libspwd}
196197
\input{libgrp}
197198
\input{libcrypt}
198199
\input{libdl}

Doc/lib/libpwd.tex

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,4 +50,5 @@ \section{\module{pwd} ---
5050

5151
\begin{seealso}
5252
\seemodule{grp}{An interface to the group database, similar to this.}
53+
\seemodule{spwd}{An interface to the shadow password database, similar to this.}
5354
\end{seealso}

Doc/lib/libspwd.tex

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
\section{\module{spwd} ---
2+
The shadow password database}
3+
4+
\declaremodule{builtin}{spwd}
5+
\platform{Unix}
6+
\modulesynopsis{The shadow password database (\function{getspnam()} and friends).}
7+
8+
This module provides access to the \UNIX{} shadow password database.
9+
It is available on various Unix versions.
10+
11+
You must have enough privileges to access the shadow password database
12+
(this usually means you have to be root).
13+
14+
Shadow password database entries are reported as a tuple-like object, whose
15+
attributes correspond to the members of the \code{spwd} structure
16+
(Attribute field below, see \code{<shadow.h>}):
17+
18+
\begin{tableiii}{r|l|l}{textrm}{Index}{Attribute}{Meaning}
19+
\lineiii{0}{\code{sp_nam}}{Login name}
20+
\lineiii{1}{\code{sp_pwd}}{Encrypted password}
21+
\lineiii{2}{\code{sp_lstchg}}{Date of last change}
22+
\lineiii{3}{\code{sp_min}}{Minimal number of days between changes}
23+
\lineiii{4}{\code{sp_max}}{Maximum number of days between changes}
24+
\lineiii{5}{\code{sp_warn}}{Number of days before password expires to warn user about it}
25+
\lineiii{6}{\code{sp_inact}}{Number of days after password expires until account is blocked}
26+
\lineiii{7}{\code{sp_expire}}{Number of days since 1970-01-01 until account is disabled}
27+
\lineiii{8}{\code{sp_flag}}{Reserved}
28+
\end{tableiii}
29+
30+
The sp_nam and sp_pwd items are strings, all others are integers.
31+
\exception{KeyError} is raised if the entry asked for cannot be found.
32+
33+
It defines the following items:
34+
35+
\begin{funcdesc}{getspnam}{name}
36+
Return the shadow password database entry for the given user name.
37+
\end{funcdesc}
38+
39+
\begin{funcdesc}{getspall}{}
40+
Return a list of all available shadow password database entries, in arbitrary order.
41+
\end{funcdesc}
42+
43+
44+
\begin{seealso}
45+
\seemodule{pwd}{An interface to the normal password database, similar to this.}
46+
\end{seealso}

Misc/NEWS

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,8 @@ Core and builtins
2222
Extension Modules
2323
-----------------
2424

25+
- The spwd has been added, allowing access to the shadow password database.
26+
2527
- stat_float_times is now True.
2628

2729
- array.array objects are now picklable.

Modules/Setup.dist

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -183,6 +183,7 @@ GLHACK=-Dclear=__GLclear
183183

184184
#fcntl fcntlmodule.c # fcntl(2) and ioctl(2)
185185
#pwd pwdmodule.c # pwd(3)
186+
#spwd spwdmodule.c # spwd(3)
186187
#grp grpmodule.c # grp(3)
187188
#select selectmodule.c # select(2); not on ancient System V
188189

Modules/spwdmodule.c

Lines changed: 179 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,179 @@
1+
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+
15+
PyDoc_STRVAR(spwd__doc__,
16+
"This module provides access to the Unix shadow password database.\n\
17+
It is available on various Unix versions.\n\
18+
\n\
19+
Shadow password database entries are reported as 9-tuples of type struct_spwd,\n\
20+
containing the following items from the password database (see `<shadow.h>'):\n\
21+
sp_namp, sp_pwdp, sp_lstchg, sp_min, sp_max, sp_warn, sp_inact, sp_expire, sp_flag.\n\
22+
The sp_namp and sp_pwdp are strings, the rest are integers.\n\
23+
An exception is raised if the entry asked for cannot be found.\n\
24+
You have to be root to be able to use this module.");
25+
26+
27+
#if defined(HAVE_GETSPNAM) || defined(HAVE_GETSPENT)
28+
29+
static PyStructSequence_Field struct_spwd_type_fields[] = {
30+
{"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}
40+
};
41+
42+
PyDoc_STRVAR(struct_spwd__doc__,
43+
"spwd.struct_spwd: Results from getsp*() routines.\n\n\
44+
This 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\
46+
or via the object attributes as named in the above tuple.");
47+
48+
static PyStructSequence_Desc struct_spwd_type_desc = {
49+
"spwd.struct_spwd",
50+
struct_spwd__doc__,
51+
struct_spwd_type_fields,
52+
9,
53+
};
54+
55+
static PyTypeObject StructSpwdType;
56+
57+
58+
static void
59+
sets(PyObject *v, int i, char* val)
60+
{
61+
if (val)
62+
PyStructSequence_SET_ITEM(v, i, PyString_FromString(val));
63+
else {
64+
PyStructSequence_SET_ITEM(v, i, Py_None);
65+
Py_INCREF(Py_None);
66+
}
67+
}
68+
69+
static PyObject *mkspent(struct spwd *p)
70+
{
71+
int setIndex = 0;
72+
PyObject *v = PyStructSequence_New(&StructSpwdType);
73+
if (v == NULL)
74+
return NULL;
75+
76+
#define SETI(i,val) PyStructSequence_SET_ITEM(v, i, PyInt_FromLong((long) val))
77+
#define SETS(i,val) sets(v, i, val)
78+
79+
SETS(setIndex++, p->sp_namp);
80+
SETS(setIndex++, p->sp_pwdp);
81+
SETI(setIndex++, p->sp_lstchg);
82+
SETI(setIndex++, p->sp_min);
83+
SETI(setIndex++, p->sp_max);
84+
SETI(setIndex++, p->sp_warn);
85+
SETI(setIndex++, p->sp_inact);
86+
SETI(setIndex++, p->sp_expire);
87+
SETI(setIndex++, p->sp_flag);
88+
89+
#undef SETS
90+
#undef SETI
91+
92+
if (PyErr_Occurred()) {
93+
Py_XDECREF(v);
94+
return NULL;
95+
}
96+
97+
return v;
98+
}
99+
100+
#endif /* HAVE_GETSPNAM || HAVE_GETSPENT */
101+
102+
103+
#ifdef HAVE_GETSPNAM
104+
105+
PyDoc_STRVAR(spwd_getspnam__doc__,
106+
"getspnam(name) -> (sp_namp, sp_pwdp, sp_lstchg, sp_min, sp_max,\n\
107+
sp_warn, sp_inact, sp_expire, sp_flag)\n\
108+
Return the shadow password database entry for the given user name.\n\
109+
See spwd.__doc__ for more on shadow password database entries.");
110+
111+
static PyObject* spwd_getspnam(PyObject *self, PyObject *args)
112+
{
113+
char *name;
114+
struct spwd *p;
115+
if (!PyArg_ParseTuple(args, "s:getspnam", &name))
116+
return NULL;
117+
if ((p = getspnam(name)) == NULL) {
118+
PyErr_SetString(PyExc_KeyError, "getspnam(): name not found");
119+
return NULL;
120+
}
121+
return mkspent(p);
122+
}
123+
124+
PyDoc_STRVAR(spwd_getspall__doc__,
125+
"getspall() -> list_of_entries\n\
126+
Return a list of all available shadow password database entries, \
127+
in arbitrary order.\n\
128+
See spwd.__doc__ for more on shadow password database entries.");
129+
130+
#endif /* HAVE_GETSPNAM */
131+
132+
#ifdef HAVE_GETSPENT
133+
134+
static PyObject *
135+
spwd_getspall(PyObject *self, PyObject *args)
136+
{
137+
PyObject *d;
138+
struct spwd *p;
139+
// if (!PyArg_NoArgs(args))
140+
// return NULL;
141+
if ((d = PyList_New(0)) == NULL)
142+
return NULL;
143+
setspent();
144+
while ((p = getspent()) != NULL) {
145+
PyObject *v = mkspent(p);
146+
if (v == NULL || PyList_Append(d, v) != 0) {
147+
Py_XDECREF(v);
148+
Py_DECREF(d);
149+
endspent();
150+
return NULL;
151+
}
152+
Py_DECREF(v);
153+
}
154+
endspent();
155+
return d;
156+
}
157+
158+
#endif /* HAVE_GETSPENT */
159+
160+
static PyMethodDef spwd_methods[] = {
161+
#ifdef HAVE_GETSPNAM
162+
{"getspnam", spwd_getspnam, METH_VARARGS, spwd_getspnam__doc__},
163+
#endif
164+
#ifdef HAVE_GETSPENT
165+
{"getspall", spwd_getspall, METH_NOARGS, spwd_getspall__doc__},
166+
#endif
167+
{NULL, NULL} /* sentinel */
168+
};
169+
170+
171+
PyMODINIT_FUNC
172+
initspwd(void)
173+
{
174+
PyObject *m;
175+
m=Py_InitModule3("spwd", spwd_methods, spwd__doc__);
176+
PyStructSequence_InitType(&StructSpwdType, &struct_spwd_type_desc);
177+
Py_INCREF((PyObject *) &StructSpwdType);
178+
PyModule_AddObject(m, "struct_spwd", (PyObject *) &StructSpwdType);
179+
}

0 commit comments

Comments
 (0)