1 /* $OpenBSD: auth.c,v 1.79 2008/07/02 12:03:51 dtucker Exp $ */ 2 /* 3 * Copyright (c) 2000 Markus Friedl. All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 15 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 16 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 17 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 18 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 19 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 20 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 21 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 23 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 */ 25 26 #include "includes.h" 27 __RCSID("$FreeBSD$"); 28 29 #include <sys/types.h> 30 #include <sys/stat.h> 31 #include <sys/param.h> 32 33 #include <netinet/in.h> 34 35 #include <errno.h> 36 #include <fcntl.h> 37 #ifdef HAVE_PATHS_H 38 # include <paths.h> 39 #endif 40 #include <pwd.h> 41 #ifdef HAVE_LOGIN_H 42 #include <login.h> 43 #endif 44 #ifdef USE_SHADOW 45 #include <shadow.h> 46 #endif 47 #ifdef HAVE_LIBGEN_H 48 #include <libgen.h> 49 #endif 50 #include <stdarg.h> 51 #include <stdio.h> 52 #include <string.h> 53 #include <unistd.h> 54 55 #include "xmalloc.h" 56 #include "match.h" 57 #include "groupaccess.h" 58 #include "log.h" 59 #include "buffer.h" 60 #include "servconf.h" 61 #include "key.h" 62 #include "hostfile.h" 63 #include "auth.h" 64 #include "auth-options.h" 65 #include "canohost.h" 66 #include "uidswap.h" 67 #include "misc.h" 68 #include "packet.h" 69 #include "loginrec.h" 70 #ifdef GSSAPI 71 #include "ssh-gss.h" 72 #endif 73 #include "monitor_wrap.h" 74 75 /* import */ 76 extern ServerOptions options; 77 extern int use_privsep; 78 extern Buffer loginmsg; 79 extern struct passwd *privsep_pw; 80 81 /* Debugging messages */ 82 Buffer auth_debug; 83 int auth_debug_init; 84 85 /* 86 * Check if the user is allowed to log in via ssh. If user is listed 87 * in DenyUsers or one of user's groups is listed in DenyGroups, false 88 * will be returned. If AllowUsers isn't empty and user isn't listed 89 * there, or if AllowGroups isn't empty and one of user's groups isn't 90 * listed there, false will be returned. 91 * If the user's shell is not executable, false will be returned. 92 * Otherwise true is returned. 93 */ 94 int 95 allowed_user(struct passwd * pw) 96 { 97 struct stat st; 98 const char *hostname = NULL, *ipaddr = NULL, *passwd = NULL; 99 char *shell; 100 u_int i; 101 #ifdef USE_SHADOW 102 struct spwd *spw = NULL; 103 #endif 104 105 /* Shouldn't be called if pw is NULL, but better safe than sorry... */ 106 if (!pw || !pw->pw_name) 107 return 0; 108 109 #ifdef USE_SHADOW 110 if (!options.use_pam) 111 spw = getspnam(pw->pw_name); 112 #ifdef HAS_SHADOW_EXPIRE 113 if (!options.use_pam && spw != NULL && auth_shadow_acctexpired(spw)) 114 return 0; 115 #endif /* HAS_SHADOW_EXPIRE */ 116 #endif /* USE_SHADOW */ 117 118 /* grab passwd field for locked account check */ 119 passwd = pw->pw_passwd; 120 #ifdef USE_SHADOW 121 if (spw != NULL) 122 #ifdef USE_LIBIAF 123 passwd = get_iaf_password(pw); 124 #else 125 passwd = spw->sp_pwdp; 126 #endif /* USE_LIBIAF */ 127 #endif 128 129 /* check for locked account */ 130 if (!options.use_pam && passwd && *passwd) { 131 int locked = 0; 132 133 #ifdef LOCKED_PASSWD_STRING 134 if (strcmp(passwd, LOCKED_PASSWD_STRING) == 0) 135 locked = 1; 136 #endif 137 #ifdef LOCKED_PASSWD_PREFIX 138 if (strncmp(passwd, LOCKED_PASSWD_PREFIX, 139 strlen(LOCKED_PASSWD_PREFIX)) == 0) 140 locked = 1; 141 #endif 142 #ifdef LOCKED_PASSWD_SUBSTR 143 if (strstr(passwd, LOCKED_PASSWD_SUBSTR)) 144 locked = 1; 145 #endif 146 #ifdef USE_LIBIAF 147 free(passwd); 148 #endif /* USE_LIBIAF */ 149 if (locked) { 150 logit("User %.100s not allowed because account is locked", 151 pw->pw_name); 152 return 0; 153 } 154 } 155 156 /* 157 * Get the shell from the password data. An empty shell field is 158 * legal, and means /bin/sh. 159 */ 160 shell = (pw->pw_shell[0] == '\0') ? _PATH_BSHELL : pw->pw_shell; 161 162 /* deny if shell does not exists or is not executable */ 163 if (stat(shell, &st) != 0) { 164 logit("User %.100s not allowed because shell %.100s does not exist", 165 pw->pw_name, shell); 166 return 0; 167 } 168 if (S_ISREG(st.st_mode) == 0 || 169 (st.st_mode & (S_IXOTH|S_IXUSR|S_IXGRP)) == 0) { 170 logit("User %.100s not allowed because shell %.100s is not executable", 171 pw->pw_name, shell); 172 return 0; 173 } 174 175 if (options.num_deny_users > 0 || options.num_allow_users > 0 || 176 options.num_deny_groups > 0 || options.num_allow_groups > 0) { 177 hostname = get_canonical_hostname(options.use_dns); 178 ipaddr = get_remote_ipaddr(); 179 } 180 181 /* Return false if user is listed in DenyUsers */ 182 if (options.num_deny_users > 0) { 183 for (i = 0; i < options.num_deny_users; i++) 184 if (match_user(pw->pw_name, hostname, ipaddr, 185 options.deny_users[i])) { 186 logit("User %.100s from %.100s not allowed " 187 "because listed in DenyUsers", 188 pw->pw_name, hostname); 189 return 0; 190 } 191 } 192 /* Return false if AllowUsers isn't empty and user isn't listed there */ 193 if (options.num_allow_users > 0) { 194 for (i = 0; i < options.num_allow_users; i++) 195 if (match_user(pw->pw_name, hostname, ipaddr, 196 options.allow_users[i])) 197 break; 198 /* i < options.num_allow_users iff we break for loop */ 199 if (i >= options.num_allow_users) { 200 logit("User %.100s from %.100s not allowed because " 201 "not listed in AllowUsers", pw->pw_name, hostname); 202 return 0; 203 } 204 } 205 if (options.num_deny_groups > 0 || options.num_allow_groups > 0) { 206 /* Get the user's group access list (primary and supplementary) */ 207 if (ga_init(pw->pw_name, pw->pw_gid) == 0) { 208 logit("User %.100s from %.100s not allowed because " 209 "not in any group", pw->pw_name, hostname); 210 return 0; 211 } 212 213 /* Return false if one of user's groups is listed in DenyGroups */ 214 if (options.num_deny_groups > 0) 215 if (ga_match(options.deny_groups, 216 options.num_deny_groups)) { 217 ga_free(); 218 logit("User %.100s from %.100s not allowed " 219 "because a group is listed in DenyGroups", 220 pw->pw_name, hostname); 221 return 0; 222 } 223 /* 224 * Return false if AllowGroups isn't empty and one of user's groups 225 * isn't listed there 226 */ 227 if (options.num_allow_groups > 0) 228 if (!ga_match(options.allow_groups, 229 options.num_allow_groups)) { 230 ga_free(); 231 logit("User %.100s from %.100s not allowed " 232 "because none of user's groups are listed " 233 "in AllowGroups", pw->pw_name, hostname); 234 return 0; 235 } 236 ga_free(); 237 } 238 239 #ifdef CUSTOM_SYS_AUTH_ALLOWED_USER 240 if (!sys_auth_allowed_user(pw, &loginmsg)) 241 return 0; 242 #endif 243 244 /* We found no reason not to let this user try to log on... */ 245 return 1; 246 } 247 248 void 249 auth_log(Authctxt *authctxt, int authenticated, char *method, char *info) 250 { 251 void (*authlog) (const char *fmt,...) = verbose; 252 char *authmsg; 253 254 if (use_privsep && !mm_is_monitor() && !authctxt->postponed) 255 return; 256 257 /* Raise logging level */ 258 if (authenticated == 1 || 259 !authctxt->valid || 260 authctxt->failures >= options.max_authtries / 2 || 261 strcmp(method, "password") == 0) 262 authlog = logit; 263 264 if (authctxt->postponed) 265 authmsg = "Postponed"; 266 else 267 authmsg = authenticated ? "Accepted" : "Failed"; 268 269 authlog("%s %s for %s%.100s from %.200s port %d%s", 270 authmsg, 271 method, 272 authctxt->valid ? "" : "invalid user ", 273 authctxt->user, 274 get_remote_ipaddr(), 275 get_remote_port(), 276 info); 277 278 #ifdef CUSTOM_FAILED_LOGIN 279 if (authenticated == 0 && !authctxt->postponed && 280 (strcmp(method, "password") == 0 || 281 strncmp(method, "keyboard-interactive", 20) == 0 || 282 strcmp(method, "challenge-response") == 0)) 283 record_failed_login(authctxt->user, 284 get_canonical_hostname(options.use_dns), "ssh"); 285 # ifdef WITH_AIXAUTHENTICATE 286 if (authenticated) 287 sys_auth_record_login(authctxt->user, 288 get_canonical_hostname(options.use_dns), "ssh", &loginmsg); 289 # endif 290 #endif 291 #ifdef SSH_AUDIT_EVENTS 292 if (authenticated == 0 && !authctxt->postponed) 293 audit_event(audit_classify_auth(method)); 294 #endif 295 } 296 297 /* 298 * Check whether root logins are disallowed. 299 */ 300 int 301 auth_root_allowed(char *method) 302 { 303 switch (options.permit_root_login) { 304 case PERMIT_YES: 305 return 1; 306 case PERMIT_NO_PASSWD: 307 if (strcmp(method, "password") != 0) 308 return 1; 309 break; 310 case PERMIT_FORCED_ONLY: 311 if (forced_command) { 312 logit("Root login accepted for forced command."); 313 return 1; 314 } 315 break; 316 } 317 logit("ROOT LOGIN REFUSED FROM %.200s", get_remote_ipaddr()); 318 return 0; 319 } 320 321 322 /* 323 * Given a template and a passwd structure, build a filename 324 * by substituting % tokenised options. Currently, %% becomes '%', 325 * %h becomes the home directory and %u the username. 326 * 327 * This returns a buffer allocated by xmalloc. 328 */ 329 static char * 330 expand_authorized_keys(const char *filename, struct passwd *pw) 331 { 332 char *file, ret[MAXPATHLEN]; 333 int i; 334 335 file = percent_expand(filename, "h", pw->pw_dir, 336 "u", pw->pw_name, (char *)NULL); 337 338 /* 339 * Ensure that filename starts anchored. If not, be backward 340 * compatible and prepend the '%h/' 341 */ 342 if (*file == '/') 343 return (file); 344 345 i = snprintf(ret, sizeof(ret), "%s/%s", pw->pw_dir, file); 346 if (i < 0 || (size_t)i >= sizeof(ret)) 347 fatal("expand_authorized_keys: path too long"); 348 xfree(file); 349 return (xstrdup(ret)); 350 } 351 352 char * 353 authorized_keys_file(struct passwd *pw) 354 { 355 return expand_authorized_keys(options.authorized_keys_file, pw); 356 } 357 358 char * 359 authorized_keys_file2(struct passwd *pw) 360 { 361 return expand_authorized_keys(options.authorized_keys_file2, pw); 362 } 363 364 /* return ok if key exists in sysfile or userfile */ 365 HostStatus 366 check_key_in_hostfiles(struct passwd *pw, Key *key, const char *host, 367 const char *sysfile, const char *userfile) 368 { 369 Key *found; 370 char *user_hostfile; 371 struct stat st; 372 HostStatus host_status; 373 374 /* Check if we know the host and its host key. */ 375 found = key_new(key->type); 376 host_status = check_host_in_hostfile(sysfile, host, key, found, NULL); 377 378 if (host_status != HOST_OK && userfile != NULL) { 379 user_hostfile = tilde_expand_filename(userfile, pw->pw_uid); 380 if (options.strict_modes && 381 (stat(user_hostfile, &st) == 0) && 382 ((st.st_uid != 0 && st.st_uid != pw->pw_uid) || 383 (st.st_mode & 022) != 0)) { 384 logit("Authentication refused for %.100s: " 385 "bad owner or modes for %.200s", 386 pw->pw_name, user_hostfile); 387 } else { 388 temporarily_use_uid(pw); 389 host_status = check_host_in_hostfile(user_hostfile, 390 host, key, found, NULL); 391 restore_uid(); 392 } 393 xfree(user_hostfile); 394 } 395 key_free(found); 396 397 debug2("check_key_in_hostfiles: key %s for %s", host_status == HOST_OK ? 398 "ok" : "not found", host); 399 return host_status; 400 } 401 402 403 /* 404 * Check a given file for security. This is defined as all components 405 * of the path to the file must be owned by either the owner of 406 * of the file or root and no directories must be group or world writable. 407 * 408 * XXX Should any specific check be done for sym links ? 409 * 410 * Takes an open file descriptor, the file name, a uid and and 411 * error buffer plus max size as arguments. 412 * 413 * Returns 0 on success and -1 on failure 414 */ 415 static int 416 secure_filename(FILE *f, const char *file, struct passwd *pw, 417 char *err, size_t errlen) 418 { 419 uid_t uid = pw->pw_uid; 420 char buf[MAXPATHLEN], homedir[MAXPATHLEN]; 421 char *cp; 422 int comparehome = 0; 423 struct stat st; 424 425 if (realpath(file, buf) == NULL) { 426 snprintf(err, errlen, "realpath %s failed: %s", file, 427 strerror(errno)); 428 return -1; 429 } 430 if (realpath(pw->pw_dir, homedir) != NULL) 431 comparehome = 1; 432 433 /* check the open file to avoid races */ 434 if (fstat(fileno(f), &st) < 0 || 435 (st.st_uid != 0 && st.st_uid != uid) || 436 (st.st_mode & 022) != 0) { 437 snprintf(err, errlen, "bad ownership or modes for file %s", 438 buf); 439 return -1; 440 } 441 442 /* for each component of the canonical path, walking upwards */ 443 for (;;) { 444 if ((cp = dirname(buf)) == NULL) { 445 snprintf(err, errlen, "dirname() failed"); 446 return -1; 447 } 448 strlcpy(buf, cp, sizeof(buf)); 449 450 debug3("secure_filename: checking '%s'", buf); 451 if (stat(buf, &st) < 0 || 452 (st.st_uid != 0 && st.st_uid != uid) || 453 (st.st_mode & 022) != 0) { 454 snprintf(err, errlen, 455 "bad ownership or modes for directory %s", buf); 456 return -1; 457 } 458 459 /* If are passed the homedir then we can stop */ 460 if (comparehome && strcmp(homedir, buf) == 0) { 461 debug3("secure_filename: terminating check at '%s'", 462 buf); 463 break; 464 } 465 /* 466 * dirname should always complete with a "/" path, 467 * but we can be paranoid and check for "." too 468 */ 469 if ((strcmp("/", buf) == 0) || (strcmp(".", buf) == 0)) 470 break; 471 } 472 return 0; 473 } 474 475 FILE * 476 auth_openkeyfile(const char *file, struct passwd *pw, int strict_modes) 477 { 478 char line[1024]; 479 struct stat st; 480 int fd; 481 FILE *f; 482 483 /* 484 * Open the file containing the authorized keys 485 * Fail quietly if file does not exist 486 */ 487 if ((fd = open(file, O_RDONLY|O_NONBLOCK)) == -1) 488 return NULL; 489 490 if (fstat(fd, &st) < 0) { 491 close(fd); 492 return NULL; 493 } 494 if (!S_ISREG(st.st_mode)) { 495 logit("User %s authorized keys %s is not a regular file", 496 pw->pw_name, file); 497 close(fd); 498 return NULL; 499 } 500 unset_nonblock(fd); 501 if ((f = fdopen(fd, "r")) == NULL) { 502 close(fd); 503 return NULL; 504 } 505 if (options.strict_modes && 506 secure_filename(f, file, pw, line, sizeof(line)) != 0) { 507 fclose(f); 508 logit("Authentication refused: %s", line); 509 return NULL; 510 } 511 512 return f; 513 } 514 515 struct passwd * 516 getpwnamallow(const char *user) 517 { 518 #ifdef HAVE_LOGIN_CAP 519 extern login_cap_t *lc; 520 #ifdef BSD_AUTH 521 auth_session_t *as; 522 #endif 523 #endif 524 struct passwd *pw; 525 526 parse_server_match_config(&options, user, 527 get_canonical_hostname(options.use_dns), get_remote_ipaddr()); 528 529 pw = getpwnam(user); 530 if (pw == NULL) { 531 logit("Invalid user %.100s from %.100s", 532 user, get_remote_ipaddr()); 533 #ifdef CUSTOM_FAILED_LOGIN 534 record_failed_login(user, 535 get_canonical_hostname(options.use_dns), "ssh"); 536 #endif 537 #ifdef SSH_AUDIT_EVENTS 538 audit_event(SSH_INVALID_USER); 539 #endif /* SSH_AUDIT_EVENTS */ 540 return (NULL); 541 } 542 if (!allowed_user(pw)) 543 return (NULL); 544 #ifdef HAVE_LOGIN_CAP 545 if ((lc = login_getpwclass(pw)) == NULL) { 546 debug("unable to get login class: %s", user); 547 return (NULL); 548 } 549 #ifdef BSD_AUTH 550 if ((as = auth_open()) == NULL || auth_setpwd(as, pw) != 0 || 551 auth_approval(as, lc, pw->pw_name, "ssh") <= 0) { 552 debug("Approval failure for %s", user); 553 pw = NULL; 554 } 555 if (as != NULL) 556 auth_close(as); 557 #endif 558 #endif 559 if (pw != NULL) 560 return (pwcopy(pw)); 561 return (NULL); 562 } 563 564 void 565 auth_debug_add(const char *fmt,...) 566 { 567 char buf[1024]; 568 va_list args; 569 570 if (!auth_debug_init) 571 return; 572 573 va_start(args, fmt); 574 vsnprintf(buf, sizeof(buf), fmt, args); 575 va_end(args); 576 buffer_put_cstring(&auth_debug, buf); 577 } 578 579 void 580 auth_debug_send(void) 581 { 582 char *msg; 583 584 if (!auth_debug_init) 585 return; 586 while (buffer_len(&auth_debug)) { 587 msg = buffer_get_string(&auth_debug, NULL); 588 packet_send_debug("%s", msg); 589 xfree(msg); 590 } 591 } 592 593 void 594 auth_debug_reset(void) 595 { 596 if (auth_debug_init) 597 buffer_clear(&auth_debug); 598 else { 599 buffer_init(&auth_debug); 600 auth_debug_init = 1; 601 } 602 } 603 604 struct passwd * 605 fakepw(void) 606 { 607 static struct passwd fake; 608 609 memset(&fake, 0, sizeof(fake)); 610 fake.pw_name = "NOUSER"; 611 fake.pw_passwd = 612 "$2a$06$r3.juUaHZDlIbQaO2dS9FuYxL1W9M81R1Tc92PoSNmzvpEqLkLGrK"; 613 fake.pw_gecos = "NOUSER"; 614 fake.pw_uid = privsep_pw == NULL ? (uid_t)-1 : privsep_pw->pw_uid; 615 fake.pw_gid = privsep_pw == NULL ? (gid_t)-1 : privsep_pw->pw_gid; 616 #ifdef HAVE_PW_CLASS_IN_PASSWD 617 fake.pw_class = ""; 618 #endif 619 fake.pw_dir = "/nonexist"; 620 fake.pw_shell = "/nonexist"; 621 622 return (&fake); 623 } 624