Home | History | Annotate | Download | only in openssh
      1 /* $OpenBSD: auth1.c,v 1.82 2014/07/15 15:54:14 millert Exp $ */
      2 /*
      3  * Copyright (c) 1995 Tatu Ylonen <ylo (at) cs.hut.fi>, Espoo, Finland
      4  *                    All rights reserved
      5  *
      6  * As far as I am concerned, the code I have written for this software
      7  * can be used freely for any purpose.  Any derived versions of this
      8  * software must be clearly marked as such, and if the derived work is
      9  * incompatible with the protocol description in the RFC file, it must be
     10  * called by a name other than "ssh" or "Secure Shell".
     11  */
     12 
     13 #include "includes.h"
     14 
     15 #ifdef WITH_SSH1
     16 
     17 #include <sys/types.h>
     18 
     19 #include <stdarg.h>
     20 #include <stdio.h>
     21 #include <string.h>
     22 #include <unistd.h>
     23 #include <pwd.h>
     24 
     25 #include "openbsd-compat/sys-queue.h"
     26 #include "xmalloc.h"
     27 #include "rsa.h"
     28 #include "ssh1.h"
     29 #include "packet.h"
     30 #include "buffer.h"
     31 #include "log.h"
     32 #include "misc.h"
     33 #include "servconf.h"
     34 #include "compat.h"
     35 #include "key.h"
     36 #include "hostfile.h"
     37 #include "auth.h"
     38 #include "channels.h"
     39 #include "session.h"
     40 #include "uidswap.h"
     41 #ifdef GSSAPI
     42 #include "ssh-gss.h"
     43 #endif
     44 #include "monitor_wrap.h"
     45 #include "buffer.h"
     46 
     47 /* import */
     48 extern ServerOptions options;
     49 extern Buffer loginmsg;
     50 
     51 static int auth1_process_password(Authctxt *);
     52 static int auth1_process_rsa(Authctxt *);
     53 static int auth1_process_rhosts_rsa(Authctxt *);
     54 static int auth1_process_tis_challenge(Authctxt *);
     55 static int auth1_process_tis_response(Authctxt *);
     56 
     57 static char *client_user = NULL;    /* Used to fill in remote user for PAM */
     58 
     59 struct AuthMethod1 {
     60 	int type;
     61 	char *name;
     62 	int *enabled;
     63 	int (*method)(Authctxt *);
     64 };
     65 
     66 const struct AuthMethod1 auth1_methods[] = {
     67 	{
     68 		SSH_CMSG_AUTH_PASSWORD, "password",
     69 		&options.password_authentication, auth1_process_password
     70 	},
     71 	{
     72 		SSH_CMSG_AUTH_RSA, "rsa",
     73 		&options.rsa_authentication, auth1_process_rsa
     74 	},
     75 	{
     76 		SSH_CMSG_AUTH_RHOSTS_RSA, "rhosts-rsa",
     77 		&options.rhosts_rsa_authentication, auth1_process_rhosts_rsa
     78 	},
     79 	{
     80 		SSH_CMSG_AUTH_TIS, "challenge-response",
     81 		&options.challenge_response_authentication,
     82 		auth1_process_tis_challenge
     83 	},
     84 	{
     85 		SSH_CMSG_AUTH_TIS_RESPONSE, "challenge-response",
     86 		&options.challenge_response_authentication,
     87 		auth1_process_tis_response
     88 	},
     89 	{ -1, NULL, NULL, NULL}
     90 };
     91 
     92 static const struct AuthMethod1
     93 *lookup_authmethod1(int type)
     94 {
     95 	int i;
     96 
     97 	for (i = 0; auth1_methods[i].name != NULL; i++)
     98 		if (auth1_methods[i].type == type)
     99 			return (&(auth1_methods[i]));
    100 
    101 	return (NULL);
    102 }
    103 
    104 static char *
    105 get_authname(int type)
    106 {
    107 	const struct AuthMethod1 *a;
    108 	static char buf[64];
    109 
    110 	if ((a = lookup_authmethod1(type)) != NULL)
    111 		return (a->name);
    112 	snprintf(buf, sizeof(buf), "bad-auth-msg-%d", type);
    113 	return (buf);
    114 }
    115 
    116 /*ARGSUSED*/
    117 static int
    118 auth1_process_password(Authctxt *authctxt)
    119 {
    120 	int authenticated = 0;
    121 	char *password;
    122 	u_int dlen;
    123 
    124 	/*
    125 	 * Read user password.  It is in plain text, but was
    126 	 * transmitted over the encrypted channel so it is
    127 	 * not visible to an outside observer.
    128 	 */
    129 	password = packet_get_string(&dlen);
    130 	packet_check_eom();
    131 
    132 	/* Try authentication with the password. */
    133 	authenticated = PRIVSEP(auth_password(authctxt, password));
    134 
    135 	explicit_bzero(password, dlen);
    136 	free(password);
    137 
    138 	return (authenticated);
    139 }
    140 
    141 /*ARGSUSED*/
    142 static int
    143 auth1_process_rsa(Authctxt *authctxt)
    144 {
    145 	int authenticated = 0;
    146 	BIGNUM *n;
    147 
    148 	/* RSA authentication requested. */
    149 	if ((n = BN_new()) == NULL)
    150 		fatal("do_authloop: BN_new failed");
    151 	packet_get_bignum(n);
    152 	packet_check_eom();
    153 	authenticated = auth_rsa(authctxt, n);
    154 	BN_clear_free(n);
    155 
    156 	return (authenticated);
    157 }
    158 
    159 /*ARGSUSED*/
    160 static int
    161 auth1_process_rhosts_rsa(Authctxt *authctxt)
    162 {
    163 	int keybits, authenticated = 0;
    164 	u_int bits;
    165 	Key *client_host_key;
    166 	u_int ulen;
    167 
    168 	/*
    169 	 * Get client user name.  Note that we just have to
    170 	 * trust the client; root on the client machine can
    171 	 * claim to be any user.
    172 	 */
    173 	client_user = packet_get_cstring(&ulen);
    174 
    175 	/* Get the client host key. */
    176 	client_host_key = key_new(KEY_RSA1);
    177 	bits = packet_get_int();
    178 	packet_get_bignum(client_host_key->rsa->e);
    179 	packet_get_bignum(client_host_key->rsa->n);
    180 
    181 	keybits = BN_num_bits(client_host_key->rsa->n);
    182 	if (keybits < 0 || bits != (u_int)keybits) {
    183 		verbose("Warning: keysize mismatch for client_host_key: "
    184 		    "actual %d, announced %d",
    185 		    BN_num_bits(client_host_key->rsa->n), bits);
    186 	}
    187 	packet_check_eom();
    188 
    189 	authenticated = auth_rhosts_rsa(authctxt, client_user,
    190 	    client_host_key);
    191 	key_free(client_host_key);
    192 
    193 	auth_info(authctxt, "ruser %.100s", client_user);
    194 
    195 	return (authenticated);
    196 }
    197 
    198 /*ARGSUSED*/
    199 static int
    200 auth1_process_tis_challenge(Authctxt *authctxt)
    201 {
    202 	char *challenge;
    203 
    204 	if ((challenge = get_challenge(authctxt)) == NULL)
    205 		return (0);
    206 
    207 	debug("sending challenge '%s'", challenge);
    208 	packet_start(SSH_SMSG_AUTH_TIS_CHALLENGE);
    209 	packet_put_cstring(challenge);
    210 	free(challenge);
    211 	packet_send();
    212 	packet_write_wait();
    213 
    214 	return (-1);
    215 }
    216 
    217 /*ARGSUSED*/
    218 static int
    219 auth1_process_tis_response(Authctxt *authctxt)
    220 {
    221 	int authenticated = 0;
    222 	char *response;
    223 	u_int dlen;
    224 
    225 	response = packet_get_string(&dlen);
    226 	packet_check_eom();
    227 	authenticated = verify_response(authctxt, response);
    228 	explicit_bzero(response, dlen);
    229 	free(response);
    230 
    231 	return (authenticated);
    232 }
    233 
    234 /*
    235  * read packets, try to authenticate the user and
    236  * return only if authentication is successful
    237  */
    238 static void
    239 do_authloop(Authctxt *authctxt)
    240 {
    241 	int authenticated = 0;
    242 	int prev = 0, type = 0;
    243 	const struct AuthMethod1 *meth;
    244 
    245 	debug("Attempting authentication for %s%.100s.",
    246 	    authctxt->valid ? "" : "invalid user ", authctxt->user);
    247 
    248 	/* If the user has no password, accept authentication immediately. */
    249 	if (options.permit_empty_passwd && options.password_authentication &&
    250 #ifdef KRB5
    251 	    (!options.kerberos_authentication || options.kerberos_or_local_passwd) &&
    252 #endif
    253 	    PRIVSEP(auth_password(authctxt, ""))) {
    254 #ifdef USE_PAM
    255 		if (options.use_pam && (PRIVSEP(do_pam_account())))
    256 #endif
    257 		{
    258 			auth_log(authctxt, 1, 0, "without authentication",
    259 			    NULL);
    260 			return;
    261 		}
    262 	}
    263 
    264 	/* Indicate that authentication is needed. */
    265 	packet_start(SSH_SMSG_FAILURE);
    266 	packet_send();
    267 	packet_write_wait();
    268 
    269 	for (;;) {
    270 		/* default to fail */
    271 		authenticated = 0;
    272 
    273 
    274 		/* Get a packet from the client. */
    275 		prev = type;
    276 		type = packet_read();
    277 
    278 		/*
    279 		 * If we started challenge-response authentication but the
    280 		 * next packet is not a response to our challenge, release
    281 		 * the resources allocated by get_challenge() (which would
    282 		 * normally have been released by verify_response() had we
    283 		 * received such a response)
    284 		 */
    285 		if (prev == SSH_CMSG_AUTH_TIS &&
    286 		    type != SSH_CMSG_AUTH_TIS_RESPONSE)
    287 			abandon_challenge_response(authctxt);
    288 
    289 		if (authctxt->failures >= options.max_authtries)
    290 			goto skip;
    291 		if ((meth = lookup_authmethod1(type)) == NULL) {
    292 			logit("Unknown message during authentication: "
    293 			    "type %d", type);
    294 			goto skip;
    295 		}
    296 
    297 		if (!*(meth->enabled)) {
    298 			verbose("%s authentication disabled.", meth->name);
    299 			goto skip;
    300 		}
    301 
    302 		authenticated = meth->method(authctxt);
    303 		if (authenticated == -1)
    304 			continue; /* "postponed" */
    305 
    306 #ifdef BSD_AUTH
    307 		if (authctxt->as) {
    308 			auth_close(authctxt->as);
    309 			authctxt->as = NULL;
    310 		}
    311 #endif
    312 		if (!authctxt->valid && authenticated)
    313 			fatal("INTERNAL ERROR: authenticated invalid user %s",
    314 			    authctxt->user);
    315 
    316 #ifdef _UNICOS
    317 		if (authenticated && cray_access_denied(authctxt->user)) {
    318 			authenticated = 0;
    319 			fatal("Access denied for user %s.",authctxt->user);
    320 		}
    321 #endif /* _UNICOS */
    322 
    323 #ifndef HAVE_CYGWIN
    324 		/* Special handling for root */
    325 		if (authenticated && authctxt->pw->pw_uid == 0 &&
    326 		    !auth_root_allowed(meth->name)) {
    327  			authenticated = 0;
    328 # ifdef SSH_AUDIT_EVENTS
    329 			PRIVSEP(audit_event(SSH_LOGIN_ROOT_DENIED));
    330 # endif
    331 		}
    332 #endif
    333 
    334 #ifdef USE_PAM
    335 		if (options.use_pam && authenticated &&
    336 		    !PRIVSEP(do_pam_account())) {
    337 			char *msg;
    338 			size_t len;
    339 
    340 			error("Access denied for user %s by PAM account "
    341 			    "configuration", authctxt->user);
    342 			len = buffer_len(&loginmsg);
    343 			buffer_append(&loginmsg, "\0", 1);
    344 			msg = buffer_ptr(&loginmsg);
    345 			/* strip trailing newlines */
    346 			if (len > 0)
    347 				while (len > 0 && msg[--len] == '\n')
    348 					msg[len] = '\0';
    349 			else
    350 				msg = "Access denied.";
    351 			packet_disconnect("%s", msg);
    352 		}
    353 #endif
    354 
    355  skip:
    356 		/* Log before sending the reply */
    357 		auth_log(authctxt, authenticated, 0, get_authname(type), NULL);
    358 
    359 		free(client_user);
    360 		client_user = NULL;
    361 
    362 		if (authenticated)
    363 			return;
    364 
    365 		if (++authctxt->failures >= options.max_authtries) {
    366 #ifdef SSH_AUDIT_EVENTS
    367 			PRIVSEP(audit_event(SSH_LOGIN_EXCEED_MAXTRIES));
    368 #endif
    369 			auth_maxtries_exceeded(authctxt);
    370 		}
    371 
    372 		packet_start(SSH_SMSG_FAILURE);
    373 		packet_send();
    374 		packet_write_wait();
    375 	}
    376 }
    377 
    378 /*
    379  * Performs authentication of an incoming connection.  Session key has already
    380  * been exchanged and encryption is enabled.
    381  */
    382 void
    383 do_authentication(Authctxt *authctxt)
    384 {
    385 	u_int ulen;
    386 	char *user, *style = NULL;
    387 
    388 	/* Get the name of the user that we wish to log in as. */
    389 	packet_read_expect(SSH_CMSG_USER);
    390 
    391 	/* Get the user name. */
    392 	user = packet_get_cstring(&ulen);
    393 	packet_check_eom();
    394 
    395 	if ((style = strchr(user, ':')) != NULL)
    396 		*style++ = '\0';
    397 
    398 	authctxt->user = user;
    399 	authctxt->style = style;
    400 
    401 	/* Verify that the user is a valid user. */
    402 	if ((authctxt->pw = PRIVSEP(getpwnamallow(user))) != NULL)
    403 		authctxt->valid = 1;
    404 	else {
    405 		debug("do_authentication: invalid user %s", user);
    406 		authctxt->pw = fakepw();
    407 	}
    408 
    409 	/* Configuration may have changed as a result of Match */
    410 	if (options.num_auth_methods != 0)
    411 		fatal("AuthenticationMethods is not supported with SSH "
    412 		    "protocol 1");
    413 
    414 	setproctitle("%s%s", authctxt->valid ? user : "unknown",
    415 	    use_privsep ? " [net]" : "");
    416 
    417 #ifdef USE_PAM
    418 	if (options.use_pam)
    419 		PRIVSEP(start_pam(authctxt));
    420 #endif
    421 
    422 	/*
    423 	 * If we are not running as root, the user must have the same uid as
    424 	 * the server.
    425 	 */
    426 #ifndef HAVE_CYGWIN
    427 	if (!use_privsep && getuid() != 0 && authctxt->pw &&
    428 	    authctxt->pw->pw_uid != getuid())
    429 		packet_disconnect("Cannot change user when server not running as root.");
    430 #endif
    431 
    432 	/*
    433 	 * Loop until the user has been authenticated or the connection is
    434 	 * closed, do_authloop() returns only if authentication is successful
    435 	 */
    436 	do_authloop(authctxt);
    437 
    438 	/* The user has been authenticated and accepted. */
    439 	packet_start(SSH_SMSG_SUCCESS);
    440 	packet_send();
    441 	packet_write_wait();
    442 }
    443 
    444 #endif /* WITH_SSH1 */
    445