TISviaPAM patch

Frank Cusack frank at google.com
Tue Oct 9 18:14:34 EST 2001


On Mon, Oct 08, 2001 at 08:46:33PM -0700, Frank Cusack wrote:
> Here is a patch that does TIS auth via PAM.  It's controlled by a switch
> in the sshd_config.  You'd use it by having a PAM module that sets
> PAM_PROMPT_ECHO_ON.  eg, you could use it with pam_skey or pam_smxs.
> 
> The patch is against the 2.9.9p2 distribution.

oops.  Here's the actual patch.

/fc
-------------- next part --------------
	Add 'TISviaPAM' option, which uses PAM for ssh1 TIS authentication.
	This allows arbitrary challenge/response authentications instead
	of the built-in S/Key.  Also fixed 2-3 small typos and a bug in
	password handling for TIS (turn echo on).
	
Index: openssh/auth-pam.c
@@ -26,6 +26,8 @@
 
 #ifdef USE_PAM
 #include "ssh.h"
+#include "ssh1.h"
+#include "packet.h"
 #include "xmalloc.h"
 #include "log.h"
 #include "auth-pam.h"
@@ -54,6 +56,8 @@
 
 /* states for do_pam_conversation() */
 enum { INITIAL_LOGIN, OTHER } pamstate = INITIAL_LOGIN;
+/* which type of prompts we should handle, set in auth_pam_password */
+static int pamprompt;
 /* remember whether pam_acct_mgmt() returned PAM_NEWAUTHTOK_REQD */
 static int password_change_required = 0;
 /* remember whether the last pam_authenticate() succeeded or not */
@@ -98,6 +102,10 @@
 	int count;
 	char buf[1024];
 
+	u_int dlen;
+	int plen, type;
+	char *response;
+
 	/* PAM will free this later */
 	reply = malloc(num_msg * sizeof(*reply));
 	if (reply == NULL)
@@ -111,10 +119,40 @@
 			 */
 			switch(PAM_MSG_MEMBER(msg, count, msg_style)) {
 			case PAM_PROMPT_ECHO_ON:
-				free(reply);
-				return PAM_CONV_ERR;
+				if (pamprompt != PAM_PROMPT_ECHO_ON ||
+				    (*msg)[count].msg == NULL) {
+					free(reply);
+					return PAM_CONV_ERR;
+				}
+
+				/* handle challenge/response (ssh1 TIS) */
+				/* Send the challenge */
+				strlcpy(buf, PAM_MSG_MEMBER(msg, count, msg),
+					sizeof(buf));
+				debug("sending challenge '%s'", buf);
+				packet_start(SSH_SMSG_AUTH_TIS_CHALLENGE);
+				packet_put_cstring(buf);
+				packet_send();
+				packet_write_wait();
+
+				/* Give the response to the PAM module */
+				if ((type = packet_read(&plen)) !=
+				    SSH_CMSG_AUTH_TIS_RESPONSE) {
+					free(reply);
+					return PAM_CONV_ERR;
+				}
+				debug("rcvd SSH_CMSG_AUTH_TIS_RESPONSE");
+				response = packet_get_string(&dlen);
+				debug("got response '%s'", response);
+				packet_integrity_check(plen, 4 + dlen, type);
+				reply[count].resp = xstrdup(response);
+				reply[count].resp_retcode = PAM_SUCCESS;
+				xfree(response);
+				break;
+
 			case PAM_PROMPT_ECHO_OFF:
-				if (__pampasswd == NULL) {
+				if (__pampasswd == NULL ||
+				    pamprompt != PAM_PROMPT_ECHO_OFF) {
 					free(reply);
 					return PAM_CONV_ERR;
 				}
@@ -198,8 +236,8 @@
 	}
 }
 
