summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--security/pam-pwauth_suid/DESCR7
-rw-r--r--security/pam-pwauth_suid/MESSAGE6
-rw-r--r--security/pam-pwauth_suid/Makefile30
-rw-r--r--security/pam-pwauth_suid/PLIST3
-rw-r--r--security/pam-pwauth_suid/files/pam_pwauth_suid.c75
-rw-r--r--security/pam-pwauth_suid/files/pwauth_suid_helper.c60
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);
+}