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