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