summaryrefslogtreecommitdiff
path: root/security/pam-pwauth_suid
diff options
context:
space:
mode:
authordrochner <drochner>2007-01-08 18:39:44 +0000
committerdrochner <drochner>2007-01-08 18:39:44 +0000
commit4456b94a2e3d6e8d0a1341789bac894a0218b082 (patch)
tree473c92a4f1addea8775b249c8c747fa13669690f /security/pam-pwauth_suid
parentd3f9739cc6304c6d896af9395f26d7dca72be945 (diff)
downloadpkgsrc-4456b94a2e3d6e8d0a1341789bac894a0218b082.tar.gz
add a PAM module which used a suid helper program to access the passwd
database, for use by unprivileged users to verify their own password (in particular for screen savers) thanks to many people for comments
Diffstat (limited to 'security/pam-pwauth_suid')
-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);
+}