1 /* $OpenBSD: sshconnect.c,v 1.287 2017/09/14 04:32:21 djm Exp $ */
3 * Author: Tatu Ylonen <ylo@cs.hut.fi>
4 * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
6 * Code to connect to a remote host, and to perform the client side of the
7 * login (authentication) dialog.
9 * As far as I am concerned, the code I have written for this software
10 * can be used freely for any purpose. Any derived versions of this
11 * software must be clearly marked as such, and if the derived work is
12 * incompatible with the protocol description in the RFC file, it must be
13 * called by a name other than "ssh" or "Secure Shell".
18 #include <sys/types.h>
21 #include <sys/socket.h>
22 #ifdef HAVE_SYS_TIME_H
23 # include <sys/time.h>
26 #include <netinet/in.h>
27 #include <arpa/inet.h>
57 #include "sshconnect.h"
64 #include "monitor_fdpass.h"
71 char *client_version_string
= NULL
;
72 char *server_version_string
= NULL
;
73 struct sshkey
*previous_host_key
= NULL
;
75 static int matching_host_key_dns
= 0;
77 static pid_t proxy_command_pid
= 0;
80 extern Options options
;
81 extern char *__progname
;
82 extern uid_t original_real_uid
;
83 extern uid_t original_effective_uid
;
85 static int show_other_keys(struct hostkeys
*, struct sshkey
*);
86 static void warn_changed_key(struct sshkey
*);
88 /* Expand a proxy command */
90 expand_proxy_command(const char *proxy_command
, const char *user
,
91 const char *host
, int port
)
93 char *tmp
, *ret
, strport
[NI_MAXSERV
];
95 snprintf(strport
, sizeof strport
, "%d", port
);
96 xasprintf(&tmp
, "exec %s", proxy_command
);
97 ret
= percent_expand(tmp
, "h", host
, "p", strport
,
98 "r", options
.user
, (char *)NULL
);
104 * Connect to the given ssh server using a proxy command that passes a
105 * a connected fd back to us.
108 ssh_proxy_fdpass_connect(struct ssh
*ssh
, const char *host
, u_short port
,
109 const char *proxy_command
)
111 char *command_string
;
116 if ((shell
= getenv("SHELL")) == NULL
)
117 shell
= _PATH_BSHELL
;
119 if (socketpair(AF_UNIX
, SOCK_STREAM
, 0, sp
) < 0)
120 fatal("Could not create socketpair to communicate with "
121 "proxy dialer: %.100s", strerror(errno
));
123 command_string
= expand_proxy_command(proxy_command
, options
.user
,
125 debug("Executing proxy dialer command: %.500s", command_string
);
127 /* Fork and execute the proxy command. */
128 if ((pid
= fork()) == 0) {
131 /* Child. Permanently give up superuser privileges. */
132 permanently_drop_suid(original_real_uid
);
135 /* Redirect stdin and stdout. */
137 if (dup2(sp
[0], 0) < 0)
138 perror("dup2 stdin");
141 if (dup2(sp
[0], 1) < 0)
142 perror("dup2 stdout");
148 * Stderr is left as it is so that error messages get
149 * printed on the user's terminal.
153 argv
[2] = command_string
;
157 * Execute the proxy command.
158 * Note that we gave up any extra privileges above.
160 execv(argv
[0], argv
);
166 fatal("fork failed: %.100s", strerror(errno
));
168 free(command_string
);
170 if ((sock
= mm_receive_fd(sp
[1])) == -1)
171 fatal("proxy dialer did not pass back a connection");
174 while (waitpid(pid
, NULL
, 0) == -1)
176 fatal("Couldn't wait for child: %s", strerror(errno
));
178 /* Set the connection file descriptors. */
179 if (ssh_packet_set_connection(ssh
, sock
, sock
) == NULL
)
180 return -1; /* ssh_packet_set_connection logs error */
186 * Connect to the given ssh server using a proxy command.
189 ssh_proxy_connect(struct ssh
*ssh
, const char *host
, u_short port
,
190 const char *proxy_command
)
192 char *command_string
;
197 if ((shell
= getenv("SHELL")) == NULL
|| *shell
== '\0')
198 shell
= _PATH_BSHELL
;
200 /* Create pipes for communicating with the proxy. */
201 if (pipe(pin
) < 0 || pipe(pout
) < 0)
202 fatal("Could not create pipes to communicate with the proxy: %.100s",
205 command_string
= expand_proxy_command(proxy_command
, options
.user
,
207 debug("Executing proxy command: %.500s", command_string
);
209 /* Fork and execute the proxy command. */
210 if ((pid
= fork()) == 0) {
213 /* Child. Permanently give up superuser privileges. */
214 permanently_drop_suid(original_real_uid
);
216 /* Redirect stdin and stdout. */
219 if (dup2(pin
[0], 0) < 0)
220 perror("dup2 stdin");
224 if (dup2(pout
[1], 1) < 0)
225 perror("dup2 stdout");
226 /* Cannot be 1 because pin allocated two descriptors. */
229 /* Stderr is left as it is so that error messages get
230 printed on the user's terminal. */
233 argv
[2] = command_string
;
236 /* Execute the proxy command. Note that we gave up any
237 extra privileges above. */
238 signal(SIGPIPE
, SIG_DFL
);
239 execv(argv
[0], argv
);
245 fatal("fork failed: %.100s", strerror(errno
));
247 proxy_command_pid
= pid
; /* save pid to clean up later */
249 /* Close child side of the descriptors. */
253 /* Free the command name. */
254 free(command_string
);
256 /* Set the connection file descriptors. */
257 if (ssh_packet_set_connection(ssh
, pout
[0], pin
[1]) == NULL
)
258 return -1; /* ssh_packet_set_connection logs error */
264 ssh_kill_proxy_command(void)
267 * Send SIGHUP to proxy command if used. We don't wait() in
268 * case it hangs and instead rely on init to reap the child
270 if (proxy_command_pid
> 1)
271 kill(proxy_command_pid
, SIGHUP
);
275 * Creates a (possibly privileged) socket for use as the ssh connection.
278 ssh_create_socket(int privileged
, struct addrinfo
*ai
)
281 struct addrinfo hints
, *res
= NULL
;
283 sock
= socket(ai
->ai_family
, ai
->ai_socktype
, ai
->ai_protocol
);
285 error("socket: %s", strerror(errno
));
288 fcntl(sock
, F_SETFD
, FD_CLOEXEC
);
290 /* Bind the socket to an alternative local IP address */
291 if (options
.bind_address
== NULL
&& !privileged
)
294 if (options
.bind_address
) {
295 memset(&hints
, 0, sizeof(hints
));
296 hints
.ai_family
= ai
->ai_family
;
297 hints
.ai_socktype
= ai
->ai_socktype
;
298 hints
.ai_protocol
= ai
->ai_protocol
;
299 hints
.ai_flags
= AI_PASSIVE
;
300 gaierr
= getaddrinfo(options
.bind_address
, NULL
, &hints
, &res
);
302 error("getaddrinfo: %s: %s", options
.bind_address
,
303 ssh_gai_strerror(gaierr
));
309 * If we are running as root and want to connect to a privileged
310 * port, bind our own socket to a privileged port.
314 r
= bindresvport_sa(sock
, res
? res
->ai_addr
: NULL
);
317 error("bindresvport_sa: af=%d %s", ai
->ai_family
,
322 if (bind(sock
, res
->ai_addr
, res
->ai_addrlen
) < 0) {
323 error("bind: %s: %s", options
.bind_address
,
337 * Wait up to *timeoutp milliseconds for fd to be readable. Updates
338 * *timeoutp with time remaining.
339 * Returns 0 if fd ready or -1 on timeout or error (see errno).
342 waitrfd(int fd
, int *timeoutp
)
345 struct timeval t_start
;
348 gettimeofday(&t_start
, NULL
);
351 for (; *timeoutp
>= 0;) {
352 r
= poll(&pfd
, 1, *timeoutp
);
354 ms_subtract_diff(&t_start
, timeoutp
);
358 else if (r
== -1 && errno
!= EAGAIN
)
369 timeout_connect(int sockfd
, const struct sockaddr
*serv_addr
,
370 socklen_t addrlen
, int *timeoutp
)
373 socklen_t optlen
= sizeof(optval
);
375 /* No timeout: just do a blocking connect() */
377 return connect(sockfd
, serv_addr
, addrlen
);
379 set_nonblock(sockfd
);
380 if (connect(sockfd
, serv_addr
, addrlen
) == 0) {
381 /* Succeeded already? */
382 unset_nonblock(sockfd
);
384 } else if (errno
!= EINPROGRESS
)
387 if (waitrfd(sockfd
, timeoutp
) == -1)
390 /* Completed or failed */
391 if (getsockopt(sockfd
, SOL_SOCKET
, SO_ERROR
, &optval
, &optlen
) == -1) {
392 debug("getsockopt: %s", strerror(errno
));
399 unset_nonblock(sockfd
);
404 * Opens a TCP/IP connection to the remote server on the given host.
405 * The address of the remote host will be returned in hostaddr.
406 * If port is 0, the default port will be used. If needpriv is true,
407 * a privileged port will be allocated to make the connection.
408 * This requires super-user privileges if needpriv is true.
409 * Connection_attempts specifies the maximum number of tries (one per
410 * second). If proxy_command is non-NULL, it specifies the command (with %h
411 * and %p substituted for host and port, respectively) to use to contact
415 ssh_connect_direct(struct ssh
*ssh
, const char *host
, struct addrinfo
*aitop
,
416 struct sockaddr_storage
*hostaddr
, u_short port
, int family
,
417 int connection_attempts
, int *timeout_ms
, int want_keepalive
, int needpriv
)
420 int sock
= -1, attempt
;
421 char ntop
[NI_MAXHOST
], strport
[NI_MAXSERV
];
424 debug2("%s: needpriv %d", __func__
, needpriv
);
425 memset(ntop
, 0, sizeof(ntop
));
426 memset(strport
, 0, sizeof(strport
));
428 for (attempt
= 0; attempt
< connection_attempts
; attempt
++) {
430 /* Sleep a moment before retrying. */
432 debug("Trying again...");
435 * Loop through addresses for this host, and try each one in
436 * sequence until the connection succeeds.
438 for (ai
= aitop
; ai
; ai
= ai
->ai_next
) {
439 if (ai
->ai_family
!= AF_INET
&&
440 ai
->ai_family
!= AF_INET6
)
442 if (getnameinfo(ai
->ai_addr
, ai
->ai_addrlen
,
443 ntop
, sizeof(ntop
), strport
, sizeof(strport
),
444 NI_NUMERICHOST
|NI_NUMERICSERV
) != 0) {
445 error("%s: getnameinfo failed", __func__
);
448 debug("Connecting to %.200s [%.100s] port %s.",
449 host
, ntop
, strport
);
451 /* Create a socket for connecting. */
452 sock
= ssh_create_socket(needpriv
, ai
);
454 /* Any error is already output */
457 if (timeout_connect(sock
, ai
->ai_addr
, ai
->ai_addrlen
,
459 /* Successful connection. */
460 memcpy(hostaddr
, ai
->ai_addr
, ai
->ai_addrlen
);
463 debug("connect to address %s port %s: %s",
464 ntop
, strport
, strerror(errno
));
470 break; /* Successful connection. */
473 /* Return failure if we didn't get a successful connection. */
475 error("ssh: connect to host %s port %s: %s",
476 host
, strport
, strerror(errno
));
480 debug("Connection established.");
482 /* Set SO_KEEPALIVE if requested. */
483 if (want_keepalive
&&
484 setsockopt(sock
, SOL_SOCKET
, SO_KEEPALIVE
, (void *)&on
,
486 error("setsockopt SO_KEEPALIVE: %.100s", strerror(errno
));
488 /* Set the connection. */
489 if (ssh_packet_set_connection(ssh
, sock
, sock
) == NULL
)
490 return -1; /* ssh_packet_set_connection logs error */
496 ssh_connect(struct ssh
*ssh
, const char *host
, struct addrinfo
*addrs
,
497 struct sockaddr_storage
*hostaddr
, u_short port
, int family
,
498 int connection_attempts
, int *timeout_ms
, int want_keepalive
, int needpriv
)
500 if (options
.proxy_command
== NULL
) {
501 return ssh_connect_direct(ssh
, host
, addrs
, hostaddr
, port
,
502 family
, connection_attempts
, timeout_ms
, want_keepalive
,
504 } else if (strcmp(options
.proxy_command
, "-") == 0) {
505 if ((ssh_packet_set_connection(ssh
,
506 STDIN_FILENO
, STDOUT_FILENO
)) == NULL
)
507 return -1; /* ssh_packet_set_connection logs error */
509 } else if (options
.proxy_use_fdpass
) {
510 return ssh_proxy_fdpass_connect(ssh
, host
, port
,
511 options
.proxy_command
);
513 return ssh_proxy_connect(ssh
, host
, port
, options
.proxy_command
);
517 send_client_banner(int connection_out
, int minor1
)
519 /* Send our own protocol version identification. */
520 xasprintf(&client_version_string
, "SSH-%d.%d-%.100s\r\n",
521 PROTOCOL_MAJOR_2
, PROTOCOL_MINOR_2
, SSH_VERSION
);
522 if (atomicio(vwrite
, connection_out
, client_version_string
,
523 strlen(client_version_string
)) != strlen(client_version_string
))
524 fatal("write: %.100s", strerror(errno
));
525 chop(client_version_string
);
526 debug("Local version string %.100s", client_version_string
);
530 * Waits for the server identification string, and sends our own
531 * identification string.
534 ssh_exchange_identification(int timeout_ms
)
536 char buf
[256], remote_version
[256]; /* must be same size! */
537 int remote_major
, remote_minor
, mismatch
;
538 int connection_in
= packet_get_connection_in();
539 int connection_out
= packet_get_connection_out();
544 send_client_banner(connection_out
, 0);
546 /* Read other side's version identification. */
548 for (i
= 0; i
< sizeof(buf
) - 1; i
++) {
549 if (timeout_ms
> 0) {
550 rc
= waitrfd(connection_in
, &timeout_ms
);
551 if (rc
== -1 && errno
== ETIMEDOUT
) {
552 fatal("Connection timed out during "
554 } else if (rc
== -1) {
556 __func__
, strerror(errno
));
560 len
= atomicio(read
, connection_in
, &buf
[i
], 1);
561 if (len
!= 1 && errno
== EPIPE
)
562 fatal("ssh_exchange_identification: "
563 "Connection closed by remote host");
565 fatal("ssh_exchange_identification: "
566 "read: %.100s", strerror(errno
));
567 if (buf
[i
] == '\r') {
570 continue; /**XXX wait for \n */
572 if (buf
[i
] == '\n') {
577 fatal("ssh_exchange_identification: "
578 "No banner received");
580 buf
[sizeof(buf
) - 1] = 0;
581 if (strncmp(buf
, "SSH-", 4) == 0)
583 debug("ssh_exchange_identification: %s", buf
);
585 server_version_string
= xstrdup(buf
);
588 * Check that the versions match. In future this might accept
589 * several versions and set appropriate flags to handle them.
591 if (sscanf(server_version_string
, "SSH-%d.%d-%[^\n]\n",
592 &remote_major
, &remote_minor
, remote_version
) != 3)
593 fatal("Bad remote protocol version identification: '%.100s'", buf
);
594 debug("Remote protocol version %d.%d, remote software version %.100s",
595 remote_major
, remote_minor
, remote_version
);
597 active_state
->compat
= compat_datafellows(remote_version
);
600 switch (remote_major
) {
604 if (remote_minor
!= 99)
612 fatal("Protocol major versions differ: %d vs. %d",
613 PROTOCOL_MAJOR_2
, remote_major
);
614 if ((datafellows
& SSH_BUG_DERIVEKEY
) != 0)
615 fatal("Server version \"%.100s\" uses unsafe key agreement; "
616 "refusing connection", remote_version
);
617 if ((datafellows
& SSH_BUG_RSASIGMD5
) != 0)
618 logit("Server version \"%.100s\" uses unsafe RSA signature "
619 "scheme; disabling use of RSA keys", remote_version
);
620 chop(server_version_string
);
623 /* defaults to 'no' */
625 confirm(const char *prompt
)
627 const char *msg
, *again
= "Please type 'yes' or 'no': ";
631 if (options
.batch_mode
)
633 for (msg
= prompt
;;msg
= again
) {
634 p
= read_passphrase(msg
, RP_ECHO
);
636 (p
[0] == '\0') || (p
[0] == '\n') ||
637 strncasecmp(p
, "no", 2) == 0)
639 if (p
&& strncasecmp(p
, "yes", 3) == 0)
648 check_host_cert(const char *host
, const struct sshkey
*host_key
)
652 if (key_cert_check_authority(host_key
, 1, 0, host
, &reason
) != 0) {
656 if (buffer_len(host_key
->cert
->critical
) != 0) {
657 error("Certificate for %s contains unsupported "
658 "critical options(s)", host
);
665 sockaddr_is_local(struct sockaddr
*hostaddr
)
667 switch (hostaddr
->sa_family
) {
669 return (ntohl(((struct sockaddr_in
*)hostaddr
)->
670 sin_addr
.s_addr
) >> 24) == IN_LOOPBACKNET
;
672 return IN6_IS_ADDR_LOOPBACK(
673 &(((struct sockaddr_in6
*)hostaddr
)->sin6_addr
));
680 * Prepare the hostname and ip address strings that are used to lookup
681 * host keys in known_hosts files. These may have a port number appended.
684 get_hostfile_hostname_ipaddr(char *hostname
, struct sockaddr
*hostaddr
,
685 u_short port
, char **hostfile_hostname
, char **hostfile_ipaddr
)
687 char ntop
[NI_MAXHOST
];
690 switch (hostaddr
== NULL
? -1 : hostaddr
->sa_family
) {
695 addrlen
= sizeof(struct sockaddr_in
);
698 addrlen
= sizeof(struct sockaddr_in6
);
701 addrlen
= sizeof(struct sockaddr
);
706 * We don't have the remote ip-address for connections
707 * using a proxy command
709 if (hostfile_ipaddr
!= NULL
) {
710 if (options
.proxy_command
== NULL
) {
711 if (getnameinfo(hostaddr
, addrlen
,
712 ntop
, sizeof(ntop
), NULL
, 0, NI_NUMERICHOST
) != 0)
713 fatal("%s: getnameinfo failed", __func__
);
714 *hostfile_ipaddr
= put_host_port(ntop
, port
);
716 *hostfile_ipaddr
= xstrdup("<no hostip for proxy "
722 * Allow the user to record the key under a different name or
723 * differentiate a non-standard port. This is useful for ssh
724 * tunneling over forwarded connections or if you run multiple
725 * sshd's on different ports on the same machine.
727 if (hostfile_hostname
!= NULL
) {
728 if (options
.host_key_alias
!= NULL
) {
729 *hostfile_hostname
= xstrdup(options
.host_key_alias
);
730 debug("using hostkeyalias: %s", *hostfile_hostname
);
732 *hostfile_hostname
= put_host_port(hostname
, port
);
738 * check whether the supplied host key is valid, return -1 if the key
739 * is not valid. user_hostfile[0] will not be updated if 'readonly' is true.
745 check_host_key(char *hostname
, struct sockaddr
*hostaddr
, u_short port
,
746 struct sshkey
*host_key
, int readonly
,
747 char **user_hostfiles
, u_int num_user_hostfiles
,
748 char **system_hostfiles
, u_int num_system_hostfiles
)
750 HostStatus host_status
;
751 HostStatus ip_status
;
752 struct sshkey
*raw_key
= NULL
;
753 char *ip
= NULL
, *host
= NULL
;
754 char hostline
[1000], *hostp
, *fp
, *ra
;
757 const struct hostkey_entry
*host_found
, *ip_found
;
758 int len
, cancelled_forwarding
= 0;
759 int local
= sockaddr_is_local(hostaddr
);
760 int r
, want_cert
= sshkey_is_cert(host_key
), host_ip_differ
= 0;
761 int hostkey_trusted
= 0; /* Known or explicitly accepted by user */
762 struct hostkeys
*host_hostkeys
, *ip_hostkeys
;
766 * Force accepting of the host key for loopback/localhost. The
767 * problem is that if the home directory is NFS-mounted to multiple
768 * machines, localhost will refer to a different machine in each of
769 * them, and the user will get bogus HOST_CHANGED warnings. This
770 * essentially disables host authentication for localhost; however,
771 * this is probably not a real problem.
773 if (options
.no_host_authentication_for_localhost
== 1 && local
&&
774 options
.host_key_alias
== NULL
) {
775 debug("Forcing accepting of host key for "
776 "loopback/localhost.");
781 * Prepare the hostname and address strings used for hostkey lookup.
782 * In some cases, these will have a port number appended.
784 get_hostfile_hostname_ipaddr(hostname
, hostaddr
, port
, &host
, &ip
);
787 * Turn off check_host_ip if the connection is to localhost, via proxy
788 * command or if we don't have a hostname to compare with
790 if (options
.check_host_ip
&& (local
||
791 strcmp(hostname
, ip
) == 0 || options
.proxy_command
!= NULL
))
792 options
.check_host_ip
= 0;
794 host_hostkeys
= init_hostkeys();
795 for (i
= 0; i
< num_user_hostfiles
; i
++)
796 load_hostkeys(host_hostkeys
, host
, user_hostfiles
[i
]);
797 for (i
= 0; i
< num_system_hostfiles
; i
++)
798 load_hostkeys(host_hostkeys
, host
, system_hostfiles
[i
]);
801 if (!want_cert
&& options
.check_host_ip
) {
802 ip_hostkeys
= init_hostkeys();
803 for (i
= 0; i
< num_user_hostfiles
; i
++)
804 load_hostkeys(ip_hostkeys
, ip
, user_hostfiles
[i
]);
805 for (i
= 0; i
< num_system_hostfiles
; i
++)
806 load_hostkeys(ip_hostkeys
, ip
, system_hostfiles
[i
]);
810 /* Reload these as they may have changed on cert->key downgrade */
811 want_cert
= sshkey_is_cert(host_key
);
812 type
= sshkey_type(host_key
);
815 * Check if the host key is present in the user's list of known
816 * hosts or in the systemwide list.
818 host_status
= check_key_in_hostkeys(host_hostkeys
, host_key
,
822 * Also perform check for the ip address, skip the check if we are
823 * localhost, looking for a certificate, or the hostname was an ip
824 * address to begin with.
826 if (!want_cert
&& ip_hostkeys
!= NULL
) {
827 ip_status
= check_key_in_hostkeys(ip_hostkeys
, host_key
,
829 if (host_status
== HOST_CHANGED
&&
830 (ip_status
!= HOST_CHANGED
||
832 !sshkey_equal(ip_found
->key
, host_found
->key
))))
835 ip_status
= host_status
;
837 switch (host_status
) {
839 /* The host is known and the key matches. */
840 debug("Host '%.200s' is known and matches the %s host %s.",
841 host
, type
, want_cert
? "certificate" : "key");
842 debug("Found %s in %s:%lu", want_cert
? "CA key" : "key",
843 host_found
->file
, host_found
->line
);
845 !check_host_cert(options
.host_key_alias
== NULL
?
846 hostname
: options
.host_key_alias
, host_key
))
848 if (options
.check_host_ip
&& ip_status
== HOST_NEW
) {
849 if (readonly
|| want_cert
)
850 logit("%s host key for IP address "
851 "'%.128s' not in list of known hosts.",
853 else if (!add_host_to_hostfile(user_hostfiles
[0], ip
,
854 host_key
, options
.hash_known_hosts
))
855 logit("Failed to add the %s host key for IP "
856 "address '%.128s' to the list of known "
857 "hosts (%.500s).", type
, ip
,
860 logit("Warning: Permanently added the %s host "
861 "key for IP address '%.128s' to the list "
862 "of known hosts.", type
, ip
);
863 } else if (options
.visual_host_key
) {
864 fp
= sshkey_fingerprint(host_key
,
865 options
.fingerprint_hash
, SSH_FP_DEFAULT
);
866 ra
= sshkey_fingerprint(host_key
,
867 options
.fingerprint_hash
, SSH_FP_RANDOMART
);
868 if (fp
== NULL
|| ra
== NULL
)
869 fatal("%s: sshkey_fingerprint fail", __func__
);
870 logit("Host key fingerprint is %s\n%s", fp
, ra
);
877 if (options
.host_key_alias
== NULL
&& port
!= 0 &&
878 port
!= SSH_DEFAULT_PORT
) {
879 debug("checking without port identifier");
880 if (check_host_key(hostname
, hostaddr
, 0, host_key
,
881 ROQUIET
, user_hostfiles
, num_user_hostfiles
,
882 system_hostfiles
, num_system_hostfiles
) == 0) {
883 debug("found matching key w/out port");
887 if (readonly
|| want_cert
)
889 /* The host is new. */
890 if (options
.strict_host_key_checking
==
891 SSH_STRICT_HOSTKEY_YES
) {
893 * User has requested strict host key checking. We
894 * will not add the host key automatically. The only
895 * alternative left is to abort.
897 error("No %s host key is known for %.200s and you "
898 "have requested strict checking.", type
, host
);
900 } else if (options
.strict_host_key_checking
==
901 SSH_STRICT_HOSTKEY_ASK
) {
902 char msg1
[1024], msg2
[1024];
904 if (show_other_keys(host_hostkeys
, host_key
))
905 snprintf(msg1
, sizeof(msg1
),
906 "\nbut keys of different type are already"
907 " known for this host.");
909 snprintf(msg1
, sizeof(msg1
), ".");
911 fp
= sshkey_fingerprint(host_key
,
912 options
.fingerprint_hash
, SSH_FP_DEFAULT
);
913 ra
= sshkey_fingerprint(host_key
,
914 options
.fingerprint_hash
, SSH_FP_RANDOMART
);
915 if (fp
== NULL
|| ra
== NULL
)
916 fatal("%s: sshkey_fingerprint fail", __func__
);
918 if (options
.verify_host_key_dns
) {
919 if (matching_host_key_dns
)
920 snprintf(msg2
, sizeof(msg2
),
921 "Matching host key fingerprint"
924 snprintf(msg2
, sizeof(msg2
),
925 "No matching host key fingerprint"
928 snprintf(msg
, sizeof(msg
),
929 "The authenticity of host '%.200s (%s)' can't be "
931 "%s key fingerprint is %s.%s%s\n%s"
932 "Are you sure you want to continue connecting "
934 host
, ip
, msg1
, type
, fp
,
935 options
.visual_host_key
? "\n" : "",
936 options
.visual_host_key
? ra
: "",
942 hostkey_trusted
= 1; /* user explicitly confirmed */
945 * If in "new" or "off" strict mode, add the key automatically
946 * to the local known_hosts file.
948 if (options
.check_host_ip
&& ip_status
== HOST_NEW
) {
949 snprintf(hostline
, sizeof(hostline
), "%s,%s", host
, ip
);
951 if (options
.hash_known_hosts
) {
952 /* Add hash of host and IP separately */
953 r
= add_host_to_hostfile(user_hostfiles
[0],
954 host
, host_key
, options
.hash_known_hosts
) &&
955 add_host_to_hostfile(user_hostfiles
[0], ip
,
956 host_key
, options
.hash_known_hosts
);
958 /* Add unhashed "host,ip" */
959 r
= add_host_to_hostfile(user_hostfiles
[0],
961 options
.hash_known_hosts
);
964 r
= add_host_to_hostfile(user_hostfiles
[0], host
,
965 host_key
, options
.hash_known_hosts
);
970 logit("Failed to add the host to the list of known "
971 "hosts (%.500s).", user_hostfiles
[0]);
973 logit("Warning: Permanently added '%.200s' (%s) to the "
974 "list of known hosts.", hostp
, type
);
977 error("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@");
978 error("@ WARNING: REVOKED HOST KEY DETECTED! @");
979 error("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@");
980 error("The %s host key for %s is marked as revoked.", type
, host
);
981 error("This could mean that a stolen key is being used to");
982 error("impersonate this host.");
985 * If strict host key checking is in use, the user will have
986 * to edit the key manually and we can only abort.
988 if (options
.strict_host_key_checking
!=
989 SSH_STRICT_HOSTKEY_OFF
) {
990 error("%s host key for %.200s was revoked and you have "
991 "requested strict checking.", type
, host
);
994 goto continue_unsafe
;
999 * This is only a debug() since it is valid to have
1000 * CAs with wildcard DNS matches that don't match
1001 * all hosts that one might visit.
1003 debug("Host certificate authority does not "
1004 "match %s in %s:%lu", CA_MARKER
,
1005 host_found
->file
, host_found
->line
);
1008 if (readonly
== ROQUIET
)
1010 if (options
.check_host_ip
&& host_ip_differ
) {
1012 if (ip_status
== HOST_NEW
)
1013 key_msg
= "is unknown";
1014 else if (ip_status
== HOST_OK
)
1015 key_msg
= "is unchanged";
1017 key_msg
= "has a different value";
1018 error("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@");
1019 error("@ WARNING: POSSIBLE DNS SPOOFING DETECTED! @");
1020 error("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@");
1021 error("The %s host key for %s has changed,", type
, host
);
1022 error("and the key for the corresponding IP address %s", ip
);
1023 error("%s. This could either mean that", key_msg
);
1024 error("DNS SPOOFING is happening or the IP address for the host");
1025 error("and its host key have changed at the same time.");
1026 if (ip_status
!= HOST_NEW
)
1027 error("Offending key for IP in %s:%lu",
1028 ip_found
->file
, ip_found
->line
);
1030 /* The host key has changed. */
1031 warn_changed_key(host_key
);
1032 error("Add correct host key in %.100s to get rid of this message.",
1034 error("Offending %s key in %s:%lu",
1035 sshkey_type(host_found
->key
),
1036 host_found
->file
, host_found
->line
);
1039 * If strict host key checking is in use, the user will have
1040 * to edit the key manually and we can only abort.
1042 if (options
.strict_host_key_checking
!=
1043 SSH_STRICT_HOSTKEY_OFF
) {
1044 error("%s host key for %.200s has changed and you have "
1045 "requested strict checking.", type
, host
);
1051 * If strict host key checking has not been requested, allow
1052 * the connection but without MITM-able authentication or
1055 if (options
.password_authentication
) {
1056 error("Password authentication is disabled to avoid "
1057 "man-in-the-middle attacks.");
1058 options
.password_authentication
= 0;
1059 cancelled_forwarding
= 1;
1061 if (options
.kbd_interactive_authentication
) {
1062 error("Keyboard-interactive authentication is disabled"
1063 " to avoid man-in-the-middle attacks.");
1064 options
.kbd_interactive_authentication
= 0;
1065 options
.challenge_response_authentication
= 0;
1066 cancelled_forwarding
= 1;
1068 if (options
.challenge_response_authentication
) {
1069 error("Challenge/response authentication is disabled"
1070 " to avoid man-in-the-middle attacks.");
1071 options
.challenge_response_authentication
= 0;
1072 cancelled_forwarding
= 1;
1074 if (options
.forward_agent
) {
1075 error("Agent forwarding is disabled to avoid "
1076 "man-in-the-middle attacks.");
1077 options
.forward_agent
= 0;
1078 cancelled_forwarding
= 1;
1080 if (options
.forward_x11
) {
1081 error("X11 forwarding is disabled to avoid "
1082 "man-in-the-middle attacks.");
1083 options
.forward_x11
= 0;
1084 cancelled_forwarding
= 1;
1086 if (options
.num_local_forwards
> 0 ||
1087 options
.num_remote_forwards
> 0) {
1088 error("Port forwarding is disabled to avoid "
1089 "man-in-the-middle attacks.");
1090 options
.num_local_forwards
=
1091 options
.num_remote_forwards
= 0;
1092 cancelled_forwarding
= 1;
1094 if (options
.tun_open
!= SSH_TUNMODE_NO
) {
1095 error("Tunnel forwarding is disabled to avoid "
1096 "man-in-the-middle attacks.");
1097 options
.tun_open
= SSH_TUNMODE_NO
;
1098 cancelled_forwarding
= 1;
1100 if (options
.exit_on_forward_failure
&& cancelled_forwarding
)
1101 fatal("Error: forwarding disabled due to host key "
1105 * XXX Should permit the user to change to use the new id.
1106 * This could be done by converting the host key to an
1107 * identifying sentence, tell that the host identifies itself
1108 * by that sentence, and ask the user if he/she wishes to
1109 * accept the authentication.
1113 fatal("internal error");
1117 if (options
.check_host_ip
&& host_status
!= HOST_CHANGED
&&
1118 ip_status
== HOST_CHANGED
) {
1119 snprintf(msg
, sizeof(msg
),
1120 "Warning: the %s host key for '%.200s' "
1121 "differs from the key for the IP address '%.128s'"
1122 "\nOffending key for IP in %s:%lu",
1123 type
, host
, ip
, ip_found
->file
, ip_found
->line
);
1124 if (host_status
== HOST_OK
) {
1126 snprintf(msg
+ len
, sizeof(msg
) - len
,
1127 "\nMatching host key in %s:%lu",
1128 host_found
->file
, host_found
->line
);
1130 if (options
.strict_host_key_checking
==
1131 SSH_STRICT_HOSTKEY_ASK
) {
1132 strlcat(msg
, "\nAre you sure you want "
1133 "to continue connecting (yes/no)? ", sizeof(msg
));
1136 } else if (options
.strict_host_key_checking
!=
1137 SSH_STRICT_HOSTKEY_OFF
) {
1139 error("Exiting, you have requested strict checking.");
1146 if (!hostkey_trusted
&& options
.update_hostkeys
) {
1147 debug("%s: hostkey not known or explicitly trusted: "
1148 "disabling UpdateHostkeys", __func__
);
1149 options
.update_hostkeys
= 0;
1154 if (host_hostkeys
!= NULL
)
1155 free_hostkeys(host_hostkeys
);
1156 if (ip_hostkeys
!= NULL
)
1157 free_hostkeys(ip_hostkeys
);
1161 if (want_cert
&& host_status
!= HOST_REVOKED
) {
1163 * No matching certificate. Downgrade cert to raw key and
1166 debug("No matching CA found. Retry with plain key");
1167 if ((r
= sshkey_from_private(host_key
, &raw_key
)) != 0)
1168 fatal("%s: sshkey_from_private: %s",
1169 __func__
, ssh_err(r
));
1170 if ((r
= sshkey_drop_cert(raw_key
)) != 0)
1171 fatal("Couldn't drop certificate: %s", ssh_err(r
));
1175 if (raw_key
!= NULL
)
1176 sshkey_free(raw_key
);
1179 if (host_hostkeys
!= NULL
)
1180 free_hostkeys(host_hostkeys
);
1181 if (ip_hostkeys
!= NULL
)
1182 free_hostkeys(ip_hostkeys
);
1186 /* returns 0 if key verifies or -1 if key does NOT verify */
1188 verify_host_key(char *host
, struct sockaddr
*hostaddr
, struct sshkey
*host_key
)
1191 int r
= -1, flags
= 0;
1192 char valid
[64], *fp
= NULL
, *cafp
= NULL
;
1193 struct sshkey
*plain
= NULL
;
1195 if ((fp
= sshkey_fingerprint(host_key
,
1196 options
.fingerprint_hash
, SSH_FP_DEFAULT
)) == NULL
) {
1197 error("%s: fingerprint host key: %s", __func__
, ssh_err(r
));
1202 if (sshkey_is_cert(host_key
)) {
1203 if ((cafp
= sshkey_fingerprint(host_key
->cert
->signature_key
,
1204 options
.fingerprint_hash
, SSH_FP_DEFAULT
)) == NULL
) {
1205 error("%s: fingerprint CA key: %s",
1206 __func__
, ssh_err(r
));
1210 sshkey_format_cert_validity(host_key
->cert
,
1211 valid
, sizeof(valid
));
1212 debug("Server host certificate: %s %s, serial %llu "
1213 "ID \"%s\" CA %s %s valid %s",
1214 sshkey_ssh_name(host_key
), fp
,
1215 (unsigned long long)host_key
->cert
->serial
,
1216 host_key
->cert
->key_id
,
1217 sshkey_ssh_name(host_key
->cert
->signature_key
), cafp
,
1219 for (i
= 0; i
< host_key
->cert
->nprincipals
; i
++) {
1220 debug2("Server host certificate hostname: %s",
1221 host_key
->cert
->principals
[i
]);
1224 debug("Server host key: %s %s", sshkey_ssh_name(host_key
), fp
);
1227 if (sshkey_equal(previous_host_key
, host_key
)) {
1228 debug2("%s: server host key %s %s matches cached key",
1229 __func__
, sshkey_type(host_key
), fp
);
1234 /* Check in RevokedHostKeys file if specified */
1235 if (options
.revoked_host_keys
!= NULL
) {
1236 r
= sshkey_check_revoked(host_key
, options
.revoked_host_keys
);
1239 break; /* not revoked */
1240 case SSH_ERR_KEY_REVOKED
:
1241 error("Host key %s %s revoked by file %s",
1242 sshkey_type(host_key
), fp
,
1243 options
.revoked_host_keys
);
1247 error("Error checking host key %s %s in "
1248 "revoked keys file %s: %s", sshkey_type(host_key
),
1249 fp
, options
.revoked_host_keys
, ssh_err(r
));
1255 if (options
.verify_host_key_dns
) {
1257 * XXX certs are not yet supported for DNS, so downgrade
1258 * them and try the plain key.
1260 if ((r
= sshkey_from_private(host_key
, &plain
)) != 0)
1262 if (sshkey_is_cert(plain
))
1263 sshkey_drop_cert(plain
);
1264 if (verify_host_key_dns(host
, hostaddr
, plain
, &flags
) == 0) {
1265 if (flags
& DNS_VERIFY_FOUND
) {
1266 if (options
.verify_host_key_dns
== 1 &&
1267 flags
& DNS_VERIFY_MATCH
&&
1268 flags
& DNS_VERIFY_SECURE
) {
1272 if (flags
& DNS_VERIFY_MATCH
) {
1273 matching_host_key_dns
= 1;
1275 warn_changed_key(plain
);
1276 error("Update the SSHFP RR in DNS "
1277 "with the new host key to get rid "
1278 "of this message.");
1283 r
= check_host_key(host
, hostaddr
, options
.port
, host_key
, RDRW
,
1284 options
.user_hostfiles
, options
.num_user_hostfiles
,
1285 options
.system_hostfiles
, options
.num_system_hostfiles
);
1291 if (r
== 0 && host_key
!= NULL
) {
1292 sshkey_free(previous_host_key
);
1293 r
= sshkey_from_private(host_key
, &previous_host_key
);
1300 * Starts a dialog with the server, and authenticates the current user on the
1301 * server. This does not need any extra privileges. The basic connection
1302 * to the server must already have been established before this is called.
1303 * If login fails, this function prints an error and never returns.
1304 * This function does not require super-user privileges.
1307 ssh_login(Sensitive
*sensitive
, const char *orighost
,
1308 struct sockaddr
*hostaddr
, u_short port
, struct passwd
*pw
, int timeout_ms
)
1311 char *server_user
, *local_user
;
1313 local_user
= xstrdup(pw
->pw_name
);
1314 server_user
= options
.user
? options
.user
: local_user
;
1316 /* Convert the user-supplied hostname into all lowercase. */
1317 host
= xstrdup(orighost
);
1320 /* Exchange protocol version identification strings with the server. */
1321 ssh_exchange_identification(timeout_ms
);
1323 /* Put the connection into non-blocking mode. */
1324 packet_set_nonblocking();
1327 /* authenticate user */
1328 debug("Authenticating to %s:%d as '%s'", host
, port
, server_user
);
1329 ssh_kex2(host
, hostaddr
, port
);
1330 ssh_userauth2(local_user
, server_user
, host
, sensitive
);
1335 ssh_put_password(char *password
)
1340 if (datafellows
& SSH_BUG_PASSWORDPAD
) {
1341 packet_put_cstring(password
);
1344 size
= ROUNDUP(strlen(password
) + 1, 32);
1345 padded
= xcalloc(1, size
);
1346 strlcpy(padded
, password
, size
);
1347 packet_put_string(padded
, size
);
1348 explicit_bzero(padded
, size
);
1352 /* print all known host keys for a given host, but skip keys of given type */
1354 show_other_keys(struct hostkeys
*hostkeys
, struct sshkey
*key
)
1365 const struct hostkey_entry
*found
;
1367 for (i
= 0; type
[i
] != -1; i
++) {
1368 if (type
[i
] == key
->type
)
1370 if (!lookup_key_in_hostkeys_by_type(hostkeys
, type
[i
], &found
))
1372 fp
= sshkey_fingerprint(found
->key
,
1373 options
.fingerprint_hash
, SSH_FP_DEFAULT
);
1374 ra
= sshkey_fingerprint(found
->key
,
1375 options
.fingerprint_hash
, SSH_FP_RANDOMART
);
1376 if (fp
== NULL
|| ra
== NULL
)
1377 fatal("%s: sshkey_fingerprint fail", __func__
);
1378 logit("WARNING: %s key found for host %s\n"
1380 "%s key fingerprint %s.",
1381 key_type(found
->key
),
1382 found
->host
, found
->file
, found
->line
,
1383 key_type(found
->key
), fp
);
1384 if (options
.visual_host_key
)
1394 warn_changed_key(struct sshkey
*host_key
)
1398 fp
= sshkey_fingerprint(host_key
, options
.fingerprint_hash
,
1401 fatal("%s: sshkey_fingerprint fail", __func__
);
1403 error("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@");
1404 error("@ WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED! @");
1405 error("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@");
1406 error("IT IS POSSIBLE THAT SOMEONE IS DOING SOMETHING NASTY!");
1407 error("Someone could be eavesdropping on you right now (man-in-the-middle attack)!");
1408 error("It is also possible that a host key has just been changed.");
1409 error("The fingerprint for the %s key sent by the remote host is\n%s.",
1410 key_type(host_key
), fp
);
1411 error("Please contact your system administrator.");
1417 * Execute a local command
1420 ssh_local_cmd(const char *args
)
1425 void (*osighand
)(int);
1427 if (!options
.permit_local_command
||
1428 args
== NULL
|| !*args
)
1431 if ((shell
= getenv("SHELL")) == NULL
|| *shell
== '\0')
1432 shell
= _PATH_BSHELL
;
1434 osighand
= signal(SIGCHLD
, SIG_DFL
);
1437 signal(SIGPIPE
, SIG_DFL
);
1438 debug3("Executing %s -c \"%s\"", shell
, args
);
1439 execl(shell
, shell
, "-c", args
, (char *)NULL
);
1440 error("Couldn't execute %s -c \"%s\": %s",
1441 shell
, args
, strerror(errno
));
1443 } else if (pid
== -1)
1444 fatal("fork failed: %.100s", strerror(errno
));
1445 while (waitpid(pid
, &status
, 0) == -1)
1447 fatal("Couldn't wait for child: %s", strerror(errno
));
1448 signal(SIGCHLD
, osighand
);
1450 if (!WIFEXITED(status
))
1453 return (WEXITSTATUS(status
));
1457 maybe_add_key_to_agent(char *authfile
, struct sshkey
*private, char *comment
,
1460 int auth_sock
= -1, r
;
1462 if (options
.add_keys_to_agent
== 0)
1465 if ((r
= ssh_get_authentication_socket(&auth_sock
)) != 0) {
1466 debug3("no authentication agent, not adding key");
1470 if (options
.add_keys_to_agent
== 2 &&
1471 !ask_permission("Add key %s (%s) to agent?", authfile
, comment
)) {
1472 debug3("user denied adding this key");
1477 if ((r
= ssh_add_identity_constrained(auth_sock
, private, comment
, 0,
1478 (options
.add_keys_to_agent
== 3))) == 0)
1479 debug("identity added to agent: %s", authfile
);
1481 debug("could not add identity to agent: %s (%d)", authfile
, r
);