-/* Attempt password authentation using PAM */
-int auth_pam_password(struct passwd *pw, const char *password)
+/* Attempt password authentication using PAM */
+int auth_pam_password(struct passwd *pw, const char *password, int prompt_type)
 {
 	extern ServerOptions options;
 	int pam_retval;
@@ -211,12 +249,14 @@
 		return 0;
 	if (pw->pw_uid == 0 && options.permit_root_login == PERMIT_NO_PASSWD)
 		return 0;
-	if (*password == '\0' && options.permit_empty_passwd == 0)
+	if (*password == '\0' && options.permit_empty_passwd == 0 &&
+	    prompt_type == PAM_PROMPT_ECHO_OFF)
 		return 0;
 
 	__pampasswd = password;
 
 	pamstate = INITIAL_LOGIN;
+	pamprompt = prompt_type;
 	pam_retval = do_pam_authenticate(0);
 	if (pam_retval == PAM_SUCCESS) {
 		debug("PAM Password authentication accepted for "

Index: openssh/auth-pam.h
@@ -7,7 +7,7 @@
 
 void start_pam(const char *user);
 void finish_pam(void);
-int auth_pam_password(struct passwd *pw, const char *password);
+int auth_pam_password(struct passwd *pw, const char *password, int prompt_type);
 char **fetch_pam_environment(void);
 int do_pam_authenticate(int flags);
 int do_pam_account(char *username, char *remote_user);

Index: openssh/auth1.c
@@ -89,7 +89,7 @@
 	    (!options.kerberos_authentication || options.kerberos_or_local_passwd) &&
 #endif
 #ifdef USE_PAM
-	    auth_pam_password(pw, "")) {
+	    auth_pam_password(pw, "", PAM_PROMPT_ECHO_OFF)) {
 #elif defined(HAVE_OSF_SIA)
 	    0) {
 #else
@@ -258,7 +258,8 @@
 
 #ifdef USE_PAM
 			/* Do PAM auth with password */
-			authenticated = auth_pam_password(pw, password);
+			authenticated = auth_pam_password(pw, password,
+							  PAM_PROMPT_ECHO_OFF);
 #elif defined(HAVE_OSF_SIA)
 			/* Do SIA auth with password */
 			authenticated = auth_sia_password(authctxt->user, 
@@ -275,6 +276,15 @@
 		case SSH_CMSG_AUTH_TIS:
 			debug("rcvd SSH_CMSG_AUTH_TIS");
 			if (options.challenge_response_authentication == 1) {
+#ifdef USE_PAM
+			    if (options.tis_via_pam == 1) {
+				authenticated = auth_pam_password(pw, "",
+							  PAM_PROMPT_ECHO_ON);
+				break;
+			    } else {
+#else
+			    {
+#endif /* USE_PAM */
 				char *challenge = get_challenge(authctxt);
 				if (challenge != NULL) {
 					debug("sending challenge '%s'", challenge);
@@ -285,6 +295,7 @@
 					packet_write_wait();
 					continue;
 				}
+			    }
 			}
 			break;
 		case SSH_CMSG_AUTH_TIS_RESPONSE:

Index: openssh/auth2-chall.c
@@ -139,7 +139,7 @@
 }
 
 /*
- * try challenge-reponse, set authctxt->postponed if we have to
+ * try challenge-response, set authctxt->postponed if we have to
  * wait for the response.
  */
 int

Index: openssh/auth2.c
@@ -122,7 +122,7 @@
 
 	x_authctxt = authctxt;		/*XXX*/
 
-	/* challenge-reponse is implemented via keyboard interactive */
+	/* challenge-response is implemented via keyboard interactive */
 	if (options.challenge_response_authentication)
 		options.kbd_interactive_authentication = 1;
 	if (options.pam_authentication_via_kbd_int)
@@ -344,7 +344,7 @@
 		return(0);
 #endif
 #ifdef USE_PAM
-	return auth_pam_password(authctxt->pw, "");
+	return auth_pam_password(authctxt->pw, "", PAM_PROMPT_ECHO_OFF);
 #elif defined(HAVE_OSF_SIA)
 	return 0;
 #else /* !HAVE_OSF_SIA && !USE_PAM */
@@ -369,7 +369,7 @@
 		check_nt_auth(1, authctxt->pw->pw_uid) &&
 #endif
 #ifdef USE_PAM
-	    auth_pam_password(authctxt->pw, password) == 1)
+	    auth_pam_password(authctxt->pw, password, PAM_PROMPT_ECHO_OFF) == 1)
 #elif defined(HAVE_OSF_SIA)
 	    auth_sia_password(authctxt->user, password) == 1)
 #else /* !USE_PAM && !HAVE_OSF_SIA */

Index: openssh/servconf.c
@@ -83,6 +83,7 @@
 	options->password_authentication = -1;
 	options->kbd_interactive_authentication = -1;
 	options->challenge_response_authentication = -1;
+	options->tis_via_pam = -1;
 	options->permit_empty_passwd = -1;
 	options->use_login = -1;
 	options->allow_tcp_forwarding = -1;
@@ -234,7 +235,7 @@
 #ifdef AFS
 	sAFSTokenPassing,
 #endif
-	sChallengeResponseAuthentication,
+	sChallengeResponseAuthentication, sTISviaPAM,
 	sPasswordAuthentication, sKbdInteractiveAuthentication, sListenAddress,
 	sPrintMotd, sPrintLastLog, sIgnoreRhosts,
 	sX11Forwarding, sX11DisplayOffset,
@@ -286,6 +287,7 @@
 	{ "kbdinteractiveauthentication", sKbdInteractiveAuthentication },
 	{ "challengeresponseauthentication", sChallengeResponseAuthentication },
 	{ "skeyauthentication", sChallengeResponseAuthentication }, /* alias */
+	{ "tisviapam", sTISviaPAM },
 	{ "checkmail", sDeprecated },
 	{ "listenaddress", sListenAddress },
 	{ "printmotd", sPrintMotd },
@@ -626,6 +628,10 @@
 			intptr = &options->challenge_response_authentication;
 			goto parse_flag;
 
+		case sTISviaPAM:
+			intptr = &options->tis_via_pam;
+			goto parse_flag;
+
 		case sPrintMotd:
 			intptr = &options->print_motd;
 			goto parse_flag;

Index: openssh/servconf.h
@@ -94,6 +94,7 @@
 						 * authentication. */
 	int     kbd_interactive_authentication;	/* If true, permit */
 	int     challenge_response_authentication;
+	int	tis_via_pam;			/* Use PAM for TIS? */
 	int     permit_empty_passwd;	/* If false, do not permit empty
 					 * passwords. */
 	int     use_login;	/* If true, login(1) is used */

Index: openssh/sshconnect1.c
@@ -821,7 +821,7 @@
 	char prompt[1024];
 	char *challenge, *response;
 	
-	debug("Doing challenge reponse authentication.");
+	debug("Doing challenge response authentication.");
 	
 	for (i = 0; i < options.number_of_password_prompts; i++) {
 		/* request a challenge */
@@ -849,7 +849,7 @@
 		if (options.cipher == SSH_CIPHER_NONE)
 			log("WARNING: Encryption is disabled! "
 			    "Reponse will be transmitted in clear text.");
-		response = read_passphrase(prompt, 0);
+		response = read_passphrase(prompt, RP_ECHO);
 		if (strcmp(response, "") == 0) {
 			xfree(response);
 			break;

Index: openssh/sshd.8
@@ -379,6 +379,12 @@
 are supported.
 The default is
 .Dq yes .
+.It Cm TISviaPAM
+Specifies whether protocol version 1 challenge response authentication (TIS)
+should be handled via PAM.  This is incompatible with with password
+authentication.
+The default is
+.Dq no .
 .It Cm Ciphers
 Specifies the ciphers allowed for protocol version 2.
 Multiple ciphers must be comma-separated.

Index: openssh/sshd_config
@@ -52,6 +52,9 @@
 
 # Uncomment to disable s/key passwords 
 #ChallengeResponseAuthentication no
+# Do ssh1 TIS authentication (challenge/response) via PAM?
+# ChallengeResponseAuthentication must be set for this to take effect.
+#TISviaPAM no
 
 # Uncomment to enable PAM keyboard-interactive authentication 
 # Warning: enabling this may bypass the setting of 'PasswordAuthentication'


More information about the openssh-unix-dev mailing list