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: auth.c,v 1.58 2005/03/14 11:44:42 dtucker Exp $"); 27 RCSID("$FreeBSD$"); 28 29 #ifdef HAVE_LOGIN_H 30 #include <login.h> 31 #endif 32 #ifdef USE_SHADOW 33 #include <shadow.h> 34 #endif 35 36 #ifdef HAVE_LIBGEN_H 37 #include <libgen.h> 38 #endif 39 40 #include "xmalloc.h" 41 #include "match.h" 42 #include "groupaccess.h" 43 #include "log.h" 44 #include "servconf.h" 45 #include "auth.h" 46 #include "auth-options.h" 47 #include "canohost.h" 48 #include "buffer.h" 49 #include "bufaux.h" 50 #include "uidswap.h" 51 #include "misc.h" 52 #include "bufaux.h" 53 #include "packet.h" 54 #include "loginrec.h" 55 #include "monitor_wrap.h" 56 57 /* import */ 58 extern ServerOptions options; 59 extern Buffer loginmsg; 60 61 /* Debugging messages */ 62 Buffer auth_debug; 63 int auth_debug_init; 64 65 /* 66 * Check if the user is allowed to log in via ssh. If user is listed 67 * in DenyUsers or one of user's groups is listed in DenyGroups, false 68 * will be returned. If AllowUsers isn't empty and user isn't listed 69 * there, or if AllowGroups isn't empty and one of user's groups isn't 70 * listed there, false will be returned. 71 * If the user's shell is not executable, false will be returned. 72 * Otherwise true is returned. 73 */ 74 int 75 allowed_user(struct passwd * pw) 76 { 77 struct stat st; 78 const char *hostname = NULL, *ipaddr = NULL, *passwd = NULL; 79 char *shell; 80 int i; 81 #ifdef USE_SHADOW 82 struct spwd *spw = NULL; 83 #endif 84 85 /* Shouldn't be called if pw is NULL, but better safe than sorry... */ 86 if (!pw || !pw->pw_name) 87 return 0; 88 89 #ifdef USE_SHADOW 90 if (!options.use_pam) 91 spw = getspnam(pw->pw_name); 92 #ifdef HAS_SHADOW_EXPIRE 93 if (!options.use_pam && spw != NULL && auth_shadow_acctexpired(spw)) 94 return 0; 95 #endif /* HAS_SHADOW_EXPIRE */ 96 #endif /* USE_SHADOW */ 97 98 /* grab passwd field for locked account check */ 99 #ifdef USE_SHADOW 100 if (spw != NULL) 101 passwd = spw->sp_pwdp; 102 #else 103 passwd = pw->pw_passwd; 104 #endif 105 106 /* check for locked account */ 107 if (!options.use_pam && passwd && *passwd) { 108 int locked = 0; 109 110 #ifdef LOCKED_PASSWD_STRING 111 if (strcmp(passwd, LOCKED_PASSWD_STRING) == 0) 112 locked = 1; 113 #endif 114 #ifdef LOCKED_PASSWD_PREFIX 115 if (strncmp(passwd, LOCKED_PASSWD_PREFIX, 116 strlen(LOCKED_PASSWD_PREFIX)) == 0) 117 locked = 1; 118 #endif 119 #ifdef LOCKED_PASSWD_SUBSTR 120 if (strstr(passwd, LOCKED_PASSWD_SUBSTR)) 121 locked = 1; 122 #endif 123 if (locked) { 124 logit("User %.100s not allowed because account is locked", 125 pw->pw_name); 126 return 0; 127 } 128 } 129 130 /* 131 * Get the shell from the password data. An empty shell field is 132 * legal, and means /bin/sh. 133 */ 134 shell = (pw->pw_shell[0] == '\0') ? _PATH_BSHELL : pw->pw_shell; 135 136 /* deny if shell does not exists or is not executable */ 137 if (stat(shell, &st) != 0) { 138 logit("User %.100s not allowed because shell %.100s does not exist", 139 pw->pw_name, shell); 140 return 0; 141 } 142 if (S_ISREG(st.st_mode) == 0 || 143 (st.st_mode & (S_IXOTH|S_IXUSR|S_IXGRP)) == 0) { 144 logit("User %.100s not allowed because shell %.100s is not executable", 145 pw->pw_name, shell); 146 return 0; 147 } 148 149 if (options.num_deny_users > 0 || options.num_allow_users > 0 || 150 options.num_deny_groups > 0 || options.num_allow_groups > 0) { 151 hostname = get_canonical_hostname(options.use_dns); 152 ipaddr = get_remote_ipaddr(); 153 } 154 155 /* Return false if user is listed in DenyUsers */ 156 if (options.num_deny_users > 0) { 157 for (i = 0; i < options.num_deny_users; i++) 158 if (match_user(pw->pw_name, hostname, ipaddr, 159 options.deny_users[i])) { 160 logit("User %.100s from %.100s not allowed " 161 "because listed in DenyUsers", 162 pw->pw_name, hostname); 163 return 0; 164 } 165 } 166 /* Return false if AllowUsers isn't empty and user isn't listed there */ 167 if (options.num_allow_users > 0) { 168 for (i = 0; i < options.num_allow_users; i++) 169 if (match_user(pw->pw_name, hostname, ipaddr, 170 options.allow_users[i])) 171 break; 172 /* i < options.num_allow_users iff we break for loop */ 173 if (i >= options.num_allow_users) { 174 logit("User %.100s from %.100s not allowed because " 175 "not listed in AllowUsers", pw->pw_name, hostname); 176 return 0; 177 } 178 } 179 if (options.num_deny_groups > 0 || options.num_allow_groups > 0) { 180 /* Get the user's group access list (primary and supplementary) */ 181 if (ga_init(pw->pw_name, pw->pw_gid) == 0) { 182 logit("User %.100s from %.100s not allowed because " 183 "not in any group", pw->pw_name, hostname); 184 return 0; 185 } 186 187 /* Return false if one of user's groups is listed in DenyGroups */ 188 if (options.num_deny_groups > 0) 189 if (ga_match(options.deny_groups, 190 options.num_deny_groups)) { 191 ga_free(); 192 logit("User %.100s from %.100s not allowed " 193 "because a group is listed in DenyGroups", 194 pw->pw_name, hostname); 195 return 0; 196 } 197 /* 198 * Return false if AllowGroups isn't empty and one of user's groups 199 * isn't listed there 200 */ 201 if (options.num_allow_groups > 0) 202 if (!ga_match(options.allow_groups, 203 options.num_allow_groups)) { 204 ga_free(); 205 logit("User %.100s from %.100s not allowed " 206 "because none of user's groups are listed " 207 "in AllowGroups", pw->pw_name, hostname); 208 return 0; 209 } 210 ga_free(); 211 } 212 213 #ifdef CUSTOM_SYS_AUTH_ALLOWED_USER 214 if (!sys_auth_allowed_user(pw, &loginmsg)) 215 return 0; 216 #endif 217 218 /* We found no reason not to let this user try to log on... */ 219 return 1; 220 } 221 222 void 223 auth_log(Authctxt *authctxt, int authenticated, char *method, char *info) 224 { 225 void (*authlog) (const char *fmt,...) = verbose; 226 char *authmsg; 227 228 /* Raise logging level */ 229 if (authenticated == 1 || 230 !authctxt->valid || 231 authctxt->failures >= options.max_authtries / 2 || 232 strcmp(method, "password") == 0) 233 authlog = logit; 234 235 if (authctxt->postponed) 236 authmsg = "Postponed"; 237 else 238 authmsg = authenticated ? "Accepted" : "Failed"; 239 240 authlog("%s %s for %s%.100s from %.200s port %d%s", 241 authmsg, 242 method, 243 authctxt->valid ? "" : "invalid user ", 244 authctxt->user, 245 get_remote_ipaddr(), 246 get_remote_port(), 247 info); 248 249 #ifdef CUSTOM_FAILED_LOGIN 250 if (authenticated == 0 && !authctxt->postponed && 251 (strcmp(method, "password") == 0 || 252 strncmp(method, "keyboard-interactive", 20) == 0 || 253 strcmp(method, "challenge-response") == 0)) 254 record_failed_login(authctxt->user, 255 get_canonical_hostname(options.use_dns), "ssh"); 256 #endif 257 #ifdef SSH_AUDIT_EVENTS 258 if (authenticated == 0 && !authctxt->postponed) { 259 ssh_audit_event_t event; 260 261 debug3("audit failed auth attempt, method %s euid %d", 262 method, (int)geteuid()); 263 /* 264 * Because the auth loop is used in both monitor and slave, 265 * we must be careful to send each event only once and with 266 * enough privs to write the event. 267 */ 268 event = audit_classify_auth(method); 269 switch(event) { 270 case SSH_AUTH_FAIL_NONE: 271 case SSH_AUTH_FAIL_PASSWD: 272 case SSH_AUTH_FAIL_KBDINT: 273 if (geteuid() == 0) 274 audit_event(event); 275 break; 276 case SSH_AUTH_FAIL_PUBKEY: 277 case SSH_AUTH_FAIL_HOSTBASED: 278 case SSH_AUTH_FAIL_GSSAPI: 279 /* 280 * This is required to handle the case where privsep 281 * is enabled but it's root logging in, since 282 * use_privsep won't be cleared until after a 283 * successful login. 284 */ 285 if (geteuid() == 0) 286 audit_event(event); 287 else 288 PRIVSEP(audit_event(event)); 289 break; 290 default: 291 error("unknown authentication audit event %d", event); 292 } 293 } 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 break; 307 case PERMIT_NO_PASSWD: 308 if (strcmp(method, "password") != 0) 309 return 1; 310 break; 311 case PERMIT_FORCED_ONLY: 312 if (forced_command) { 313 logit("Root login accepted for forced command."); 314 return 1; 315 } 316 break; 317 } 318 logit("ROOT LOGIN REFUSED FROM %.200s", get_remote_ipaddr()); 319 return 0; 320 } 321 322 323 /* 324 * Given a template and a passwd structure, build a filename 325 * by substituting % tokenised options. Currently, %% becomes '%', 326 * %h becomes the home directory and %u the username. 327 * 328 * This returns a buffer allocated by xmalloc. 329 */ 330 char * 331 expand_filename(const char *filename, struct passwd *pw) 332 { 333 Buffer buffer; 334 char *file; 335 const char *cp; 336 337 /* 338 * Build the filename string in the buffer by making the appropriate 339 * substitutions to the given file name. 340 */ 341 buffer_init(&buffer); 342 for (cp = filename; *cp; cp++) { 343 if (cp[0] == '%' && cp[1] == '%') { 344 buffer_append(&buffer, "%", 1); 345 cp++; 346 continue; 347 } 348 if (cp[0] == '%' && cp[1] == 'h') { 349 buffer_append(&buffer, pw->pw_dir, strlen(pw->pw_dir)); 350 cp++; 351 continue; 352 } 353 if (cp[0] == '%' && cp[1] == 'u') { 354 buffer_append(&buffer, pw->pw_name, 355 strlen(pw->pw_name)); 356 cp++; 357 continue; 358 } 359 buffer_append(&buffer, cp, 1); 360 } 361 buffer_append(&buffer, "\0", 1); 362 363 /* 364 * Ensure that filename starts anchored. If not, be backward 365 * compatible and prepend the '%h/' 366 */ 367 file = xmalloc(MAXPATHLEN); 368 cp = buffer_ptr(&buffer); 369 if (*cp != '/') 370 snprintf(file, MAXPATHLEN, "%s/%s", pw->pw_dir, cp); 371 else 372 strlcpy(file, cp, MAXPATHLEN); 373 374 buffer_free(&buffer); 375 return file; 376 } 377 378 char * 379 authorized_keys_file(struct passwd *pw) 380 { 381 return expand_filename(options.authorized_keys_file, pw); 382 } 383 384 char * 385 authorized_keys_file2(struct passwd *pw) 386 { 387 return expand_filename(options.authorized_keys_file2, pw); 388 } 389 390 /* return ok if key exists in sysfile or userfile */ 391 HostStatus 392 check_key_in_hostfiles(struct passwd *pw, Key *key, const char *host, 393 const char *sysfile, const char *userfile) 394 { 395 Key *found; 396 char *user_hostfile; 397 struct stat st; 398 HostStatus host_status; 399 400 /* Check if we know the host and its host key. */ 401 found = key_new(key->type); 402 host_status = check_host_in_hostfile(sysfile, host, key, found, NULL); 403 404 if (host_status != HOST_OK && userfile != NULL) { 405 user_hostfile = tilde_expand_filename(userfile, pw->pw_uid); 406 if (options.strict_modes && 407 (stat(user_hostfile, &st) == 0) && 408 ((st.st_uid != 0 && st.st_uid != pw->pw_uid) || 409 (st.st_mode & 022) != 0)) { 410 logit("Authentication refused for %.100s: " 411 "bad owner or modes for %.200s", 412 pw->pw_name, user_hostfile); 413 } else { 414 temporarily_use_uid(pw); 415 host_status = check_host_in_hostfile(user_hostfile, 416 host, key, found, NULL); 417 restore_uid(); 418 } 419 xfree(user_hostfile); 420 } 421 key_free(found); 422 423 debug2("check_key_in_hostfiles: key %s for %s", host_status == HOST_OK ? 424 "ok" : "not found", host); 425 return host_status; 426 } 427 428 429 /* 430 * Check a given file for security. This is defined as all components 431 * of the path to the file must be owned by either the owner of 432 * of the file or root and no directories must be group or world writable. 433 * 434 * XXX Should any specific check be done for sym links ? 435 * 436 * Takes an open file descriptor, the file name, a uid and and 437 * error buffer plus max size as arguments. 438 * 439 * Returns 0 on success and -1 on failure 440 */ 441 int 442 secure_filename(FILE *f, const char *file, struct passwd *pw, 443 char *err, size_t errlen) 444 { 445 uid_t uid = pw->pw_uid; 446 char buf[MAXPATHLEN], homedir[MAXPATHLEN]; 447 char *cp; 448 int comparehome = 0; 449 struct stat st; 450 451 if (realpath(file, buf) == NULL) { 452 snprintf(err, errlen, "realpath %s failed: %s", file, 453 strerror(errno)); 454 return -1; 455 } 456 if (realpath(pw->pw_dir, homedir) != NULL) 457 comparehome = 1; 458 459 /* check the open file to avoid races */ 460 if (fstat(fileno(f), &st) < 0 || 461 (st.st_uid != 0 && st.st_uid != uid) || 462 (st.st_mode & 022) != 0) { 463 snprintf(err, errlen, "bad ownership or modes for file %s", 464 buf); 465 return -1; 466 } 467 468 /* for each component of the canonical path, walking upwards */ 469 for (;;) { 470 if ((cp = dirname(buf)) == NULL) { 471 snprintf(err, errlen, "dirname() failed"); 472 return -1; 473 } 474 strlcpy(buf, cp, sizeof(buf)); 475 476 debug3("secure_filename: checking '%s'", buf); 477 if (stat(buf, &st) < 0 || 478 (st.st_uid != 0 && st.st_uid != uid) || 479 (st.st_mode & 022) != 0) { 480 snprintf(err, errlen, 481 "bad ownership or modes for directory %s", buf); 482 return -1; 483 } 484 485 /* If are passed the homedir then we can stop */ 486 if (comparehome && strcmp(homedir, buf) == 0) { 487 debug3("secure_filename: terminating check at '%s'", 488 buf); 489 break; 490 } 491 /* 492 * dirname should always complete with a "/" path, 493 * but we can be paranoid and check for "." too 494 */ 495 if ((strcmp("/", buf) == 0) || (strcmp(".", buf) == 0)) 496 break; 497 } 498 return 0; 499 } 500 501 struct passwd * 502 getpwnamallow(const char *user) 503 { 504 #ifdef HAVE_LOGIN_CAP 505 extern login_cap_t *lc; 506 #ifdef BSD_AUTH 507 auth_session_t *as; 508 #endif 509 #endif 510 struct passwd *pw; 511 512 pw = getpwnam(user); 513 if (pw == NULL) { 514 logit("Invalid user %.100s from %.100s", 515 user, get_remote_ipaddr()); 516 #ifdef CUSTOM_FAILED_LOGIN 517 record_failed_login(user, 518 get_canonical_hostname(options.use_dns), "ssh"); 519 #endif 520 #ifdef SSH_AUDIT_EVENTS 521 audit_event(SSH_INVALID_USER); 522 #endif /* SSH_AUDIT_EVENTS */ 523 return (NULL); 524 } 525 if (!allowed_user(pw)) 526 return (NULL); 527 #ifdef HAVE_LOGIN_CAP 528 if ((lc = login_getpwclass(pw)) == NULL) { 529 debug("unable to get login class: %s", user); 530 return (NULL); 531 } 532 #ifdef BSD_AUTH 533 if ((as = auth_open()) == NULL || auth_setpwd(as, pw) != 0 || 534 auth_approval(as, lc, pw->pw_name, "ssh") <= 0) { 535 debug("Approval failure for %s", user); 536 pw = NULL; 537 } 538 if (as != NULL) 539 auth_close(as); 540 #endif 541 #endif 542 if (pw != NULL) 543 return (pwcopy(pw)); 544 return (NULL); 545 } 546 547 void 548 auth_debug_add(const char *fmt,...) 549 { 550 char buf[1024]; 551 va_list args; 552 553 if (!auth_debug_init) 554 return; 555 556 va_start(args, fmt); 557 vsnprintf(buf, sizeof(buf), fmt, args); 558 va_end(args); 559 buffer_put_cstring(&auth_debug, buf); 560 } 561 562 void 563 auth_debug_send(void) 564 { 565 char *msg; 566 567 if (!auth_debug_init) 568 return; 569 while (buffer_len(&auth_debug)) { 570 msg = buffer_get_string(&auth_debug, NULL); 571 packet_send_debug("%s", msg); 572 xfree(msg); 573 } 574 } 575 576 void 577 auth_debug_reset(void) 578 { 579 if (auth_debug_init) 580 buffer_clear(&auth_debug); 581 else { 582 buffer_init(&auth_debug); 583 auth_debug_init = 1; 584 } 585 } 586 587 struct passwd * 588 fakepw(void) 589 { 590 static struct passwd fake; 591 592 memset(&fake, 0, sizeof(fake)); 593 fake.pw_name = "NOUSER"; 594 fake.pw_passwd = 595 "$2a$06$r3.juUaHZDlIbQaO2dS9FuYxL1W9M81R1Tc92PoSNmzvpEqLkLGrK"; 596 fake.pw_gecos = "NOUSER"; 597 fake.pw_uid = (uid_t)-1; 598 fake.pw_gid = (gid_t)-1; 599 #ifdef HAVE_PW_CLASS_IN_PASSWD 600 fake.pw_class = ""; 601 #endif 602 fake.pw_dir = "/nonexist"; 603 fake.pw_shell = "/nonexist"; 604 605 return (&fake); 606 } 607