Skip site navigation (1)Skip section navigation (2)
Date:      Mon, 21 Jan 2002 01:02:56 +0300
From:      "Andrey A. Chernov" <ache@nagual.pp.ru>
To:        markm@freebsd.org, des@freebsd.org, current@freebsd.org
Subject:   Step5, pam_opie OPIE auth fix for review
Message-ID:  <20020120220254.GA25886@nagual.pp.ru>

next in thread | raw e-mail | index | archive | help
Bug:

pam_opie module _always_ allows Unix (plaintext) password, even in the
cases which are disabled by OPIE auth procedure.

Description:

How non-PAM standalone OPIE works:

1) If OPIE user exists, its remote host checked against /etc/opieaccess
via opieaccessfile()

2) If remote host is found there, user home dir checked for ~/.opiealways 
file via opiealways()

3) If no such file, it is assumed than OPIE user is allowed to
authenticate with plaintext (Unix) password additionly to OPIE exchange.

In all other cases OPIE user is not allowed to authenticate with plaintext
(Unix) password.

How PAM OPIE works:

OPIE user can _always_ authenticate with plaintext (Unix) password which 
is is security lowering and violates OPIE way of things.

Fix:

It can't be fixed in current 2-state pam_opie return codes model, we need 
3 codes:

1) For OPIE exchange success
2) For OPIE exchange failure, but Unix (plaintext) passwords allowed
3) For OPIE exchange failure, but Unix (plaintext) passwords disabled

1) and 2) works exact as in old 2-state model, so 1) is PAM_SUCCESS and 2) 
is PAM_AUTH_ERR.

I choose PAM_CRED_INSUFFICIENT for case 3) which means that pam_opie 
module deside that all additionally possible auth will be insufficient and 
returns immediately from modules chain with this code.

--- pam_opie.c.old	Sun Jan 20 23:56:47 2002
+++ pam_opie.c	Mon Jan 21 00:24:51 2002
@@ -66,13 +66,14 @@
 	struct opie opie;
 	struct options options;
 	struct passwd *pwd;
-	int retval, i;
+	int retval, i, pwok;
 	char *(promptstr[]) = { "%s\nPassword: ", "%s\nPassword [echo on]: "};
 	char challenge[OPIE_CHALLENGE_MAX];
 	char prompt[OPIE_CHALLENGE_MAX+22];
 	char resp[OPIE_SECRET_MAX];
 	const char *user;
 	const char *response;
+	const char *rhost;
 
 	pam_std_option(&options, other_options, argc, argv);
 
@@ -97,6 +98,8 @@
 		retval = pam_get_user(pamh, (const char **)&user, NULL);
 		if (retval != PAM_SUCCESS)
 			PAM_RETURN(retval);
+		if ((pwd = getpwnam(user)) == NULL)
+			PAM_RETURN(PAM_AUTH_ERR);
 	}
 
 	PAM_LOG("Got user: %s", user);
@@ -107,7 +110,14 @@
 	 */
 	opiedisableaeh();
 
-	opiechallenge(&opie, (char *)user, challenge);
+	if (opiechallenge(&opie, (char *)user, challenge) == 0) {
+		rhost = NULL;
+		(void) pam_get_item(pamh, PAM_RHOST, (const void **)&rhost);
+		pwok = (rhost != NULL) && (*rhost != '\0') &&
+		       opieaccessfile((char *)rhost) &&
+		       opiealways(pwd->pw_dir);
+	} else
+		pwok = 1;
 	for (i = 0; i < 2; i++) {
 		snprintf(prompt, sizeof prompt, promptstr[i], challenge);
 		retval = pam_get_pass(pamh, &response, prompt, &options);
@@ -134,7 +144,10 @@
 	 * it expects.  Thus we can't log an error and can only check for
 	 * success or lack thereof.
 	 */
-	retval = opieverify(&opie, resp) == 0 ? PAM_SUCCESS : PAM_AUTH_ERR;
+	if (opieverify(&opie, resp) != 0)
+		retval = pwok ? PAM_AUTH_ERR : PAM_CRED_INSUFFICIENT;
+	else
+		retval = PAM_SUCCESS;
 	PAM_RETURN(retval);
 }
 
--- ftpd.c.bak	Sat Jan 19 21:29:50 2002
+++ ftpd.c	Mon Jan 21 00:30:03 2002
@@ -1190,6 +1190,7 @@
 		break;
 
 	case PAM_AUTH_ERR:
+	case PAM_CRED_INSUFFICIENT:
 	case PAM_USER_UNKNOWN:
 	case PAM_MAXTRIES:
 		rval = 1;
--- login.c.bak	Sat Jan 19 21:05:16 2002
+++ login.c	Mon Jan 21 00:31:45 2002
@@ -802,6 +802,7 @@
 		break;
 
 	case PAM_AUTH_ERR:
+	case PAM_CRED_INSUFFICIENT:
 	case PAM_USER_UNKNOWN:
 	case PAM_MAXTRIES:
 		rval = 1;
--- su.bak	Sat Jan 19 21:29:49 2002
+++ su	Mon Jan 21 00:39:04 2002
@@ -9,7 +9,7 @@
 auth		requisite	pam_wheel.so	no_warn auth_as_self noroot_ok
 #auth		sufficient	pam_kerberosIV.so	no_warn
 #auth		sufficient	pam_krb5.so	no_warn try_first_pass auth_as_self
-#auth		required	pam_opie.so	no_warn
+#auth [defalt=ignore success=done cred_insufficient=die] pam_opie.so  no_warn
 #auth		required	pam_ssh.so	no_warn try_first_pass
 auth		required	pam_unix.so	no_warn try_first_pass nullok
 #auth		sufficient	pam_rootok.so	no_warn
--- login.bak	Sat Jan 19 21:29:49 2002
+++ login	Mon Jan 21 00:39:04 2002
@@ -6,7 +6,7 @@
 
 # auth
 auth		required	pam_nologin.so	no_warn
-#auth		sufficient	pam_opie.so	no_warn
+#auth [defalt=ignore success=done cred_insufficient=die] pam_opie.so  no_warn
 #auth		sufficient	pam_kerberosIV.so	no_warn try_first_pass
 #auth		sufficient	pam_krb5.so	no_warn try_first_pass
 #auth		required	pam_ssh.so	no_warn try_first_pass
--- ftpd.bak	Sat Jan 19 21:29:49 2002
+++ ftpd	Mon Jan 21 00:39:04 2002
@@ -9,10 +9,8 @@
 #auth		sufficient	pam_kerberosIV.so	no_warn
 #auth		sufficient	pam_krb5.so	no_warn
 #auth           sufficient      pam_ssh.so      no_warn try_first_pass
-# Uncomment either pam_opie or pam_unix, but not both of them.
-# pam_unix can't be simple chained with pam_opie, ftpd provides proper fallback
-auth		required	pam_opie.so	no_warn
-#auth		required	pam_unix.so	no_warn try_first_pass
+#auth [defalt=ignore success=done cred_insufficient=die] pam_opie.so  no_warn
+auth		required	pam_unix.so	no_warn	try_first_pass
 
 # account
 #account	required	pam_kerberosIV.so

-- 
Andrey A. Chernov
http://ache.pp.ru/

To Unsubscribe: send mail to majordomo@FreeBSD.org
with "unsubscribe freebsd-current" in the body of the message




Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20020120220254.GA25886>