diff options
Diffstat (limited to 'sshconnect.c')
-rw-r--r-- | sshconnect.c | 278 |
1 files changed, 63 insertions, 215 deletions
diff --git a/sshconnect.c b/sshconnect.c index 6d819279e..fdcdcd855 100644 --- a/sshconnect.c +++ b/sshconnect.c | |||
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: sshconnect.c,v 1.305 2018/09/20 03:30:44 djm Exp $ */ | 1 | /* $OpenBSD: sshconnect.c,v 1.314 2019/02/27 19:37:01 markus Exp $ */ |
2 | /* | 2 | /* |
3 | * Author: Tatu Ylonen <ylo@cs.hut.fi> | 3 | * Author: Tatu Ylonen <ylo@cs.hut.fi> |
4 | * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland | 4 | * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland |
@@ -68,9 +68,8 @@ | |||
68 | #include "authfile.h" | 68 | #include "authfile.h" |
69 | #include "ssherr.h" | 69 | #include "ssherr.h" |
70 | #include "authfd.h" | 70 | #include "authfd.h" |
71 | #include "kex.h" | ||
71 | 72 | ||
72 | char *client_version_string = NULL; | ||
73 | char *server_version_string = NULL; | ||
74 | struct sshkey *previous_host_key = NULL; | 73 | struct sshkey *previous_host_key = NULL; |
75 | 74 | ||
76 | static int matching_host_key_dns = 0; | 75 | static int matching_host_key_dns = 0; |
@@ -78,6 +77,7 @@ static int matching_host_key_dns = 0; | |||
78 | static pid_t proxy_command_pid = 0; | 77 | static pid_t proxy_command_pid = 0; |
79 | 78 | ||
80 | /* import */ | 79 | /* import */ |
80 | extern int debug_flag; | ||
81 | extern Options options; | 81 | extern Options options; |
82 | extern char *__progname; | 82 | extern char *__progname; |
83 | 83 | ||
@@ -99,6 +99,24 @@ expand_proxy_command(const char *proxy_command, const char *user, | |||
99 | return ret; | 99 | return ret; |
100 | } | 100 | } |
101 | 101 | ||
102 | static void | ||
103 | stderr_null(void) | ||
104 | { | ||
105 | int devnull; | ||
106 | |||
107 | if ((devnull = open(_PATH_DEVNULL, O_WRONLY)) == -1) { | ||
108 | error("Can't open %s for stderr redirection: %s", | ||
109 | _PATH_DEVNULL, strerror(errno)); | ||
110 | return; | ||
111 | } | ||
112 | if (devnull == STDERR_FILENO) | ||
113 | return; | ||
114 | if (dup2(devnull, STDERR_FILENO) == -1) | ||
115 | error("Cannot redirect stderr to %s", _PATH_DEVNULL); | ||
116 | if (devnull > STDERR_FILENO) | ||
117 | close(devnull); | ||
118 | } | ||
119 | |||
102 | /* | 120 | /* |
103 | * Connect to the given ssh server using a proxy command that passes a | 121 | * Connect to the given ssh server using a proxy command that passes a |
104 | * a connected fd back to us. | 122 | * a connected fd back to us. |
@@ -141,9 +159,13 @@ ssh_proxy_fdpass_connect(struct ssh *ssh, const char *host, u_short port, | |||
141 | close(sp[0]); | 159 | close(sp[0]); |
142 | 160 | ||
143 | /* | 161 | /* |
144 | * Stderr is left as it is so that error messages get | 162 | * Stderr is left for non-ControlPersist connections is so |
145 | * printed on the user's terminal. | 163 | * error messages may be printed on the user's terminal. |
146 | */ | 164 | */ |
165 | if (!debug_flag && options.control_path != NULL && | ||
166 | options.control_persist) | ||
167 | stderr_null(); | ||
168 | |||
147 | argv[0] = shell; | 169 | argv[0] = shell; |
148 | argv[1] = "-c"; | 170 | argv[1] = "-c"; |
149 | argv[2] = command_string; | 171 | argv[2] = command_string; |
@@ -219,8 +241,14 @@ ssh_proxy_connect(struct ssh *ssh, const char *host, u_short port, | |||
219 | /* Cannot be 1 because pin allocated two descriptors. */ | 241 | /* Cannot be 1 because pin allocated two descriptors. */ |
220 | close(pout[1]); | 242 | close(pout[1]); |
221 | 243 | ||
222 | /* Stderr is left as it is so that error messages get | 244 | /* |
223 | printed on the user's terminal. */ | 245 | * Stderr is left for non-ControlPersist connections is so |
246 | * error messages may be printed on the user's terminal. | ||
247 | */ | ||
248 | if (!debug_flag && options.control_path != NULL && | ||
249 | options.control_persist) | ||
250 | stderr_null(); | ||
251 | |||
224 | argv[0] = shell; | 252 | argv[0] = shell; |
225 | argv[1] = "-c"; | 253 | argv[1] = "-c"; |
226 | argv[2] = command_string; | 254 | argv[2] = command_string; |
@@ -369,10 +397,6 @@ ssh_create_socket(struct addrinfo *ai) | |||
369 | error("getaddrinfo: no addrs"); | 397 | error("getaddrinfo: no addrs"); |
370 | goto fail; | 398 | goto fail; |
371 | } | 399 | } |
372 | if (res->ai_addrlen > sizeof(bindaddr)) { | ||
373 | error("%s: addr doesn't fit", __func__); | ||
374 | goto fail; | ||
375 | } | ||
376 | memcpy(&bindaddr, res->ai_addr, res->ai_addrlen); | 400 | memcpy(&bindaddr, res->ai_addr, res->ai_addrlen); |
377 | bindaddrlen = res->ai_addrlen; | 401 | bindaddrlen = res->ai_addrlen; |
378 | } else if (options.bind_interface != NULL) { | 402 | } else if (options.bind_interface != NULL) { |
@@ -420,73 +444,6 @@ fail: | |||
420 | } | 444 | } |
421 | 445 | ||
422 | /* | 446 | /* |
423 | * Wait up to *timeoutp milliseconds for fd to be readable. Updates | ||
424 | * *timeoutp with time remaining. | ||
425 | * Returns 0 if fd ready or -1 on timeout or error (see errno). | ||
426 | */ | ||
427 | static int | ||
428 | waitrfd(int fd, int *timeoutp) | ||
429 | { | ||
430 | struct pollfd pfd; | ||
431 | struct timeval t_start; | ||
432 | int oerrno, r; | ||
433 | |||
434 | monotime_tv(&t_start); | ||
435 | pfd.fd = fd; | ||
436 | pfd.events = POLLIN; | ||
437 | for (; *timeoutp >= 0;) { | ||
438 | r = poll(&pfd, 1, *timeoutp); | ||
439 | oerrno = errno; | ||
440 | ms_subtract_diff(&t_start, timeoutp); | ||
441 | errno = oerrno; | ||
442 | if (r > 0) | ||
443 | return 0; | ||
444 | else if (r == -1 && errno != EAGAIN) | ||
445 | return -1; | ||
446 | else if (r == 0) | ||
447 | break; | ||
448 | } | ||
449 | /* timeout */ | ||
450 | errno = ETIMEDOUT; | ||
451 | return -1; | ||
452 | } | ||
453 | |||
454 | static int | ||
455 | timeout_connect(int sockfd, const struct sockaddr *serv_addr, | ||
456 | socklen_t addrlen, int *timeoutp) | ||
457 | { | ||
458 | int optval = 0; | ||
459 | socklen_t optlen = sizeof(optval); | ||
460 | |||
461 | /* No timeout: just do a blocking connect() */ | ||
462 | if (*timeoutp <= 0) | ||
463 | return connect(sockfd, serv_addr, addrlen); | ||
464 | |||
465 | set_nonblock(sockfd); | ||
466 | if (connect(sockfd, serv_addr, addrlen) == 0) { | ||
467 | /* Succeeded already? */ | ||
468 | unset_nonblock(sockfd); | ||
469 | return 0; | ||
470 | } else if (errno != EINPROGRESS) | ||
471 | return -1; | ||
472 | |||
473 | if (waitrfd(sockfd, timeoutp) == -1) | ||
474 | return -1; | ||
475 | |||
476 | /* Completed or failed */ | ||
477 | if (getsockopt(sockfd, SOL_SOCKET, SO_ERROR, &optval, &optlen) == -1) { | ||
478 | debug("getsockopt: %s", strerror(errno)); | ||
479 | return -1; | ||
480 | } | ||
481 | if (optval != 0) { | ||
482 | errno = optval; | ||
483 | return -1; | ||
484 | } | ||
485 | unset_nonblock(sockfd); | ||
486 | return 0; | ||
487 | } | ||
488 | |||
489 | /* | ||
490 | * Opens a TCP/IP connection to the remote server on the given host. | 447 | * Opens a TCP/IP connection to the remote server on the given host. |
491 | * The address of the remote host will be returned in hostaddr. | 448 | * The address of the remote host will be returned in hostaddr. |
492 | * If port is 0, the default port will be used. | 449 | * If port is 0, the default port will be used. |
@@ -500,7 +457,7 @@ ssh_connect_direct(struct ssh *ssh, const char *host, struct addrinfo *aitop, | |||
500 | struct sockaddr_storage *hostaddr, u_short port, int family, | 457 | struct sockaddr_storage *hostaddr, u_short port, int family, |
501 | int connection_attempts, int *timeout_ms, int want_keepalive) | 458 | int connection_attempts, int *timeout_ms, int want_keepalive) |
502 | { | 459 | { |
503 | int on = 1; | 460 | int on = 1, saved_timeout_ms = *timeout_ms; |
504 | int oerrno, sock = -1, attempt; | 461 | int oerrno, sock = -1, attempt; |
505 | char ntop[NI_MAXHOST], strport[NI_MAXSERV]; | 462 | char ntop[NI_MAXHOST], strport[NI_MAXSERV]; |
506 | struct addrinfo *ai; | 463 | struct addrinfo *ai; |
@@ -544,6 +501,7 @@ ssh_connect_direct(struct ssh *ssh, const char *host, struct addrinfo *aitop, | |||
544 | continue; | 501 | continue; |
545 | } | 502 | } |
546 | 503 | ||
504 | *timeout_ms = saved_timeout_ms; | ||
547 | if (timeout_connect(sock, ai->ai_addr, ai->ai_addrlen, | 505 | if (timeout_connect(sock, ai->ai_addr, ai->ai_addrlen, |
548 | timeout_ms) >= 0) { | 506 | timeout_ms) >= 0) { |
549 | /* Successful connection. */ | 507 | /* Successful connection. */ |
@@ -589,12 +547,20 @@ ssh_connect(struct ssh *ssh, const char *host, struct addrinfo *addrs, | |||
589 | struct sockaddr_storage *hostaddr, u_short port, int family, | 547 | struct sockaddr_storage *hostaddr, u_short port, int family, |
590 | int connection_attempts, int *timeout_ms, int want_keepalive) | 548 | int connection_attempts, int *timeout_ms, int want_keepalive) |
591 | { | 549 | { |
550 | int in, out; | ||
551 | |||
592 | if (options.proxy_command == NULL) { | 552 | if (options.proxy_command == NULL) { |
593 | return ssh_connect_direct(ssh, host, addrs, hostaddr, port, | 553 | return ssh_connect_direct(ssh, host, addrs, hostaddr, port, |
594 | family, connection_attempts, timeout_ms, want_keepalive); | 554 | family, connection_attempts, timeout_ms, want_keepalive); |
595 | } else if (strcmp(options.proxy_command, "-") == 0) { | 555 | } else if (strcmp(options.proxy_command, "-") == 0) { |
596 | if ((ssh_packet_set_connection(ssh, | 556 | if ((in = dup(STDIN_FILENO)) < 0 || |
597 | STDIN_FILENO, STDOUT_FILENO)) == NULL) | 557 | (out = dup(STDOUT_FILENO)) < 0) { |
558 | if (in >= 0) | ||
559 | close(in); | ||
560 | error("%s: dup() in/out failed", __func__); | ||
561 | return -1; /* ssh_packet_set_connection logs error */ | ||
562 | } | ||
563 | if ((ssh_packet_set_connection(ssh, in, out)) == NULL) | ||
598 | return -1; /* ssh_packet_set_connection logs error */ | 564 | return -1; /* ssh_packet_set_connection logs error */ |
599 | return 0; | 565 | return 0; |
600 | } else if (options.proxy_use_fdpass) { | 566 | } else if (options.proxy_use_fdpass) { |
@@ -604,128 +570,26 @@ ssh_connect(struct ssh *ssh, const char *host, struct addrinfo *addrs, | |||
604 | return ssh_proxy_connect(ssh, host, port, options.proxy_command); | 570 | return ssh_proxy_connect(ssh, host, port, options.proxy_command); |
605 | } | 571 | } |
606 | 572 | ||
607 | static void | ||
608 | send_client_banner(int connection_out, int minor1) | ||
609 | { | ||
610 | /* Send our own protocol version identification. */ | ||
611 | xasprintf(&client_version_string, "SSH-%d.%d-%.100s\r\n", | ||
612 | PROTOCOL_MAJOR_2, PROTOCOL_MINOR_2, SSH_VERSION); | ||
613 | if (atomicio(vwrite, connection_out, client_version_string, | ||
614 | strlen(client_version_string)) != strlen(client_version_string)) | ||
615 | fatal("write: %.100s", strerror(errno)); | ||
616 | chop(client_version_string); | ||
617 | debug("Local version string %.100s", client_version_string); | ||
618 | } | ||
619 | |||
620 | /* | ||
621 | * Waits for the server identification string, and sends our own | ||
622 | * identification string. | ||
623 | */ | ||
624 | void | ||
625 | ssh_exchange_identification(int timeout_ms) | ||
626 | { | ||
627 | char buf[256], remote_version[256]; /* must be same size! */ | ||
628 | int remote_major, remote_minor, mismatch; | ||
629 | int connection_in = packet_get_connection_in(); | ||
630 | int connection_out = packet_get_connection_out(); | ||
631 | u_int i, n; | ||
632 | size_t len; | ||
633 | int rc; | ||
634 | |||
635 | send_client_banner(connection_out, 0); | ||
636 | |||
637 | /* Read other side's version identification. */ | ||
638 | for (n = 0;;) { | ||
639 | for (i = 0; i < sizeof(buf) - 1; i++) { | ||
640 | if (timeout_ms > 0) { | ||
641 | rc = waitrfd(connection_in, &timeout_ms); | ||
642 | if (rc == -1 && errno == ETIMEDOUT) { | ||
643 | fatal("Connection timed out during " | ||
644 | "banner exchange"); | ||
645 | } else if (rc == -1) { | ||
646 | fatal("%s: %s", | ||
647 | __func__, strerror(errno)); | ||
648 | } | ||
649 | } | ||
650 | |||
651 | len = atomicio(read, connection_in, &buf[i], 1); | ||
652 | if (len != 1 && errno == EPIPE) | ||
653 | fatal("ssh_exchange_identification: " | ||
654 | "Connection closed by remote host"); | ||
655 | else if (len != 1) | ||
656 | fatal("ssh_exchange_identification: " | ||
657 | "read: %.100s", strerror(errno)); | ||
658 | if (buf[i] == '\r') { | ||
659 | buf[i] = '\n'; | ||
660 | buf[i + 1] = 0; | ||
661 | continue; /**XXX wait for \n */ | ||
662 | } | ||
663 | if (buf[i] == '\n') { | ||
664 | buf[i + 1] = 0; | ||
665 | break; | ||
666 | } | ||
667 | if (++n > 65536) | ||
668 | fatal("ssh_exchange_identification: " | ||
669 | "No banner received"); | ||
670 | } | ||
671 | buf[sizeof(buf) - 1] = 0; | ||
672 | if (strncmp(buf, "SSH-", 4) == 0) | ||
673 | break; | ||
674 | debug("ssh_exchange_identification: %s", buf); | ||
675 | } | ||
676 | server_version_string = xstrdup(buf); | ||
677 | |||
678 | /* | ||
679 | * Check that the versions match. In future this might accept | ||
680 | * several versions and set appropriate flags to handle them. | ||
681 | */ | ||
682 | if (sscanf(server_version_string, "SSH-%d.%d-%[^\n]\n", | ||
683 | &remote_major, &remote_minor, remote_version) != 3) | ||
684 | fatal("Bad remote protocol version identification: '%.100s'", buf); | ||
685 | debug("Remote protocol version %d.%d, remote software version %.100s", | ||
686 | remote_major, remote_minor, remote_version); | ||
687 | |||
688 | active_state->compat = compat_datafellows(remote_version); | ||
689 | mismatch = 0; | ||
690 | |||
691 | switch (remote_major) { | ||
692 | case 2: | ||
693 | break; | ||
694 | case 1: | ||
695 | if (remote_minor != 99) | ||
696 | mismatch = 1; | ||
697 | break; | ||
698 | default: | ||
699 | mismatch = 1; | ||
700 | break; | ||
701 | } | ||
702 | if (mismatch) | ||
703 | fatal("Protocol major versions differ: %d vs. %d", | ||
704 | PROTOCOL_MAJOR_2, remote_major); | ||
705 | if ((datafellows & SSH_BUG_RSASIGMD5) != 0) | ||
706 | logit("Server version \"%.100s\" uses unsafe RSA signature " | ||
707 | "scheme; disabling use of RSA keys", remote_version); | ||
708 | chop(server_version_string); | ||
709 | } | ||
710 | |||
711 | /* defaults to 'no' */ | 573 | /* defaults to 'no' */ |
712 | static int | 574 | static int |
713 | confirm(const char *prompt) | 575 | confirm(const char *prompt, const char *fingerprint) |
714 | { | 576 | { |
715 | const char *msg, *again = "Please type 'yes' or 'no': "; | 577 | const char *msg, *again = "Please type 'yes' or 'no': "; |
578 | const char *again_fp = "Please type 'yes', 'no' or the fingerprint: "; | ||
716 | char *p; | 579 | char *p; |
717 | int ret = -1; | 580 | int ret = -1; |
718 | 581 | ||
719 | if (options.batch_mode) | 582 | if (options.batch_mode) |
720 | return 0; | 583 | return 0; |
721 | for (msg = prompt;;msg = again) { | 584 | for (msg = prompt;;msg = fingerprint ? again_fp : again) { |
722 | p = read_passphrase(msg, RP_ECHO); | 585 | p = read_passphrase(msg, RP_ECHO); |
723 | if (p == NULL) | 586 | if (p == NULL) |
724 | return 0; | 587 | return 0; |
725 | p[strcspn(p, "\n")] = '\0'; | 588 | p[strcspn(p, "\n")] = '\0'; |
726 | if (p[0] == '\0' || strcasecmp(p, "no") == 0) | 589 | if (p[0] == '\0' || strcasecmp(p, "no") == 0) |
727 | ret = 0; | 590 | ret = 0; |
728 | else if (strcasecmp(p, "yes") == 0) | 591 | else if (strcasecmp(p, "yes") == 0 || (fingerprint != NULL && |
592 | strcasecmp(p, fingerprint) == 0)) | ||
729 | ret = 1; | 593 | ret = 1; |
730 | free(p); | 594 | free(p); |
731 | if (ret != -1) | 595 | if (ret != -1) |
@@ -853,7 +717,7 @@ check_host_key(char *hostname, struct sockaddr *hostaddr, u_short port, | |||
853 | char msg[1024]; | 717 | char msg[1024]; |
854 | const char *type; | 718 | const char *type; |
855 | const struct hostkey_entry *host_found, *ip_found; | 719 | const struct hostkey_entry *host_found, *ip_found; |
856 | int len, cancelled_forwarding = 0; | 720 | int len, cancelled_forwarding = 0, confirmed; |
857 | int local = sockaddr_is_local(hostaddr); | 721 | int local = sockaddr_is_local(hostaddr); |
858 | int r, want_cert = sshkey_is_cert(host_key), host_ip_differ = 0; | 722 | int r, want_cert = sshkey_is_cert(host_key), host_ip_differ = 0; |
859 | int hostkey_trusted = 0; /* Known or explicitly accepted by user */ | 723 | int hostkey_trusted = 0; /* Known or explicitly accepted by user */ |
@@ -1028,14 +892,15 @@ check_host_key(char *hostname, struct sockaddr *hostaddr, u_short port, | |||
1028 | "established%s\n" | 892 | "established%s\n" |
1029 | "%s key fingerprint is %s.%s%s\n%s" | 893 | "%s key fingerprint is %s.%s%s\n%s" |
1030 | "Are you sure you want to continue connecting " | 894 | "Are you sure you want to continue connecting " |
1031 | "(yes/no)? ", | 895 | "(yes/no/[fingerprint])? ", |
1032 | host, ip, msg1, type, fp, | 896 | host, ip, msg1, type, fp, |
1033 | options.visual_host_key ? "\n" : "", | 897 | options.visual_host_key ? "\n" : "", |
1034 | options.visual_host_key ? ra : "", | 898 | options.visual_host_key ? ra : "", |
1035 | msg2); | 899 | msg2); |
1036 | free(ra); | 900 | free(ra); |
901 | confirmed = confirm(msg, fp); | ||
1037 | free(fp); | 902 | free(fp); |
1038 | if (!confirm(msg)) | 903 | if (!confirmed) |
1039 | goto fail; | 904 | goto fail; |
1040 | hostkey_trusted = 1; /* user explicitly confirmed */ | 905 | hostkey_trusted = 1; /* user explicitly confirmed */ |
1041 | } | 906 | } |
@@ -1229,7 +1094,7 @@ check_host_key(char *hostname, struct sockaddr *hostaddr, u_short port, | |||
1229 | SSH_STRICT_HOSTKEY_ASK) { | 1094 | SSH_STRICT_HOSTKEY_ASK) { |
1230 | strlcat(msg, "\nAre you sure you want " | 1095 | strlcat(msg, "\nAre you sure you want " |
1231 | "to continue connecting (yes/no)? ", sizeof(msg)); | 1096 | "to continue connecting (yes/no)? ", sizeof(msg)); |
1232 | if (!confirm(msg)) | 1097 | if (!confirm(msg, NULL)) |
1233 | goto fail; | 1098 | goto fail; |
1234 | } else if (options.strict_host_key_checking != | 1099 | } else if (options.strict_host_key_checking != |
1235 | SSH_STRICT_HOSTKEY_OFF) { | 1100 | SSH_STRICT_HOSTKEY_OFF) { |
@@ -1401,7 +1266,7 @@ out: | |||
1401 | * This function does not require super-user privileges. | 1266 | * This function does not require super-user privileges. |
1402 | */ | 1267 | */ |
1403 | void | 1268 | void |
1404 | ssh_login(Sensitive *sensitive, const char *orighost, | 1269 | ssh_login(struct ssh *ssh, Sensitive *sensitive, const char *orighost, |
1405 | struct sockaddr *hostaddr, u_short port, struct passwd *pw, int timeout_ms) | 1270 | struct sockaddr *hostaddr, u_short port, struct passwd *pw, int timeout_ms) |
1406 | { | 1271 | { |
1407 | char *host; | 1272 | char *host; |
@@ -1415,37 +1280,20 @@ ssh_login(Sensitive *sensitive, const char *orighost, | |||
1415 | lowercase(host); | 1280 | lowercase(host); |
1416 | 1281 | ||
1417 | /* Exchange protocol version identification strings with the server. */ | 1282 | /* Exchange protocol version identification strings with the server. */ |
1418 | ssh_exchange_identification(timeout_ms); | 1283 | if (kex_exchange_identification(ssh, timeout_ms, NULL) != 0) |
1284 | cleanup_exit(255); /* error already logged */ | ||
1419 | 1285 | ||
1420 | /* Put the connection into non-blocking mode. */ | 1286 | /* Put the connection into non-blocking mode. */ |
1421 | packet_set_nonblocking(); | 1287 | ssh_packet_set_nonblocking(ssh); |
1422 | 1288 | ||
1423 | /* key exchange */ | 1289 | /* key exchange */ |
1424 | /* authenticate user */ | 1290 | /* authenticate user */ |
1425 | debug("Authenticating to %s:%d as '%s'", host, port, server_user); | 1291 | debug("Authenticating to %s:%d as '%s'", host, port, server_user); |
1426 | ssh_kex2(host, hostaddr, port); | 1292 | ssh_kex2(ssh, host, hostaddr, port); |
1427 | ssh_userauth2(local_user, server_user, host, sensitive); | 1293 | ssh_userauth2(ssh, local_user, server_user, host, sensitive); |
1428 | free(local_user); | 1294 | free(local_user); |
1429 | } | 1295 | } |
1430 | 1296 | ||
1431 | void | ||
1432 | ssh_put_password(char *password) | ||
1433 | { | ||
1434 | int size; | ||
1435 | char *padded; | ||
1436 | |||
1437 | if (datafellows & SSH_BUG_PASSWORDPAD) { | ||
1438 | packet_put_cstring(password); | ||
1439 | return; | ||
1440 | } | ||
1441 | size = ROUNDUP(strlen(password) + 1, 32); | ||
1442 | padded = xcalloc(1, size); | ||
1443 | strlcpy(padded, password, size); | ||
1444 | packet_put_string(padded, size); | ||
1445 | explicit_bzero(padded, size); | ||
1446 | free(padded); | ||
1447 | } | ||
1448 | |||
1449 | /* print all known host keys for a given host, but skip keys of given type */ | 1297 | /* print all known host keys for a given host, but skip keys of given type */ |
1450 | static int | 1298 | static int |
1451 | show_other_keys(struct hostkeys *hostkeys, struct sshkey *key) | 1299 | show_other_keys(struct hostkeys *hostkeys, struct sshkey *key) |