diff options
Diffstat (limited to 'sshconnect.c')
-rw-r--r-- | sshconnect.c | 67 |
1 files changed, 47 insertions, 20 deletions
diff --git a/sshconnect.c b/sshconnect.c index 87c3770c0..b8510d201 100644 --- a/sshconnect.c +++ b/sshconnect.c | |||
@@ -1218,36 +1218,63 @@ fail: | |||
1218 | return -1; | 1218 | return -1; |
1219 | } | 1219 | } |
1220 | 1220 | ||
1221 | static int | ||
1222 | check_host_key_sshfp(char *host, struct sockaddr *hostaddr, Key *host_key) | ||
1223 | { | ||
1224 | int rc = -1; | ||
1225 | int flags = 0; | ||
1226 | Key *raw_key = NULL; | ||
1227 | |||
1228 | if (!options.verify_host_key_dns) | ||
1229 | goto done; | ||
1230 | |||
1231 | /* XXX certs are not yet supported for DNS; try looking the raw key | ||
1232 | * up in the DNS anyway. | ||
1233 | */ | ||
1234 | if (key_is_cert(host_key)) { | ||
1235 | debug2("Extracting key from cert for SSHFP lookup"); | ||
1236 | raw_key = key_from_private(host_key); | ||
1237 | if (key_drop_cert(raw_key)) | ||
1238 | fatal("Couldn't drop certificate"); | ||
1239 | host_key = raw_key; | ||
1240 | } | ||
1241 | |||
1242 | if (verify_host_key_dns(host, hostaddr, host_key, &flags)) | ||
1243 | goto done; | ||
1244 | |||
1245 | if (flags & DNS_VERIFY_FOUND) { | ||
1246 | |||
1247 | if (options.verify_host_key_dns == 1 && | ||
1248 | flags & DNS_VERIFY_MATCH && | ||
1249 | flags & DNS_VERIFY_SECURE) { | ||
1250 | rc = 0; | ||
1251 | } else if (flags & DNS_VERIFY_MATCH) { | ||
1252 | matching_host_key_dns = 1; | ||
1253 | } else { | ||
1254 | warn_changed_key(host_key); | ||
1255 | error("Update the SSHFP RR in DNS with the new " | ||
1256 | "host key to get rid of this message."); | ||
1257 | } | ||
1258 | } | ||
1259 | |||
1260 | done: | ||
1261 | if (raw_key) | ||
1262 | key_free(raw_key); | ||
1263 | return rc; | ||
1264 | } | ||
1265 | |||
1221 | /* returns 0 if key verifies or -1 if key does NOT verify */ | 1266 | /* returns 0 if key verifies or -1 if key does NOT verify */ |
1222 | int | 1267 | int |
1223 | verify_host_key(char *host, struct sockaddr *hostaddr, Key *host_key) | 1268 | verify_host_key(char *host, struct sockaddr *hostaddr, Key *host_key) |
1224 | { | 1269 | { |
1225 | int flags = 0; | ||
1226 | char *fp; | 1270 | char *fp; |
1227 | 1271 | ||
1228 | fp = key_fingerprint(host_key, SSH_FP_MD5, SSH_FP_HEX); | 1272 | fp = key_fingerprint(host_key, SSH_FP_MD5, SSH_FP_HEX); |
1229 | debug("Server host key: %s %s", key_type(host_key), fp); | 1273 | debug("Server host key: %s %s", key_type(host_key), fp); |
1230 | free(fp); | 1274 | free(fp); |
1231 | 1275 | ||
1232 | /* XXX certs are not yet supported for DNS */ | 1276 | if (check_host_key_sshfp(host, hostaddr, host_key) == 0) |
1233 | if (!key_is_cert(host_key) && options.verify_host_key_dns && | 1277 | return 0; |
1234 | verify_host_key_dns(host, hostaddr, host_key, &flags) == 0) { | ||
1235 | if (flags & DNS_VERIFY_FOUND) { | ||
1236 | |||
1237 | if (options.verify_host_key_dns == 1 && | ||
1238 | flags & DNS_VERIFY_MATCH && | ||
1239 | flags & DNS_VERIFY_SECURE) | ||
1240 | return 0; | ||
1241 | |||
1242 | if (flags & DNS_VERIFY_MATCH) { | ||
1243 | matching_host_key_dns = 1; | ||
1244 | } else { | ||
1245 | warn_changed_key(host_key); | ||
1246 | error("Update the SSHFP RR in DNS with the new " | ||
1247 | "host key to get rid of this message."); | ||
1248 | } | ||
1249 | } | ||
1250 | } | ||
1251 | 1278 | ||
1252 | return check_host_key(host, hostaddr, options.port, host_key, RDRW, | 1279 | return check_host_key(host, hostaddr, options.port, host_key, RDRW, |
1253 | options.user_hostfiles, options.num_user_hostfiles, | 1280 | options.user_hostfiles, options.num_user_hostfiles, |