Annotation of src/usr.bin/ssh/sshconnect.c, Revision 1.147.2.1
1.1 deraadt 1: /*
1.39 deraadt 2: * Author: Tatu Ylonen <ylo@cs.hut.fi>
3: * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
4: * All rights reserved
5: * Code to connect to a remote host, and to perform the client side of the
6: * login (authentication) dialog.
1.78 deraadt 7: *
8: * As far as I am concerned, the code I have written for this software
9: * can be used freely for any purpose. Any derived versions of this
10: * software must be clearly marked as such, and if the derived work is
11: * incompatible with the protocol description in the RFC file, it must be
12: * called by a name other than "ssh" or "Secure Shell".
1.39 deraadt 13: */
1.1 deraadt 14:
15: #include "includes.h"
1.147.2.1! brad 16: RCSID("$OpenBSD: sshconnect.c,v 1.156 2004/01/25 03:49:09 djm Exp $");
1.1 deraadt 17:
1.66 markus 18: #include <openssl/bn.h>
1.71 markus 19:
1.91 markus 20: #include "ssh.h"
1.1 deraadt 21: #include "xmalloc.h"
22: #include "rsa.h"
1.59 markus 23: #include "buffer.h"
1.1 deraadt 24: #include "packet.h"
25: #include "uidswap.h"
1.21 markus 26: #include "compat.h"
1.58 markus 27: #include "key.h"
1.71 markus 28: #include "sshconnect.h"
1.58 markus 29: #include "hostfile.h"
1.91 markus 30: #include "log.h"
31: #include "readconf.h"
32: #include "atomicio.h"
33: #include "misc.h"
1.119 markus 34: #include "readpass.h"
1.51 markus 35:
1.140 jakob 36: #include "dns.h"
37:
1.70 markus 38: char *client_version_string = NULL;
39: char *server_version_string = NULL;
1.59 markus 40:
1.147.2.1! brad 41: int matching_host_key_dns = 0;
1.145 jakob 42:
1.124 markus 43: /* import */
1.43 markus 44: extern Options options;
1.50 markus 45: extern char *__progname;
1.124 markus 46: extern uid_t original_real_uid;
47: extern uid_t original_effective_uid;
1.135 djm 48: extern pid_t proxy_command_pid;
1.91 markus 49:
1.132 markus 50: static int show_other_keys(const char *, Key *);
1.147.2.1! brad 51: static void warn_changed_key(Key *);
1.132 markus 52:
1.39 deraadt 53: /*
54: * Connect to the given ssh server using a proxy command.
55: */
1.109 itojun 56: static int
1.124 markus 57: ssh_proxy_connect(const char *host, u_short port, const char *proxy_command)
1.1 deraadt 58: {
1.38 markus 59: Buffer command;
60: const char *cp;
61: char *command_string;
62: int pin[2], pout[2];
1.69 deraadt 63: pid_t pid;
1.49 markus 64: char strport[NI_MAXSERV];
1.38 markus 65:
66: /* Convert the port number into a string. */
1.49 markus 67: snprintf(strport, sizeof strport, "%hu", port);
1.38 markus 68:
1.135 djm 69: /*
70: * Build the final command string in the buffer by making the
71: * appropriate substitutions to the given proxy command.
72: *
1.147.2.1! brad 73: * Use "exec" to avoid "sh -c" processes on some platforms
1.135 djm 74: * (e.g. Solaris)
75: */
1.38 markus 76: buffer_init(&command);
1.135 djm 77: buffer_append(&command, "exec ", 5);
78:
1.38 markus 79: for (cp = proxy_command; *cp; cp++) {
80: if (cp[0] == '%' && cp[1] == '%') {
81: buffer_append(&command, "%", 1);
82: cp++;
83: continue;
84: }
85: if (cp[0] == '%' && cp[1] == 'h') {
86: buffer_append(&command, host, strlen(host));
87: cp++;
88: continue;
89: }
90: if (cp[0] == '%' && cp[1] == 'p') {
1.49 markus 91: buffer_append(&command, strport, strlen(strport));
1.38 markus 92: cp++;
93: continue;
94: }
95: buffer_append(&command, cp, 1);
96: }
97: buffer_append(&command, "\0", 1);
98:
99: /* Get the final command string. */
100: command_string = buffer_ptr(&command);
101:
102: /* Create pipes for communicating with the proxy. */
103: if (pipe(pin) < 0 || pipe(pout) < 0)
104: fatal("Could not create pipes to communicate with the proxy: %.100s",
1.118 deraadt 105: strerror(errno));
1.38 markus 106:
107: debug("Executing proxy command: %.500s", command_string);
108:
109: /* Fork and execute the proxy command. */
110: if ((pid = fork()) == 0) {
111: char *argv[10];
112:
113: /* Child. Permanently give up superuser privileges. */
1.124 markus 114: seteuid(original_real_uid);
115: setuid(original_real_uid);
1.38 markus 116:
117: /* Redirect stdin and stdout. */
118: close(pin[1]);
119: if (pin[0] != 0) {
120: if (dup2(pin[0], 0) < 0)
121: perror("dup2 stdin");
122: close(pin[0]);
123: }
124: close(pout[0]);
125: if (dup2(pout[1], 1) < 0)
126: perror("dup2 stdout");
127: /* Cannot be 1 because pin allocated two descriptors. */
128: close(pout[1]);
129:
130: /* Stderr is left as it is so that error messages get
131: printed on the user's terminal. */
1.89 markus 132: argv[0] = _PATH_BSHELL;
1.38 markus 133: argv[1] = "-c";
134: argv[2] = command_string;
135: argv[3] = NULL;
136:
137: /* Execute the proxy command. Note that we gave up any
138: extra privileges above. */
1.89 markus 139: execv(argv[0], argv);
140: perror(argv[0]);
1.38 markus 141: exit(1);
142: }
143: /* Parent. */
144: if (pid < 0)
145: fatal("fork failed: %.100s", strerror(errno));
1.135 djm 146: else
147: proxy_command_pid = pid; /* save pid to clean up later */
1.38 markus 148:
149: /* Close child side of the descriptors. */
150: close(pin[0]);
151: close(pout[1]);
152:
153: /* Free the command name. */
154: buffer_free(&command);
155:
156: /* Set the connection file descriptors. */
157: packet_set_connection(pout[0], pin[1]);
1.1 deraadt 158:
1.110 markus 159: /* Indicate OK return */
160: return 0;
1.1 deraadt 161: }
162:
1.39 deraadt 163: /*
164: * Creates a (possibly privileged) socket for use as the ssh connection.
165: */
1.109 itojun 166: static int
1.139 markus 167: ssh_create_socket(int privileged, struct addrinfo *ai)
1.1 deraadt 168: {
1.105 markus 169: int sock, gaierr;
170: struct addrinfo hints, *res;
1.1 deraadt 171:
1.40 markus 172: /*
173: * If we are running as root and want to connect to a privileged
174: * port, bind our own socket to a privileged port.
175: */
1.38 markus 176: if (privileged) {
177: int p = IPPORT_RESERVED - 1;
1.124 markus 178: PRIV_START;
1.139 markus 179: sock = rresvport_af(&p, ai->ai_family);
1.124 markus 180: PRIV_END;
1.38 markus 181: if (sock < 0)
1.139 markus 182: error("rresvport: af=%d %.100s", ai->ai_family,
183: strerror(errno));
1.55 markus 184: else
185: debug("Allocated local port %d.", p);
1.105 markus 186: return sock;
187: }
1.139 markus 188: sock = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol);
1.105 markus 189: if (sock < 0)
190: error("socket: %.100s", strerror(errno));
191:
192: /* Bind the socket to an alternative local IP address */
193: if (options.bind_address == NULL)
194: return sock;
195:
196: memset(&hints, 0, sizeof(hints));
1.139 markus 197: hints.ai_family = ai->ai_family;
198: hints.ai_socktype = ai->ai_socktype;
199: hints.ai_protocol = ai->ai_protocol;
1.105 markus 200: hints.ai_flags = AI_PASSIVE;
201: gaierr = getaddrinfo(options.bind_address, "0", &hints, &res);
202: if (gaierr) {
203: error("getaddrinfo: %s: %s", options.bind_address,
204: gai_strerror(gaierr));
205: close(sock);
206: return -1;
207: }
208: if (bind(sock, res->ai_addr, res->ai_addrlen) < 0) {
209: error("bind: %s: %s", options.bind_address, strerror(errno));
210: close(sock);
211: freeaddrinfo(res);
212: return -1;
1.38 markus 213: }
1.105 markus 214: freeaddrinfo(res);
1.38 markus 215: return sock;
1.1 deraadt 216: }
217:
1.141 djm 218: static int
219: timeout_connect(int sockfd, const struct sockaddr *serv_addr,
220: socklen_t addrlen, int timeout)
221: {
222: fd_set *fdset;
223: struct timeval tv;
224: socklen_t optlen;
1.142 djm 225: int fdsetsz, optval, rc, result = -1;
1.141 djm 226:
227: if (timeout <= 0)
228: return (connect(sockfd, serv_addr, addrlen));
229:
1.147.2.1! brad 230: set_nonblock(sockfd);
1.141 djm 231: rc = connect(sockfd, serv_addr, addrlen);
1.147.2.1! brad 232: if (rc == 0) {
! 233: unset_nonblock(sockfd);
1.141 djm 234: return (0);
1.147.2.1! brad 235: }
1.141 djm 236: if (errno != EINPROGRESS)
237: return (-1);
238:
239: fdsetsz = howmany(sockfd + 1, NFDBITS) * sizeof(fd_mask);
240: fdset = (fd_set *)xmalloc(fdsetsz);
241:
1.147 markus 242: memset(fdset, 0, fdsetsz);
1.141 djm 243: FD_SET(sockfd, fdset);
244: tv.tv_sec = timeout;
245: tv.tv_usec = 0;
246:
247: for(;;) {
248: rc = select(sockfd + 1, NULL, fdset, NULL, &tv);
249: if (rc != -1 || errno != EINTR)
250: break;
251: }
252:
253: switch(rc) {
254: case 0:
255: /* Timed out */
256: errno = ETIMEDOUT;
1.142 djm 257: break;
1.141 djm 258: case -1:
259: /* Select error */
1.147.2.1! brad 260: debug("select: %s", strerror(errno));
1.142 djm 261: break;
1.141 djm 262: case 1:
263: /* Completed or failed */
264: optval = 0;
265: optlen = sizeof(optval);
1.147.2.1! brad 266: if (getsockopt(sockfd, SOL_SOCKET, SO_ERROR, &optval,
! 267: &optlen) == -1) {
! 268: debug("getsockopt: %s", strerror(errno));
1.142 djm 269: break;
1.147.2.1! brad 270: }
1.141 djm 271: if (optval != 0) {
272: errno = optval;
1.142 djm 273: break;
1.141 djm 274: }
1.142 djm 275: result = 0;
1.147.2.1! brad 276: unset_nonblock(sockfd);
1.141 djm 277: break;
278: default:
279: /* Should not occur */
280: fatal("Bogus return (%d) from select()", rc);
281: }
282:
1.142 djm 283: xfree(fdset);
284: return (result);
1.141 djm 285: }
286:
1.39 deraadt 287: /*
1.49 markus 288: * Opens a TCP/IP connection to the remote server on the given host.
289: * The address of the remote host will be returned in hostaddr.
1.124 markus 290: * If port is 0, the default port will be used. If needpriv is true,
1.39 deraadt 291: * a privileged port will be allocated to make the connection.
1.124 markus 292: * This requires super-user privileges if needpriv is true.
1.39 deraadt 293: * Connection_attempts specifies the maximum number of tries (one per
294: * second). If proxy_command is non-NULL, it specifies the command (with %h
295: * and %p substituted for host and port, respectively) to use to contact
296: * the daemon.
1.110 markus 297: * Return values:
298: * 0 for OK
299: * ECONNREFUSED if we got a "Connection Refused" by the peer on any address
300: * ECONNABORTED if we failed without a "Connection refused"
301: * Suitable error messages for the connection failure will already have been
302: * printed.
1.39 deraadt 303: */
1.38 markus 304: int
1.49 markus 305: ssh_connect(const char *host, struct sockaddr_storage * hostaddr,
1.115 markus 306: u_short port, int family, int connection_attempts,
1.124 markus 307: int needpriv, const char *proxy_command)
1.1 deraadt 308: {
1.90 markus 309: int gaierr;
310: int on = 1;
1.49 markus 311: int sock = -1, attempt;
1.90 markus 312: char ntop[NI_MAXHOST], strport[NI_MAXSERV];
1.49 markus 313: struct addrinfo hints, *ai, *aitop;
1.90 markus 314: struct servent *sp;
1.110 markus 315: /*
316: * Did we get only other errors than "Connection refused" (which
317: * should block fallback to rsh and similar), or did we get at least
318: * one "Connection refused"?
319: */
320: int full_failure = 1;
1.38 markus 321:
1.136 markus 322: debug2("ssh_connect: needpriv %d", needpriv);
1.38 markus 323:
324: /* Get default port if port has not been set. */
325: if (port == 0) {
326: sp = getservbyname(SSH_SERVICE_NAME, "tcp");
327: if (sp)
328: port = ntohs(sp->s_port);
329: else
330: port = SSH_DEFAULT_PORT;
331: }
332: /* If a proxy command is given, connect using it. */
333: if (proxy_command != NULL)
1.124 markus 334: return ssh_proxy_connect(host, port, proxy_command);
1.38 markus 335:
336: /* No proxy command. */
337:
1.49 markus 338: memset(&hints, 0, sizeof(hints));
1.115 markus 339: hints.ai_family = family;
1.49 markus 340: hints.ai_socktype = SOCK_STREAM;
1.126 deraadt 341: snprintf(strport, sizeof strport, "%u", port);
1.49 markus 342: if ((gaierr = getaddrinfo(host, strport, &hints, &aitop)) != 0)
1.50 markus 343: fatal("%s: %.100s: %s", __progname, host,
344: gai_strerror(gaierr));
1.38 markus 345:
1.46 markus 346: /*
347: * Try to connect several times. On some machines, the first time
348: * will sometimes fail. In general socket code appears to behave
349: * quite magically on many machines.
1.110 markus 350: */
351: for (attempt = 0; ;) {
1.38 markus 352: if (attempt > 0)
353: debug("Trying again...");
354:
1.49 markus 355: /* Loop through addresses for this host, and try each one in
1.68 markus 356: sequence until the connection succeeds. */
1.49 markus 357: for (ai = aitop; ai; ai = ai->ai_next) {
358: if (ai->ai_family != AF_INET && ai->ai_family != AF_INET6)
359: continue;
360: if (getnameinfo(ai->ai_addr, ai->ai_addrlen,
361: ntop, sizeof(ntop), strport, sizeof(strport),
362: NI_NUMERICHOST|NI_NUMERICSERV) != 0) {
363: error("ssh_connect: getnameinfo failed");
364: continue;
365: }
366: debug("Connecting to %.200s [%.100s] port %s.",
367: host, ntop, strport);
368:
369: /* Create a socket for connecting. */
1.139 markus 370: sock = ssh_create_socket(needpriv, ai);
1.49 markus 371: if (sock < 0)
1.110 markus 372: /* Any error is already output */
1.49 markus 373: continue;
374:
1.141 djm 375: if (timeout_connect(sock, ai->ai_addr, ai->ai_addrlen,
376: options.connection_timeout) >= 0) {
1.49 markus 377: /* Successful connection. */
1.102 markus 378: memcpy(hostaddr, ai->ai_addr, ai->ai_addrlen);
1.38 markus 379: break;
1.49 markus 380: } else {
1.110 markus 381: if (errno == ECONNREFUSED)
382: full_failure = 0;
1.131 itojun 383: debug("connect to address %s port %s: %s",
384: ntop, strport, strerror(errno));
1.40 markus 385: /*
386: * Close the failed socket; there appear to
387: * be some problems when reusing a socket for
388: * which connect() has already returned an
389: * error.
390: */
1.38 markus 391: close(sock);
392: }
393: }
1.49 markus 394: if (ai)
395: break; /* Successful connection. */
1.1 deraadt 396:
1.110 markus 397: attempt++;
398: if (attempt >= connection_attempts)
399: break;
1.38 markus 400: /* Sleep a moment before retrying. */
401: sleep(1);
402: }
1.49 markus 403:
404: freeaddrinfo(aitop);
405:
1.38 markus 406: /* Return failure if we didn't get a successful connection. */
1.130 itojun 407: if (attempt >= connection_attempts) {
1.138 itojun 408: logit("ssh: connect to host %s port %s: %s",
1.130 itojun 409: host, strport, strerror(errno));
1.110 markus 410: return full_failure ? ECONNABORTED : ECONNREFUSED;
1.130 itojun 411: }
1.38 markus 412:
413: debug("Connection established.");
1.90 markus 414:
1.147.2.1! brad 415: /* Set SO_KEEPALIVE if requested. */
! 416: if (options.tcp_keep_alive &&
1.90 markus 417: setsockopt(sock, SOL_SOCKET, SO_KEEPALIVE, (void *)&on,
418: sizeof(on)) < 0)
419: error("setsockopt SO_KEEPALIVE: %.100s", strerror(errno));
1.38 markus 420:
421: /* Set the connection. */
422: packet_set_connection(sock, sock);
1.1 deraadt 423:
1.110 markus 424: return 0;
1.59 markus 425: }
426:
1.43 markus 427: /*
1.39 deraadt 428: * Waits for the server identification string, and sends our own
429: * identification string.
430: */
1.109 itojun 431: static void
1.95 itojun 432: ssh_exchange_identification(void)
1.1 deraadt 433: {
1.38 markus 434: char buf[256], remote_version[256]; /* must be same size! */
1.64 markus 435: int remote_major, remote_minor, i, mismatch;
1.38 markus 436: int connection_in = packet_get_connection_in();
437: int connection_out = packet_get_connection_out();
1.93 stevesk 438: int minor1 = PROTOCOL_MINOR_1;
1.38 markus 439:
440: /* Read other side\'s version identification. */
1.75 markus 441: for (;;) {
442: for (i = 0; i < sizeof(buf) - 1; i++) {
1.76 markus 443: int len = atomicio(read, connection_in, &buf[i], 1);
1.75 markus 444: if (len < 0)
445: fatal("ssh_exchange_identification: read: %.100s", strerror(errno));
446: if (len != 1)
447: fatal("ssh_exchange_identification: Connection closed by remote host");
448: if (buf[i] == '\r') {
449: buf[i] = '\n';
450: buf[i + 1] = 0;
451: continue; /**XXX wait for \n */
452: }
453: if (buf[i] == '\n') {
454: buf[i + 1] = 0;
455: break;
456: }
1.38 markus 457: }
1.75 markus 458: buf[sizeof(buf) - 1] = 0;
1.76 markus 459: if (strncmp(buf, "SSH-", 4) == 0)
1.38 markus 460: break;
1.75 markus 461: debug("ssh_exchange_identification: %s", buf);
1.38 markus 462: }
1.59 markus 463: server_version_string = xstrdup(buf);
1.38 markus 464:
1.40 markus 465: /*
466: * Check that the versions match. In future this might accept
467: * several versions and set appropriate flags to handle them.
468: */
1.59 markus 469: if (sscanf(server_version_string, "SSH-%d.%d-%[^\n]\n",
470: &remote_major, &remote_minor, remote_version) != 3)
1.38 markus 471: fatal("Bad remote protocol version identification: '%.100s'", buf);
472: debug("Remote protocol version %d.%d, remote software version %.100s",
1.118 deraadt 473: remote_major, remote_minor, remote_version);
1.38 markus 474:
1.59 markus 475: compat_datafellows(remote_version);
1.64 markus 476: mismatch = 0;
1.59 markus 477:
1.116 deraadt 478: switch (remote_major) {
1.64 markus 479: case 1:
480: if (remote_minor == 99 &&
481: (options.protocol & SSH_PROTO_2) &&
482: !(options.protocol & SSH_PROTO_1_PREFERRED)) {
483: enable_compat20();
484: break;
485: }
486: if (!(options.protocol & SSH_PROTO_1)) {
487: mismatch = 1;
488: break;
489: }
490: if (remote_minor < 3) {
491: fatal("Remote machine has too old SSH software version.");
1.81 markus 492: } else if (remote_minor == 3 || remote_minor == 4) {
1.64 markus 493: /* We speak 1.3, too. */
494: enable_compat13();
1.81 markus 495: minor1 = 3;
1.64 markus 496: if (options.forward_agent) {
1.138 itojun 497: logit("Agent forwarding disabled for protocol 1.3");
1.64 markus 498: options.forward_agent = 0;
499: }
500: }
501: break;
502: case 2:
503: if (options.protocol & SSH_PROTO_2) {
504: enable_compat20();
505: break;
1.38 markus 506: }
1.64 markus 507: /* FALLTHROUGH */
1.68 markus 508: default:
1.64 markus 509: mismatch = 1;
510: break;
1.38 markus 511: }
1.64 markus 512: if (mismatch)
1.38 markus 513: fatal("Protocol major versions differ: %d vs. %d",
1.64 markus 514: (options.protocol & SSH_PROTO_2) ? PROTOCOL_MAJOR_2 : PROTOCOL_MAJOR_1,
515: remote_major);
1.38 markus 516: /* Send our own protocol version identification. */
517: snprintf(buf, sizeof buf, "SSH-%d.%d-%.100s\n",
1.64 markus 518: compat20 ? PROTOCOL_MAJOR_2 : PROTOCOL_MAJOR_1,
1.81 markus 519: compat20 ? PROTOCOL_MINOR_2 : minor1,
1.59 markus 520: SSH_VERSION);
1.146 deraadt 521: if (atomicio(vwrite, connection_out, buf, strlen(buf)) != strlen(buf))
1.38 markus 522: fatal("write: %.100s", strerror(errno));
1.59 markus 523: client_version_string = xstrdup(buf);
524: chop(client_version_string);
525: chop(server_version_string);
526: debug("Local version string %.100s", client_version_string);
1.1 deraadt 527: }
528:
1.96 markus 529: /* defaults to 'no' */
1.109 itojun 530: static int
1.112 markus 531: confirm(const char *prompt)
1.1 deraadt 532: {
1.119 markus 533: const char *msg, *again = "Please type 'yes' or 'no': ";
534: char *p;
535: int ret = -1;
1.96 markus 536:
537: if (options.batch_mode)
538: return 0;
1.119 markus 539: for (msg = prompt;;msg = again) {
540: p = read_passphrase(msg, RP_ECHO);
541: if (p == NULL ||
542: (p[0] == '\0') || (p[0] == '\n') ||
543: strncasecmp(p, "no", 2) == 0)
544: ret = 0;
1.127 markus 545: if (p && strncasecmp(p, "yes", 3) == 0)
1.119 markus 546: ret = 1;
547: if (p)
548: xfree(p);
549: if (ret != -1)
550: return ret;
1.1 deraadt 551: }
552: }
553:
1.39 deraadt 554: /*
1.108 markus 555: * check whether the supplied host key is valid, return -1 if the key
556: * is not valid. the user_hostfile will not be updated if 'readonly' is true.
1.39 deraadt 557: */
1.109 itojun 558: static int
1.70 markus 559: check_host_key(char *host, struct sockaddr *hostaddr, Key *host_key,
1.108 markus 560: int readonly, const char *user_hostfile, const char *system_hostfile)
1.1 deraadt 561: {
1.58 markus 562: Key *file_key;
1.147.2.1! brad 563: const char *type = key_type(host_key);
1.46 markus 564: char *ip = NULL;
1.100 markus 565: char hostline[1000], *hostp, *fp;
1.38 markus 566: HostStatus host_status;
567: HostStatus ip_status;
1.49 markus 568: int local = 0, host_ip_differ = 0;
569: char ntop[NI_MAXHOST];
1.119 markus 570: char msg[1024];
1.145 jakob 571: int len, host_line, ip_line;
1.85 markus 572: const char *host_file = NULL, *ip_file = NULL;
1.49 markus 573:
574: /*
575: * Force accepting of the host key for loopback/localhost. The
576: * problem is that if the home directory is NFS-mounted to multiple
577: * machines, localhost will refer to a different machine in each of
578: * them, and the user will get bogus HOST_CHANGED warnings. This
579: * essentially disables host authentication for localhost; however,
580: * this is probably not a real problem.
581: */
1.70 markus 582: /** hostaddr == 0! */
1.49 markus 583: switch (hostaddr->sa_family) {
584: case AF_INET:
1.108 markus 585: local = (ntohl(((struct sockaddr_in *)hostaddr)->
586: sin_addr.s_addr) >> 24) == IN_LOOPBACKNET;
1.49 markus 587: break;
588: case AF_INET6:
1.108 markus 589: local = IN6_IS_ADDR_LOOPBACK(
590: &(((struct sockaddr_in6 *)hostaddr)->sin6_addr));
1.49 markus 591: break;
592: default:
593: local = 0;
594: break;
595: }
1.111 markus 596: if (options.no_host_authentication_for_localhost == 1 && local &&
597: options.host_key_alias == NULL) {
1.88 markus 598: debug("Forcing accepting of host key for "
599: "loopback/localhost.");
1.108 markus 600: return 0;
1.49 markus 601: }
1.42 markus 602:
603: /*
1.88 markus 604: * We don't have the remote ip-address for connections
605: * using a proxy command
1.42 markus 606: */
1.84 markus 607: if (options.proxy_command == NULL) {
608: if (getnameinfo(hostaddr, hostaddr->sa_len, ntop, sizeof(ntop),
1.86 markus 609: NULL, 0, NI_NUMERICHOST) != 0)
1.84 markus 610: fatal("check_host_key: getnameinfo failed");
611: ip = xstrdup(ntop);
612: } else {
613: ip = xstrdup("<no hostip for proxy command>");
1.86 markus 614: }
1.88 markus 615: /*
616: * Turn off check_host_ip if the connection is to localhost, via proxy
617: * command or if we don't have a hostname to compare with
618: */
619: if (options.check_host_ip &&
620: (local || strcmp(host, ip) == 0 || options.proxy_command != NULL))
621: options.check_host_ip = 0;
1.86 markus 622:
623: /*
624: * Allow the user to record the key under a different name. This is
625: * useful for ssh tunneling over forwarded connections or if you run
626: * multiple sshd's on different ports on the same machine.
627: */
628: if (options.host_key_alias != NULL) {
629: host = options.host_key_alias;
630: debug("using hostkeyalias: %s", host);
1.84 markus 631: }
1.38 markus 632:
1.46 markus 633: /*
634: * Store the host key from the known host file in here so that we can
635: * compare it with the key for the IP address.
636: */
1.58 markus 637: file_key = key_new(host_key->type);
1.38 markus 638:
1.40 markus 639: /*
640: * Check if the host key is present in the user\'s list of known
641: * hosts or in the systemwide list.
642: */
1.85 markus 643: host_file = user_hostfile;
1.108 markus 644: host_status = check_host_in_hostfile(host_file, host, host_key,
1.118 deraadt 645: file_key, &host_line);
1.85 markus 646: if (host_status == HOST_NEW) {
647: host_file = system_hostfile;
1.108 markus 648: host_status = check_host_in_hostfile(host_file, host, host_key,
649: file_key, &host_line);
1.85 markus 650: }
1.40 markus 651: /*
652: * Also perform check for the ip address, skip the check if we are
653: * localhost or the hostname was an ip address to begin with
654: */
1.88 markus 655: if (options.check_host_ip) {
1.58 markus 656: Key *ip_key = key_new(host_key->type);
1.38 markus 657:
1.85 markus 658: ip_file = user_hostfile;
1.108 markus 659: ip_status = check_host_in_hostfile(ip_file, ip, host_key,
660: ip_key, &ip_line);
1.85 markus 661: if (ip_status == HOST_NEW) {
662: ip_file = system_hostfile;
1.108 markus 663: ip_status = check_host_in_hostfile(ip_file, ip,
664: host_key, ip_key, &ip_line);
1.85 markus 665: }
1.38 markus 666: if (host_status == HOST_CHANGED &&
1.58 markus 667: (ip_status != HOST_CHANGED || !key_equal(ip_key, file_key)))
1.38 markus 668: host_ip_differ = 1;
669:
1.58 markus 670: key_free(ip_key);
1.38 markus 671: } else
672: ip_status = host_status;
673:
1.58 markus 674: key_free(file_key);
1.38 markus 675:
676: switch (host_status) {
677: case HOST_OK:
678: /* The host is known and the key matches. */
1.72 markus 679: debug("Host '%.200s' is known and matches the %s host key.",
680: host, type);
1.85 markus 681: debug("Found key in %s:%d", host_file, host_line);
1.88 markus 682: if (options.check_host_ip && ip_status == HOST_NEW) {
1.108 markus 683: if (readonly)
1.138 itojun 684: logit("%s host key for IP address "
1.108 markus 685: "'%.128s' not in list of known hosts.",
686: type, ip);
687: else if (!add_host_to_hostfile(user_hostfile, ip,
1.118 deraadt 688: host_key))
1.138 itojun 689: logit("Failed to add the %s host key for IP "
1.108 markus 690: "address '%.128s' to the list of known "
691: "hosts (%.30s).", type, ip, user_hostfile);
1.88 markus 692: else
1.138 itojun 693: logit("Warning: Permanently added the %s host "
1.108 markus 694: "key for IP address '%.128s' to the list "
695: "of known hosts.", type, ip);
1.38 markus 696: }
697: break;
698: case HOST_NEW:
1.108 markus 699: if (readonly)
700: goto fail;
1.38 markus 701: /* The host is new. */
702: if (options.strict_host_key_checking == 1) {
1.108 markus 703: /*
704: * User has requested strict host key checking. We
705: * will not add the host key automatically. The only
706: * alternative left is to abort.
707: */
708: error("No %s host key is known for %.200s and you "
709: "have requested strict checking.", type, host);
710: goto fail;
1.38 markus 711: } else if (options.strict_host_key_checking == 2) {
1.145 jakob 712: char msg1[1024], msg2[1024];
713:
714: if (show_other_keys(host, host_key))
715: snprintf(msg1, sizeof(msg1),
716: "\nbut keys of different type are already"
717: " known for this host.");
718: else
719: snprintf(msg1, sizeof(msg1), ".");
1.38 markus 720: /* The default */
1.100 markus 721: fp = key_fingerprint(host_key, SSH_FP_MD5, SSH_FP_HEX);
1.145 jakob 722: msg2[0] = '\0';
723: if (options.verify_host_key_dns) {
1.147.2.1! brad 724: if (matching_host_key_dns)
1.145 jakob 725: snprintf(msg2, sizeof(msg2),
726: "Matching host key fingerprint"
727: " found in DNS.\n");
728: else
729: snprintf(msg2, sizeof(msg2),
730: "No matching host key fingerprint"
731: " found in DNS.\n");
732: }
1.119 markus 733: snprintf(msg, sizeof(msg),
1.108 markus 734: "The authenticity of host '%.200s (%s)' can't be "
1.132 markus 735: "established%s\n"
1.145 jakob 736: "%s key fingerprint is %s.\n%s"
1.108 markus 737: "Are you sure you want to continue connecting "
1.132 markus 738: "(yes/no)? ",
1.145 jakob 739: host, ip, msg1, type, fp, msg2);
1.100 markus 740: xfree(fp);
1.119 markus 741: if (!confirm(msg))
1.108 markus 742: goto fail;
1.38 markus 743: }
1.88 markus 744: if (options.check_host_ip && ip_status == HOST_NEW) {
1.38 markus 745: snprintf(hostline, sizeof(hostline), "%s,%s", host, ip);
746: hostp = hostline;
747: } else
748: hostp = host;
749:
1.108 markus 750: /*
751: * If not in strict mode, add the key automatically to the
752: * local known_hosts file.
753: */
1.70 markus 754: if (!add_host_to_hostfile(user_hostfile, hostp, host_key))
1.138 itojun 755: logit("Failed to add the host to the list of known "
1.108 markus 756: "hosts (%.500s).", user_hostfile);
1.38 markus 757: else
1.138 itojun 758: logit("Warning: Permanently added '%.200s' (%s) to the "
1.108 markus 759: "list of known hosts.", hostp, type);
1.38 markus 760: break;
761: case HOST_CHANGED:
762: if (options.check_host_ip && host_ip_differ) {
763: char *msg;
764: if (ip_status == HOST_NEW)
765: msg = "is unknown";
766: else if (ip_status == HOST_OK)
767: msg = "is unchanged";
768: else
769: msg = "has a different value";
770: error("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@");
771: error("@ WARNING: POSSIBLE DNS SPOOFING DETECTED! @");
772: error("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@");
1.72 markus 773: error("The %s host key for %s has changed,", type, host);
1.38 markus 774: error("and the key for the according IP address %s", ip);
775: error("%s. This could either mean that", msg);
776: error("DNS SPOOFING is happening or the IP address for the host");
1.85 markus 777: error("and its host key have changed at the same time.");
1.88 markus 778: if (ip_status != HOST_NEW)
1.85 markus 779: error("Offending key for IP in %s:%d", ip_file, ip_line);
1.38 markus 780: }
781: /* The host key has changed. */
1.147.2.1! brad 782: warn_changed_key(host_key);
1.38 markus 783: error("Add correct host key in %.100s to get rid of this message.",
1.87 markus 784: user_hostfile);
1.85 markus 785: error("Offending key in %s:%d", host_file, host_line);
1.38 markus 786:
1.40 markus 787: /*
788: * If strict host key checking is in use, the user will have
789: * to edit the key manually and we can only abort.
790: */
1.108 markus 791: if (options.strict_host_key_checking) {
792: error("%s host key for %.200s has changed and you have "
793: "requested strict checking.", type, host);
794: goto fail;
795: }
1.38 markus 796:
1.40 markus 797: /*
798: * If strict host key checking has not been requested, allow
1.144 djm 799: * the connection but without MITM-able authentication or
1.40 markus 800: * agent forwarding.
801: */
1.38 markus 802: if (options.password_authentication) {
1.108 markus 803: error("Password authentication is disabled to avoid "
804: "man-in-the-middle attacks.");
1.38 markus 805: options.password_authentication = 0;
1.144 djm 806: }
807: if (options.kbd_interactive_authentication) {
808: error("Keyboard-interactive authentication is disabled"
809: " to avoid man-in-the-middle attacks.");
810: options.kbd_interactive_authentication = 0;
811: options.challenge_response_authentication = 0;
812: }
813: if (options.challenge_response_authentication) {
814: error("Challenge/response authentication is disabled"
815: " to avoid man-in-the-middle attacks.");
816: options.challenge_response_authentication = 0;
1.38 markus 817: }
818: if (options.forward_agent) {
1.108 markus 819: error("Agent forwarding is disabled to avoid "
820: "man-in-the-middle attacks.");
1.38 markus 821: options.forward_agent = 0;
1.83 markus 822: }
823: if (options.forward_x11) {
1.108 markus 824: error("X11 forwarding is disabled to avoid "
825: "man-in-the-middle attacks.");
1.83 markus 826: options.forward_x11 = 0;
827: }
1.108 markus 828: if (options.num_local_forwards > 0 ||
829: options.num_remote_forwards > 0) {
830: error("Port forwarding is disabled to avoid "
831: "man-in-the-middle attacks.");
832: options.num_local_forwards =
1.118 deraadt 833: options.num_remote_forwards = 0;
1.38 markus 834: }
1.40 markus 835: /*
836: * XXX Should permit the user to change to use the new id.
837: * This could be done by converting the host key to an
838: * identifying sentence, tell that the host identifies itself
839: * by that sentence, and ask the user if he/she whishes to
840: * accept the authentication.
841: */
1.38 markus 842: break;
1.132 markus 843: case HOST_FOUND:
844: fatal("internal error");
845: break;
1.88 markus 846: }
847:
848: if (options.check_host_ip && host_status != HOST_CHANGED &&
849: ip_status == HOST_CHANGED) {
1.119 markus 850: snprintf(msg, sizeof(msg),
851: "Warning: the %s host key for '%.200s' "
852: "differs from the key for the IP address '%.128s'"
853: "\nOffending key for IP in %s:%d",
854: type, host, ip, ip_file, ip_line);
855: if (host_status == HOST_OK) {
856: len = strlen(msg);
857: snprintf(msg + len, sizeof(msg) - len,
858: "\nMatching host key in %s:%d",
1.125 deraadt 859: host_file, host_line);
1.119 markus 860: }
1.88 markus 861: if (options.strict_host_key_checking == 1) {
1.143 djm 862: logit("%s", msg);
1.108 markus 863: error("Exiting, you have requested strict checking.");
864: goto fail;
1.88 markus 865: } else if (options.strict_host_key_checking == 2) {
1.119 markus 866: strlcat(msg, "\nAre you sure you want "
867: "to continue connecting (yes/no)? ", sizeof(msg));
868: if (!confirm(msg))
1.108 markus 869: goto fail;
1.119 markus 870: } else {
1.143 djm 871: logit("%s", msg);
1.88 markus 872: }
1.38 markus 873: }
1.82 provos 874:
875: xfree(ip);
1.108 markus 876: return 0;
877:
878: fail:
879: xfree(ip);
880: return -1;
881: }
882:
1.140 jakob 883: /* returns 0 if key verifies or -1 if key does NOT verify */
1.108 markus 884: int
885: verify_host_key(char *host, struct sockaddr *hostaddr, Key *host_key)
886: {
887: struct stat st;
1.147.2.1! brad 888: int flags = 0;
1.140 jakob 889:
1.147.2.1! brad 890: if (options.verify_host_key_dns &&
! 891: verify_host_key_dns(host, hostaddr, host_key, &flags) == 0) {
! 892:
! 893: if (flags & DNS_VERIFY_FOUND) {
! 894:
! 895: if (options.verify_host_key_dns == 1 &&
! 896: flags & DNS_VERIFY_MATCH &&
! 897: flags & DNS_VERIFY_SECURE)
! 898: return 0;
! 899:
! 900: if (flags & DNS_VERIFY_MATCH) {
! 901: matching_host_key_dns = 1;
! 902: } else {
! 903: warn_changed_key(host_key);
! 904: error("Update the SSHFP RR in DNS with the new "
! 905: "host key to get rid of this message.");
! 906: }
1.140 jakob 907: }
908: }
1.108 markus 909:
910: /* return ok if the key can be found in an old keyfile */
911: if (stat(options.system_hostfile2, &st) == 0 ||
912: stat(options.user_hostfile2, &st) == 0) {
913: if (check_host_key(host, hostaddr, host_key, /*readonly*/ 1,
914: options.user_hostfile2, options.system_hostfile2) == 0)
915: return 0;
916: }
917: return check_host_key(host, hostaddr, host_key, /*readonly*/ 0,
918: options.user_hostfile, options.system_hostfile);
1.51 markus 919: }
1.70 markus 920:
1.51 markus 921: /*
922: * Starts a dialog with the server, and authenticates the current user on the
923: * server. This does not need any extra privileges. The basic connection
924: * to the server must already have been established before this is called.
925: * If login fails, this function prints an error and never returns.
926: * This function does not require super-user privileges.
927: */
928: void
1.120 markus 929: ssh_login(Sensitive *sensitive, const char *orighost,
1.103 markus 930: struct sockaddr *hostaddr, struct passwd *pw)
1.51 markus 931: {
932: char *host, *cp;
1.70 markus 933: char *server_user, *local_user;
934:
935: local_user = xstrdup(pw->pw_name);
936: server_user = options.user ? options.user : local_user;
1.51 markus 937:
938: /* Convert the user-supplied hostname into all lowercase. */
939: host = xstrdup(orighost);
940: for (cp = host; *cp; cp++)
941: if (isupper(*cp))
942: *cp = tolower(*cp);
943:
944: /* Exchange protocol version identification strings with the server. */
945: ssh_exchange_identification();
946:
947: /* Put the connection into non-blocking mode. */
948: packet_set_nonblocking();
949:
950: /* key exchange */
951: /* authenticate user */
1.59 markus 952: if (compat20) {
953: ssh_kex2(host, hostaddr);
1.120 markus 954: ssh_userauth2(local_user, server_user, host, sensitive);
1.59 markus 955: } else {
956: ssh_kex(host, hostaddr);
1.120 markus 957: ssh_userauth1(local_user, server_user, host, sensitive);
1.59 markus 958: }
1.97 markus 959: }
960:
961: void
962: ssh_put_password(char *password)
963: {
964: int size;
965: char *padded;
966:
1.99 deraadt 967: if (datafellows & SSH_BUG_PASSWORDPAD) {
1.107 markus 968: packet_put_cstring(password);
1.99 deraadt 969: return;
970: }
1.97 markus 971: size = roundup(strlen(password) + 1, 32);
972: padded = xmalloc(size);
973: memset(padded, 0, size);
974: strlcpy(padded, password, size);
975: packet_put_string(padded, size);
976: memset(padded, 0, size);
977: xfree(padded);
1.132 markus 978: }
979:
980: static int
981: show_key_from_file(const char *file, const char *host, int keytype)
982: {
983: Key *found;
984: char *fp;
985: int line, ret;
986:
987: found = key_new(keytype);
988: if ((ret = lookup_key_in_hostfile_by_type(file, host,
989: keytype, found, &line))) {
990: fp = key_fingerprint(found, SSH_FP_MD5, SSH_FP_HEX);
1.138 itojun 991: logit("WARNING: %s key found for host %s\n"
1.133 markus 992: "in %s:%d\n"
1.132 markus 993: "%s key fingerprint %s.",
994: key_type(found), host, file, line,
995: key_type(found), fp);
996: xfree(fp);
997: }
998: key_free(found);
999: return (ret);
1000: }
1001:
1002: /* print all known host keys for a given host, but skip keys of given type */
1003: static int
1004: show_other_keys(const char *host, Key *key)
1005: {
1006: int type[] = { KEY_RSA1, KEY_RSA, KEY_DSA, -1};
1007: int i, found = 0;
1008:
1009: for (i = 0; type[i] != -1; i++) {
1010: if (type[i] == key->type)
1011: continue;
1012: if (type[i] != KEY_RSA1 &&
1013: show_key_from_file(options.user_hostfile2, host, type[i])) {
1014: found = 1;
1015: continue;
1016: }
1017: if (type[i] != KEY_RSA1 &&
1018: show_key_from_file(options.system_hostfile2, host, type[i])) {
1019: found = 1;
1020: continue;
1021: }
1022: if (show_key_from_file(options.user_hostfile, host, type[i])) {
1023: found = 1;
1024: continue;
1025: }
1026: if (show_key_from_file(options.system_hostfile, host, type[i])) {
1027: found = 1;
1028: continue;
1029: }
1030: debug2("no key of type %d for host %s", type[i], host);
1031: }
1032: return (found);
1.147.2.1! brad 1033: }
! 1034:
! 1035: static void
! 1036: warn_changed_key(Key *host_key)
! 1037: {
! 1038: char *fp;
! 1039: const char *type = key_type(host_key);
! 1040:
! 1041: fp = key_fingerprint(host_key, SSH_FP_MD5, SSH_FP_HEX);
! 1042:
! 1043: error("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@");
! 1044: error("@ WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED! @");
! 1045: error("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@");
! 1046: error("IT IS POSSIBLE THAT SOMEONE IS DOING SOMETHING NASTY!");
! 1047: error("Someone could be eavesdropping on you right now (man-in-the-middle attack)!");
! 1048: error("It is also possible that the %s host key has just been changed.", type);
! 1049: error("The fingerprint for the %s key sent by the remote host is\n%s.",
! 1050: type, fp);
! 1051: error("Please contact your system administrator.");
! 1052:
! 1053: xfree(fp);
1.1 deraadt 1054: }