From 8485ce5651694aa988c8186d1675230328fb0e18 Mon Sep 17 00:00:00 2001 From: djm Date: Sat, 18 Jun 2005 21:31:37 +0000 Subject: [PATCH] - djm@cvs.openbsd.org 2005/05/20 12:57:01; [auth1.c] split protocol 1 auth methods into separate functions, makes authloop much more readable; fixes and ok markus@ (portable ok & polish dtucker@) --- ChangeLog | 7 ++ auth1.c | 323 ++++++++++++++++++++++++++++++++---------------------- 2 files changed, 199 insertions(+), 131 deletions(-) diff --git a/ChangeLog b/ChangeLog index ac6328af..e7aead7f 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,10 @@ +20050618 + - (djm) OpenBSD CVS Sync + - djm@cvs.openbsd.org 2005/05/20 12:57:01; + [auth1.c] split protocol 1 auth methods into separate functions, makes + authloop much more readable; fixes and ok markus@ (portable ok & + polish dtucker@) + 20050617 - (djm) OpenBSD CVS Sync - djm@cvs.openbsd.org 2005/06/16 03:38:36 diff --git a/auth1.c b/auth1.c index d0892845..b7dfa987 100644 --- a/auth1.c +++ b/auth1.c @@ -10,7 +10,7 @@ */ #include "includes.h" -RCSID("$OpenBSD: auth1.c,v 1.59 2004/07/28 09:40:29 markus Exp $"); +RCSID("$OpenBSD: auth1.c,v 1.60 2005/05/20 12:57:01 djm Exp $"); #include "xmalloc.h" #include "rsa.h" @@ -31,28 +31,181 @@ RCSID("$OpenBSD: auth1.c,v 1.59 2004/07/28 09:40:29 markus Exp $"); extern ServerOptions options; extern Buffer loginmsg; -/* - * convert ssh auth msg type into description - */ +static int auth1_process_password(Authctxt *, char *, size_t); +static int auth1_process_rsa(Authctxt *, char *, size_t); +static int auth1_process_rhosts_rsa(Authctxt *, char *, size_t); +static int auth1_process_tis_challenge(Authctxt *, char *, size_t); +static int auth1_process_tis_response(Authctxt *, char *, size_t); + +static char *client_user = NULL; /* Used to fill in remote user for PAM */ + +struct AuthMethod1 { + int type; + char *name; + int *enabled; + int (*method)(Authctxt *, char *, size_t); +}; + +const struct AuthMethod1 auth1_methods[] = { + { + SSH_CMSG_AUTH_PASSWORD, "password", + &options.password_authentication, auth1_process_password + }, + { + SSH_CMSG_AUTH_RSA, "rsa", + &options.rsa_authentication, auth1_process_rsa + }, + { + SSH_CMSG_AUTH_RHOSTS_RSA, "rhosts-rsa", + &options.rhosts_rsa_authentication, auth1_process_rhosts_rsa + }, + { + SSH_CMSG_AUTH_TIS, "challenge-response", + &options.challenge_response_authentication, + auth1_process_tis_challenge + }, + { + SSH_CMSG_AUTH_TIS_RESPONSE, "challenge-response", + &options.challenge_response_authentication, + auth1_process_tis_response + }, + { -1, NULL, NULL, NULL} +}; + +static const struct AuthMethod1 +*lookup_authmethod1(int type) +{ + int i; + + for(i = 0; auth1_methods[i].name != NULL; i++) + if (auth1_methods[i].type == type) + return (&(auth1_methods[i])); + + return (NULL); +} + static char * get_authname(int type) { - static char buf[1024]; - switch (type) { - case SSH_CMSG_AUTH_PASSWORD: - return "password"; - case SSH_CMSG_AUTH_RSA: - return "rsa"; - case SSH_CMSG_AUTH_RHOSTS_RSA: - return "rhosts-rsa"; - case SSH_CMSG_AUTH_RHOSTS: - return "rhosts"; - case SSH_CMSG_AUTH_TIS: - case SSH_CMSG_AUTH_TIS_RESPONSE: - return "challenge-response"; + const struct AuthMethod1 *a; + static char buf[64]; + + if ((a = lookup_authmethod1(type)) != NULL) + return (a->name); + snprintf(buf, sizeof(buf), "bad-auth-msg-%d", type); + return (buf); +} + +static int +auth1_process_password(Authctxt *authctxt, char *info, size_t infolen) +{ + int authenticated = 0; + char *password; + u_int dlen; + + /* + * Read user password. It is in plain text, but was + * transmitted over the encrypted channel so it is + * not visible to an outside observer. + */ + password = packet_get_string(&dlen); + packet_check_eom(); + + /* Try authentication with the password. */ + authenticated = PRIVSEP(auth_password(authctxt, password)); + + memset(password, 0, dlen); + xfree(password); + + return (authenticated); +} + +static int +auth1_process_rsa(Authctxt *authctxt, char *info, size_t infolen) +{ + int authenticated = 0; + BIGNUM *n; + + /* RSA authentication requested. */ + if ((n = BN_new()) == NULL) + fatal("do_authloop: BN_new failed"); + packet_get_bignum(n); + packet_check_eom(); + authenticated = auth_rsa(authctxt, n); + BN_clear_free(n); + + return (authenticated); +} + +static int +auth1_process_rhosts_rsa(Authctxt *authctxt, char *info, size_t infolen) +{ + int authenticated = 0; + u_int bits; + Key *client_host_key; + u_int ulen; + + /* + * Get client user name. Note that we just have to + * trust the client; root on the client machine can + * claim to be any user. + */ + client_user = packet_get_string(&ulen); + + /* Get the client host key. */ + client_host_key = key_new(KEY_RSA1); + bits = packet_get_int(); + packet_get_bignum(client_host_key->rsa->e); + packet_get_bignum(client_host_key->rsa->n); + + if (bits != BN_num_bits(client_host_key->rsa->n)) { + verbose("Warning: keysize mismatch for client_host_key: " + "actual %d, announced %d", + BN_num_bits(client_host_key->rsa->n), bits); } - snprintf(buf, sizeof buf, "bad-auth-msg-%d", type); - return buf; + packet_check_eom(); + + authenticated = auth_rhosts_rsa(authctxt, client_user, + client_host_key); + key_free(client_host_key); + + snprintf(info, infolen, " ruser %.100s", client_user); + + return (authenticated); +} + +static int +auth1_process_tis_challenge(Authctxt *authctxt, char *info, size_t infolen) +{ + char *challenge; + + if ((challenge = get_challenge(authctxt)) == NULL) + return (0); + + debug("sending challenge '%s'", challenge); + packet_start(SSH_SMSG_AUTH_TIS_CHALLENGE); + packet_put_cstring(challenge); + xfree(challenge); + packet_send(); + packet_write_wait(); + + return (-1); +} + +static int +auth1_process_tis_response(Authctxt *authctxt, char *info, size_t infolen) +{ + int authenticated = 0; + char *response; + u_int dlen; + + response = packet_get_string(&dlen); + packet_check_eom(); + authenticated = verify_response(authctxt, response); + memset(response, 'r', dlen); + xfree(response); + + return (authenticated); } /* @@ -63,14 +216,9 @@ static void do_authloop(Authctxt *authctxt) { int authenticated = 0; - u_int bits; - Key *client_host_key; - BIGNUM *n; - char *client_user, *password; char info[1024]; - u_int dlen; - u_int ulen; - int prev, type = 0; + int prev = 0, type = 0; + const struct AuthMethod1 *meth; debug("Attempting authentication for %s%.100s.", authctxt->valid ? "" : "invalid user ", authctxt->user); @@ -95,8 +243,6 @@ do_authloop(Authctxt *authctxt) packet_send(); packet_write_wait(); - client_user = NULL; - for (;;) { /* default to fail */ authenticated = 0; @@ -118,107 +264,21 @@ do_authloop(Authctxt *authctxt) type != SSH_CMSG_AUTH_TIS_RESPONSE) abandon_challenge_response(authctxt); - /* Process the packet. */ - switch (type) { - case SSH_CMSG_AUTH_RHOSTS_RSA: - if (!options.rhosts_rsa_authentication) { - verbose("Rhosts with RSA authentication disabled."); - break; - } - /* - * Get client user name. Note that we just have to - * trust the client; root on the client machine can - * claim to be any user. - */ - client_user = packet_get_string(&ulen); - - /* Get the client host key. */ - client_host_key = key_new(KEY_RSA1); - bits = packet_get_int(); - packet_get_bignum(client_host_key->rsa->e); - packet_get_bignum(client_host_key->rsa->n); - - if (bits != BN_num_bits(client_host_key->rsa->n)) - verbose("Warning: keysize mismatch for client_host_key: " - "actual %d, announced %d", - BN_num_bits(client_host_key->rsa->n), bits); - packet_check_eom(); - - authenticated = auth_rhosts_rsa(authctxt, client_user, - client_host_key); - key_free(client_host_key); - - snprintf(info, sizeof info, " ruser %.100s", client_user); - break; - - case SSH_CMSG_AUTH_RSA: - if (!options.rsa_authentication) { - verbose("RSA authentication disabled."); - break; - } - /* RSA authentication requested. */ - if ((n = BN_new()) == NULL) - fatal("do_authloop: BN_new failed"); - packet_get_bignum(n); - packet_check_eom(); - authenticated = auth_rsa(authctxt, n); - BN_clear_free(n); - break; - - case SSH_CMSG_AUTH_PASSWORD: - if (!options.password_authentication) { - verbose("Password authentication disabled."); - break; - } - /* - * Read user password. It is in plain text, but was - * transmitted over the encrypted channel so it is - * not visible to an outside observer. - */ - password = packet_get_string(&dlen); - packet_check_eom(); - - /* Try authentication with the password. */ - authenticated = PRIVSEP(auth_password(authctxt, password)); - - memset(password, 0, strlen(password)); - xfree(password); - break; - - case SSH_CMSG_AUTH_TIS: - debug("rcvd SSH_CMSG_AUTH_TIS"); - if (options.challenge_response_authentication == 1) { - char *challenge = get_challenge(authctxt); - if (challenge != NULL) { - debug("sending challenge '%s'", challenge); - packet_start(SSH_SMSG_AUTH_TIS_CHALLENGE); - packet_put_cstring(challenge); - xfree(challenge); - packet_send(); - packet_write_wait(); - continue; - } - } - break; - case SSH_CMSG_AUTH_TIS_RESPONSE: - debug("rcvd SSH_CMSG_AUTH_TIS_RESPONSE"); - if (options.challenge_response_authentication == 1) { - char *response = packet_get_string(&dlen); - packet_check_eom(); - authenticated = verify_response(authctxt, response); - memset(response, 'r', dlen); - xfree(response); - } - break; - - default: - /* - * Any unknown messages will be ignored (and failure - * returned) during authentication. - */ - logit("Unknown message during authentication: type %d", type); - break; + if ((meth = lookup_authmethod1(type)) == NULL) { + logit("Unknown message during authentication: " + "type %d", type); + goto skip; + } + + if (!*(meth->enabled)) { + verbose("%s authentication disabled.", meth->name); + goto skip; } + + authenticated = meth->method(authctxt, info, sizeof(info)); + if (authenticated == -1) + continue; /* "postponed" */ + #ifdef BSD_AUTH if (authctxt->as) { auth_close(authctxt->as); @@ -247,8 +307,8 @@ do_authloop(Authctxt *authctxt) #else /* Special handling for root */ if (authenticated && authctxt->pw->pw_uid == 0 && - !auth_root_allowed(get_authname(type))) { - authenticated = 0; + !auth_root_allowed(meth->name)) { + authenticated = 0; # ifdef SSH_AUDIT_EVENTS PRIVSEP(audit_event(SSH_LOGIN_ROOT_DENIED)); # endif @@ -276,6 +336,7 @@ do_authloop(Authctxt *authctxt) } #endif + skip: /* Log before sending the reply */ auth_log(authctxt, authenticated, get_authname(type), info); @@ -341,7 +402,7 @@ do_authentication(Authctxt *authctxt) /* * If we are not running as root, the user must have the same uid as - * the server. (Unless you are running Windows) + * the server. */ #ifndef HAVE_CYGWIN if (!use_privsep && getuid() != 0 && authctxt->pw && -- 2.45.1