Annotation of src/usr.bin/ssh/auth.c, Revision 1.123
1.123 ! djm 1: /* $OpenBSD: auth.c,v 1.122 2017/06/24 06:34:38 djm Exp $ */
1.1 markus 2: /*
1.19 deraadt 3: * Copyright (c) 2000 Markus Friedl. All rights reserved.
1.9 deraadt 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.
1.1 markus 24: */
25:
1.62 stevesk 26: #include <sys/types.h>
27: #include <sys/stat.h>
1.114 djm 28: #include <sys/socket.h>
1.22 markus 29:
1.70 stevesk 30: #include <errno.h>
1.79 dtucker 31: #include <fcntl.h>
1.77 djm 32: #include <login_cap.h>
1.61 stevesk 33: #include <paths.h>
1.68 stevesk 34: #include <pwd.h>
1.69 stevesk 35: #include <stdarg.h>
1.74 stevesk 36: #include <stdio.h>
1.72 stevesk 37: #include <string.h>
1.80 djm 38: #include <unistd.h>
1.109 deraadt 39: #include <limits.h>
1.114 djm 40: #include <netdb.h>
1.1 markus 41:
42: #include "xmalloc.h"
1.13 markus 43: #include "match.h"
1.14 markus 44: #include "groupaccess.h"
45: #include "log.h"
1.75 deraadt 46: #include "buffer.h"
1.106 millert 47: #include "misc.h"
1.1 markus 48: #include "servconf.h"
1.75 deraadt 49: #include "key.h"
50: #include "hostfile.h"
1.2 markus 51: #include "auth.h"
1.13 markus 52: #include "auth-options.h"
1.14 markus 53: #include "canohost.h"
1.24 markus 54: #include "uidswap.h"
1.42 markus 55: #include "packet.h"
1.75 deraadt 56: #ifdef GSSAPI
57: #include "ssh-gss.h"
58: #endif
1.85 djm 59: #include "authfile.h"
1.67 dtucker 60: #include "monitor_wrap.h"
1.107 djm 61: #include "authfile.h"
62: #include "ssherr.h"
1.103 djm 63: #include "compat.h"
1.2 markus 64:
1.1 markus 65: /* import */
66: extern ServerOptions options;
1.67 dtucker 67: extern int use_privsep;
1.1 markus 68:
1.42 markus 69: /* Debugging messages */
70: Buffer auth_debug;
71: int auth_debug_init;
72:
1.1 markus 73: /*
1.12 markus 74: * Check if the user is allowed to log in via ssh. If user is listed
75: * in DenyUsers or one of user's groups is listed in DenyGroups, false
76: * will be returned. If AllowUsers isn't empty and user isn't listed
77: * there, or if AllowGroups isn't empty and one of user's groups isn't
78: * listed there, false will be returned.
1.1 markus 79: * If the user's shell is not executable, false will be returned.
1.4 markus 80: * Otherwise true is returned.
1.1 markus 81: */
1.5 markus 82: int
1.1 markus 83: allowed_user(struct passwd * pw)
84: {
1.114 djm 85: struct ssh *ssh = active_state; /* XXX */
1.1 markus 86: struct stat st;
1.35 markus 87: const char *hostname = NULL, *ipaddr = NULL;
1.117 djm 88: int r;
1.60 djm 89: u_int i;
1.1 markus 90:
91: /* Shouldn't be called if pw is NULL, but better safe than sorry... */
1.12 markus 92: if (!pw || !pw->pw_name)
1.1 markus 93: return 0;
94:
1.7 deraadt 95: /*
1.84 djm 96: * Deny if shell does not exist or is not executable unless we
97: * are chrooting.
1.7 deraadt 98: */
1.84 djm 99: if (options.chroot_directory == NULL ||
100: strcasecmp(options.chroot_directory, "none") == 0) {
101: char *shell = xstrdup((pw->pw_shell[0] == '\0') ?
102: _PATH_BSHELL : pw->pw_shell); /* empty = /bin/sh */
103:
104: if (stat(shell, &st) != 0) {
105: logit("User %.100s not allowed because shell %.100s "
106: "does not exist", pw->pw_name, shell);
1.102 djm 107: free(shell);
1.84 djm 108: return 0;
109: }
110: if (S_ISREG(st.st_mode) == 0 ||
111: (st.st_mode & (S_IXOTH|S_IXUSR|S_IXGRP)) == 0) {
112: logit("User %.100s not allowed because shell %.100s "
113: "is not executable", pw->pw_name, shell);
1.102 djm 114: free(shell);
1.84 djm 115: return 0;
116: }
1.102 djm 117: free(shell);
1.34 stevesk 118: }
1.1 markus 119:
1.58 dtucker 120: if (options.num_deny_users > 0 || options.num_allow_users > 0 ||
121: options.num_deny_groups > 0 || options.num_allow_groups > 0) {
1.114 djm 122: hostname = auth_get_canonical_hostname(ssh, options.use_dns);
123: ipaddr = ssh_remote_ipaddr(ssh);
1.35 markus 124: }
125:
1.1 markus 126: /* Return false if user is listed in DenyUsers */
127: if (options.num_deny_users > 0) {
1.119 dtucker 128: for (i = 0; i < options.num_deny_users; i++) {
1.117 djm 129: r = match_user(pw->pw_name, hostname, ipaddr,
130: options.deny_users[i]);
131: if (r < 0) {
132: fatal("Invalid DenyUsers pattern \"%.100s\"",
133: options.deny_users[i]);
1.118 djm 134: } else if (r != 0) {
1.57 dtucker 135: logit("User %.100s from %.100s not allowed "
136: "because listed in DenyUsers",
137: pw->pw_name, hostname);
1.1 markus 138: return 0;
1.34 stevesk 139: }
1.119 dtucker 140: }
1.1 markus 141: }
142: /* Return false if AllowUsers isn't empty and user isn't listed there */
143: if (options.num_allow_users > 0) {
1.117 djm 144: for (i = 0; i < options.num_allow_users; i++) {
145: r = match_user(pw->pw_name, hostname, ipaddr,
146: options.allow_users[i]);
147: if (r < 0) {
148: fatal("Invalid AllowUsers pattern \"%.100s\"",
149: options.allow_users[i]);
150: } else if (r == 1)
1.1 markus 151: break;
1.117 djm 152: }
1.1 markus 153: /* i < options.num_allow_users iff we break for loop */
1.34 stevesk 154: if (i >= options.num_allow_users) {
1.57 dtucker 155: logit("User %.100s from %.100s not allowed because "
156: "not listed in AllowUsers", pw->pw_name, hostname);
1.1 markus 157: return 0;
1.34 stevesk 158: }
1.1 markus 159: }
160: if (options.num_deny_groups > 0 || options.num_allow_groups > 0) {
1.12 markus 161: /* Get the user's group access list (primary and supplementary) */
1.34 stevesk 162: if (ga_init(pw->pw_name, pw->pw_gid) == 0) {
1.57 dtucker 163: logit("User %.100s from %.100s not allowed because "
164: "not in any group", pw->pw_name, hostname);
1.1 markus 165: return 0;
1.34 stevesk 166: }
1.1 markus 167:
1.12 markus 168: /* Return false if one of user's groups is listed in DenyGroups */
169: if (options.num_deny_groups > 0)
170: if (ga_match(options.deny_groups,
171: options.num_deny_groups)) {
172: ga_free();
1.57 dtucker 173: logit("User %.100s from %.100s not allowed "
174: "because a group is listed in DenyGroups",
175: pw->pw_name, hostname);
1.1 markus 176: return 0;
1.12 markus 177: }
1.1 markus 178: /*
1.12 markus 179: * Return false if AllowGroups isn't empty and one of user's groups
1.1 markus 180: * isn't listed there
181: */
1.12 markus 182: if (options.num_allow_groups > 0)
183: if (!ga_match(options.allow_groups,
184: options.num_allow_groups)) {
185: ga_free();
1.57 dtucker 186: logit("User %.100s from %.100s not allowed "
187: "because none of user's groups are listed "
188: "in AllowGroups", pw->pw_name, hostname);
1.1 markus 189: return 0;
1.12 markus 190: }
191: ga_free();
1.1 markus 192: }
193: /* We found no reason not to let this user try to log on... */
194: return 1;
1.13 markus 195: }
196:
1.122 djm 197: /*
198: * Formats any key left in authctxt->auth_method_key for inclusion in
199: * auth_log()'s message. Also includes authxtct->auth_method_info if present.
200: */
201: static char *
202: format_method_key(Authctxt *authctxt)
1.103 djm 203: {
1.122 djm 204: const struct sshkey *key = authctxt->auth_method_key;
205: const char *methinfo = authctxt->auth_method_info;
206: char *fp, *ret = NULL;
207:
208: if (key == NULL)
209: return NULL;
210:
211: if (key_is_cert(key)) {
212: fp = sshkey_fingerprint(key->cert->signature_key,
213: options.fingerprint_hash, SSH_FP_DEFAULT);
214: xasprintf(&ret, "%s ID %s (serial %llu) CA %s %s%s%s",
215: sshkey_type(key), key->cert->key_id,
216: (unsigned long long)key->cert->serial,
217: sshkey_type(key->cert->signature_key),
218: fp == NULL ? "(null)" : fp,
219: methinfo == NULL ? "" : ", ",
220: methinfo == NULL ? "" : methinfo);
221: free(fp);
222: } else {
223: fp = sshkey_fingerprint(key, options.fingerprint_hash,
224: SSH_FP_DEFAULT);
225: xasprintf(&ret, "%s %s%s%s", sshkey_type(key),
226: fp == NULL ? "(null)" : fp,
227: methinfo == NULL ? "" : ", ",
228: methinfo == NULL ? "" : methinfo);
229: free(fp);
230: }
231: return ret;
1.103 djm 232: }
233:
234: void
1.98 djm 235: auth_log(Authctxt *authctxt, int authenticated, int partial,
1.103 djm 236: const char *method, const char *submethod)
1.13 markus 237: {
1.114 djm 238: struct ssh *ssh = active_state; /* XXX */
1.13 markus 239: void (*authlog) (const char *fmt,...) = verbose;
1.122 djm 240: const char *authmsg;
241: char *extra = NULL;
1.67 dtucker 242:
243: if (use_privsep && !mm_is_monitor() && !authctxt->postponed)
244: return;
1.13 markus 245:
246: /* Raise logging level */
247: if (authenticated == 1 ||
248: !authctxt->valid ||
1.54 dtucker 249: authctxt->failures >= options.max_authtries / 2 ||
1.13 markus 250: strcmp(method, "password") == 0)
1.47 itojun 251: authlog = logit;
1.13 markus 252:
253: if (authctxt->postponed)
254: authmsg = "Postponed";
1.98 djm 255: else if (partial)
256: authmsg = "Partial";
1.13 markus 257: else
258: authmsg = authenticated ? "Accepted" : "Failed";
259:
1.122 djm 260: if ((extra = format_method_key(authctxt)) == NULL) {
261: if (authctxt->auth_method_info != NULL)
262: extra = xstrdup(authctxt->auth_method_info);
263: }
264:
1.116 markus 265: authlog("%s %s%s%s for %s%.100s from %.200s port %d ssh2%s%s",
1.13 markus 266: authmsg,
267: method,
1.98 djm 268: submethod != NULL ? "/" : "", submethod == NULL ? "" : submethod,
1.56 markus 269: authctxt->valid ? "" : "invalid user ",
1.29 markus 270: authctxt->user,
1.114 djm 271: ssh_remote_ipaddr(ssh),
272: ssh_remote_port(ssh),
1.122 djm 273: extra != NULL ? ": " : "",
274: extra != NULL ? extra : "");
275:
276: free(extra);
1.105 djm 277: }
278:
279: void
280: auth_maxtries_exceeded(Authctxt *authctxt)
281: {
1.114 djm 282: struct ssh *ssh = active_state; /* XXX */
283:
1.110 djm 284: error("maximum authentication attempts exceeded for "
1.116 markus 285: "%s%.100s from %.200s port %d ssh2",
1.105 djm 286: authctxt->valid ? "" : "invalid user ",
287: authctxt->user,
1.114 djm 288: ssh_remote_ipaddr(ssh),
1.116 markus 289: ssh_remote_port(ssh));
1.110 djm 290: packet_disconnect("Too many authentication failures");
1.105 djm 291: /* NOTREACHED */
1.13 markus 292: }
293:
294: /*
1.17 markus 295: * Check whether root logins are disallowed.
1.13 markus 296: */
297: int
1.98 djm 298: auth_root_allowed(const char *method)
1.13 markus 299: {
1.114 djm 300: struct ssh *ssh = active_state; /* XXX */
301:
1.17 markus 302: switch (options.permit_root_login) {
303: case PERMIT_YES:
1.13 markus 304: return 1;
1.17 markus 305: case PERMIT_NO_PASSWD:
1.112 deraadt 306: if (strcmp(method, "publickey") == 0 ||
307: strcmp(method, "hostbased") == 0 ||
1.113 djm 308: strcmp(method, "gssapi-with-mic") == 0)
1.17 markus 309: return 1;
310: break;
311: case PERMIT_FORCED_ONLY:
312: if (forced_command) {
1.47 itojun 313: logit("Root login accepted for forced command.");
1.17 markus 314: return 1;
315: }
316: break;
1.13 markus 317: }
1.114 djm 318: logit("ROOT LOGIN REFUSED FROM %.200s port %d",
319: ssh_remote_ipaddr(ssh), ssh_remote_port(ssh));
1.22 markus 320: return 0;
321: }
322:
323:
324: /*
325: * Given a template and a passwd structure, build a filename
326: * by substituting % tokenised options. Currently, %% becomes '%',
327: * %h becomes the home directory and %u the username.
328: *
329: * This returns a buffer allocated by xmalloc.
330: */
1.93 djm 331: char *
1.59 djm 332: expand_authorized_keys(const char *filename, struct passwd *pw)
1.22 markus 333: {
1.109 deraadt 334: char *file, ret[PATH_MAX];
1.65 djm 335: int i;
1.22 markus 336:
1.59 djm 337: file = percent_expand(filename, "h", pw->pw_dir,
338: "u", pw->pw_name, (char *)NULL);
1.22 markus 339:
340: /*
341: * Ensure that filename starts anchored. If not, be backward
342: * compatible and prepend the '%h/'
343: */
1.59 djm 344: if (*file == '/')
345: return (file);
346:
1.65 djm 347: i = snprintf(ret, sizeof(ret), "%s/%s", pw->pw_dir, file);
348: if (i < 0 || (size_t)i >= sizeof(ret))
1.59 djm 349: fatal("expand_authorized_keys: path too long");
1.102 djm 350: free(file);
1.65 djm 351: return (xstrdup(ret));
1.22 markus 352: }
1.24 markus 353:
1.87 djm 354: char *
355: authorized_principals_file(struct passwd *pw)
356: {
1.111 djm 357: if (options.authorized_principals_file == NULL)
1.87 djm 358: return NULL;
359: return expand_authorized_keys(options.authorized_principals_file, pw);
360: }
361:
1.24 markus 362: /* return ok if key exists in sysfile or userfile */
363: HostStatus
1.121 markus 364: check_key_in_hostfiles(struct passwd *pw, struct sshkey *key, const char *host,
1.24 markus 365: const char *sysfile, const char *userfile)
366: {
367: char *user_hostfile;
368: struct stat st;
1.30 stevesk 369: HostStatus host_status;
1.91 djm 370: struct hostkeys *hostkeys;
371: const struct hostkey_entry *found;
1.24 markus 372:
1.91 djm 373: hostkeys = init_hostkeys();
374: load_hostkeys(hostkeys, host, sysfile);
375: if (userfile != NULL) {
1.24 markus 376: user_hostfile = tilde_expand_filename(userfile, pw->pw_uid);
377: if (options.strict_modes &&
378: (stat(user_hostfile, &st) == 0) &&
379: ((st.st_uid != 0 && st.st_uid != pw->pw_uid) ||
1.31 deraadt 380: (st.st_mode & 022) != 0)) {
1.47 itojun 381: logit("Authentication refused for %.100s: "
1.24 markus 382: "bad owner or modes for %.200s",
383: pw->pw_name, user_hostfile);
1.88 djm 384: auth_debug_add("Ignored %.200s: bad ownership or modes",
385: user_hostfile);
1.24 markus 386: } else {
387: temporarily_use_uid(pw);
1.91 djm 388: load_hostkeys(hostkeys, host, user_hostfile);
1.24 markus 389: restore_uid();
390: }
1.102 djm 391: free(user_hostfile);
1.24 markus 392: }
1.91 djm 393: host_status = check_key_in_hostkeys(hostkeys, key, &found);
394: if (host_status == HOST_REVOKED)
395: error("WARNING: revoked key for %s attempted authentication",
396: found->host);
397: else if (host_status == HOST_OK)
398: debug("%s: key for %s found at %s:%ld", __func__,
399: found->host, found->file, found->line);
400: else
401: debug("%s: key for host %s not found", __func__, host);
402:
403: free_hostkeys(hostkeys);
1.24 markus 404:
405: return host_status;
406: }
407:
1.87 djm 408: static FILE *
409: auth_openfile(const char *file, struct passwd *pw, int strict_modes,
410: int log_missing, char *file_type)
1.79 dtucker 411: {
412: char line[1024];
413: struct stat st;
414: int fd;
415: FILE *f;
416:
1.81 dtucker 417: if ((fd = open(file, O_RDONLY|O_NONBLOCK)) == -1) {
1.87 djm 418: if (log_missing || errno != ENOENT)
419: debug("Could not open %s '%s': %s", file_type, file,
1.81 dtucker 420: strerror(errno));
1.79 dtucker 421: return NULL;
1.81 dtucker 422: }
1.79 dtucker 423:
424: if (fstat(fd, &st) < 0) {
425: close(fd);
426: return NULL;
427: }
428: if (!S_ISREG(st.st_mode)) {
1.87 djm 429: logit("User %s %s %s is not a regular file",
430: pw->pw_name, file_type, file);
1.79 dtucker 431: close(fd);
432: return NULL;
433: }
434: unset_nonblock(fd);
435: if ((f = fdopen(fd, "r")) == NULL) {
436: close(fd);
437: return NULL;
438: }
1.90 djm 439: if (strict_modes &&
1.123 ! djm 440: safe_path_fd(fileno(f), file, pw, line, sizeof(line)) != 0) {
1.79 dtucker 441: fclose(f);
442: logit("Authentication refused: %s", line);
1.88 djm 443: auth_debug_add("Ignored %s: %s", file_type, line);
1.79 dtucker 444: return NULL;
445: }
446:
447: return f;
1.87 djm 448: }
449:
450:
451: FILE *
452: auth_openkeyfile(const char *file, struct passwd *pw, int strict_modes)
453: {
454: return auth_openfile(file, pw, strict_modes, 1, "authorized keys");
455: }
456:
457: FILE *
458: auth_openprincipals(const char *file, struct passwd *pw, int strict_modes)
459: {
460: return auth_openfile(file, pw, strict_modes, 0,
461: "authorized principals");
1.37 provos 462: }
463:
464: struct passwd *
465: getpwnamallow(const char *user)
466: {
1.114 djm 467: struct ssh *ssh = active_state; /* XXX */
1.38 provos 468: extern login_cap_t *lc;
469: auth_session_t *as;
1.37 provos 470: struct passwd *pw;
1.96 dtucker 471: struct connection_info *ci = get_connection_info(1, options.use_dns);
1.71 dtucker 472:
1.96 dtucker 473: ci->user = user;
474: parse_server_match_config(&options, ci);
1.120 djm 475: log_change_level(options.log_level);
1.37 provos 476:
477: pw = getpwnam(user);
1.45 stevesk 478: if (pw == NULL) {
1.114 djm 479: logit("Invalid user %.100s from %.100s port %d",
480: user, ssh_remote_ipaddr(ssh), ssh_remote_port(ssh));
1.45 stevesk 481: return (NULL);
482: }
483: if (!allowed_user(pw))
1.38 provos 484: return (NULL);
485: if ((lc = login_getclass(pw->pw_class)) == NULL) {
486: debug("unable to get login class: %s", user);
487: return (NULL);
488: }
489: if ((as = auth_open()) == NULL || auth_setpwd(as, pw) != 0 ||
1.43 millert 490: auth_approval(as, lc, pw->pw_name, "ssh") <= 0) {
1.38 provos 491: debug("Approval failure for %s", user);
1.37 provos 492: pw = NULL;
1.38 provos 493: }
494: if (as != NULL)
495: auth_close(as);
1.41 markus 496: if (pw != NULL)
497: return (pwcopy(pw));
498: return (NULL);
1.85 djm 499: }
500:
501: /* Returns 1 if key is revoked by revoked_keys_file, 0 otherwise */
502: int
1.121 markus 503: auth_key_is_revoked(struct sshkey *key)
1.85 djm 504: {
1.107 djm 505: char *fp = NULL;
506: int r;
1.85 djm 507:
508: if (options.revoked_keys_file == NULL)
509: return 0;
1.108 djm 510: if ((fp = sshkey_fingerprint(key, options.fingerprint_hash,
511: SSH_FP_DEFAULT)) == NULL) {
1.107 djm 512: r = SSH_ERR_ALLOC_FAIL;
513: error("%s: fingerprint key: %s", __func__, ssh_err(r));
514: goto out;
515: }
516:
517: r = sshkey_check_revoked(key, options.revoked_keys_file);
518: switch (r) {
1.100 djm 519: case 0:
1.107 djm 520: break; /* not revoked */
521: case SSH_ERR_KEY_REVOKED:
522: error("Authentication key %s %s revoked by file %s",
523: sshkey_type(key), fp, options.revoked_keys_file);
524: goto out;
1.100 djm 525: default:
1.107 djm 526: error("Error checking authentication key %s %s in "
527: "revoked keys file %s: %s", sshkey_type(key), fp,
528: options.revoked_keys_file, ssh_err(r));
529: goto out;
1.100 djm 530: }
1.107 djm 531:
532: /* Success */
533: r = 0;
534:
535: out:
536: free(fp);
537: return r == 0 ? 0 : 1;
1.42 markus 538: }
539:
540: void
541: auth_debug_add(const char *fmt,...)
542: {
543: char buf[1024];
544: va_list args;
545:
546: if (!auth_debug_init)
547: return;
548:
549: va_start(args, fmt);
550: vsnprintf(buf, sizeof(buf), fmt, args);
551: va_end(args);
552: buffer_put_cstring(&auth_debug, buf);
553: }
554:
555: void
556: auth_debug_send(void)
557: {
558: char *msg;
559:
560: if (!auth_debug_init)
561: return;
562: while (buffer_len(&auth_debug)) {
563: msg = buffer_get_string(&auth_debug, NULL);
564: packet_send_debug("%s", msg);
1.102 djm 565: free(msg);
1.42 markus 566: }
567: }
568:
569: void
570: auth_debug_reset(void)
571: {
572: if (auth_debug_init)
573: buffer_clear(&auth_debug);
574: else {
575: buffer_init(&auth_debug);
576: auth_debug_init = 1;
577: }
1.49 markus 578: }
579:
580: struct passwd *
581: fakepw(void)
582: {
583: static struct passwd fake;
584:
585: memset(&fake, 0, sizeof(fake));
586: fake.pw_name = "NOUSER";
587: fake.pw_passwd =
1.51 djm 588: "$2a$06$r3.juUaHZDlIbQaO2dS9FuYxL1W9M81R1Tc92PoSNmzvpEqLkLGrK";
1.49 markus 589: fake.pw_gecos = "NOUSER";
1.53 deraadt 590: fake.pw_uid = (uid_t)-1;
591: fake.pw_gid = (gid_t)-1;
1.49 markus 592: fake.pw_class = "";
593: fake.pw_dir = "/nonexist";
594: fake.pw_shell = "/nonexist";
595:
596: return (&fake);
1.114 djm 597: }
598:
599: /*
600: * Returns the remote DNS hostname as a string. The returned string must not
601: * be freed. NB. this will usually trigger a DNS query the first time it is
602: * called.
603: * This function does additional checks on the hostname to mitigate some
604: * attacks on legacy rhosts-style authentication.
605: * XXX is RhostsRSAAuthentication vulnerable to these?
606: * XXX Can we remove these checks? (or if not, remove RhostsRSAAuthentication?)
607: */
608:
609: static char *
610: remote_hostname(struct ssh *ssh)
611: {
612: struct sockaddr_storage from;
613: socklen_t fromlen;
614: struct addrinfo hints, *ai, *aitop;
615: char name[NI_MAXHOST], ntop2[NI_MAXHOST];
616: const char *ntop = ssh_remote_ipaddr(ssh);
617:
618: /* Get IP address of client. */
619: fromlen = sizeof(from);
620: memset(&from, 0, sizeof(from));
621: if (getpeername(ssh_packet_get_connection_in(ssh),
622: (struct sockaddr *)&from, &fromlen) < 0) {
623: debug("getpeername failed: %.100s", strerror(errno));
624: return strdup(ntop);
625: }
626:
627: debug3("Trying to reverse map address %.100s.", ntop);
628: /* Map the IP address to a host name. */
629: if (getnameinfo((struct sockaddr *)&from, fromlen, name, sizeof(name),
630: NULL, 0, NI_NAMEREQD) != 0) {
631: /* Host name not found. Use ip address. */
632: return strdup(ntop);
633: }
634:
635: /*
636: * if reverse lookup result looks like a numeric hostname,
637: * someone is trying to trick us by PTR record like following:
638: * 1.1.1.10.in-addr.arpa. IN PTR 2.3.4.5
639: */
640: memset(&hints, 0, sizeof(hints));
641: hints.ai_socktype = SOCK_DGRAM; /*dummy*/
642: hints.ai_flags = AI_NUMERICHOST;
643: if (getaddrinfo(name, NULL, &hints, &ai) == 0) {
644: logit("Nasty PTR record \"%s\" is set up for %s, ignoring",
645: name, ntop);
646: freeaddrinfo(ai);
647: return strdup(ntop);
648: }
649:
650: /* Names are stored in lowercase. */
651: lowercase(name);
652:
653: /*
654: * Map it back to an IP address and check that the given
655: * address actually is an address of this host. This is
656: * necessary because anyone with access to a name server can
657: * define arbitrary names for an IP address. Mapping from
658: * name to IP address can be trusted better (but can still be
659: * fooled if the intruder has access to the name server of
660: * the domain).
661: */
662: memset(&hints, 0, sizeof(hints));
663: hints.ai_family = from.ss_family;
664: hints.ai_socktype = SOCK_STREAM;
665: if (getaddrinfo(name, NULL, &hints, &aitop) != 0) {
666: logit("reverse mapping checking getaddrinfo for %.700s "
1.115 dtucker 667: "[%s] failed.", name, ntop);
1.114 djm 668: return strdup(ntop);
669: }
670: /* Look for the address from the list of addresses. */
671: for (ai = aitop; ai; ai = ai->ai_next) {
672: if (getnameinfo(ai->ai_addr, ai->ai_addrlen, ntop2,
673: sizeof(ntop2), NULL, 0, NI_NUMERICHOST) == 0 &&
674: (strcmp(ntop, ntop2) == 0))
675: break;
676: }
677: freeaddrinfo(aitop);
678: /* If we reached the end of the list, the address was not there. */
679: if (ai == NULL) {
680: /* Address not found for the host name. */
681: logit("Address %.100s maps to %.600s, but this does not "
1.115 dtucker 682: "map back to the address.", ntop, name);
1.114 djm 683: return strdup(ntop);
684: }
685: return strdup(name);
686: }
687:
688: /*
689: * Return the canonical name of the host in the other side of the current
690: * connection. The host name is cached, so it is efficient to call this
691: * several times.
692: */
693:
694: const char *
695: auth_get_canonical_hostname(struct ssh *ssh, int use_dns)
696: {
697: static char *dnsname;
698:
699: if (!use_dns)
700: return ssh_remote_ipaddr(ssh);
701: else if (dnsname != NULL)
702: return dnsname;
703: else {
704: dnsname = remote_hostname(ssh);
705: return dnsname;
706: }
1.1 markus 707: }