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