xref: /freebsd/crypto/openssh/auth2.c (revision c17d43407fe04133a94055b0dbc7ea8965654a9f)
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.85 2002/02/24 19:14:59 markus Exp $");
27 RCSID("$FreeBSD$");
28 
29 #include <openssl/evp.h>
30 
31 #include "ssh2.h"
32 #include "xmalloc.h"
33 #include "rsa.h"
34 #include "sshpty.h"
35 #include "packet.h"
36 #include "buffer.h"
37 #include "log.h"
38 #include "servconf.h"
39 #include "compat.h"
40 #include "channels.h"
41 #include "bufaux.h"
42 #include "auth.h"
43 #include "session.h"
44 #include "dispatch.h"
45 #include "key.h"
46 #include "cipher.h"
47 #include "kex.h"
48 #include "pathnames.h"
49 #include "uidswap.h"
50 #include "auth-options.h"
51 #include "misc.h"
52 #include "hostfile.h"
53 #include "canohost.h"
54 #include "match.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 u_char *session_id2;
63 extern int session_id2_len;
64 
65 static Authctxt	*x_authctxt = NULL;
66 static int one = 1;
67 
68 typedef struct Authmethod Authmethod;
69 struct Authmethod {
70 	char	*name;
71 	int	(*userauth)(Authctxt *authctxt);
72 	int	*enabled;
73 };
74 
75 /* protocol */
76 
77 static void input_service_request(int, u_int32_t, void *);
78 static void input_userauth_request(int, u_int32_t, void *);
79 
80 /* helper */
81 static Authmethod *authmethod_lookup(const char *);
82 static char *authmethods_get(void);
83 static int user_key_allowed(struct passwd *, Key *);
84 static int hostbased_key_allowed(struct passwd *, const char *, char *, Key *);
85 
86 /* auth */
87 static void userauth_banner(void);
88 static int userauth_none(Authctxt *);
89 static int userauth_passwd(Authctxt *);
90 static int userauth_pubkey(Authctxt *);
91 static int userauth_hostbased(Authctxt *);
92 static int userauth_kbdint(Authctxt *);
93 
94 Authmethod authmethods[] = {
95 	{"none",
96 		userauth_none,
97 		&one},
98 	{"publickey",
99 		userauth_pubkey,
100 		&options.pubkey_authentication},
101 	{"password",
102 		userauth_passwd,
103 		&options.password_authentication},
104 	{"keyboard-interactive",
105 		userauth_kbdint,
106 		&options.kbd_interactive_authentication},
107 	{"hostbased",
108 		userauth_hostbased,
109 		&options.hostbased_authentication},
110 	{NULL, NULL, NULL}
111 };
112 
113 /*
114  * loop until authctxt->success == TRUE
115  */
116 
117 void
118 do_authentication2(void)
119 {
120 	Authctxt *authctxt = authctxt_new();
121 
122 	x_authctxt = authctxt;		/*XXX*/
123 
124 	/* challenge-response is implemented via keyboard interactive */
125 	if (options.challenge_response_authentication)
126 		options.kbd_interactive_authentication = 1;
127 
128 	dispatch_init(&dispatch_protocol_error);
129 	dispatch_set(SSH2_MSG_SERVICE_REQUEST, &input_service_request);
130 	dispatch_run(DISPATCH_BLOCK, &authctxt->success, authctxt);
131 	do_authenticated(authctxt);
132 }
133 
134 static void
135 input_service_request(int type, u_int32_t seq, void *ctxt)
136 {
137 	Authctxt *authctxt = ctxt;
138 	u_int len;
139 	int accept = 0;
140 	char *service = packet_get_string(&len);
141 	packet_check_eom();
142 
143 	if (authctxt == NULL)
144 		fatal("input_service_request: no authctxt");
145 
146 	if (strcmp(service, "ssh-userauth") == 0) {
147 		if (!authctxt->success) {
148 			accept = 1;
149 			/* now we can handle user-auth requests */
150 			dispatch_set(SSH2_MSG_USERAUTH_REQUEST, &input_userauth_request);
151 		}
152 	}
153 	/* XXX all other service requests are denied */
154 
155 	if (accept) {
156 		packet_start(SSH2_MSG_SERVICE_ACCEPT);
157 		packet_put_cstring(service);
158 		packet_send();
159 		packet_write_wait();
160 	} else {
161 		debug("bad service request %s", service);
162 		packet_disconnect("bad service request %s", service);
163 	}
164 	xfree(service);
165 }
166 
167 static void
168 input_userauth_request(int type, u_int32_t seq, void *ctxt)
169 {
170 	Authctxt *authctxt = ctxt;
171 	Authmethod *m = NULL;
172 	char *user, *service, *method, *style = NULL;
173 	int authenticated = 0;
174 #ifdef HAVE_LOGIN_CAP
175 	login_cap_t *lc;
176 #endif /* HAVE_LOGIN_CAP */
177 #if defined(HAVE_LOGIN_CAP) || defined(LOGIN_ACCESS)
178 	const char *from_host, *from_ip;
179 
180 	from_host = get_canonical_hostname(options.verify_reverse_mapping);
181 	from_ip = get_remote_ipaddr();
182 #endif /* HAVE_LOGIN_CAP || LOGIN_ACCESS */
183 
184 	if (authctxt == NULL)
185 		fatal("input_userauth_request: no authctxt");
186 
187 	user = packet_get_string(NULL);
188 	service = packet_get_string(NULL);
189 	method = packet_get_string(NULL);
190 	debug("userauth-request for user %s service %s method %s", user, service, method);
191 	debug("attempt %d failures %d", authctxt->attempt, authctxt->failures);
192 
193 	if ((style = strchr(user, ':')) != NULL)
194 		*style++ = 0;
195 
196 	if (authctxt->attempt++ == 0) {
197 		/* setup auth context */
198 		struct passwd *pw = NULL;
199 		pw = getpwnam(user);
200 		if (pw && allowed_user(pw) && strcmp(service, "ssh-connection")==0) {
201 			authctxt->pw = pwcopy(pw);
202 			authctxt->valid = 1;
203 			debug2("input_userauth_request: setting up authctxt for %s", user);
204 #ifdef USE_PAM
205 			start_pam(pw);
206 #endif
207 		} else {
208 			log("input_userauth_request: illegal user %s", user);
209 			authctxt->pw = NULL;
210 		}
211 		setproctitle("%s", pw ? user : "unknown");
212 		authctxt->user = xstrdup(user);
213 		authctxt->service = xstrdup(service);
214 		authctxt->style = style ? xstrdup(style) : NULL;
215 	} else if (strcmp(user, authctxt->user) != 0 ||
216 	    strcmp(service, authctxt->service) != 0) {
217 		packet_disconnect("Change of username or service not allowed: "
218 		    "(%s,%s) -> (%s,%s)",
219 		    authctxt->user, authctxt->service, user, service);
220 	}
221 
222 #ifdef HAVE_LOGIN_CAP
223 	if (authctxt->pw != NULL) {
224 		lc = login_getpwclass(authctxt->pw);
225 		if (lc == NULL)
226 			lc = login_getclassbyname(NULL, authctxt->pw);
227 		if (!auth_hostok(lc, from_host, from_ip)) {
228 			log("Denied connection for %.200s from %.200s [%.200s].",
229 			    authctxt->pw->pw_name, from_host, from_ip);
230 			packet_disconnect("Sorry, you are not allowed to connect.");
231 		}
232 		if (!auth_timeok(lc, time(NULL))) {
233 			log("LOGIN %.200s REFUSED (TIME) FROM %.200s",
234 			    authctxt->pw->pw_name, from_host);
235 			packet_disconnect("Logins not available right now.");
236 		}
237 		login_close(lc);
238 		lc = NULL;
239 	}
240 #endif  /* HAVE_LOGIN_CAP */
241 #ifdef LOGIN_ACCESS
242 	if (authctxt->pw != NULL &&
243 	    !login_access(authctxt->pw->pw_name, from_host)) {
244 		log("Denied connection for %.200s from %.200s [%.200s].",
245 		    authctxt->pw->pw_name, from_host, from_ip);
246 		packet_disconnect("Sorry, you are not allowed to connect.");
247 	}
248 #endif /* LOGIN_ACCESS */
249 	/* reset state */
250 	auth2_challenge_stop(authctxt);
251 	authctxt->postponed = 0;
252 
253 	/* try to authenticate user */
254 	m = authmethod_lookup(method);
255 	if (m != NULL) {
256 		debug2("input_userauth_request: try method %s", method);
257 		authenticated =	m->userauth(authctxt);
258 	}
259 #ifdef USE_PAM
260 	if (authenticated && authctxt->user && !do_pam_account(authctxt->user, NULL))
261 		authenticated = 0;
262 #endif /* USE_PAM */
263 	userauth_finish(authctxt, authenticated, method);
264 
265 	xfree(service);
266 	xfree(user);
267 	xfree(method);
268 }
269 
270 void
271 userauth_finish(Authctxt *authctxt, int authenticated, char *method)
272 {
273 	char *methods;
274 
275 	if (!authctxt->valid && authenticated)
276 		fatal("INTERNAL ERROR: authenticated invalid user %s",
277 		    authctxt->user);
278 
279 	/* Special handling for root */
280 	if (authenticated && authctxt->pw->pw_uid == 0 &&
281 	    !auth_root_allowed(method))
282 		authenticated = 0;
283 
284 	/* Log before sending the reply */
285 	auth_log(authctxt, authenticated, method, " ssh2");
286 
287 	if (authctxt->postponed)
288 		return;
289 
290 	/* XXX todo: check if multiple auth methods are needed */
291 	if (authenticated == 1) {
292 		/* turn off userauth */
293 		dispatch_set(SSH2_MSG_USERAUTH_REQUEST, &dispatch_protocol_ignore);
294 		packet_start(SSH2_MSG_USERAUTH_SUCCESS);
295 		packet_send();
296 		packet_write_wait();
297 		/* now we can break out */
298 		authctxt->success = 1;
299 	} else {
300 		if (authctxt->failures++ > AUTH_FAIL_MAX)
301 			packet_disconnect(AUTH_FAIL_MSG, authctxt->user);
302 		methods = authmethods_get();
303 		packet_start(SSH2_MSG_USERAUTH_FAILURE);
304 		packet_put_cstring(methods);
305 		packet_put_char(0);	/* XXX partial success, unused */
306 		packet_send();
307 		packet_write_wait();
308 		xfree(methods);
309 	}
310 }
311 
312 static void
313 userauth_banner(void)
314 {
315 	struct stat st;
316 	char *banner = NULL;
317 	off_t len, n;
318 	int fd;
319 
320 	if (options.banner == NULL || (datafellows & SSH_BUG_BANNER))
321 		return;
322 	if ((fd = open(options.banner, O_RDONLY)) < 0)
323 		return;
324 	if (fstat(fd, &st) < 0)
325 		goto done;
326 	len = st.st_size;
327 	banner = xmalloc(len + 1);
328 	if ((n = read(fd, banner, len)) < 0)
329 		goto done;
330 	banner[n] = '\0';
331 	packet_start(SSH2_MSG_USERAUTH_BANNER);
332 	packet_put_cstring(banner);
333 	packet_put_cstring("");		/* language, unused */
334 	packet_send();
335 	debug("userauth_banner: sent");
336 done:
337 	if (banner)
338 		xfree(banner);
339 	close(fd);
340 	return;
341 }
342 
343 static int
344 userauth_none(Authctxt *authctxt)
345 {
346 	/* disable method "none", only allowed one time */
347 	Authmethod *m = authmethod_lookup("none");
348 	if (m != NULL)
349 		m->enabled = NULL;
350 	packet_check_eom();
351 	userauth_banner();
352 #ifdef USE_PAM
353 	return authctxt->valid ? auth_pam_password(authctxt, "") : 0;
354 #else /* !USE_PAM */
355 	return authctxt->valid ? auth_password(authctxt, "") : 0;
356 #endif /* USE_PAM */
357 }
358 
359 static int
360 userauth_passwd(Authctxt *authctxt)
361 {
362 	char *password;
363 	int authenticated = 0;
364 	int change;
365 	u_int len;
366 	change = packet_get_char();
367 	if (change)
368 		log("password change not supported");
369 	password = packet_get_string(&len);
370 	packet_check_eom();
371 	if (authctxt->valid &&
372 #ifdef USE_PAM
373 	    auth_password(authctxt, password) == 1)
374 #else
375 	    auth_password(authctxt, password) == 1)
376 #endif
377 		authenticated = 1;
378 	memset(password, 0, len);
379 	xfree(password);
380 	return authenticated;
381 }
382 
383 static int
384 userauth_kbdint(Authctxt *authctxt)
385 {
386 	int authenticated = 0;
387 	char *lang, *devs;
388 
389 	lang = packet_get_string(NULL);
390 	devs = packet_get_string(NULL);
391 	packet_check_eom();
392 
393 	debug("keyboard-interactive devs %s", devs);
394 
395 	if (options.challenge_response_authentication)
396 		authenticated = auth2_challenge(authctxt, devs);
397 
398 	xfree(devs);
399 	xfree(lang);
400 	return authenticated;
401 }
402 
403 static int
404 userauth_pubkey(Authctxt *authctxt)
405 {
406 	Buffer b;
407 	Key *key = NULL;
408 	char *pkalg;
409 	u_char *pkblob, *sig;
410 	u_int alen, blen, slen;
411 	int have_sig, pktype;
412 	int authenticated = 0;
413 
414 	if (!authctxt->valid) {
415 		debug2("userauth_pubkey: disabled because of invalid user");
416 		return 0;
417 	}
418 	have_sig = packet_get_char();
419 	if (datafellows & SSH_BUG_PKAUTH) {
420 		debug2("userauth_pubkey: SSH_BUG_PKAUTH");
421 		/* no explicit pkalg given */
422 		pkblob = packet_get_string(&blen);
423 		buffer_init(&b);
424 		buffer_append(&b, pkblob, blen);
425 		/* so we have to extract the pkalg from the pkblob */
426 		pkalg = buffer_get_string(&b, &alen);
427 		buffer_free(&b);
428 	} else {
429 		pkalg = packet_get_string(&alen);
430 		pkblob = packet_get_string(&blen);
431 	}
432 	pktype = key_type_from_name(pkalg);
433 	if (pktype == KEY_UNSPEC) {
434 		/* this is perfectly legal */
435 		log("userauth_pubkey: unsupported public key algorithm: %s",
436 		    pkalg);
437 		goto done;
438 	}
439 	key = key_from_blob(pkblob, blen);
440 	if (key == NULL) {
441 		error("userauth_pubkey: cannot decode key: %s", pkalg);
442 		goto done;
443 	}
444 	if (key->type != pktype) {
445 		error("userauth_pubkey: type mismatch for decoded key "
446 		    "(received %d, expected %d)", key->type, pktype);
447 		goto done;
448 	}
449 	if (have_sig) {
450 		sig = packet_get_string(&slen);
451 		packet_check_eom();
452 		buffer_init(&b);
453 		if (datafellows & SSH_OLD_SESSIONID) {
454 			buffer_append(&b, session_id2, session_id2_len);
455 		} else {
456 			buffer_put_string(&b, session_id2, session_id2_len);
457 		}
458 		/* reconstruct packet */
459 		buffer_put_char(&b, SSH2_MSG_USERAUTH_REQUEST);
460 		buffer_put_cstring(&b, authctxt->user);
461 		buffer_put_cstring(&b,
462 		    datafellows & SSH_BUG_PKSERVICE ?
463 		    "ssh-userauth" :
464 		    authctxt->service);
465 		if (datafellows & SSH_BUG_PKAUTH) {
466 			buffer_put_char(&b, have_sig);
467 		} else {
468 			buffer_put_cstring(&b, "publickey");
469 			buffer_put_char(&b, have_sig);
470 			buffer_put_cstring(&b, pkalg);
471 		}
472 		buffer_put_string(&b, pkblob, blen);
473 #ifdef DEBUG_PK
474 		buffer_dump(&b);
475 #endif
476 		/* test for correct signature */
477 		if (user_key_allowed(authctxt->pw, key) &&
478 		    key_verify(key, sig, slen, buffer_ptr(&b), buffer_len(&b)) == 1)
479 			authenticated = 1;
480 		buffer_clear(&b);
481 		xfree(sig);
482 	} else {
483 		debug("test whether pkalg/pkblob are acceptable");
484 		packet_check_eom();
485 
486 		/* XXX fake reply and always send PK_OK ? */
487 		/*
488 		 * XXX this allows testing whether a user is allowed
489 		 * to login: if you happen to have a valid pubkey this
490 		 * message is sent. the message is NEVER sent at all
491 		 * if a user is not allowed to login. is this an
492 		 * issue? -markus
493 		 */
494 		if (user_key_allowed(authctxt->pw, key)) {
495 			packet_start(SSH2_MSG_USERAUTH_PK_OK);
496 			packet_put_string(pkalg, alen);
497 			packet_put_string(pkblob, blen);
498 			packet_send();
499 			packet_write_wait();
500 			authctxt->postponed = 1;
501 		}
502 	}
503 	if (authenticated != 1)
504 		auth_clear_options();
505 done:
506 	debug2("userauth_pubkey: authenticated %d pkalg %s", authenticated, pkalg);
507 	if (key != NULL)
508 		key_free(key);
509 	xfree(pkalg);
510 	xfree(pkblob);
511 	return authenticated;
512 }
513 
514 static int
515 userauth_hostbased(Authctxt *authctxt)
516 {
517 	Buffer b;
518 	Key *key = NULL;
519 	char *pkalg, *cuser, *chost, *service;
520 	u_char *pkblob, *sig;
521 	u_int alen, blen, slen;
522 	int pktype;
523 	int authenticated = 0;
524 
525 	if (!authctxt->valid) {
526 		debug2("userauth_hostbased: disabled because of invalid user");
527 		return 0;
528 	}
529 	pkalg = packet_get_string(&alen);
530 	pkblob = packet_get_string(&blen);
531 	chost = packet_get_string(NULL);
532 	cuser = packet_get_string(NULL);
533 	sig = packet_get_string(&slen);
534 
535 	debug("userauth_hostbased: cuser %s chost %s pkalg %s slen %d",
536 	    cuser, chost, pkalg, slen);
537 #ifdef DEBUG_PK
538 	debug("signature:");
539 	buffer_init(&b);
540 	buffer_append(&b, sig, slen);
541 	buffer_dump(&b);
542 	buffer_free(&b);
543 #endif
544 	pktype = key_type_from_name(pkalg);
545 	if (pktype == KEY_UNSPEC) {
546 		/* this is perfectly legal */
547 		log("userauth_hostbased: unsupported "
548 		    "public key algorithm: %s", pkalg);
549 		goto done;
550 	}
551 	key = key_from_blob(pkblob, blen);
552 	if (key == NULL) {
553 		error("userauth_hostbased: cannot decode key: %s", pkalg);
554 		goto done;
555 	}
556 	if (key->type != pktype) {
557 		error("userauth_hostbased: type mismatch for decoded key "
558 		    "(received %d, expected %d)", key->type, pktype);
559 		goto done;
560 	}
561 	service = datafellows & SSH_BUG_HBSERVICE ? "ssh-userauth" :
562 	    authctxt->service;
563 	buffer_init(&b);
564 	buffer_put_string(&b, session_id2, session_id2_len);
565 	/* reconstruct packet */
566 	buffer_put_char(&b, SSH2_MSG_USERAUTH_REQUEST);
567 	buffer_put_cstring(&b, authctxt->user);
568 	buffer_put_cstring(&b, service);
569 	buffer_put_cstring(&b, "hostbased");
570 	buffer_put_string(&b, pkalg, alen);
571 	buffer_put_string(&b, pkblob, blen);
572 	buffer_put_cstring(&b, chost);
573 	buffer_put_cstring(&b, cuser);
574 #ifdef DEBUG_PK
575 	buffer_dump(&b);
576 #endif
577 	/* test for allowed key and correct signature */
578 	if (hostbased_key_allowed(authctxt->pw, cuser, chost, key) &&
579 	    key_verify(key, sig, slen, buffer_ptr(&b), buffer_len(&b)) == 1)
580 		authenticated = 1;
581 
582 	buffer_clear(&b);
583 done:
584 	debug2("userauth_hostbased: authenticated %d", authenticated);
585 	if (key != NULL)
586 		key_free(key);
587 	xfree(pkalg);
588 	xfree(pkblob);
589 	xfree(cuser);
590 	xfree(chost);
591 	xfree(sig);
592 	return authenticated;
593 }
594 
595 /* get current user */
596 
597 struct passwd*
598 auth_get_user(void)
599 {
600 	return (x_authctxt != NULL && x_authctxt->valid) ? x_authctxt->pw : NULL;
601 }
602 
603 #define	DELIM	","
604 
605 static char *
606 authmethods_get(void)
607 {
608 	Authmethod *method = NULL;
609 	Buffer b;
610 	char *list;
611 
612 	buffer_init(&b);
613 	for (method = authmethods; method->name != NULL; method++) {
614 		if (strcmp(method->name, "none") == 0)
615 			continue;
616 		if (method->enabled != NULL && *(method->enabled) != 0) {
617 			if (buffer_len(&b) > 0)
618 				buffer_append(&b, ",", 1);
619 			buffer_append(&b, method->name, strlen(method->name));
620 		}
621 	}
622 	buffer_append(&b, "\0", 1);
623 	list = xstrdup(buffer_ptr(&b));
624 	buffer_free(&b);
625 	return list;
626 }
627 
628 static Authmethod *
629 authmethod_lookup(const char *name)
630 {
631 	Authmethod *method = NULL;
632 	if (name != NULL)
633 		for (method = authmethods; method->name != NULL; method++)
634 			if (method->enabled != NULL &&
635 			    *(method->enabled) != 0 &&
636 			    strcmp(name, method->name) == 0)
637 				return method;
638 	debug2("Unrecognized authentication method name: %s", name ? name : "NULL");
639 	return NULL;
640 }
641 
642 /* return 1 if user allows given key */
643 static int
644 user_key_allowed2(struct passwd *pw, Key *key, char *file)
645 {
646 	char line[8192];
647 	int found_key = 0;
648 	FILE *f;
649 	u_long linenum = 0;
650 	struct stat st;
651 	Key *found;
652 	char *fp;
653 
654 	if (pw == NULL)
655 		return 0;
656 
657 	/* Temporarily use the user's uid. */
658 	temporarily_use_uid(pw);
659 
660 	debug("trying public key file %s", file);
661 
662 	/* Fail quietly if file does not exist */
663 	if (stat(file, &st) < 0) {
664 		/* Restore the privileged uid. */
665 		restore_uid();
666 		return 0;
667 	}
668 	/* Open the file containing the authorized keys. */
669 	f = fopen(file, "r");
670 	if (!f) {
671 		/* Restore the privileged uid. */
672 		restore_uid();
673 		return 0;
674 	}
675 	if (options.strict_modes &&
676 	    secure_filename(f, file, pw, line, sizeof(line)) != 0) {
677 		fclose(f);
678 		log("Authentication refused: %s", line);
679 		restore_uid();
680 		return 0;
681 	}
682 
683 	found_key = 0;
684 	found = key_new(key->type);
685 
686 	while (fgets(line, sizeof(line), f)) {
687 		char *cp, *options = NULL;
688 		linenum++;
689 		/* Skip leading whitespace, empty and comment lines. */
690 		for (cp = line; *cp == ' ' || *cp == '\t'; cp++)
691 			;
692 		if (!*cp || *cp == '\n' || *cp == '#')
693 			continue;
694 
695 		if (key_read(found, &cp) != 1) {
696 			/* no key?  check if there are options for this key */
697 			int quoted = 0;
698 			debug2("user_key_allowed: check options: '%s'", cp);
699 			options = cp;
700 			for (; *cp && (quoted || (*cp != ' ' && *cp != '\t')); cp++) {
701 				if (*cp == '\\' && cp[1] == '"')
702 					cp++;	/* Skip both */
703 				else if (*cp == '"')
704 					quoted = !quoted;
705 			}
706 			/* Skip remaining whitespace. */
707 			for (; *cp == ' ' || *cp == '\t'; cp++)
708 				;
709 			if (key_read(found, &cp) != 1) {
710 				debug2("user_key_allowed: advance: '%s'", cp);
711 				/* still no key?  advance to next line*/
712 				continue;
713 			}
714 		}
715 		if (key_equal(found, key) &&
716 		    auth_parse_options(pw, options, file, linenum) == 1) {
717 			found_key = 1;
718 			debug("matching key found: file %s, line %lu",
719 			    file, linenum);
720 			fp = key_fingerprint(found, SSH_FP_MD5, SSH_FP_HEX);
721 			verbose("Found matching %s key: %s",
722 			    key_type(found), fp);
723 			xfree(fp);
724 			break;
725 		}
726 	}
727 	restore_uid();
728 	fclose(f);
729 	key_free(found);
730 	if (!found_key)
731 		debug2("key not found");
732 	return found_key;
733 }
734 
735 /* check whether given key is in .ssh/authorized_keys* */
736 static int
737 user_key_allowed(struct passwd *pw, Key *key)
738 {
739 	int success;
740 	char *file;
741 
742 	file = authorized_keys_file(pw);
743 	success = user_key_allowed2(pw, key, file);
744 	xfree(file);
745 	if (success)
746 		return success;
747 
748 	/* try suffix "2" for backward compat, too */
749 	file = authorized_keys_file2(pw);
750 	success = user_key_allowed2(pw, key, file);
751 	xfree(file);
752 	return success;
753 }
754 
755 /* return 1 if given hostkey is allowed */
756 static int
757 hostbased_key_allowed(struct passwd *pw, const char *cuser, char *chost,
758     Key *key)
759 {
760 	const char *resolvedname, *ipaddr, *lookup;
761 	HostStatus host_status;
762 	int len;
763 
764 	resolvedname = get_canonical_hostname(options.verify_reverse_mapping);
765 	ipaddr = get_remote_ipaddr();
766 
767 	debug2("userauth_hostbased: chost %s resolvedname %s ipaddr %s",
768 	    chost, resolvedname, ipaddr);
769 
770 	if (options.hostbased_uses_name_from_packet_only) {
771 		if (auth_rhosts2(pw, cuser, chost, chost) == 0)
772 			return 0;
773 		lookup = chost;
774 	} else {
775 		if (((len = strlen(chost)) > 0) && chost[len - 1] == '.') {
776 			debug2("stripping trailing dot from chost %s", chost);
777 			chost[len - 1] = '\0';
778 		}
779 		if (strcasecmp(resolvedname, chost) != 0)
780 			log("userauth_hostbased mismatch: "
781 			    "client sends %s, but we resolve %s to %s",
782 			    chost, ipaddr, resolvedname);
783 		if (auth_rhosts2(pw, cuser, resolvedname, ipaddr) == 0)
784 			return 0;
785 		lookup = resolvedname;
786 	}
787 	debug2("userauth_hostbased: access allowed by auth_rhosts2");
788 
789 	host_status = check_key_in_hostfiles(pw, key, lookup,
790 	    _PATH_SSH_SYSTEM_HOSTFILE,
791 	    options.ignore_user_known_hosts ? NULL : _PATH_SSH_USER_HOSTFILE);
792 
793 	/* backward compat if no key has been found. */
794 	if (host_status == HOST_NEW)
795 		host_status = check_key_in_hostfiles(pw, key, lookup,
796 		    _PATH_SSH_SYSTEM_HOSTFILE2,
797 		    options.ignore_user_known_hosts ? NULL :
798 		    _PATH_SSH_USER_HOSTFILE2);
799 
800 	return (host_status == HOST_OK);
801 }
802