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