diff options
author | djm@openbsd.org <djm@openbsd.org> | 2015-09-24 06:15:11 +0000 |
---|---|---|
committer | Damien Miller <djm@mindrot.org> | 2015-10-06 12:21:54 +1100 |
commit | 4e44a79a07d4b88b6a4e5e8c1bed5f58c841b1b8 (patch) | |
tree | 7ef647dabf413a83da2f0c26917a8e0b5e1d2145 /sshconnect2.c | |
parent | e3cbb06ade83c72b640a53728d362bbefa0008e2 (diff) |
upstream commit
add ssh_config CertificateFile option to explicitly list
a certificate; patch from Meghana Bhat on bz#2436; ok markus@
Upstream-ID: 58648ec53c510b41c1f46d8fe293aadc87229ab8
Diffstat (limited to 'sshconnect2.c')
-rw-r--r-- | sshconnect2.c | 61 |
1 files changed, 52 insertions, 9 deletions
diff --git a/sshconnect2.c b/sshconnect2.c index 775103185..e82188392 100644 --- a/sshconnect2.c +++ b/sshconnect2.c | |||
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: sshconnect2.c,v 1.226 2015/07/30 00:01:34 djm Exp $ */ | 1 | /* $OpenBSD: sshconnect2.c,v 1.227 2015/09/24 06:15:11 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. |
@@ -1001,18 +1001,17 @@ static int | |||
1001 | sign_and_send_pubkey(Authctxt *authctxt, Identity *id) | 1001 | sign_and_send_pubkey(Authctxt *authctxt, Identity *id) |
1002 | { | 1002 | { |
1003 | Buffer b; | 1003 | Buffer b; |
1004 | Identity *private_id; | ||
1004 | u_char *blob, *signature; | 1005 | u_char *blob, *signature; |
1005 | u_int bloblen; | ||
1006 | size_t slen; | 1006 | size_t slen; |
1007 | u_int skip = 0; | 1007 | u_int bloblen, skip = 0; |
1008 | int ret = -1; | 1008 | int matched, ret = -1, have_sig = 1; |
1009 | int have_sig = 1; | ||
1010 | char *fp; | 1009 | char *fp; |
1011 | 1010 | ||
1012 | if ((fp = sshkey_fingerprint(id->key, options.fingerprint_hash, | 1011 | if ((fp = sshkey_fingerprint(id->key, options.fingerprint_hash, |
1013 | SSH_FP_DEFAULT)) == NULL) | 1012 | SSH_FP_DEFAULT)) == NULL) |
1014 | return 0; | 1013 | return 0; |
1015 | debug3("sign_and_send_pubkey: %s %s", key_type(id->key), fp); | 1014 | debug3("%s: %s %s", __func__, key_type(id->key), fp); |
1016 | free(fp); | 1015 | free(fp); |
1017 | 1016 | ||
1018 | if (key_to_blob(id->key, &blob, &bloblen) == 0) { | 1017 | if (key_to_blob(id->key, &blob, &bloblen) == 0) { |
@@ -1044,6 +1043,36 @@ sign_and_send_pubkey(Authctxt *authctxt, Identity *id) | |||
1044 | } | 1043 | } |
1045 | buffer_put_string(&b, blob, bloblen); | 1044 | buffer_put_string(&b, blob, bloblen); |
1046 | 1045 | ||
1046 | /* | ||
1047 | * If the key is an certificate, try to find a matching private key | ||
1048 | * and use it to complete the signature. | ||
1049 | * If no such private key exists, return failure and continue with | ||
1050 | * other methods of authentication. | ||
1051 | */ | ||
1052 | if (key_is_cert(id->key)) { | ||
1053 | matched = 0; | ||
1054 | TAILQ_FOREACH(private_id, &authctxt->keys, next) { | ||
1055 | if (sshkey_equal_public(id->key, private_id->key) && | ||
1056 | id->key->type != private_id->key->type) { | ||
1057 | id = private_id; | ||
1058 | matched = 1; | ||
1059 | break; | ||
1060 | } | ||
1061 | } | ||
1062 | if (matched) { | ||
1063 | debug2("%s: using private key \"%s\"%s for " | ||
1064 | "certificate", __func__, id->filename, | ||
1065 | id->agent_fd != -1 ? " from agent" : ""); | ||
1066 | } else { | ||
1067 | /* XXX maybe verbose/error? */ | ||
1068 | debug("%s: no private key for certificate " | ||
1069 | "\"%s\"", __func__, id->filename); | ||
1070 | free(blob); | ||
1071 | buffer_free(&b); | ||
1072 | return 0; | ||
1073 | } | ||
1074 | } | ||
1075 | |||
1047 | /* generate signature */ | 1076 | /* generate signature */ |
1048 | ret = identity_sign(id, &signature, &slen, | 1077 | ret = identity_sign(id, &signature, &slen, |
1049 | buffer_ptr(&b), buffer_len(&b), datafellows); | 1078 | buffer_ptr(&b), buffer_len(&b), datafellows); |
@@ -1180,9 +1209,11 @@ load_identity_file(char *filename, int userprovided) | |||
1180 | 1209 | ||
1181 | /* | 1210 | /* |
1182 | * try keys in the following order: | 1211 | * try keys in the following order: |
1183 | * 1. agent keys that are found in the config file | 1212 | * 1. certificates listed in the config file |
1184 | * 2. other agent keys | 1213 | * 2. other input certificates |
1185 | * 3. keys that are only listed in the config file | 1214 | * 3. agent keys that are found in the config file |
1215 | * 4. other agent keys | ||
1216 | * 5. keys that are only listed in the config file | ||
1186 | */ | 1217 | */ |
1187 | static void | 1218 | static void |
1188 | pubkey_prepare(Authctxt *authctxt) | 1219 | pubkey_prepare(Authctxt *authctxt) |
@@ -1236,6 +1267,18 @@ pubkey_prepare(Authctxt *authctxt) | |||
1236 | free(id); | 1267 | free(id); |
1237 | } | 1268 | } |
1238 | } | 1269 | } |
1270 | /* list of certificates specified by user */ | ||
1271 | for (i = 0; i < options.num_certificate_files; i++) { | ||
1272 | key = options.certificates[i]; | ||
1273 | if (!key_is_cert(key) || key->cert == NULL || | ||
1274 | key->cert->type != SSH2_CERT_TYPE_USER) | ||
1275 | continue; | ||
1276 | id = xcalloc(1, sizeof(*id)); | ||
1277 | id->key = key; | ||
1278 | id->filename = xstrdup(options.certificate_files[i]); | ||
1279 | id->userprovided = options.certificate_file_userprovided[i]; | ||
1280 | TAILQ_INSERT_TAIL(preferred, id, next); | ||
1281 | } | ||
1239 | /* list of keys supported by the agent */ | 1282 | /* list of keys supported by the agent */ |
1240 | if ((r = ssh_get_authentication_socket(&agent_fd)) != 0) { | 1283 | if ((r = ssh_get_authentication_socket(&agent_fd)) != 0) { |
1241 | if (r != SSH_ERR_AGENT_NOT_PRESENT) | 1284 | if (r != SSH_ERR_AGENT_NOT_PRESENT) |