summaryrefslogtreecommitdiff
path: root/sshconnect.c
diff options
context:
space:
mode:
Diffstat (limited to 'sshconnect.c')
-rw-r--r--sshconnect.c110
1 files changed, 82 insertions, 28 deletions
diff --git a/sshconnect.c b/sshconnect.c
index 563405ecb..a6c9e20ed 100644
--- a/sshconnect.c
+++ b/sshconnect.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: sshconnect.c,v 1.251 2014/07/15 15:54:14 millert Exp $ */ 1/* $OpenBSD: sshconnect.c,v 1.259 2015/01/28 22:36:00 djm 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
@@ -15,6 +15,7 @@
15 15
16#include "includes.h" 16#include "includes.h"
17 17
18#include <sys/param.h> /* roundup */
18#include <sys/types.h> 19#include <sys/types.h>
19#include <sys/wait.h> 20#include <sys/wait.h>
20#include <sys/stat.h> 21#include <sys/stat.h>
@@ -62,6 +63,8 @@
62#include "monitor_fdpass.h" 63#include "monitor_fdpass.h"
63#include "ssh2.h" 64#include "ssh2.h"
64#include "version.h" 65#include "version.h"
66#include "authfile.h"
67#include "ssherr.h"
65 68
66char *client_version_string = NULL; 69char *client_version_string = NULL;
67char *server_version_string = NULL; 70char *server_version_string = NULL;
@@ -625,7 +628,7 @@ ssh_exchange_identification(int timeout_ms)
625 debug("Remote protocol version %d.%d, remote software version %.100s", 628 debug("Remote protocol version %d.%d, remote software version %.100s",
626 remote_major, remote_minor, remote_version); 629 remote_major, remote_minor, remote_version);
627 630
628 compat_datafellows(remote_version); 631 active_state->compat = compat_datafellows(remote_version);
629 mismatch = 0; 632 mismatch = 0;
630 633
631 switch (remote_major) { 634 switch (remote_major) {
@@ -767,7 +770,7 @@ get_hostfile_hostname_ipaddr(char *hostname, struct sockaddr *hostaddr,
767 if (options.proxy_command == NULL) { 770 if (options.proxy_command == NULL) {
768 if (getnameinfo(hostaddr, addrlen, 771 if (getnameinfo(hostaddr, addrlen,
769 ntop, sizeof(ntop), NULL, 0, NI_NUMERICHOST) != 0) 772 ntop, sizeof(ntop), NULL, 0, NI_NUMERICHOST) != 0)
770 fatal("check_host_key: getnameinfo failed"); 773 fatal("%s: getnameinfo failed", __func__);
771 *hostfile_ipaddr = put_host_port(ntop, port); 774 *hostfile_ipaddr = put_host_port(ntop, port);
772 } else { 775 } else {
773 *hostfile_ipaddr = xstrdup("<no hostip for proxy " 776 *hostfile_ipaddr = xstrdup("<no hostip for proxy "
@@ -815,6 +818,7 @@ check_host_key(char *hostname, struct sockaddr *hostaddr, u_short port,
815 int len, cancelled_forwarding = 0; 818 int len, cancelled_forwarding = 0;
816 int local = sockaddr_is_local(hostaddr); 819 int local = sockaddr_is_local(hostaddr);
817 int r, want_cert = key_is_cert(host_key), host_ip_differ = 0; 820 int r, want_cert = key_is_cert(host_key), host_ip_differ = 0;
821 int hostkey_trusted = 0; /* Known or explicitly accepted by user */
818 struct hostkeys *host_hostkeys, *ip_hostkeys; 822 struct hostkeys *host_hostkeys, *ip_hostkeys;
819 u_int i; 823 u_int i;
820 824
@@ -915,13 +919,17 @@ check_host_key(char *hostname, struct sockaddr *hostaddr, u_short port,
915 "key for IP address '%.128s' to the list " 919 "key for IP address '%.128s' to the list "
916 "of known hosts.", type, ip); 920 "of known hosts.", type, ip);
917 } else if (options.visual_host_key) { 921 } else if (options.visual_host_key) {
918 fp = key_fingerprint(host_key, SSH_FP_MD5, SSH_FP_HEX); 922 fp = sshkey_fingerprint(host_key,
919 ra = key_fingerprint(host_key, SSH_FP_MD5, 923 options.fingerprint_hash, SSH_FP_DEFAULT);
920 SSH_FP_RANDOMART); 924 ra = sshkey_fingerprint(host_key,
925 options.fingerprint_hash, SSH_FP_RANDOMART);
926 if (fp == NULL || ra == NULL)
927 fatal("%s: sshkey_fingerprint fail", __func__);
921 logit("Host key fingerprint is %s\n%s\n", fp, ra); 928 logit("Host key fingerprint is %s\n%s\n", fp, ra);
922 free(ra); 929 free(ra);
923 free(fp); 930 free(fp);
924 } 931 }
932 hostkey_trusted = 1;
925 break; 933 break;
926 case HOST_NEW: 934 case HOST_NEW:
927 if (options.host_key_alias == NULL && port != 0 && 935 if (options.host_key_alias == NULL && port != 0 &&
@@ -956,9 +964,12 @@ check_host_key(char *hostname, struct sockaddr *hostaddr, u_short port,
956 else 964 else
957 snprintf(msg1, sizeof(msg1), "."); 965 snprintf(msg1, sizeof(msg1), ".");
958 /* The default */ 966 /* The default */
959 fp = key_fingerprint(host_key, SSH_FP_MD5, SSH_FP_HEX); 967 fp = sshkey_fingerprint(host_key,
960 ra = key_fingerprint(host_key, SSH_FP_MD5, 968 options.fingerprint_hash, SSH_FP_DEFAULT);
961 SSH_FP_RANDOMART); 969 ra = sshkey_fingerprint(host_key,
970 options.fingerprint_hash, SSH_FP_RANDOMART);
971 if (fp == NULL || ra == NULL)
972 fatal("%s: sshkey_fingerprint fail", __func__);
962 msg2[0] = '\0'; 973 msg2[0] = '\0';
963 if (options.verify_host_key_dns) { 974 if (options.verify_host_key_dns) {
964 if (matching_host_key_dns) 975 if (matching_host_key_dns)
@@ -984,6 +995,7 @@ check_host_key(char *hostname, struct sockaddr *hostaddr, u_short port,
984 free(fp); 995 free(fp);
985 if (!confirm(msg)) 996 if (!confirm(msg))
986 goto fail; 997 goto fail;
998 hostkey_trusted = 1; /* user explicitly confirmed */
987 } 999 }
988 /* 1000 /*
989 * If not in strict mode, add the key automatically to the 1001 * If not in strict mode, add the key automatically to the
@@ -1187,6 +1199,12 @@ check_host_key(char *hostname, struct sockaddr *hostaddr, u_short port,
1187 } 1199 }
1188 } 1200 }
1189 1201
1202 if (!hostkey_trusted && options.update_hostkeys) {
1203 debug("%s: hostkey not known or explicitly trusted: "
1204 "disabling UpdateHostkeys", __func__);
1205 options.update_hostkeys = 0;
1206 }
1207
1190 free(ip); 1208 free(ip);
1191 free(host); 1209 free(host);
1192 if (host_hostkeys != NULL) 1210 if (host_hostkeys != NULL)
@@ -1224,16 +1242,45 @@ int
1224verify_host_key(char *host, struct sockaddr *hostaddr, Key *host_key) 1242verify_host_key(char *host, struct sockaddr *hostaddr, Key *host_key)
1225{ 1243{
1226 int r = -1, flags = 0; 1244 int r = -1, flags = 0;
1227 char *fp; 1245 char *fp = NULL;
1228 Key *plain = NULL; 1246 struct sshkey *plain = NULL;
1247
1248 if ((fp = sshkey_fingerprint(host_key,
1249 options.fingerprint_hash, SSH_FP_DEFAULT)) == NULL) {
1250 error("%s: fingerprint host key: %s", __func__, ssh_err(r));
1251 r = -1;
1252 goto out;
1253 }
1229 1254
1230 fp = key_fingerprint(host_key, SSH_FP_MD5, SSH_FP_HEX); 1255 debug("Server host key: %s %s",
1231 debug("Server host key: %s %s", key_type(host_key), fp); 1256 compat20 ? sshkey_ssh_name(host_key) : sshkey_type(host_key), fp);
1232 free(fp);
1233 1257
1234 if (key_equal(previous_host_key, host_key)) { 1258 if (sshkey_equal(previous_host_key, host_key)) {
1235 debug("%s: server host key matches cached key", __func__); 1259 debug2("%s: server host key %s %s matches cached key",
1236 return 0; 1260 __func__, sshkey_type(host_key), fp);
1261 r = 0;
1262 goto out;
1263 }
1264
1265 /* Check in RevokedHostKeys file if specified */
1266 if (options.revoked_host_keys != NULL) {
1267 r = sshkey_check_revoked(host_key, options.revoked_host_keys);
1268 switch (r) {
1269 case 0:
1270 break; /* not revoked */
1271 case SSH_ERR_KEY_REVOKED:
1272 error("Host key %s %s revoked by file %s",
1273 sshkey_type(host_key), fp,
1274 options.revoked_host_keys);
1275 r = -1;
1276 goto out;
1277 default:
1278 error("Error checking host key %s %s in "
1279 "revoked keys file %s: %s", sshkey_type(host_key),
1280 fp, options.revoked_host_keys, ssh_err(r));
1281 r = -1;
1282 goto out;
1283 }
1237 } 1284 }
1238 1285
1239 if (options.verify_host_key_dns) { 1286 if (options.verify_host_key_dns) {
@@ -1241,17 +1288,17 @@ verify_host_key(char *host, struct sockaddr *hostaddr, Key *host_key)
1241 * XXX certs are not yet supported for DNS, so downgrade 1288 * XXX certs are not yet supported for DNS, so downgrade
1242 * them and try the plain key. 1289 * them and try the plain key.
1243 */ 1290 */
1244 plain = key_from_private(host_key); 1291 if ((r = sshkey_from_private(host_key, &plain)) != 0)
1245 if (key_is_cert(plain)) 1292 goto out;
1246 key_drop_cert(plain); 1293 if (sshkey_is_cert(plain))
1294 sshkey_drop_cert(plain);
1247 if (verify_host_key_dns(host, hostaddr, plain, &flags) == 0) { 1295 if (verify_host_key_dns(host, hostaddr, plain, &flags) == 0) {
1248 if (flags & DNS_VERIFY_FOUND) { 1296 if (flags & DNS_VERIFY_FOUND) {
1249 if (options.verify_host_key_dns == 1 && 1297 if (options.verify_host_key_dns == 1 &&
1250 flags & DNS_VERIFY_MATCH && 1298 flags & DNS_VERIFY_MATCH &&
1251 flags & DNS_VERIFY_SECURE) { 1299 flags & DNS_VERIFY_SECURE) {
1252 key_free(plain);
1253 r = 0; 1300 r = 0;
1254 goto done; 1301 goto out;
1255 } 1302 }
1256 if (flags & DNS_VERIFY_MATCH) { 1303 if (flags & DNS_VERIFY_MATCH) {
1257 matching_host_key_dns = 1; 1304 matching_host_key_dns = 1;
@@ -1263,14 +1310,14 @@ verify_host_key(char *host, struct sockaddr *hostaddr, Key *host_key)
1263 } 1310 }
1264 } 1311 }
1265 } 1312 }
1266 key_free(plain);
1267 } 1313 }
1268
1269 r = check_host_key(host, hostaddr, options.port, host_key, RDRW, 1314 r = check_host_key(host, hostaddr, options.port, host_key, RDRW,
1270 options.user_hostfiles, options.num_user_hostfiles, 1315 options.user_hostfiles, options.num_user_hostfiles,
1271 options.system_hostfiles, options.num_system_hostfiles); 1316 options.system_hostfiles, options.num_system_hostfiles);
1272 1317
1273done: 1318out:
1319 sshkey_free(plain);
1320 free(fp);
1274 if (r == 0 && host_key != NULL) { 1321 if (r == 0 && host_key != NULL) {
1275 key_free(previous_host_key); 1322 key_free(previous_host_key);
1276 previous_host_key = key_from_private(host_key); 1323 previous_host_key = key_from_private(host_key);
@@ -1361,8 +1408,12 @@ show_other_keys(struct hostkeys *hostkeys, Key *key)
1361 continue; 1408 continue;
1362 if (!lookup_key_in_hostkeys_by_type(hostkeys, type[i], &found)) 1409 if (!lookup_key_in_hostkeys_by_type(hostkeys, type[i], &found))
1363 continue; 1410 continue;
1364 fp = key_fingerprint(found->key, SSH_FP_MD5, SSH_FP_HEX); 1411 fp = sshkey_fingerprint(found->key,
1365 ra = key_fingerprint(found->key, SSH_FP_MD5, SSH_FP_RANDOMART); 1412 options.fingerprint_hash, SSH_FP_DEFAULT);
1413 ra = sshkey_fingerprint(found->key,
1414 options.fingerprint_hash, SSH_FP_RANDOMART);
1415 if (fp == NULL || ra == NULL)
1416 fatal("%s: sshkey_fingerprint fail", __func__);
1366 logit("WARNING: %s key found for host %s\n" 1417 logit("WARNING: %s key found for host %s\n"
1367 "in %s:%lu\n" 1418 "in %s:%lu\n"
1368 "%s key fingerprint %s.", 1419 "%s key fingerprint %s.",
@@ -1383,7 +1434,10 @@ warn_changed_key(Key *host_key)
1383{ 1434{
1384 char *fp; 1435 char *fp;
1385 1436
1386 fp = key_fingerprint(host_key, SSH_FP_MD5, SSH_FP_HEX); 1437 fp = sshkey_fingerprint(host_key, options.fingerprint_hash,
1438 SSH_FP_DEFAULT);
1439 if (fp == NULL)
1440 fatal("%s: sshkey_fingerprint fail", __func__);
1387 1441
1388 error("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@"); 1442 error("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@");
1389 error("@ WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED! @"); 1443 error("@ WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED! @");