Page MenuHomeFreeBSD

D34322.diff
No OneTemporary

D34322.diff

Index: lib/libpam/modules/pam_unix/pam_unix.c
===================================================================
--- lib/libpam/modules/pam_unix/pam_unix.c
+++ lib/libpam/modules/pam_unix/pam_unix.c
@@ -42,6 +42,8 @@
#include <sys/param.h>
#include <sys/socket.h>
#include <sys/time.h>
+#include <sys/types.h>
+#include <sys/wait.h>
#include <netinet/in.h>
#include <arpa/inet.h>
@@ -69,6 +71,8 @@
#include <security/pam_modules.h>
#include <security/pam_mod_misc.h>
+#define AUTHHELPER "/usr/libexec/pam_unix-helper"
+
#define PASSWORD_HASH "md5"
#define DEFAULT_WARN (2L * 7L * 86400L) /* Two weeks */
#define SALTSIZE 32
@@ -83,6 +87,56 @@
#define PAM_OPT_LOCAL_PASS "local_pass"
#define PAM_OPT_NIS_PASS "nis_pass"
+static int
+helper_checkpw(const char *user, const char *pass, int nullok, int emptyok)
+{
+ int authpipe[2];
+ int status;
+ pid_t pid;
+ char helper[] = AUTHHELPER;
+ char userarg[MAXLOGNAME] = { '\0' };
+ char eflag[] = "-e";
+ char nflag[] = "-n";
+ char *argv[5] = { helper, NULL };
+ char *envp[1] = { NULL };
+ int argc = 1;
+
+ if (pipe(authpipe) < 0) return (-1);
+
+ if (emptyok) argv[argc++] = eflag;
+ if (nullok) argv[argc++] = nflag;
+ (void)strncpy(userarg, user, MAXLOGNAME-1);
+ argv[argc++] = userarg;
+
+ pid = fork();
+ if (pid < 0) {
+ close(authpipe[0]);
+ close(authpipe[1]);
+ return (-1);
+ }
+
+ if (pid == 0) {
+ close(authpipe[1]);
+ if (dup2(authpipe[0], STDIN_FILENO) < 0)
+ exit(1);
+ close(authpipe[0]);
+ if (execve(helper, argv, envp) < 0)
+ exit(1);
+ }
+
+ close(authpipe[0]);
+ (void)write(authpipe[1], pass, strlen(pass));
+ close(authpipe[1]);
+
+ if (waitpid(pid, &status, WEXITED) < 0)
+ return (-1);
+
+ if (WIFEXITED(status) && WEXITSTATUS(status) == 0)
+ return (0);
+
+ return (-1);
+}
+
/*
* authentication management
*/
@@ -95,6 +149,9 @@
int retval;
const char *pass, *user, *realpw, *prompt;
const char *emptypasswd = "";
+ int usehelper = 0;
+ int hlpnullok = 0;
+ int hlpemptyok = 0;
if (openpam_get_option(pamh, PAM_OPT_AUTH_AS_SELF)) {
user = getlogin();
@@ -110,22 +167,35 @@
if (pwd != NULL) {
PAM_LOG("Doing real authentication");
realpw = pwd->pw_passwd;
- if (realpw[0] == '\0') {
+ if (geteuid() != 0 && getuid() == pwd->pw_uid)
+ usehelper = 1;
+ if (usehelper) {
if (!(flags & PAM_DISALLOW_NULL_AUTHTOK) &&
openpam_get_option(pamh, PAM_OPT_NULLOK))
+ hlpnullok = 1;
+ if (!(flags & PAM_DISALLOW_NULL_AUTHTOK) &&
+ openpam_get_option(pamh, PAM_OPT_EMPTYOK))
+ hlpemptyok = 1;
+ } else {
+ if (realpw[0] == '\0') {
+ if (!(flags & PAM_DISALLOW_NULL_AUTHTOK) &&
+ openpam_get_option(pamh, PAM_OPT_NULLOK))
+ return (PAM_SUCCESS);
+ PAM_LOG("Password is empty, "
+ "using fake password");
+ realpw = "*";
+ }
+ /*
+ * Check whether the saved password hash matches the
+ * one generated from an empty password - as opposed
+ * to empty saved password hash, which is handled
+ * above.
+ */
+ if (!(flags & PAM_DISALLOW_NULL_AUTHTOK) &&
+ openpam_get_option(pamh, PAM_OPT_EMPTYOK) &&
+ strcmp(crypt(emptypasswd, realpw), realpw) == 0)
return (PAM_SUCCESS);
- PAM_LOG("Password is empty, using fake password");
- realpw = "*";
}
- /*
- * Check whether the saved password hash matches the one
- * generated from an empty password - as opposed to empty
- * saved password hash, which is handled above.
- */
- if (!(flags & PAM_DISALLOW_NULL_AUTHTOK) &&
- openpam_get_option(pamh, PAM_OPT_EMPTYOK) &&
- strcmp(crypt(emptypasswd, realpw), realpw) == 0)
- return (PAM_SUCCESS);
lc = login_getpwclass(pwd);
} else {
PAM_LOG("Doing dummy authentication");
@@ -138,12 +208,17 @@
if (retval != PAM_SUCCESS)
return (retval);
PAM_LOG("Got password");
- if (strnlen(pass, _PASSWORD_LEN + 1) > _PASSWORD_LEN) {
- PAM_LOG("Password is too long, using fake password");
- realpw = "*";
+ if (usehelper) {
+ if (helper_checkpw(user, pass, hlpnullok, hlpemptyok) == 0)
+ return (PAM_SUCCESS);
+ } else {
+ if (strnlen(pass, _PASSWORD_LEN + 1) > _PASSWORD_LEN) {
+ PAM_LOG("Password is too long, using fake password");
+ realpw = "*";
+ }
+ if (strcmp(crypt(pass, realpw), realpw) == 0)
+ return (PAM_SUCCESS);
}
- if (strcmp(crypt(pass, realpw), realpw) == 0)
- return (PAM_SUCCESS);
PAM_VERBOSE_ERROR("UNIX authentication refused");
return (PAM_AUTH_ERR);

File Metadata

Mime Type
text/plain
Expires
Sat, Jan 11, 10:50 PM (20 h, 44 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
15758593
Default Alt Text
D34322.diff (4 KB)

Event Timeline