bugzilla-daemon at mindrot.org
2002-Feb-15 10:44 UTC
[Bug 118] New: Implement TIS (protocol 1) via PAM
http://bugzilla.mindrot.org/show_bug.cgi?id=118 Summary: Implement TIS (protocol 1) via PAM Product: Portable OpenSSH Version: -current Platform: All OS/Version: All Status: NEW Severity: normal Priority: P3 Component: sshd AssignedTo: openssh-unix-dev at mindrot.org ReportedBy: fcusack at fcusack.com Currently, TIS is handled "natively" by sshd and only supports S/Key. With this patch, TIS is done via PAM, which gives a lot more flexibility on choice of "backend", eg you could do x9.9 tokens with protocol 1. It's a little bit less flexible if you have a server you want to be capable of doing either C/R or password. You can't do both via PAM in protocol 1. But the patch doesn't *break* doing both, you need merely turn off the TISviaPAM option and you are limited to the builtin S/Key for C/R. I hope this cut/pastes ok. This also fixes a bug in the current TIS handling, it turns echo on when doing TIS. diff -uNr openssh-3.0.2p1.orig/auth-pam.c openssh-3.0.2p1/auth-pam.c --- openssh-3.0.2p1.orig/auth-pam.c Fri Nov 9 12:22:17 2001 +++ openssh-3.0.2p1/auth-pam.c Fri Feb 15 02:17:19 2002 @@ -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( options.permit_empty_passwd == 0 ? PAM_DISALLOW_NULL_AUTHTOK : 0); if (pam_retval == PAM_SUCCESS) { diff -uNr openssh-3.0.2p1.orig/auth-pam.h openssh-3.0.2p1/auth-pam.h --- openssh-3.0.2p1.orig/auth-pam.h Mon Mar 26 22:12:24 2001 +++ openssh-3.0.2p1/auth-pam.h Fri Feb 15 02:15:02 2002 @@ -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); diff -uNr openssh-3.0.2p1.orig/auth1.c openssh-3.0.2p1/auth1.c --- openssh-3.0.2p1.orig/auth1.c Tue Nov 13 04:46:19 2001 +++ openssh-3.0.2p1/auth1.c Fri Feb 15 02:15:02 2002 @@ -85,7 +85,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 @@ -252,7 +252,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, @@ -269,6 +270,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); @@ -279,6 +289,7 @@ packet_write_wait(); continue; } + } } break; case SSH_CMSG_AUTH_TIS_RESPONSE: diff -uNr openssh-3.0.2p1.orig/auth2.c openssh-3.0.2p1/auth2.c --- openssh-3.0.2p1.orig/auth2.c Tue Nov 13 04:46:19 2001 +++ openssh-3.0.2p1/auth2.c Fri Feb 15 02:20:36 2002 @@ -345,7 +345,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 */ @@ -370,7 +370,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 */ diff -uNr openssh-3.0.2p1.orig/servconf.c openssh-3.0.2p1/servconf.c --- openssh-3.0.2p1.orig/servconf.c Tue Nov 13 05:03:15 2001 +++ openssh-3.0.2p1/servconf.c Fri Feb 15 02:15:05 2002 @@ -88,6 +88,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; @@ -249,7 +250,7 @@ #ifdef AFS sAFSTokenPassing, #endif - sChallengeResponseAuthentication, + sChallengeResponseAuthentication, sTISviaPAM, sPasswordAuthentication, sKbdInteractiveAuthentication, sListenAddress, sPrintMotd, sPrintLastLog, sIgnoreRhosts, sX11Forwarding, sX11DisplayOffset, @@ -304,6 +305,7 @@ { "kbdinteractiveauthentication", sKbdInteractiveAuthentication }, { "challengeresponseauthentication", sChallengeResponseAuthentication }, { "skeyauthentication", sChallengeResponseAuthentication }, /* alias */ + { "tisviapam", sTISviaPAM }, { "checkmail", sDeprecated }, { "listenaddress", sListenAddress }, { "printmotd", sPrintMotd }, @@ -648,6 +650,10 @@ case sChallengeResponseAuthentication: intptr = &options->challenge_response_authentication; + goto parse_flag; + + case sTISviaPAM: + intptr = &options->tis_via_pam; goto parse_flag; case sPrintMotd: diff -uNr openssh-3.0.2p1.orig/servconf.h openssh-3.0.2p1/servconf.h --- openssh-3.0.2p1.orig/servconf.h Wed Sep 12 09:40:06 2001 +++ openssh-3.0.2p1/servconf.h Fri Feb 15 02:15:05 2002 @@ -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 */ diff -uNr openssh-3.0.2p1.orig/sshconnect1.c openssh-3.0.2p1/sshconnect1.c --- openssh-3.0.2p1.orig/sshconnect1.c Tue Oct 9 22:03:12 2001 +++ openssh-3.0.2p1/sshconnect1.c Fri Feb 15 02:15:05 2002 @@ -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; diff -uNr openssh-3.0.2p1.orig/sshd.8 openssh-3.0.2p1/sshd.8 --- openssh-3.0.2p1.orig/sshd.8 Sat Dec 1 15:37:08 2001 +++ openssh-3.0.2p1/sshd.8 Fri Feb 15 02:15:05 2002 @@ -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. diff -uNr openssh-3.0.2p1.orig/sshd_config openssh-3.0.2p1/sshd_config --- openssh-3.0.2p1.orig/sshd_config Thu Sep 20 16:15:44 2001 +++ openssh-3.0.2p1/sshd_config Fri Feb 15 02:15:05 2002 @@ -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' ------- You are receiving this mail because: ------- You are the assignee for the bug, or are watching the assignee.