sshconnect.c (181110) | sshconnect.c (181111) |
---|---|
1/* $OpenBSD: sshconnect.c,v 1.200 2006/10/10 10:12:45 markus Exp $ */ | 1/* $OpenBSD: sshconnect.c,v 1.211 2008/07/01 07:24:22 dtucker Exp $ */ 2/* $FreeBSD: head/crypto/openssh/sshconnect.c 181111 2008-08-01 02:48:36Z des $ */ |
2/* 3 * Author: Tatu Ylonen <ylo@cs.hut.fi> 4 * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland 5 * All rights reserved 6 * Code to connect to a remote host, and to perform the client side of the 7 * login (authentication) dialog. 8 * 9 * As far as I am concerned, the code I have written for this software --- 71 unchanged lines hidden (view full) --- 81 * Connect to the given ssh server using a proxy command. 82 */ 83static int 84ssh_proxy_connect(const char *host, u_short port, const char *proxy_command) 85{ 86 char *command_string, *tmp; 87 int pin[2], pout[2]; 88 pid_t pid; | 3/* 4 * Author: Tatu Ylonen <ylo@cs.hut.fi> 5 * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland 6 * All rights reserved 7 * Code to connect to a remote host, and to perform the client side of the 8 * login (authentication) dialog. 9 * 10 * As far as I am concerned, the code I have written for this software --- 71 unchanged lines hidden (view full) --- 82 * Connect to the given ssh server using a proxy command. 83 */ 84static int 85ssh_proxy_connect(const char *host, u_short port, const char *proxy_command) 86{ 87 char *command_string, *tmp; 88 int pin[2], pout[2]; 89 pid_t pid; |
89 char strport[NI_MAXSERV]; | 90 char *shell, strport[NI_MAXSERV]; |
90 | 91 |
92 if ((shell = getenv("SHELL")) == NULL) 93 shell = _PATH_BSHELL; 94 |
|
91 /* Convert the port number into a string. */ 92 snprintf(strport, sizeof strport, "%hu", port); 93 94 /* 95 * Build the final command string in the buffer by making the 96 * appropriate substitutions to the given proxy command. 97 * 98 * Use "exec" to avoid "sh -c" processes on some platforms --- 28 unchanged lines hidden (view full) --- 127 close(pout[0]); 128 if (dup2(pout[1], 1) < 0) 129 perror("dup2 stdout"); 130 /* Cannot be 1 because pin allocated two descriptors. */ 131 close(pout[1]); 132 133 /* Stderr is left as it is so that error messages get 134 printed on the user's terminal. */ | 95 /* Convert the port number into a string. */ 96 snprintf(strport, sizeof strport, "%hu", port); 97 98 /* 99 * Build the final command string in the buffer by making the 100 * appropriate substitutions to the given proxy command. 101 * 102 * Use "exec" to avoid "sh -c" processes on some platforms --- 28 unchanged lines hidden (view full) --- 131 close(pout[0]); 132 if (dup2(pout[1], 1) < 0) 133 perror("dup2 stdout"); 134 /* Cannot be 1 because pin allocated two descriptors. */ 135 close(pout[1]); 136 137 /* Stderr is left as it is so that error messages get 138 printed on the user's terminal. */ |
135 argv[0] = _PATH_BSHELL; | 139 argv[0] = shell; |
136 argv[1] = "-c"; 137 argv[2] = command_string; 138 argv[3] = NULL; 139 140 /* Execute the proxy command. Note that we gave up any 141 extra privileges above. */ 142 execv(argv[0], argv); 143 perror(argv[0]); --- 9 unchanged lines hidden (view full) --- 153 close(pin[0]); 154 close(pout[1]); 155 156 /* Free the command name. */ 157 xfree(command_string); 158 159 /* Set the connection file descriptors. */ 160 packet_set_connection(pout[0], pin[1]); | 140 argv[1] = "-c"; 141 argv[2] = command_string; 142 argv[3] = NULL; 143 144 /* Execute the proxy command. Note that we gave up any 145 extra privileges above. */ 146 execv(argv[0], argv); 147 perror(argv[0]); --- 9 unchanged lines hidden (view full) --- 157 close(pin[0]); 158 close(pout[1]); 159 160 /* Free the command name. */ 161 xfree(command_string); 162 163 /* Set the connection file descriptors. */ 164 packet_set_connection(pout[0], pin[1]); |
165 packet_set_timeout(options.server_alive_interval, 166 options.server_alive_count_max); |
|
161 162 /* Indicate OK return */ 163 return 0; 164} 165 166/* 167 * Creates a (possibly privileged) socket for use as the ssh connection. 168 */ --- 27 unchanged lines hidden (view full) --- 196 if (options.bind_address == NULL) 197 return sock; 198 199 memset(&hints, 0, sizeof(hints)); 200 hints.ai_family = ai->ai_family; 201 hints.ai_socktype = ai->ai_socktype; 202 hints.ai_protocol = ai->ai_protocol; 203 hints.ai_flags = AI_PASSIVE; | 167 168 /* Indicate OK return */ 169 return 0; 170} 171 172/* 173 * Creates a (possibly privileged) socket for use as the ssh connection. 174 */ --- 27 unchanged lines hidden (view full) --- 202 if (options.bind_address == NULL) 203 return sock; 204 205 memset(&hints, 0, sizeof(hints)); 206 hints.ai_family = ai->ai_family; 207 hints.ai_socktype = ai->ai_socktype; 208 hints.ai_protocol = ai->ai_protocol; 209 hints.ai_flags = AI_PASSIVE; |
204 gaierr = getaddrinfo(options.bind_address, "0", &hints, &res); | 210 gaierr = getaddrinfo(options.bind_address, NULL, &hints, &res); |
205 if (gaierr) { 206 error("getaddrinfo: %s: %s", options.bind_address, | 211 if (gaierr) { 212 error("getaddrinfo: %s: %s", options.bind_address, |
207 gai_strerror(gaierr)); | 213 ssh_gai_strerror(gaierr)); |
208 close(sock); 209 return -1; 210 } 211 if (bind(sock, res->ai_addr, res->ai_addrlen) < 0) { 212 error("bind: %s: %s", options.bind_address, strerror(errno)); 213 close(sock); 214 freeaddrinfo(res); 215 return -1; 216 } 217 freeaddrinfo(res); 218 return sock; 219} 220 221static int 222timeout_connect(int sockfd, const struct sockaddr *serv_addr, | 214 close(sock); 215 return -1; 216 } 217 if (bind(sock, res->ai_addr, res->ai_addrlen) < 0) { 218 error("bind: %s: %s", options.bind_address, strerror(errno)); 219 close(sock); 220 freeaddrinfo(res); 221 return -1; 222 } 223 freeaddrinfo(res); 224 return sock; 225} 226 227static int 228timeout_connect(int sockfd, const struct sockaddr *serv_addr, |
223 socklen_t addrlen, int timeout) | 229 socklen_t addrlen, int *timeoutp) |
224{ 225 fd_set *fdset; | 230{ 231 fd_set *fdset; |
226 struct timeval tv; | 232 struct timeval tv, t_start; |
227 socklen_t optlen; 228 int optval, rc, result = -1; 229 | 233 socklen_t optlen; 234 int optval, rc, result = -1; 235 |
230 if (timeout <= 0) 231 return (connect(sockfd, serv_addr, addrlen)); | 236 gettimeofday(&t_start, NULL); |
232 | 237 |
238 if (*timeoutp <= 0) { 239 result = connect(sockfd, serv_addr, addrlen); 240 goto done; 241 } 242 |
|
233 set_nonblock(sockfd); 234 rc = connect(sockfd, serv_addr, addrlen); 235 if (rc == 0) { 236 unset_nonblock(sockfd); | 243 set_nonblock(sockfd); 244 rc = connect(sockfd, serv_addr, addrlen); 245 if (rc == 0) { 246 unset_nonblock(sockfd); |
237 return (0); | 247 result = 0; 248 goto done; |
238 } | 249 } |
239 if (errno != EINPROGRESS) 240 return (-1); | 250 if (errno != EINPROGRESS) { 251 result = -1; 252 goto done; 253 } |
241 242 fdset = (fd_set *)xcalloc(howmany(sockfd + 1, NFDBITS), 243 sizeof(fd_mask)); 244 FD_SET(sockfd, fdset); | 254 255 fdset = (fd_set *)xcalloc(howmany(sockfd + 1, NFDBITS), 256 sizeof(fd_mask)); 257 FD_SET(sockfd, fdset); |
245 tv.tv_sec = timeout; 246 tv.tv_usec = 0; | 258 ms_to_timeval(&tv, *timeoutp); |
247 248 for (;;) { 249 rc = select(sockfd + 1, NULL, fdset, NULL, &tv); 250 if (rc != -1 || errno != EINTR) 251 break; 252 } 253 254 switch (rc) { --- 22 unchanged lines hidden (view full) --- 277 unset_nonblock(sockfd); 278 break; 279 default: 280 /* Should not occur */ 281 fatal("Bogus return (%d) from select()", rc); 282 } 283 284 xfree(fdset); | 259 260 for (;;) { 261 rc = select(sockfd + 1, NULL, fdset, NULL, &tv); 262 if (rc != -1 || errno != EINTR) 263 break; 264 } 265 266 switch (rc) { --- 22 unchanged lines hidden (view full) --- 289 unset_nonblock(sockfd); 290 break; 291 default: 292 /* Should not occur */ 293 fatal("Bogus return (%d) from select()", rc); 294 } 295 296 xfree(fdset); |
297 298 done: 299 if (result == 0 && *timeoutp > 0) { 300 ms_subtract_diff(&t_start, timeoutp); 301 if (*timeoutp <= 0) { 302 errno = ETIMEDOUT; 303 result = -1; 304 } 305 } 306 |
|
285 return (result); 286} 287 288/* 289 * Opens a TCP/IP connection to the remote server on the given host. 290 * The address of the remote host will be returned in hostaddr. 291 * If port is 0, the default port will be used. If needpriv is true, 292 * a privileged port will be allocated to make the connection. 293 * This requires super-user privileges if needpriv is true. 294 * Connection_attempts specifies the maximum number of tries (one per 295 * second). If proxy_command is non-NULL, it specifies the command (with %h 296 * and %p substituted for host and port, respectively) to use to contact 297 * the daemon. 298 */ 299int 300ssh_connect(const char *host, struct sockaddr_storage * hostaddr, | 307 return (result); 308} 309 310/* 311 * Opens a TCP/IP connection to the remote server on the given host. 312 * The address of the remote host will be returned in hostaddr. 313 * If port is 0, the default port will be used. If needpriv is true, 314 * a privileged port will be allocated to make the connection. 315 * This requires super-user privileges if needpriv is true. 316 * Connection_attempts specifies the maximum number of tries (one per 317 * second). If proxy_command is non-NULL, it specifies the command (with %h 318 * and %p substituted for host and port, respectively) to use to contact 319 * the daemon. 320 */ 321int 322ssh_connect(const char *host, struct sockaddr_storage * hostaddr, |
301 u_short port, int family, int connection_attempts, 302 int needpriv, const char *proxy_command) | 323 u_short port, int family, int connection_attempts, int *timeout_ms, 324 int want_keepalive, int needpriv, const char *proxy_command) |
303{ 304 int gaierr; 305 int on = 1; 306 int sock = -1, attempt; 307 char ntop[NI_MAXHOST], strport[NI_MAXSERV]; 308 struct addrinfo hints, *ai, *aitop; 309 310 debug2("ssh_connect: needpriv %d", needpriv); --- 4 unchanged lines hidden (view full) --- 315 316 /* No proxy command. */ 317 318 memset(&hints, 0, sizeof(hints)); 319 hints.ai_family = family; 320 hints.ai_socktype = SOCK_STREAM; 321 snprintf(strport, sizeof strport, "%u", port); 322 if ((gaierr = getaddrinfo(host, strport, &hints, &aitop)) != 0) | 325{ 326 int gaierr; 327 int on = 1; 328 int sock = -1, attempt; 329 char ntop[NI_MAXHOST], strport[NI_MAXSERV]; 330 struct addrinfo hints, *ai, *aitop; 331 332 debug2("ssh_connect: needpriv %d", needpriv); --- 4 unchanged lines hidden (view full) --- 337 338 /* No proxy command. */ 339 340 memset(&hints, 0, sizeof(hints)); 341 hints.ai_family = family; 342 hints.ai_socktype = SOCK_STREAM; 343 snprintf(strport, sizeof strport, "%u", port); 344 if ((gaierr = getaddrinfo(host, strport, &hints, &aitop)) != 0) |
323 fatal("%s: %.100s: %s", __progname, host, 324 gai_strerror(gaierr)); | 345 fatal("%s: Could not resolve hostname %.100s: %s", __progname, 346 host, ssh_gai_strerror(gaierr)); |
325 326 for (attempt = 0; attempt < connection_attempts; attempt++) { 327 if (attempt > 0) { 328 /* Sleep a moment before retrying. */ 329 sleep(1); 330 debug("Trying again..."); 331 } 332 /* --- 14 unchanged lines hidden (view full) --- 347 348 /* Create a socket for connecting. */ 349 sock = ssh_create_socket(needpriv, ai); 350 if (sock < 0) 351 /* Any error is already output */ 352 continue; 353 354 if (timeout_connect(sock, ai->ai_addr, ai->ai_addrlen, | 347 348 for (attempt = 0; attempt < connection_attempts; attempt++) { 349 if (attempt > 0) { 350 /* Sleep a moment before retrying. */ 351 sleep(1); 352 debug("Trying again..."); 353 } 354 /* --- 14 unchanged lines hidden (view full) --- 369 370 /* Create a socket for connecting. */ 371 sock = ssh_create_socket(needpriv, ai); 372 if (sock < 0) 373 /* Any error is already output */ 374 continue; 375 376 if (timeout_connect(sock, ai->ai_addr, ai->ai_addrlen, |
355 options.connection_timeout) >= 0) { | 377 timeout_ms) >= 0) { |
356 /* Successful connection. */ 357 memcpy(hostaddr, ai->ai_addr, ai->ai_addrlen); 358 break; 359 } else { 360 debug("connect to address %s port %s: %s", 361 ntop, strport, strerror(errno)); 362 close(sock); 363 sock = -1; --- 10 unchanged lines hidden (view full) --- 374 error("ssh: connect to host %s port %s: %s", 375 host, strport, strerror(errno)); 376 return (-1); 377 } 378 379 debug("Connection established."); 380 381 /* Set SO_KEEPALIVE if requested. */ | 378 /* Successful connection. */ 379 memcpy(hostaddr, ai->ai_addr, ai->ai_addrlen); 380 break; 381 } else { 382 debug("connect to address %s port %s: %s", 383 ntop, strport, strerror(errno)); 384 close(sock); 385 sock = -1; --- 10 unchanged lines hidden (view full) --- 396 error("ssh: connect to host %s port %s: %s", 397 host, strport, strerror(errno)); 398 return (-1); 399 } 400 401 debug("Connection established."); 402 403 /* Set SO_KEEPALIVE if requested. */ |
382 if (options.tcp_keep_alive && | 404 if (want_keepalive && |
383 setsockopt(sock, SOL_SOCKET, SO_KEEPALIVE, (void *)&on, 384 sizeof(on)) < 0) 385 error("setsockopt SO_KEEPALIVE: %.100s", strerror(errno)); 386 387 /* Set the connection. */ 388 packet_set_connection(sock, sock); | 405 setsockopt(sock, SOL_SOCKET, SO_KEEPALIVE, (void *)&on, 406 sizeof(on)) < 0) 407 error("setsockopt SO_KEEPALIVE: %.100s", strerror(errno)); 408 409 /* Set the connection. */ 410 packet_set_connection(sock, sock); |
411 packet_set_timeout(options.server_alive_interval, 412 options.server_alive_count_max); |
|
389 390 return 0; 391} 392 393/* 394 * Waits for the server identification string, and sends our own 395 * identification string. 396 */ 397static void | 413 414 return 0; 415} 416 417/* 418 * Waits for the server identification string, and sends our own 419 * identification string. 420 */ 421static void |
398ssh_exchange_identification(void) | 422ssh_exchange_identification(int timeout_ms) |
399{ 400 char buf[256], remote_version[256]; /* must be same size! */ 401 int remote_major, remote_minor, mismatch; 402 int connection_in = packet_get_connection_in(); 403 int connection_out = packet_get_connection_out(); 404 int minor1 = PROTOCOL_MINOR_1; 405 u_int i, n; | 423{ 424 char buf[256], remote_version[256]; /* must be same size! */ 425 int remote_major, remote_minor, mismatch; 426 int connection_in = packet_get_connection_in(); 427 int connection_out = packet_get_connection_out(); 428 int minor1 = PROTOCOL_MINOR_1; 429 u_int i, n; |
430 size_t len; 431 int fdsetsz, remaining, rc; 432 struct timeval t_start, t_remaining; 433 fd_set *fdset; |
|
406 | 434 |
435 fdsetsz = howmany(connection_in + 1, NFDBITS) * sizeof(fd_mask); 436 fdset = xcalloc(1, fdsetsz); 437 |
|
407 /* Read other side's version identification. */ | 438 /* Read other side's version identification. */ |
439 remaining = timeout_ms; |
|
408 for (n = 0;;) { 409 for (i = 0; i < sizeof(buf) - 1; i++) { | 440 for (n = 0;;) { 441 for (i = 0; i < sizeof(buf) - 1; i++) { |
410 size_t len = atomicio(read, connection_in, &buf[i], 1); | 442 if (timeout_ms > 0) { 443 gettimeofday(&t_start, NULL); 444 ms_to_timeval(&t_remaining, remaining); 445 FD_SET(connection_in, fdset); 446 rc = select(connection_in + 1, fdset, NULL, 447 fdset, &t_remaining); 448 ms_subtract_diff(&t_start, &remaining); 449 if (rc == 0 || remaining <= 0) 450 fatal("Connection timed out during " 451 "banner exchange"); 452 if (rc == -1) { 453 if (errno == EINTR) 454 continue; 455 fatal("ssh_exchange_identification: " 456 "select: %s", strerror(errno)); 457 } 458 } |
411 | 459 |
460 len = atomicio(read, connection_in, &buf[i], 1); 461 |
|
412 if (len != 1 && errno == EPIPE) | 462 if (len != 1 && errno == EPIPE) |
413 fatal("ssh_exchange_identification: Connection closed by remote host"); | 463 fatal("ssh_exchange_identification: " 464 "Connection closed by remote host"); |
414 else if (len != 1) | 465 else if (len != 1) |
415 fatal("ssh_exchange_identification: read: %.100s", strerror(errno)); | 466 fatal("ssh_exchange_identification: " 467 "read: %.100s", strerror(errno)); |
416 if (buf[i] == '\r') { 417 buf[i] = '\n'; 418 buf[i + 1] = 0; 419 continue; /**XXX wait for \n */ 420 } 421 if (buf[i] == '\n') { 422 buf[i + 1] = 0; 423 break; 424 } 425 if (++n > 65536) | 468 if (buf[i] == '\r') { 469 buf[i] = '\n'; 470 buf[i + 1] = 0; 471 continue; /**XXX wait for \n */ 472 } 473 if (buf[i] == '\n') { 474 buf[i + 1] = 0; 475 break; 476 } 477 if (++n > 65536) |
426 fatal("ssh_exchange_identification: No banner received"); | 478 fatal("ssh_exchange_identification: " 479 "No banner received"); |
427 } 428 buf[sizeof(buf) - 1] = 0; 429 if (strncmp(buf, "SSH-", 4) == 0) 430 break; 431 debug("ssh_exchange_identification: %s", buf); 432 } 433 server_version_string = xstrdup(buf); | 480 } 481 buf[sizeof(buf) - 1] = 0; 482 if (strncmp(buf, "SSH-", 4) == 0) 483 break; 484 debug("ssh_exchange_identification: %s", buf); 485 } 486 server_version_string = xstrdup(buf); |
487 xfree(fdset); |
|
434 435 /* 436 * Check that the versions match. In future this might accept 437 * several versions and set appropriate flags to handle them. 438 */ 439 if (sscanf(server_version_string, "SSH-%d.%d-%[^\n]\n", 440 &remote_major, &remote_minor, remote_version) != 3) 441 fatal("Bad remote protocol version identification: '%.100s'", buf); --- 37 unchanged lines hidden (view full) --- 479 mismatch = 1; 480 break; 481 } 482 if (mismatch) 483 fatal("Protocol major versions differ: %d vs. %d", 484 (options.protocol & SSH_PROTO_2) ? PROTOCOL_MAJOR_2 : PROTOCOL_MAJOR_1, 485 remote_major); 486 /* Send our own protocol version identification. */ | 488 489 /* 490 * Check that the versions match. In future this might accept 491 * several versions and set appropriate flags to handle them. 492 */ 493 if (sscanf(server_version_string, "SSH-%d.%d-%[^\n]\n", 494 &remote_major, &remote_minor, remote_version) != 3) 495 fatal("Bad remote protocol version identification: '%.100s'", buf); --- 37 unchanged lines hidden (view full) --- 533 mismatch = 1; 534 break; 535 } 536 if (mismatch) 537 fatal("Protocol major versions differ: %d vs. %d", 538 (options.protocol & SSH_PROTO_2) ? PROTOCOL_MAJOR_2 : PROTOCOL_MAJOR_1, 539 remote_major); 540 /* Send our own protocol version identification. */ |
487 snprintf(buf, sizeof buf, "SSH-%d.%d-%.100s\n", | 541 snprintf(buf, sizeof buf, "SSH-%d.%d-%.100s%s", |
488 compat20 ? PROTOCOL_MAJOR_2 : PROTOCOL_MAJOR_1, 489 compat20 ? PROTOCOL_MINOR_2 : minor1, | 542 compat20 ? PROTOCOL_MAJOR_2 : PROTOCOL_MAJOR_1, 543 compat20 ? PROTOCOL_MINOR_2 : minor1, |
490 SSH_VERSION); | 544 SSH_VERSION, compat20 ? "\r\n" : "\n"); |
491 if (atomicio(vwrite, connection_out, buf, strlen(buf)) != strlen(buf)) 492 fatal("write: %.100s", strerror(errno)); 493 client_version_string = xstrdup(buf); 494 chop(client_version_string); 495 chop(server_version_string); 496 debug("Local version string %.100s", client_version_string); 497} 498 --- 32 unchanged lines hidden (view full) --- 531static int 532check_host_key(char *hostname, struct sockaddr *hostaddr, u_short port, 533 Key *host_key, int readonly, const char *user_hostfile, 534 const char *system_hostfile) 535{ 536 Key *file_key; 537 const char *type = key_type(host_key); 538 char *ip = NULL, *host = NULL; | 545 if (atomicio(vwrite, connection_out, buf, strlen(buf)) != strlen(buf)) 546 fatal("write: %.100s", strerror(errno)); 547 client_version_string = xstrdup(buf); 548 chop(client_version_string); 549 chop(server_version_string); 550 debug("Local version string %.100s", client_version_string); 551} 552 --- 32 unchanged lines hidden (view full) --- 585static int 586check_host_key(char *hostname, struct sockaddr *hostaddr, u_short port, 587 Key *host_key, int readonly, const char *user_hostfile, 588 const char *system_hostfile) 589{ 590 Key *file_key; 591 const char *type = key_type(host_key); 592 char *ip = NULL, *host = NULL; |
539 char hostline[1000], *hostp, *fp; | 593 char hostline[1000], *hostp, *fp, *ra; |
540 HostStatus host_status; 541 HostStatus ip_status; 542 int r, local = 0, host_ip_differ = 0; 543 int salen; 544 char ntop[NI_MAXHOST]; 545 char msg[1024]; | 594 HostStatus host_status; 595 HostStatus ip_status; 596 int r, local = 0, host_ip_differ = 0; 597 int salen; 598 char ntop[NI_MAXHOST]; 599 char msg[1024]; |
546 int len, host_line, ip_line; | 600 int len, host_line, ip_line, cancelled_forwarding = 0; |
547 const char *host_file = NULL, *ip_file = NULL; 548 549 /* 550 * Force accepting of the host key for loopback/localhost. The 551 * problem is that if the home directory is NFS-mounted to multiple 552 * machines, localhost will refer to a different machine in each of 553 * them, and the user will get bogus HOST_CHANGED warnings. This 554 * essentially disables host authentication for localhost; however, --- 30 unchanged lines hidden (view full) --- 585 if (options.proxy_command == NULL) { 586 if (getnameinfo(hostaddr, salen, ntop, sizeof(ntop), 587 NULL, 0, NI_NUMERICHOST) != 0) 588 fatal("check_host_key: getnameinfo failed"); 589 ip = put_host_port(ntop, port); 590 } else { 591 ip = xstrdup("<no hostip for proxy command>"); 592 } | 601 const char *host_file = NULL, *ip_file = NULL; 602 603 /* 604 * Force accepting of the host key for loopback/localhost. The 605 * problem is that if the home directory is NFS-mounted to multiple 606 * machines, localhost will refer to a different machine in each of 607 * them, and the user will get bogus HOST_CHANGED warnings. This 608 * essentially disables host authentication for localhost; however, --- 30 unchanged lines hidden (view full) --- 639 if (options.proxy_command == NULL) { 640 if (getnameinfo(hostaddr, salen, ntop, sizeof(ntop), 641 NULL, 0, NI_NUMERICHOST) != 0) 642 fatal("check_host_key: getnameinfo failed"); 643 ip = put_host_port(ntop, port); 644 } else { 645 ip = xstrdup("<no hostip for proxy command>"); 646 } |
647 |
|
593 /* 594 * Turn off check_host_ip if the connection is to localhost, via proxy 595 * command or if we don't have a hostname to compare with 596 */ 597 if (options.check_host_ip && (local || 598 strcmp(hostname, ip) == 0 || options.proxy_command != NULL)) 599 options.check_host_ip = 0; 600 --- 68 unchanged lines hidden (view full) --- 669 host_key, options.hash_known_hosts)) 670 logit("Failed to add the %s host key for IP " 671 "address '%.128s' to the list of known " 672 "hosts (%.30s).", type, ip, user_hostfile); 673 else 674 logit("Warning: Permanently added the %s host " 675 "key for IP address '%.128s' to the list " 676 "of known hosts.", type, ip); | 648 /* 649 * Turn off check_host_ip if the connection is to localhost, via proxy 650 * command or if we don't have a hostname to compare with 651 */ 652 if (options.check_host_ip && (local || 653 strcmp(hostname, ip) == 0 || options.proxy_command != NULL)) 654 options.check_host_ip = 0; 655 --- 68 unchanged lines hidden (view full) --- 724 host_key, options.hash_known_hosts)) 725 logit("Failed to add the %s host key for IP " 726 "address '%.128s' to the list of known " 727 "hosts (%.30s).", type, ip, user_hostfile); 728 else 729 logit("Warning: Permanently added the %s host " 730 "key for IP address '%.128s' to the list " 731 "of known hosts.", type, ip); |
732 } else if (options.visual_host_key) { 733 fp = key_fingerprint(host_key, SSH_FP_MD5, SSH_FP_HEX); 734 ra = key_fingerprint(host_key, SSH_FP_MD5, 735 SSH_FP_RANDOMART); 736 logit("Host key fingerprint is %s\n%s\n", fp, ra); 737 xfree(ra); 738 xfree(fp); |
|
677 } 678 break; 679 case HOST_NEW: 680 if (options.host_key_alias == NULL && port != 0 && 681 port != SSH_DEFAULT_PORT) { 682 debug("checking without port identifier"); 683 if (check_host_key(hostname, hostaddr, 0, host_key, 2, 684 user_hostfile, system_hostfile) == 0) { --- 19 unchanged lines hidden (view full) --- 704 if (show_other_keys(host, host_key)) 705 snprintf(msg1, sizeof(msg1), 706 "\nbut keys of different type are already" 707 " known for this host."); 708 else 709 snprintf(msg1, sizeof(msg1), "."); 710 /* The default */ 711 fp = key_fingerprint(host_key, SSH_FP_MD5, SSH_FP_HEX); | 739 } 740 break; 741 case HOST_NEW: 742 if (options.host_key_alias == NULL && port != 0 && 743 port != SSH_DEFAULT_PORT) { 744 debug("checking without port identifier"); 745 if (check_host_key(hostname, hostaddr, 0, host_key, 2, 746 user_hostfile, system_hostfile) == 0) { --- 19 unchanged lines hidden (view full) --- 766 if (show_other_keys(host, host_key)) 767 snprintf(msg1, sizeof(msg1), 768 "\nbut keys of different type are already" 769 " known for this host."); 770 else 771 snprintf(msg1, sizeof(msg1), "."); 772 /* The default */ 773 fp = key_fingerprint(host_key, SSH_FP_MD5, SSH_FP_HEX); |
774 ra = key_fingerprint(host_key, SSH_FP_MD5, 775 SSH_FP_RANDOMART); |
|
712 msg2[0] = '\0'; 713 if (options.verify_host_key_dns) { 714 if (matching_host_key_dns) 715 snprintf(msg2, sizeof(msg2), 716 "Matching host key fingerprint" 717 " found in DNS.\n"); 718 else 719 snprintf(msg2, sizeof(msg2), 720 "No matching host key fingerprint" 721 " found in DNS.\n"); 722 } 723 snprintf(msg, sizeof(msg), 724 "The authenticity of host '%.200s (%s)' can't be " 725 "established%s\n" | 776 msg2[0] = '\0'; 777 if (options.verify_host_key_dns) { 778 if (matching_host_key_dns) 779 snprintf(msg2, sizeof(msg2), 780 "Matching host key fingerprint" 781 " found in DNS.\n"); 782 else 783 snprintf(msg2, sizeof(msg2), 784 "No matching host key fingerprint" 785 " found in DNS.\n"); 786 } 787 snprintf(msg, sizeof(msg), 788 "The authenticity of host '%.200s (%s)' can't be " 789 "established%s\n" |
726 "%s key fingerprint is %s.\n%s" | 790 "%s key fingerprint is %s.%s%s\n%s" |
727 "Are you sure you want to continue connecting " 728 "(yes/no)? ", | 791 "Are you sure you want to continue connecting " 792 "(yes/no)? ", |
729 host, ip, msg1, type, fp, msg2); | 793 host, ip, msg1, type, fp, 794 options.visual_host_key ? "\n" : "", 795 options.visual_host_key ? ra : "", 796 msg2); 797 xfree(ra); |
730 xfree(fp); 731 if (!confirm(msg)) 732 goto fail; 733 } 734 /* 735 * If not in strict mode, add the key automatically to the 736 * local known_hosts file. 737 */ --- 36 unchanged lines hidden (view full) --- 774 else if (ip_status == HOST_OK) 775 key_msg = "is unchanged"; 776 else 777 key_msg = "has a different value"; 778 error("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@"); 779 error("@ WARNING: POSSIBLE DNS SPOOFING DETECTED! @"); 780 error("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@"); 781 error("The %s host key for %s has changed,", type, host); | 798 xfree(fp); 799 if (!confirm(msg)) 800 goto fail; 801 } 802 /* 803 * If not in strict mode, add the key automatically to the 804 * local known_hosts file. 805 */ --- 36 unchanged lines hidden (view full) --- 842 else if (ip_status == HOST_OK) 843 key_msg = "is unchanged"; 844 else 845 key_msg = "has a different value"; 846 error("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@"); 847 error("@ WARNING: POSSIBLE DNS SPOOFING DETECTED! @"); 848 error("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@"); 849 error("The %s host key for %s has changed,", type, host); |
782 error("and the key for the according IP address %s", ip); | 850 error("and the key for the corresponding IP address %s", ip); |
783 error("%s. This could either mean that", key_msg); 784 error("DNS SPOOFING is happening or the IP address for the host"); 785 error("and its host key have changed at the same time."); 786 if (ip_status != HOST_NEW) 787 error("Offending key for IP in %s:%d", ip_file, ip_line); 788 } 789 /* The host key has changed. */ 790 warn_changed_key(host_key); --- 15 unchanged lines hidden (view full) --- 806 * If strict host key checking has not been requested, allow 807 * the connection but without MITM-able authentication or 808 * forwarding. 809 */ 810 if (options.password_authentication) { 811 error("Password authentication is disabled to avoid " 812 "man-in-the-middle attacks."); 813 options.password_authentication = 0; | 851 error("%s. This could either mean that", key_msg); 852 error("DNS SPOOFING is happening or the IP address for the host"); 853 error("and its host key have changed at the same time."); 854 if (ip_status != HOST_NEW) 855 error("Offending key for IP in %s:%d", ip_file, ip_line); 856 } 857 /* The host key has changed. */ 858 warn_changed_key(host_key); --- 15 unchanged lines hidden (view full) --- 874 * If strict host key checking has not been requested, allow 875 * the connection but without MITM-able authentication or 876 * forwarding. 877 */ 878 if (options.password_authentication) { 879 error("Password authentication is disabled to avoid " 880 "man-in-the-middle attacks."); 881 options.password_authentication = 0; |
882 cancelled_forwarding = 1; |
|
814 } 815 if (options.kbd_interactive_authentication) { 816 error("Keyboard-interactive authentication is disabled" 817 " to avoid man-in-the-middle attacks."); 818 options.kbd_interactive_authentication = 0; 819 options.challenge_response_authentication = 0; | 883 } 884 if (options.kbd_interactive_authentication) { 885 error("Keyboard-interactive authentication is disabled" 886 " to avoid man-in-the-middle attacks."); 887 options.kbd_interactive_authentication = 0; 888 options.challenge_response_authentication = 0; |
889 cancelled_forwarding = 1; |
|
820 } 821 if (options.challenge_response_authentication) { 822 error("Challenge/response authentication is disabled" 823 " to avoid man-in-the-middle attacks."); 824 options.challenge_response_authentication = 0; | 890 } 891 if (options.challenge_response_authentication) { 892 error("Challenge/response authentication is disabled" 893 " to avoid man-in-the-middle attacks."); 894 options.challenge_response_authentication = 0; |
895 cancelled_forwarding = 1; |
|
825 } 826 if (options.forward_agent) { 827 error("Agent forwarding is disabled to avoid " 828 "man-in-the-middle attacks."); 829 options.forward_agent = 0; | 896 } 897 if (options.forward_agent) { 898 error("Agent forwarding is disabled to avoid " 899 "man-in-the-middle attacks."); 900 options.forward_agent = 0; |
901 cancelled_forwarding = 1; |
|
830 } 831 if (options.forward_x11) { 832 error("X11 forwarding is disabled to avoid " 833 "man-in-the-middle attacks."); 834 options.forward_x11 = 0; | 902 } 903 if (options.forward_x11) { 904 error("X11 forwarding is disabled to avoid " 905 "man-in-the-middle attacks."); 906 options.forward_x11 = 0; |
907 cancelled_forwarding = 1; |
|
835 } 836 if (options.num_local_forwards > 0 || 837 options.num_remote_forwards > 0) { 838 error("Port forwarding is disabled to avoid " 839 "man-in-the-middle attacks."); 840 options.num_local_forwards = 841 options.num_remote_forwards = 0; | 908 } 909 if (options.num_local_forwards > 0 || 910 options.num_remote_forwards > 0) { 911 error("Port forwarding is disabled to avoid " 912 "man-in-the-middle attacks."); 913 options.num_local_forwards = 914 options.num_remote_forwards = 0; |
915 cancelled_forwarding = 1; |
|
842 } 843 if (options.tun_open != SSH_TUNMODE_NO) { 844 error("Tunnel forwarding is disabled to avoid " 845 "man-in-the-middle attacks."); 846 options.tun_open = SSH_TUNMODE_NO; | 916 } 917 if (options.tun_open != SSH_TUNMODE_NO) { 918 error("Tunnel forwarding is disabled to avoid " 919 "man-in-the-middle attacks."); 920 options.tun_open = SSH_TUNMODE_NO; |
921 cancelled_forwarding = 1; |
|
847 } | 922 } |
923 if (options.exit_on_forward_failure && cancelled_forwarding) 924 fatal("Error: forwarding disabled due to host key " 925 "check failure"); 926 |
|
848 /* 849 * XXX Should permit the user to change to use the new id. 850 * This could be done by converting the host key to an 851 * identifying sentence, tell that the host identifies itself 852 * by that sentence, and ask the user if he/she whishes to 853 * accept the authentication. 854 */ 855 break; --- 82 unchanged lines hidden (view full) --- 938 * Starts a dialog with the server, and authenticates the current user on the 939 * server. This does not need any extra privileges. The basic connection 940 * to the server must already have been established before this is called. 941 * If login fails, this function prints an error and never returns. 942 * This function does not require super-user privileges. 943 */ 944void 945ssh_login(Sensitive *sensitive, const char *orighost, | 927 /* 928 * XXX Should permit the user to change to use the new id. 929 * This could be done by converting the host key to an 930 * identifying sentence, tell that the host identifies itself 931 * by that sentence, and ask the user if he/she whishes to 932 * accept the authentication. 933 */ 934 break; --- 82 unchanged lines hidden (view full) --- 1017 * Starts a dialog with the server, and authenticates the current user on the 1018 * server. This does not need any extra privileges. The basic connection 1019 * to the server must already have been established before this is called. 1020 * If login fails, this function prints an error and never returns. 1021 * This function does not require super-user privileges. 1022 */ 1023void 1024ssh_login(Sensitive *sensitive, const char *orighost, |
946 struct sockaddr *hostaddr, struct passwd *pw) | 1025 struct sockaddr *hostaddr, struct passwd *pw, int timeout_ms) |
947{ 948 char *host, *cp; 949 char *server_user, *local_user; 950 951 local_user = xstrdup(pw->pw_name); 952 server_user = options.user ? options.user : local_user; 953 954 /* Convert the user-supplied hostname into all lowercase. */ 955 host = xstrdup(orighost); 956 for (cp = host; *cp; cp++) 957 if (isupper(*cp)) 958 *cp = (char)tolower(*cp); 959 960 /* Exchange protocol version identification strings with the server. */ | 1026{ 1027 char *host, *cp; 1028 char *server_user, *local_user; 1029 1030 local_user = xstrdup(pw->pw_name); 1031 server_user = options.user ? options.user : local_user; 1032 1033 /* Convert the user-supplied hostname into all lowercase. */ 1034 host = xstrdup(orighost); 1035 for (cp = host; *cp; cp++) 1036 if (isupper(*cp)) 1037 *cp = (char)tolower(*cp); 1038 1039 /* Exchange protocol version identification strings with the server. */ |
961 ssh_exchange_identification(); | 1040 ssh_exchange_identification(timeout_ms); |
962 963 /* Put the connection into non-blocking mode. */ 964 packet_set_nonblocking(); 965 966 /* key exchange */ 967 /* authenticate user */ 968 if (compat20) { 969 ssh_kex2(host, hostaddr); --- 22 unchanged lines hidden (view full) --- 992 memset(padded, 0, size); 993 xfree(padded); 994} 995 996static int 997show_key_from_file(const char *file, const char *host, int keytype) 998{ 999 Key *found; | 1041 1042 /* Put the connection into non-blocking mode. */ 1043 packet_set_nonblocking(); 1044 1045 /* key exchange */ 1046 /* authenticate user */ 1047 if (compat20) { 1048 ssh_kex2(host, hostaddr); --- 22 unchanged lines hidden (view full) --- 1071 memset(padded, 0, size); 1072 xfree(padded); 1073} 1074 1075static int 1076show_key_from_file(const char *file, const char *host, int keytype) 1077{ 1078 Key *found; |
1000 char *fp; | 1079 char *fp, *ra; |
1001 int line, ret; 1002 1003 found = key_new(keytype); 1004 if ((ret = lookup_key_in_hostfile_by_type(file, host, 1005 keytype, found, &line))) { 1006 fp = key_fingerprint(found, SSH_FP_MD5, SSH_FP_HEX); | 1080 int line, ret; 1081 1082 found = key_new(keytype); 1083 if ((ret = lookup_key_in_hostfile_by_type(file, host, 1084 keytype, found, &line))) { 1085 fp = key_fingerprint(found, SSH_FP_MD5, SSH_FP_HEX); |
1086 if (options.visual_host_key) 1087 ra = key_fingerprint(found, SSH_FP_MD5, SSH_FP_RANDOMART); |
|
1007 logit("WARNING: %s key found for host %s\n" 1008 "in %s:%d\n" | 1088 logit("WARNING: %s key found for host %s\n" 1089 "in %s:%d\n" |
1009 "%s key fingerprint %s.", | 1090 "%s key fingerprint %s.%s%s\n", |
1010 key_type(found), host, file, line, | 1091 key_type(found), host, file, line, |
1011 key_type(found), fp); | 1092 key_type(found), fp, 1093 options.visual_host_key ? "\n" : "", 1094 options.visual_host_key ? ra : ""); 1095 if (options.visual_host_key) 1096 xfree(ra); |
1012 xfree(fp); 1013 } 1014 key_free(found); 1015 return (ret); 1016} 1017 1018/* print all known host keys for a given host, but skip keys of given type */ 1019static int --- 87 unchanged lines hidden --- | 1097 xfree(fp); 1098 } 1099 key_free(found); 1100 return (ret); 1101} 1102 1103/* print all known host keys for a given host, but skip keys of given type */ 1104static int --- 87 unchanged lines hidden --- |