diff options
Diffstat (limited to 'sshconnect2.c')
-rw-r--r-- | sshconnect2.c | 77 |
1 files changed, 57 insertions, 20 deletions
diff --git a/sshconnect2.c b/sshconnect2.c index c35a0bd50..5743c2c41 100644 --- a/sshconnect2.c +++ b/sshconnect2.c | |||
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: sshconnect2.c,v 1.251 2016/12/04 23:54:02 djm Exp $ */ | 1 | /* $OpenBSD: sshconnect2.c,v 1.255 2017/03/11 23:40:26 djm Exp $ */ |
2 | /* | 2 | /* |
3 | * Copyright (c) 2000 Markus Friedl. All rights reserved. | 3 | * Copyright (c) 2000 Markus Friedl. All rights reserved. |
4 | * Copyright (c) 2008 Damien Miller. All rights reserved. | 4 | * Copyright (c) 2008 Damien Miller. All rights reserved. |
@@ -227,8 +227,8 @@ ssh_kex2(char *host, struct sockaddr *hostaddr, u_short port) | |||
227 | #endif | 227 | #endif |
228 | 228 | ||
229 | if (options.rekey_limit || options.rekey_interval) | 229 | if (options.rekey_limit || options.rekey_interval) |
230 | packet_set_rekey_limits((u_int32_t)options.rekey_limit, | 230 | packet_set_rekey_limits(options.rekey_limit, |
231 | (time_t)options.rekey_interval); | 231 | options.rekey_interval); |
232 | 232 | ||
233 | /* start key exchange */ | 233 | /* start key exchange */ |
234 | if ((r = kex_setup(active_state, myproposal)) != 0) | 234 | if ((r = kex_setup(active_state, myproposal)) != 0) |
@@ -1057,14 +1057,14 @@ input_userauth_passwd_changereq(int type, u_int32_t seqnr, void *ctxt) | |||
1057 | Authctxt *authctxt = ctxt; | 1057 | Authctxt *authctxt = ctxt; |
1058 | char *info, *lang, *password = NULL, *retype = NULL; | 1058 | char *info, *lang, *password = NULL, *retype = NULL; |
1059 | char prompt[150]; | 1059 | char prompt[150]; |
1060 | const char *host = options.host_key_alias ? options.host_key_alias : | 1060 | const char *host; |
1061 | authctxt->host; | ||
1062 | 1061 | ||
1063 | debug2("input_userauth_passwd_changereq"); | 1062 | debug2("input_userauth_passwd_changereq"); |
1064 | 1063 | ||
1065 | if (authctxt == NULL) | 1064 | if (authctxt == NULL) |
1066 | fatal("input_userauth_passwd_changereq: " | 1065 | fatal("input_userauth_passwd_changereq: " |
1067 | "no authentication context"); | 1066 | "no authentication context"); |
1067 | host = options.host_key_alias ? options.host_key_alias : authctxt->host; | ||
1068 | 1068 | ||
1069 | info = packet_get_string(NULL); | 1069 | info = packet_get_string(NULL); |
1070 | lang = packet_get_string(NULL); | 1070 | lang = packet_get_string(NULL); |
@@ -1119,11 +1119,11 @@ input_userauth_passwd_changereq(int type, u_int32_t seqnr, void *ctxt) | |||
1119 | } | 1119 | } |
1120 | 1120 | ||
1121 | static const char * | 1121 | static const char * |
1122 | identity_sign_encode(struct identity *id) | 1122 | key_sign_encode(const struct sshkey *key) |
1123 | { | 1123 | { |
1124 | struct ssh *ssh = active_state; | 1124 | struct ssh *ssh = active_state; |
1125 | 1125 | ||
1126 | if (id->key->type == KEY_RSA) { | 1126 | if (key->type == KEY_RSA) { |
1127 | switch (ssh->kex->rsa_sha2) { | 1127 | switch (ssh->kex->rsa_sha2) { |
1128 | case 256: | 1128 | case 256: |
1129 | return "rsa-sha2-256"; | 1129 | return "rsa-sha2-256"; |
@@ -1131,7 +1131,7 @@ identity_sign_encode(struct identity *id) | |||
1131 | return "rsa-sha2-512"; | 1131 | return "rsa-sha2-512"; |
1132 | } | 1132 | } |
1133 | } | 1133 | } |
1134 | return key_ssh_name(id->key); | 1134 | return key_ssh_name(key); |
1135 | } | 1135 | } |
1136 | 1136 | ||
1137 | static int | 1137 | static int |
@@ -1140,31 +1140,50 @@ identity_sign(struct identity *id, u_char **sigp, size_t *lenp, | |||
1140 | { | 1140 | { |
1141 | Key *prv; | 1141 | Key *prv; |
1142 | int ret; | 1142 | int ret; |
1143 | const char *alg; | ||
1144 | |||
1145 | alg = identity_sign_encode(id); | ||
1146 | 1143 | ||
1147 | /* the agent supports this key */ | 1144 | /* the agent supports this key */ |
1148 | if (id->agent_fd != -1) | 1145 | if (id->key != NULL && id->agent_fd != -1) |
1149 | return ssh_agent_sign(id->agent_fd, id->key, sigp, lenp, | 1146 | return ssh_agent_sign(id->agent_fd, id->key, sigp, lenp, |
1150 | data, datalen, alg, compat); | 1147 | data, datalen, key_sign_encode(id->key), compat); |
1151 | 1148 | ||
1152 | /* | 1149 | /* |
1153 | * we have already loaded the private key or | 1150 | * we have already loaded the private key or |
1154 | * the private key is stored in external hardware | 1151 | * the private key is stored in external hardware |
1155 | */ | 1152 | */ |
1156 | if (id->isprivate || (id->key->flags & SSHKEY_FLAG_EXT)) | 1153 | if (id->key != NULL && |
1157 | return (sshkey_sign(id->key, sigp, lenp, data, datalen, alg, | 1154 | (id->isprivate || (id->key->flags & SSHKEY_FLAG_EXT))) |
1158 | compat)); | 1155 | return (sshkey_sign(id->key, sigp, lenp, data, datalen, |
1156 | key_sign_encode(id->key), compat)); | ||
1157 | |||
1159 | /* load the private key from the file */ | 1158 | /* load the private key from the file */ |
1160 | if ((prv = load_identity_file(id)) == NULL) | 1159 | if ((prv = load_identity_file(id)) == NULL) |
1161 | return SSH_ERR_KEY_NOT_FOUND; | 1160 | return SSH_ERR_KEY_NOT_FOUND; |
1162 | ret = sshkey_sign(prv, sigp, lenp, data, datalen, alg, compat); | 1161 | ret = sshkey_sign(prv, sigp, lenp, data, datalen, |
1162 | key_sign_encode(prv), compat); | ||
1163 | sshkey_free(prv); | 1163 | sshkey_free(prv); |
1164 | return (ret); | 1164 | return (ret); |
1165 | } | 1165 | } |
1166 | 1166 | ||
1167 | static int | 1167 | static int |
1168 | id_filename_matches(Identity *id, Identity *private_id) | ||
1169 | { | ||
1170 | const char *suffixes[] = { ".pub", "-cert.pub", NULL }; | ||
1171 | size_t len = strlen(id->filename), plen = strlen(private_id->filename); | ||
1172 | size_t i, slen; | ||
1173 | |||
1174 | if (strcmp(id->filename, private_id->filename) == 0) | ||
1175 | return 1; | ||
1176 | for (i = 0; suffixes[i]; i++) { | ||
1177 | slen = strlen(suffixes[i]); | ||
1178 | if (len > slen && plen == len - slen && | ||
1179 | strcmp(id->filename + (len - slen), suffixes[i]) == 0 && | ||
1180 | memcmp(id->filename, private_id->filename, plen) == 0) | ||
1181 | return 1; | ||
1182 | } | ||
1183 | return 0; | ||
1184 | } | ||
1185 | |||
1186 | static int | ||
1168 | sign_and_send_pubkey(Authctxt *authctxt, Identity *id) | 1187 | sign_and_send_pubkey(Authctxt *authctxt, Identity *id) |
1169 | { | 1188 | { |
1170 | Buffer b; | 1189 | Buffer b; |
@@ -1206,7 +1225,7 @@ sign_and_send_pubkey(Authctxt *authctxt, Identity *id) | |||
1206 | } else { | 1225 | } else { |
1207 | buffer_put_cstring(&b, authctxt->method->name); | 1226 | buffer_put_cstring(&b, authctxt->method->name); |
1208 | buffer_put_char(&b, have_sig); | 1227 | buffer_put_char(&b, have_sig); |
1209 | buffer_put_cstring(&b, identity_sign_encode(id)); | 1228 | buffer_put_cstring(&b, key_sign_encode(id->key)); |
1210 | } | 1229 | } |
1211 | buffer_put_string(&b, blob, bloblen); | 1230 | buffer_put_string(&b, blob, bloblen); |
1212 | 1231 | ||
@@ -1226,6 +1245,24 @@ sign_and_send_pubkey(Authctxt *authctxt, Identity *id) | |||
1226 | break; | 1245 | break; |
1227 | } | 1246 | } |
1228 | } | 1247 | } |
1248 | /* | ||
1249 | * Exact key matches are preferred, but also allow | ||
1250 | * filename matches for non-PKCS#11/agent keys that | ||
1251 | * didn't load public keys. This supports the case | ||
1252 | * of keeping just a private key file and public | ||
1253 | * certificate on disk. | ||
1254 | */ | ||
1255 | if (!matched && !id->isprivate && id->agent_fd == -1 && | ||
1256 | (id->key->flags & SSHKEY_FLAG_EXT) == 0) { | ||
1257 | TAILQ_FOREACH(private_id, &authctxt->keys, next) { | ||
1258 | if (private_id->key == NULL && | ||
1259 | id_filename_matches(id, private_id)) { | ||
1260 | id = private_id; | ||
1261 | matched = 1; | ||
1262 | break; | ||
1263 | } | ||
1264 | } | ||
1265 | } | ||
1229 | if (matched) { | 1266 | if (matched) { |
1230 | debug2("%s: using private key \"%s\"%s for " | 1267 | debug2("%s: using private key \"%s\"%s for " |
1231 | "certificate", __func__, id->filename, | 1268 | "certificate", __func__, id->filename, |
@@ -1304,7 +1341,7 @@ send_pubkey_test(Authctxt *authctxt, Identity *id) | |||
1304 | packet_put_cstring(authctxt->method->name); | 1341 | packet_put_cstring(authctxt->method->name); |
1305 | packet_put_char(have_sig); | 1342 | packet_put_char(have_sig); |
1306 | if (!(datafellows & SSH_BUG_PKAUTH)) | 1343 | if (!(datafellows & SSH_BUG_PKAUTH)) |
1307 | packet_put_cstring(identity_sign_encode(id)); | 1344 | packet_put_cstring(key_sign_encode(id->key)); |
1308 | packet_put_string(blob, bloblen); | 1345 | packet_put_string(blob, bloblen); |
1309 | free(blob); | 1346 | free(blob); |
1310 | packet_send(); | 1347 | packet_send(); |
@@ -1755,7 +1792,7 @@ ssh_keysign(struct sshkey *key, u_char **sigp, size_t *lenp, | |||
1755 | if ((b = sshbuf_new()) == NULL) | 1792 | if ((b = sshbuf_new()) == NULL) |
1756 | fatal("%s: sshbuf_new failed", __func__); | 1793 | fatal("%s: sshbuf_new failed", __func__); |
1757 | /* send # of sock, data to be signed */ | 1794 | /* send # of sock, data to be signed */ |
1758 | if ((r = sshbuf_put_u32(b, sock) != 0) || | 1795 | if ((r = sshbuf_put_u32(b, sock)) != 0 || |
1759 | (r = sshbuf_put_string(b, data, datalen)) != 0) | 1796 | (r = sshbuf_put_string(b, data, datalen)) != 0) |
1760 | fatal("%s: buffer error: %s", __func__, ssh_err(r)); | 1797 | fatal("%s: buffer error: %s", __func__, ssh_err(r)); |
1761 | if (ssh_msg_send(to[1], version, b) == -1) | 1798 | if (ssh_msg_send(to[1], version, b) == -1) |