diff options
Diffstat (limited to 'security/pam-pwauth_suid')
-rw-r--r-- | security/pam-pwauth_suid/DESCR | 7 | ||||
-rw-r--r-- | security/pam-pwauth_suid/MESSAGE | 6 | ||||
-rw-r--r-- | security/pam-pwauth_suid/Makefile | 30 | ||||
-rw-r--r-- | security/pam-pwauth_suid/PLIST | 3 | ||||
-rw-r--r-- | security/pam-pwauth_suid/files/pam_pwauth_suid.c | 75 | ||||
-rw-r--r-- | security/pam-pwauth_suid/files/pwauth_suid_helper.c | 60 |
6 files changed, 181 insertions, 0 deletions
diff --git a/security/pam-pwauth_suid/DESCR b/security/pam-pwauth_suid/DESCR new file mode 100644 index 00000000000..8d63a911893 --- /dev/null +++ b/security/pam-pwauth_suid/DESCR @@ -0,0 +1,7 @@ +The pam_pwauth_suid authentication module uses a setuid program +to verify a password against the encrypted password in the +database used by the system. This way, an unprivileged user can +verify his own passsword stored in a shadow password database. +There might be some risk that the communication between the +invoking program and the setuid program is logged, or for abuse +for dictionary attacks. diff --git a/security/pam-pwauth_suid/MESSAGE b/security/pam-pwauth_suid/MESSAGE new file mode 100644 index 00000000000..ddac09e8820 --- /dev/null +++ b/security/pam-pwauth_suid/MESSAGE @@ -0,0 +1,6 @@ +=========================================================================== +$NetBSD: MESSAGE,v 1.1.1.1 2007/01/08 18:39:44 drochner Exp $ + +The PAM authentication module "pam_pwauth_suid.so.0" needs to be +installed into the directory "/usr/lib/security". +=========================================================================== diff --git a/security/pam-pwauth_suid/Makefile b/security/pam-pwauth_suid/Makefile new file mode 100644 index 00000000000..09daa287f87 --- /dev/null +++ b/security/pam-pwauth_suid/Makefile @@ -0,0 +1,30 @@ +# $NetBSD: Makefile,v 1.1.1.1 2007/01/08 18:39:44 drochner Exp $ + +DISTNAME= pam-pwauth_suid-1.0 +CATEGORIES= security +DISTFILES= # empty + +MAINTAINER= drochner@NetBSD.org +COMMENT= PAM authentication module for unprivileged users + +NO_CHECKSUM= yes +WRKSRC= ${WRKDIR} +CFLAGS+= -DPATH_HELPER=\"${PREFIX}/libexec/pwauth_suid_helper\" + +do-extract: + ${CP} ${FILESDIR}/pam_pwauth_suid.c ${FILESDIR}/pwauth_suid_helper.c \ + ${WRKSRC} + +do-build: + (cd ${WRKSRC} && \ + ${CC} ${CFLAGS} -shared pam_pwauth_suid.c -o pam_pwauth_suid.so.0 && \ + ${CC} ${CFLAGS} pwauth_suid_helper.c -o pwauth_suid_helper -lcrypt) + +do-install: + ${INSTALL_DATA_DIR} ${PREFIX}/lib/security + ${INSTALL_DATA} ${WRKSRC}/pam_pwauth_suid.so.0 ${PREFIX}/lib/security + ${INSTALL_PROGRAM} ${WRKSRC}/pwauth_suid_helper ${PREFIX}/libexec + ${CHMOD} 04555 ${PREFIX}/libexec/pwauth_suid_helper + +.include "../../mk/pam.buildlink3.mk" +.include "../../mk/bsd.pkg.mk" diff --git a/security/pam-pwauth_suid/PLIST b/security/pam-pwauth_suid/PLIST new file mode 100644 index 00000000000..a9f5d6e38be --- /dev/null +++ b/security/pam-pwauth_suid/PLIST @@ -0,0 +1,3 @@ +@comment $NetBSD: PLIST,v 1.1.1.1 2007/01/08 18:39:44 drochner Exp $ +lib/security/pam_pwauth_suid.so.0 +libexec/pwauth_suid_helper diff --git a/security/pam-pwauth_suid/files/pam_pwauth_suid.c b/security/pam-pwauth_suid/files/pam_pwauth_suid.c new file mode 100644 index 00000000000..0cd0643e140 --- /dev/null +++ b/security/pam-pwauth_suid/files/pam_pwauth_suid.c @@ -0,0 +1,75 @@ +/* $NetBSD: pam_pwauth_suid.c,v 1.1.1.1 2007/01/08 18:39:44 drochner Exp $ */ + +#include <sys/types.h> +#include <security/pam_appl.h> +#include <security/pam_modules.h> + +#include <unistd.h> +#include <string.h> +#include <sys/wait.h> +#include <errno.h> + +static int +askhelper(const char *user, const char *pass) +{ + int fd[2]; + pid_t pid, rpid; + ssize_t res; + size_t pwlen; + int s; + + if (pipe(fd) < 0) + return errno; + + pid = vfork(); + switch (pid) { + case -1: + return errno; + case 0: /* child, feed it through its stdin */ + (void)dup2(fd[0], STDIN_FILENO); + (void)close(fd[0]); + (void)close(fd[1]); + execl(PATH_HELPER, PATH_HELPER, user, NULL); + _exit(errno); + default: /* parent */ + (void)close(fd[0]); + break; + } + + pwlen = strlen(pass); + res = write(fd[1], pass, pwlen); + if (res != pwlen) + return (res == -1 ? errno : EIO); + + (void)close(fd[1]); /* now child gets an EOF */ + + rpid = waitpid(pid, &s, 0); + if (rpid != pid) + return errno; + if (!WIFEXITED(s) || WEXITSTATUS(s)) + return EAUTH; + + return 0; +} + +PAM_EXTERN int +pam_sm_authenticate(pam_handle_t *pamh, int flags, + int argc, const char **argv) +{ + const char *user, *pass; + int res; + + res = pam_get_user(pamh, &user, NULL); + if (res != PAM_SUCCESS) + return res; + res = pam_get_authtok(pamh, PAM_AUTHTOK, &pass, NULL); + if (res != PAM_SUCCESS) + return res; + + if (askhelper(user, pass) != 0) + return PAM_AUTH_ERR; + + return PAM_SUCCESS; +} + +PAM_MODULE_ENTRY("pam_passwdhelper"); diff --git a/security/pam-pwauth_suid/files/pwauth_suid_helper.c b/security/pam-pwauth_suid/files/pwauth_suid_helper.c new file mode 100644 index 00000000000..e1f77b3a72b --- /dev/null +++ b/security/pam-pwauth_suid/files/pwauth_suid_helper.c @@ -0,0 +1,60 @@ +/* $NetBSD: pwauth_suid_helper.c,v 1.1.1.1 2007/01/08 18:39:44 drochner Exp $ */ + +#include <pwd.h> +#include <string.h> +#include <errno.h> +#include <unistd.h> + +static char pwbuf[_PASSWORD_LEN + 1]; + +int +main(int argc, char **argv) +{ + const struct passwd *pwent; + ssize_t res; + char *bufptr; + const char *pwhash; + size_t buflen; + + if (argc != 2) + return (EINVAL); + + /* + * mlock(2) pwbuf[]? NetBSD's getpass(3) doesn't, + * so don't bother for now. + */ + + bufptr = pwbuf; + buflen = sizeof(pwbuf); + do { + res = read(STDIN_FILENO, bufptr, buflen); + if (res < 0) + return (errno); + bufptr += res; + buflen -= res; + } while (res > 0 && buflen > 0); + if (buflen == 0) + return (ENOMEM); + /* pwbuf is \0-terminated here b/c pwbuf is in bss */ + + /* + * Use username as key rather than uid so that it will not + * fail completely if multiple pw entries share a uid. + * Return same result in "not me" and "doesn't exist" cases + * to avoid leak of account information. + */ + pwent = getpwnam(argv[1]); + if (!pwent || (pwent->pw_uid != getuid())) + return (EPERM); + + /* + * Forcibly eat up some wall time to prevent use of this program + * to brute-force? For now assume that process startup time etc. + * make it already ineffective. + */ + pwhash = crypt(pwbuf, pwent->pw_passwd); + if (pwhash && strcmp(pwhash, pwent->pw_passwd) == 0) + return (0); + + return (EAUTH); +} |