Patch #579435: Shadow Password Support Module
This commit is contained in:
parent
4d394dfebb
commit
c300175547
|
@ -164,6 +164,7 @@ LIBFILES= $(MANSTYLES) $(INDEXSTYLES) $(COMMONTEX) \
|
||||||
lib/libposix.tex \
|
lib/libposix.tex \
|
||||||
lib/libposixpath.tex \
|
lib/libposixpath.tex \
|
||||||
lib/libpwd.tex \
|
lib/libpwd.tex \
|
||||||
|
lib/libspwd.tex \
|
||||||
lib/libgrp.tex \
|
lib/libgrp.tex \
|
||||||
lib/libcrypt.tex \
|
lib/libcrypt.tex \
|
||||||
lib/libdbm.tex \
|
lib/libdbm.tex \
|
||||||
|
|
|
@ -193,6 +193,7 @@ and how to embed it in other applications.
|
||||||
\input{libunix} % UNIX Specific Services
|
\input{libunix} % UNIX Specific Services
|
||||||
\input{libposix}
|
\input{libposix}
|
||||||
\input{libpwd}
|
\input{libpwd}
|
||||||
|
\input{libspwd}
|
||||||
\input{libgrp}
|
\input{libgrp}
|
||||||
\input{libcrypt}
|
\input{libcrypt}
|
||||||
\input{libdl}
|
\input{libdl}
|
||||||
|
|
|
@ -50,4 +50,5 @@ Return a list of all available password database entries, in arbitrary order.
|
||||||
|
|
||||||
\begin{seealso}
|
\begin{seealso}
|
||||||
\seemodule{grp}{An interface to the group database, similar to this.}
|
\seemodule{grp}{An interface to the group database, similar to this.}
|
||||||
|
\seemodule{spwd}{An interface to the shadow password database, similar to this.}
|
||||||
\end{seealso}
|
\end{seealso}
|
||||||
|
|
|
@ -0,0 +1,46 @@
|
||||||
|
\section{\module{spwd} ---
|
||||||
|
The shadow password database}
|
||||||
|
|
||||||
|
\declaremodule{builtin}{spwd}
|
||||||
|
\platform{Unix}
|
||||||
|
\modulesynopsis{The shadow password database (\function{getspnam()} and friends).}
|
||||||
|
|
||||||
|
This module provides access to the \UNIX{} shadow password database.
|
||||||
|
It is available on various Unix versions.
|
||||||
|
|
||||||
|
You must have enough privileges to access the shadow password database
|
||||||
|
(this usually means you have to be root).
|
||||||
|
|
||||||
|
Shadow password database entries are reported as a tuple-like object, whose
|
||||||
|
attributes correspond to the members of the \code{spwd} structure
|
||||||
|
(Attribute field below, see \code{<shadow.h>}):
|
||||||
|
|
||||||
|
\begin{tableiii}{r|l|l}{textrm}{Index}{Attribute}{Meaning}
|
||||||
|
\lineiii{0}{\code{sp_nam}}{Login name}
|
||||||
|
\lineiii{1}{\code{sp_pwd}}{Encrypted password}
|
||||||
|
\lineiii{2}{\code{sp_lstchg}}{Date of last change}
|
||||||
|
\lineiii{3}{\code{sp_min}}{Minimal number of days between changes}
|
||||||
|
\lineiii{4}{\code{sp_max}}{Maximum number of days between changes}
|
||||||
|
\lineiii{5}{\code{sp_warn}}{Number of days before password expires to warn user about it}
|
||||||
|
\lineiii{6}{\code{sp_inact}}{Number of days after password expires until account is blocked}
|
||||||
|
\lineiii{7}{\code{sp_expire}}{Number of days since 1970-01-01 until account is disabled}
|
||||||
|
\lineiii{8}{\code{sp_flag}}{Reserved}
|
||||||
|
\end{tableiii}
|
||||||
|
|
||||||
|
The sp_nam and sp_pwd items are strings, all others are integers.
|
||||||
|
\exception{KeyError} is raised if the entry asked for cannot be found.
|
||||||
|
|
||||||
|
It defines the following items:
|
||||||
|
|
||||||
|
\begin{funcdesc}{getspnam}{name}
|
||||||
|
Return the shadow password database entry for the given user name.
|
||||||
|
\end{funcdesc}
|
||||||
|
|
||||||
|
\begin{funcdesc}{getspall}{}
|
||||||
|
Return a list of all available shadow password database entries, in arbitrary order.
|
||||||
|
\end{funcdesc}
|
||||||
|
|
||||||
|
|
||||||
|
\begin{seealso}
|
||||||
|
\seemodule{pwd}{An interface to the normal password database, similar to this.}
|
||||||
|
\end{seealso}
|
|
@ -22,6 +22,8 @@ Core and builtins
|
||||||
Extension Modules
|
Extension Modules
|
||||||
-----------------
|
-----------------
|
||||||
|
|
||||||
|
- The spwd has been added, allowing access to the shadow password database.
|
||||||
|
|
||||||
- stat_float_times is now True.
|
- stat_float_times is now True.
|
||||||
|
|
||||||
- array.array objects are now picklable.
|
- array.array objects are now picklable.
|
||||||
|
|
|
@ -183,6 +183,7 @@ GLHACK=-Dclear=__GLclear
|
||||||
|
|
||||||
#fcntl fcntlmodule.c # fcntl(2) and ioctl(2)
|
#fcntl fcntlmodule.c # fcntl(2) and ioctl(2)
|
||||||
#pwd pwdmodule.c # pwd(3)
|
#pwd pwdmodule.c # pwd(3)
|
||||||
|
#spwd spwdmodule.c # spwd(3)
|
||||||
#grp grpmodule.c # grp(3)
|
#grp grpmodule.c # grp(3)
|
||||||
#select selectmodule.c # select(2); not on ancient System V
|
#select selectmodule.c # select(2); not on ancient System V
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,179 @@
|
||||||
|
|
||||||
|
/* UNIX shadow password file access module */
|
||||||
|
/* A lot of code has been taken from pwdmodule.c */
|
||||||
|
/* For info also see http://www.unixpapa.com/incnote/passwd.html */
|
||||||
|
|
||||||
|
#include "Python.h"
|
||||||
|
#include "structseq.h"
|
||||||
|
|
||||||
|
#include <sys/types.h>
|
||||||
|
#ifdef HAVE_SHADOW_H
|
||||||
|
#include <shadow.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
PyDoc_STRVAR(spwd__doc__,
|
||||||
|
"This module provides access to the Unix shadow password database.\n\
|
||||||
|
It is available on various Unix versions.\n\
|
||||||
|
\n\
|
||||||
|
Shadow password database entries are reported as 9-tuples of type struct_spwd,\n\
|
||||||
|
containing the following items from the password database (see `<shadow.h>'):\n\
|
||||||
|
sp_namp, sp_pwdp, sp_lstchg, sp_min, sp_max, sp_warn, sp_inact, sp_expire, sp_flag.\n\
|
||||||
|
The sp_namp and sp_pwdp are strings, the rest are integers.\n\
|
||||||
|
An exception is raised if the entry asked for cannot be found.\n\
|
||||||
|
You have to be root to be able to use this module.");
|
||||||
|
|
||||||
|
|
||||||
|
#if defined(HAVE_GETSPNAM) || defined(HAVE_GETSPENT)
|
||||||
|
|
||||||
|
static PyStructSequence_Field struct_spwd_type_fields[] = {
|
||||||
|
{"sp_nam", "login name"},
|
||||||
|
{"sp_pwd", "encrypted password"},
|
||||||
|
{"sp_lstchg", "date of last change"},
|
||||||
|
{"sp_min", "min #days between changes"},
|
||||||
|
{"sp_max", "max #days between changes"},
|
||||||
|
{"sp_warn", "#days before pw expires to warn user about it"},
|
||||||
|
{"sp_inact", "#days after pw expires until account is blocked"},
|
||||||
|
{"sp_expire", "#days since 1970-01-01 until account is disabled"},
|
||||||
|
{"sp_flag", "reserved"},
|
||||||
|
{0}
|
||||||
|
};
|
||||||
|
|
||||||
|
PyDoc_STRVAR(struct_spwd__doc__,
|
||||||
|
"spwd.struct_spwd: Results from getsp*() routines.\n\n\
|
||||||
|
This object may be accessed either as a 9-tuple of\n\
|
||||||
|
(sp_nam,sp_pwd,sp_lstchg,sp_min,sp_max,sp_warn,sp_inact,sp_expire,sp_flag)\n\
|
||||||
|
or via the object attributes as named in the above tuple.");
|
||||||
|
|
||||||
|
static PyStructSequence_Desc struct_spwd_type_desc = {
|
||||||
|
"spwd.struct_spwd",
|
||||||
|
struct_spwd__doc__,
|
||||||
|
struct_spwd_type_fields,
|
||||||
|
9,
|
||||||
|
};
|
||||||
|
|
||||||
|
static PyTypeObject StructSpwdType;
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
sets(PyObject *v, int i, char* val)
|
||||||
|
{
|
||||||
|
if (val)
|
||||||
|
PyStructSequence_SET_ITEM(v, i, PyString_FromString(val));
|
||||||
|
else {
|
||||||
|
PyStructSequence_SET_ITEM(v, i, Py_None);
|
||||||
|
Py_INCREF(Py_None);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static PyObject *mkspent(struct spwd *p)
|
||||||
|
{
|
||||||
|
int setIndex = 0;
|
||||||
|
PyObject *v = PyStructSequence_New(&StructSpwdType);
|
||||||
|
if (v == NULL)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
#define SETI(i,val) PyStructSequence_SET_ITEM(v, i, PyInt_FromLong((long) val))
|
||||||
|
#define SETS(i,val) sets(v, i, val)
|
||||||
|
|
||||||
|
SETS(setIndex++, p->sp_namp);
|
||||||
|
SETS(setIndex++, p->sp_pwdp);
|
||||||
|
SETI(setIndex++, p->sp_lstchg);
|
||||||
|
SETI(setIndex++, p->sp_min);
|
||||||
|
SETI(setIndex++, p->sp_max);
|
||||||
|
SETI(setIndex++, p->sp_warn);
|
||||||
|
SETI(setIndex++, p->sp_inact);
|
||||||
|
SETI(setIndex++, p->sp_expire);
|
||||||
|
SETI(setIndex++, p->sp_flag);
|
||||||
|
|
||||||
|
#undef SETS
|
||||||
|
#undef SETI
|
||||||
|
|
||||||
|
if (PyErr_Occurred()) {
|
||||||
|
Py_XDECREF(v);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return v;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* HAVE_GETSPNAM || HAVE_GETSPENT */
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef HAVE_GETSPNAM
|
||||||
|
|
||||||
|
PyDoc_STRVAR(spwd_getspnam__doc__,
|
||||||
|
"getspnam(name) -> (sp_namp, sp_pwdp, sp_lstchg, sp_min, sp_max,\n\
|
||||||
|
sp_warn, sp_inact, sp_expire, sp_flag)\n\
|
||||||
|
Return the shadow password database entry for the given user name.\n\
|
||||||
|
See spwd.__doc__ for more on shadow password database entries.");
|
||||||
|
|
||||||
|
static PyObject* spwd_getspnam(PyObject *self, PyObject *args)
|
||||||
|
{
|
||||||
|
char *name;
|
||||||
|
struct spwd *p;
|
||||||
|
if (!PyArg_ParseTuple(args, "s:getspnam", &name))
|
||||||
|
return NULL;
|
||||||
|
if ((p = getspnam(name)) == NULL) {
|
||||||
|
PyErr_SetString(PyExc_KeyError, "getspnam(): name not found");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
return mkspent(p);
|
||||||
|
}
|
||||||
|
|
||||||
|
PyDoc_STRVAR(spwd_getspall__doc__,
|
||||||
|
"getspall() -> list_of_entries\n\
|
||||||
|
Return a list of all available shadow password database entries, \
|
||||||
|
in arbitrary order.\n\
|
||||||
|
See spwd.__doc__ for more on shadow password database entries.");
|
||||||
|
|
||||||
|
#endif /* HAVE_GETSPNAM */
|
||||||
|
|
||||||
|
#ifdef HAVE_GETSPENT
|
||||||
|
|
||||||
|
static PyObject *
|
||||||
|
spwd_getspall(PyObject *self, PyObject *args)
|
||||||
|
{
|
||||||
|
PyObject *d;
|
||||||
|
struct spwd *p;
|
||||||
|
// if (!PyArg_NoArgs(args))
|
||||||
|
// return NULL;
|
||||||
|
if ((d = PyList_New(0)) == NULL)
|
||||||
|
return NULL;
|
||||||
|
setspent();
|
||||||
|
while ((p = getspent()) != NULL) {
|
||||||
|
PyObject *v = mkspent(p);
|
||||||
|
if (v == NULL || PyList_Append(d, v) != 0) {
|
||||||
|
Py_XDECREF(v);
|
||||||
|
Py_DECREF(d);
|
||||||
|
endspent();
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
Py_DECREF(v);
|
||||||
|
}
|
||||||
|
endspent();
|
||||||
|
return d;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* HAVE_GETSPENT */
|
||||||
|
|
||||||
|
static PyMethodDef spwd_methods[] = {
|
||||||
|
#ifdef HAVE_GETSPNAM
|
||||||
|
{"getspnam", spwd_getspnam, METH_VARARGS, spwd_getspnam__doc__},
|
||||||
|
#endif
|
||||||
|
#ifdef HAVE_GETSPENT
|
||||||
|
{"getspall", spwd_getspall, METH_NOARGS, spwd_getspall__doc__},
|
||||||
|
#endif
|
||||||
|
{NULL, NULL} /* sentinel */
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
PyMODINIT_FUNC
|
||||||
|
initspwd(void)
|
||||||
|
{
|
||||||
|
PyObject *m;
|
||||||
|
m=Py_InitModule3("spwd", spwd_methods, spwd__doc__);
|
||||||
|
PyStructSequence_InitType(&StructSpwdType, &struct_spwd_type_desc);
|
||||||
|
Py_INCREF((PyObject *) &StructSpwdType);
|
||||||
|
PyModule_AddObject(m, "struct_spwd", (PyObject *) &StructSpwdType);
|
||||||
|
}
|
|
@ -960,7 +960,7 @@ dnl AC_MSG_RESULT($cpp_type)
|
||||||
|
|
||||||
# checks for header files
|
# checks for header files
|
||||||
AC_HEADER_STDC
|
AC_HEADER_STDC
|
||||||
AC_CHECK_HEADERS(curses.h dlfcn.h fcntl.h grp.h langinfo.h \
|
AC_CHECK_HEADERS(curses.h dlfcn.h fcntl.h grp.h shadow.h langinfo.h \
|
||||||
libintl.h ncurses.h poll.h pthread.h \
|
libintl.h ncurses.h poll.h pthread.h \
|
||||||
stropts.h termios.h thread.h \
|
stropts.h termios.h thread.h \
|
||||||
unistd.h utime.h \
|
unistd.h utime.h \
|
||||||
|
@ -2076,7 +2076,7 @@ AC_MSG_RESULT(MACHDEP_OBJS)
|
||||||
AC_CHECK_FUNCS(alarm bind_textdomain_codeset chown clock confstr ctermid \
|
AC_CHECK_FUNCS(alarm bind_textdomain_codeset chown clock confstr ctermid \
|
||||||
execv fork fpathconf ftime ftruncate \
|
execv fork fpathconf ftime ftruncate \
|
||||||
gai_strerror getgroups getlogin getloadavg getpeername getpgid getpid \
|
gai_strerror getgroups getlogin getloadavg getpeername getpgid getpid \
|
||||||
getpriority getpwent getsid getwd \
|
getpriority getpwent getspnam getspent getsid getwd \
|
||||||
kill killpg lchown lstat mkfifo mknod mktime \
|
kill killpg lchown lstat mkfifo mknod mktime \
|
||||||
mremap nice pathconf pause plock poll pthread_init \
|
mremap nice pathconf pause plock poll pthread_init \
|
||||||
putenv readlink realpath \
|
putenv readlink realpath \
|
||||||
|
|
|
@ -215,6 +215,12 @@
|
||||||
/* Define to 1 if you have the `getsid' function. */
|
/* Define to 1 if you have the `getsid' function. */
|
||||||
#undef HAVE_GETSID
|
#undef HAVE_GETSID
|
||||||
|
|
||||||
|
/* Define to 1 if you have the `getspent' function. */
|
||||||
|
#undef HAVE_GETSPENT
|
||||||
|
|
||||||
|
/* Define to 1 if you have the `getspnam' function. */
|
||||||
|
#undef HAVE_GETSPNAM
|
||||||
|
|
||||||
/* Define to 1 if you have the `gettimeofday' function. */
|
/* Define to 1 if you have the `gettimeofday' function. */
|
||||||
#undef HAVE_GETTIMEOFDAY
|
#undef HAVE_GETTIMEOFDAY
|
||||||
|
|
||||||
|
@ -419,6 +425,9 @@
|
||||||
/* Define to 1 if you have the `setvbuf' function. */
|
/* Define to 1 if you have the `setvbuf' function. */
|
||||||
#undef HAVE_SETVBUF
|
#undef HAVE_SETVBUF
|
||||||
|
|
||||||
|
/* Define to 1 if you have the <shadow.h> header file. */
|
||||||
|
#undef HAVE_SHADOW_H
|
||||||
|
|
||||||
/* Define to 1 if you have the `sigaction' function. */
|
/* Define to 1 if you have the `sigaction' function. */
|
||||||
#undef HAVE_SIGACTION
|
#undef HAVE_SIGACTION
|
||||||
|
|
||||||
|
|
2
setup.py
2
setup.py
|
@ -388,6 +388,8 @@ class PyBuildExt(build_ext):
|
||||||
exts.append( Extension('pwd', ['pwdmodule.c']) )
|
exts.append( Extension('pwd', ['pwdmodule.c']) )
|
||||||
# grp(3)
|
# grp(3)
|
||||||
exts.append( Extension('grp', ['grpmodule.c']) )
|
exts.append( Extension('grp', ['grpmodule.c']) )
|
||||||
|
# spwd, shadow passwords
|
||||||
|
exts.append( Extension('spwd', ['spwdmodule.c']) )
|
||||||
# select(2); not on ancient System V
|
# select(2); not on ancient System V
|
||||||
exts.append( Extension('select', ['selectmodule.c']) )
|
exts.append( Extension('select', ['selectmodule.c']) )
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue