1 /* 2 * Copyright (c) 2000 Markus Friedl. All rights reserved. 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions 6 * are met: 7 * 1. Redistributions of source code must retain the above copyright 8 * notice, this list of conditions and the following disclaimer. 9 * 2. Redistributions in binary form must reproduce the above copyright 10 * notice, this list of conditions and the following disclaimer in the 11 * documentation and/or other materials provided with the distribution. 12 * 13 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 14 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 15 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 16 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 17 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 18 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 19 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 20 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 21 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 22 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 23 */ 24 25 #include "includes.h" 26 RCSID("$OpenBSD: auth2.c,v 1.14 2000/09/07 20:27:49 deraadt Exp $"); 27 RCSID("$FreeBSD$"); 28 29 #include <openssl/dsa.h> 30 #include <openssl/rsa.h> 31 #include <openssl/evp.h> 32 33 #include "xmalloc.h" 34 #include "rsa.h" 35 #include "ssh.h" 36 #include "pty.h" 37 #include "packet.h" 38 #include "buffer.h" 39 #include "cipher.h" 40 #include "servconf.h" 41 #include "compat.h" 42 #include "channels.h" 43 #include "bufaux.h" 44 #include "ssh2.h" 45 #include "auth.h" 46 #include "session.h" 47 #include "dispatch.h" 48 #include "auth.h" 49 #include "key.h" 50 #include "kex.h" 51 52 #include "dsa.h" 53 #include "uidswap.h" 54 #include "auth-options.h" 55 56 #ifdef HAVE_LOGIN_CAP 57 #include <login_cap.h> 58 #endif /* HAVE_LOGIN_CAP */ 59 60 /* import */ 61 extern ServerOptions options; 62 extern unsigned char *session_id2; 63 extern int session_id2_len; 64 65 /* protocol */ 66 67 void input_service_request(int type, int plen); 68 void input_userauth_request(int type, int plen); 69 void protocol_error(int type, int plen); 70 71 /* auth */ 72 int ssh2_auth_none(struct passwd *pw); 73 int ssh2_auth_password(struct passwd *pw); 74 int ssh2_auth_pubkey(struct passwd *pw, char *service); 75 76 /* helper */ 77 struct passwd* auth_set_user(char *u, char *s); 78 int user_dsa_key_allowed(struct passwd *pw, Key *key); 79 80 typedef struct Authctxt Authctxt; 81 struct Authctxt { 82 char *user; 83 char *service; 84 struct passwd pw; 85 int valid; 86 }; 87 static Authctxt *authctxt = NULL; 88 static int userauth_success = 0; 89 90 /* 91 * loop until userauth_success == TRUE 92 */ 93 94 void 95 do_authentication2() 96 { 97 /* turn off skey/kerberos, not supported by SSH2 */ 98 #ifdef SKEY 99 options.skey_authentication = 0; 100 #endif 101 #ifdef KRB4 102 options.krb4_authentication = 0; 103 #endif 104 105 dispatch_init(&protocol_error); 106 dispatch_set(SSH2_MSG_SERVICE_REQUEST, &input_service_request); 107 dispatch_run(DISPATCH_BLOCK, &userauth_success); 108 do_authenticated2(); 109 } 110 111 void 112 protocol_error(int type, int plen) 113 { 114 log("auth: protocol error: type %d plen %d", type, plen); 115 packet_start(SSH2_MSG_UNIMPLEMENTED); 116 packet_put_int(0); 117 packet_send(); 118 packet_write_wait(); 119 } 120 121 void 122 input_service_request(int type, int plen) 123 { 124 unsigned int len; 125 int accept = 0; 126 char *service = packet_get_string(&len); 127 packet_done(); 128 129 if (strcmp(service, "ssh-userauth") == 0) { 130 if (!userauth_success) { 131 accept = 1; 132 /* now we can handle user-auth requests */ 133 dispatch_set(SSH2_MSG_USERAUTH_REQUEST, &input_userauth_request); 134 } 135 } 136 /* XXX all other service requests are denied */ 137 138 if (accept) { 139 packet_start(SSH2_MSG_SERVICE_ACCEPT); 140 packet_put_cstring(service); 141 packet_send(); 142 packet_write_wait(); 143 } else { 144 debug("bad service request %s", service); 145 packet_disconnect("bad service request %s", service); 146 } 147 xfree(service); 148 } 149 150 void 151 input_userauth_request(int type, int plen) 152 { 153 static void (*authlog) (const char *fmt,...) = verbose; 154 static int attempt = 0; 155 unsigned int len; 156 int authenticated = 0; 157 char *user, *service, *method, *authmsg = NULL; 158 struct passwd *pw; 159 #ifdef HAVE_LOGIN_CAP 160 login_cap_t *lc; 161 #endif /* HAVE_LOGIN_CAP */ 162 #if defined(HAVE_LOGIN_CAP) || defined(LOGIN_ACCESS) 163 const char *from_host, *from_ip; 164 165 from_host = get_canonical_hostname(); 166 from_ip = get_remote_ipaddr(); 167 #endif /* HAVE_LOGIN_CAP || LOGIN_ACCESS */ 168 169 if (++attempt == AUTH_FAIL_MAX) 170 packet_disconnect("too many failed userauth_requests"); 171 172 user = packet_get_string(&len); 173 service = packet_get_string(&len); 174 method = packet_get_string(&len); 175 debug("userauth-request for user %s service %s method %s", user, service, method); 176 177 /* XXX we only allow the ssh-connection service */ 178 pw = auth_set_user(user, service); 179 if (pw && strcmp(service, "ssh-connection")==0) { 180 if (strcmp(method, "none") == 0) { 181 authenticated = ssh2_auth_none(pw); 182 } else if (strcmp(method, "password") == 0) { 183 authenticated = ssh2_auth_password(pw); 184 } else if (strcmp(method, "publickey") == 0) { 185 authenticated = ssh2_auth_pubkey(pw, service); 186 } 187 } 188 if (authenticated && pw && pw->pw_uid == 0 && !options.permit_root_login) { 189 authenticated = 0; 190 log("ROOT LOGIN REFUSED FROM %.200s", 191 get_canonical_hostname()); 192 } 193 194 #ifdef HAVE_LOGIN_CAP 195 lc = login_getpwclass(pw); 196 if (lc == NULL) 197 lc = login_getclassbyname(NULL, pw); 198 if (!auth_hostok(lc, from_host, from_ip)) { 199 log("Denied connection for %.200s from %.200s [%.200s].", 200 pw->pw_name, from_host, from_ip); 201 packet_disconnect("Sorry, you are not allowed to connect."); 202 } 203 if (!auth_timeok(lc, time(NULL))) { 204 log("LOGIN %.200s REFUSED (TIME) FROM %.200s", 205 pw->pw_name, from_host); 206 packet_disconnect("Logins not available right now."); 207 } 208 login_close(lc); 209 #endif /* HAVE_LOGIN_CAP */ 210 #ifdef LOGIN_ACCESS 211 if (!login_access(pw->pw_name, from_host)) { 212 log("Denied connection for %.200s from %.200s [%.200s].", 213 pw->pw_name, from_host, from_ip); 214 packet_disconnect("Sorry, you are not allowed to connect."); 215 } 216 #endif /* LOGIN_ACCESS */ 217 218 /* Raise logging level */ 219 if (authenticated == 1 || 220 attempt == AUTH_FAIL_LOG || 221 strcmp(method, "password") == 0) 222 authlog = log; 223 224 /* Log before sending the reply */ 225 if (authenticated == 1) { 226 authmsg = "Accepted"; 227 } else if (authenticated == 0) { 228 authmsg = "Failed"; 229 } else { 230 authmsg = "Postponed"; 231 } 232 authlog("%s %s for %.200s from %.200s port %d ssh2", 233 authmsg, 234 method, 235 pw && pw->pw_uid == 0 ? "ROOT" : user, 236 get_remote_ipaddr(), 237 get_remote_port()); 238 239 /* XXX todo: check if multiple auth methods are needed */ 240 if (authenticated == 1) { 241 /* turn off userauth */ 242 dispatch_set(SSH2_MSG_USERAUTH_REQUEST, &protocol_error); 243 packet_start(SSH2_MSG_USERAUTH_SUCCESS); 244 packet_send(); 245 packet_write_wait(); 246 /* now we can break out */ 247 userauth_success = 1; 248 } else if (authenticated == 0) { 249 packet_start(SSH2_MSG_USERAUTH_FAILURE); 250 packet_put_cstring("publickey,password"); /* XXX dynamic */ 251 packet_put_char(0); /* XXX partial success, unused */ 252 packet_send(); 253 packet_write_wait(); 254 } 255 256 xfree(service); 257 xfree(user); 258 xfree(method); 259 } 260 261 int 262 ssh2_auth_none(struct passwd *pw) 263 { 264 packet_done(); 265 return auth_password(pw, ""); 266 } 267 int 268 ssh2_auth_password(struct passwd *pw) 269 { 270 char *password; 271 int authenticated = 0; 272 int change; 273 unsigned int len; 274 change = packet_get_char(); 275 if (change) 276 log("password change not supported"); 277 password = packet_get_string(&len); 278 packet_done(); 279 if (options.password_authentication && 280 auth_password(pw, password) == 1) 281 authenticated = 1; 282 memset(password, 0, len); 283 xfree(password); 284 return authenticated; 285 } 286 int 287 ssh2_auth_pubkey(struct passwd *pw, char *service) 288 { 289 Buffer b; 290 Key *key; 291 char *pkalg, *pkblob, *sig; 292 unsigned int alen, blen, slen; 293 int have_sig; 294 int authenticated = 0; 295 296 if (options.dsa_authentication == 0) { 297 debug("pubkey auth disabled"); 298 return 0; 299 } 300 have_sig = packet_get_char(); 301 pkalg = packet_get_string(&alen); 302 if (strcmp(pkalg, KEX_DSS) != 0) { 303 xfree(pkalg); 304 log("bad pkalg %s", pkalg); /*XXX*/ 305 return 0; 306 } 307 pkblob = packet_get_string(&blen); 308 key = dsa_key_from_blob(pkblob, blen); 309 if (key != NULL) { 310 if (have_sig) { 311 sig = packet_get_string(&slen); 312 packet_done(); 313 buffer_init(&b); 314 if (datafellows & SSH_COMPAT_SESSIONID_ENCODING) { 315 buffer_put_string(&b, session_id2, session_id2_len); 316 } else { 317 buffer_append(&b, session_id2, session_id2_len); 318 } 319 /* reconstruct packet */ 320 buffer_put_char(&b, SSH2_MSG_USERAUTH_REQUEST); 321 buffer_put_cstring(&b, pw->pw_name); 322 buffer_put_cstring(&b, 323 datafellows & SSH_BUG_PUBKEYAUTH ? 324 "ssh-userauth" : 325 service); 326 buffer_put_cstring(&b, "publickey"); 327 buffer_put_char(&b, have_sig); 328 buffer_put_cstring(&b, KEX_DSS); 329 buffer_put_string(&b, pkblob, blen); 330 #ifdef DEBUG_DSS 331 buffer_dump(&b); 332 #endif 333 /* test for correct signature */ 334 if (user_dsa_key_allowed(pw, key) && 335 dsa_verify(key, sig, slen, buffer_ptr(&b), buffer_len(&b)) == 1) 336 authenticated = 1; 337 buffer_clear(&b); 338 xfree(sig); 339 } else { 340 packet_done(); 341 debug("test key..."); 342 /* test whether pkalg/pkblob are acceptable */ 343 /* XXX fake reply and always send PK_OK ? */ 344 /* 345 * XXX this allows testing whether a user is allowed 346 * to login: if you happen to have a valid pubkey this 347 * message is sent. the message is NEVER sent at all 348 * if a user is not allowed to login. is this an 349 * issue? -markus 350 */ 351 if (user_dsa_key_allowed(pw, key)) { 352 packet_start(SSH2_MSG_USERAUTH_PK_OK); 353 packet_put_string(pkalg, alen); 354 packet_put_string(pkblob, blen); 355 packet_send(); 356 packet_write_wait(); 357 authenticated = -1; 358 } 359 } 360 key_free(key); 361 } 362 xfree(pkalg); 363 xfree(pkblob); 364 return authenticated; 365 } 366 367 /* set and get current user */ 368 369 struct passwd* 370 auth_get_user(void) 371 { 372 return (authctxt != NULL && authctxt->valid) ? &authctxt->pw : NULL; 373 } 374 375 struct passwd* 376 auth_set_user(char *u, char *s) 377 { 378 struct passwd *pw, *copy; 379 380 if (authctxt == NULL) { 381 authctxt = xmalloc(sizeof(*authctxt)); 382 authctxt->valid = 0; 383 authctxt->user = xstrdup(u); 384 authctxt->service = xstrdup(s); 385 setproctitle("%s", u); 386 pw = getpwnam(u); 387 if (!pw || !allowed_user(pw)) { 388 log("auth_set_user: illegal user %s", u); 389 return NULL; 390 } 391 copy = &authctxt->pw; 392 memset(copy, 0, sizeof(*copy)); 393 copy->pw_name = xstrdup(pw->pw_name); 394 copy->pw_passwd = xstrdup(pw->pw_passwd); 395 copy->pw_uid = pw->pw_uid; 396 copy->pw_gid = pw->pw_gid; 397 copy->pw_class = xstrdup(pw->pw_class); 398 copy->pw_dir = xstrdup(pw->pw_dir); 399 copy->pw_shell = xstrdup(pw->pw_shell); 400 copy->pw_class = xstrdup(pw->pw_class); 401 copy->pw_expire = pw->pw_expire; 402 copy->pw_change = pw->pw_change; 403 authctxt->valid = 1; 404 } else { 405 if (strcmp(u, authctxt->user) != 0 || 406 strcmp(s, authctxt->service) != 0) { 407 log("auth_set_user: missmatch: (%s,%s)!=(%s,%s)", 408 u, s, authctxt->user, authctxt->service); 409 return NULL; 410 } 411 } 412 return auth_get_user(); 413 } 414 415 /* return 1 if user allows given key */ 416 int 417 user_dsa_key_allowed(struct passwd *pw, Key *key) 418 { 419 char line[8192], file[1024]; 420 int found_key = 0; 421 unsigned int bits = -1; 422 FILE *f; 423 unsigned long linenum = 0; 424 struct stat st; 425 Key *found; 426 427 /* Temporarily use the user's uid. */ 428 temporarily_use_uid(pw->pw_uid); 429 430 /* The authorized keys. */ 431 snprintf(file, sizeof file, "%.500s/%.100s", pw->pw_dir, 432 SSH_USER_PERMITTED_KEYS2); 433 434 /* Fail quietly if file does not exist */ 435 if (stat(file, &st) < 0) { 436 /* Restore the privileged uid. */ 437 restore_uid(); 438 return 0; 439 } 440 /* Open the file containing the authorized keys. */ 441 f = fopen(file, "r"); 442 if (!f) { 443 /* Restore the privileged uid. */ 444 restore_uid(); 445 return 0; 446 } 447 if (options.strict_modes) { 448 int fail = 0; 449 char buf[1024]; 450 /* Check open file in order to avoid open/stat races */ 451 if (fstat(fileno(f), &st) < 0 || 452 (st.st_uid != 0 && st.st_uid != pw->pw_uid) || 453 (st.st_mode & 022) != 0) { 454 snprintf(buf, sizeof buf, "DSA authentication refused for %.100s: " 455 "bad ownership or modes for '%s'.", pw->pw_name, file); 456 fail = 1; 457 } else { 458 /* Check path to SSH_USER_PERMITTED_KEYS */ 459 int i; 460 static const char *check[] = { 461 "", SSH_USER_DIR, NULL 462 }; 463 for (i = 0; check[i]; i++) { 464 snprintf(line, sizeof line, "%.500s/%.100s", 465 pw->pw_dir, check[i]); 466 if (stat(line, &st) < 0 || 467 (st.st_uid != 0 && st.st_uid != pw->pw_uid) || 468 (st.st_mode & 022) != 0) { 469 snprintf(buf, sizeof buf, 470 "DSA authentication refused for %.100s: " 471 "bad ownership or modes for '%s'.", 472 pw->pw_name, line); 473 fail = 1; 474 break; 475 } 476 } 477 } 478 if (fail) { 479 fclose(f); 480 log("%s",buf); 481 restore_uid(); 482 return 0; 483 } 484 } 485 found_key = 0; 486 found = key_new(KEY_DSA); 487 488 while (fgets(line, sizeof(line), f)) { 489 char *cp, *options = NULL; 490 linenum++; 491 /* Skip leading whitespace, empty and comment lines. */ 492 for (cp = line; *cp == ' ' || *cp == '\t'; cp++) 493 ; 494 if (!*cp || *cp == '\n' || *cp == '#') 495 continue; 496 497 bits = key_read(found, &cp); 498 if (bits == 0) { 499 /* no key? check if there are options for this key */ 500 int quoted = 0; 501 options = cp; 502 for (; *cp && (quoted || (*cp != ' ' && *cp != '\t')); cp++) { 503 if (*cp == '\\' && cp[1] == '"') 504 cp++; /* Skip both */ 505 else if (*cp == '"') 506 quoted = !quoted; 507 } 508 /* Skip remaining whitespace. */ 509 for (; *cp == ' ' || *cp == '\t'; cp++) 510 ; 511 bits = key_read(found, &cp); 512 if (bits == 0) { 513 /* still no key? advance to next line*/ 514 continue; 515 } 516 } 517 if (key_equal(found, key) && 518 auth_parse_options(pw, options, linenum) == 1) { 519 found_key = 1; 520 debug("matching key found: file %s, line %ld", 521 file, linenum); 522 break; 523 } 524 } 525 restore_uid(); 526 fclose(f); 527 key_free(found); 528 return found_key; 529 } 530