@@ -1,4 +1,4 @@
/* $OpenBSD: sshconnect2.c,v 1.226 2015/07/30 00:01:34 djm Exp $ */
/* $OpenBSD: sshconnect2.c,v 1.227 2015/09/24 06:15:11 djm Exp $ */
/*
* Copyright (c) 2000 Markus Friedl. All rights reserved.
* Copyright (c) 2008 Damien Miller. All rights reserved.
@@ -1001,18 +1001,17 @@ static int
sign_and_send_pubkey(Authctxt *authctxt, Identity *id)
{
Buffer b;
Identity *private_id;
u_char *blob, *signature;
u_int bloblen;
size_t slen;
u_int skip = 0;
int ret = -1;
int have_sig = 1;
u_int bloblen, skip = 0;
int matched, ret = -1, have_sig = 1;
char *fp;

if ((fp = sshkey_fingerprint(id->key, options.fingerprint_hash,
SSH_FP_DEFAULT)) == NULL)
return 0;
debug3("sign_and_send_pubkey: %s %s", key_type(id->key), fp);
debug3("%s: %s %s", __func__, key_type(id->key), fp);
free(fp);

if (key_to_blob(id->key, &blob, &bloblen) == 0) {
@@ -1044,6 +1043,36 @@ sign_and_send_pubkey(Authctxt *authctxt, Identity *id)
}
buffer_put_string(&b, blob, bloblen);

/*
* If the key is an certificate, try to find a matching private key
* and use it to complete the signature.
* If no such private key exists, return failure and continue with
* other methods of authentication.
*/
if (key_is_cert(id->key)) {
matched = 0;
TAILQ_FOREACH(private_id, &authctxt->keys, next) {
if (sshkey_equal_public(id->key, private_id->key) &&
id->key->type != private_id->key->type) {
id = private_id;
matched = 1;
break;
}
}
if (matched) {
debug2("%s: using private key \"%s\"%s for "
"certificate", __func__, id->filename,
id->agent_fd != -1 ? " from agent" : "");
} else {
/* XXX maybe verbose/error? */
debug("%s: no private key for certificate "
"\"%s\"", __func__, id->filename);
free(blob);
buffer_free(&b);
return 0;
}
}

/* generate signature */
ret = identity_sign(id, &signature, &slen,
buffer_ptr(&b), buffer_len(&b), datafellows);
@@ -1180,9 +1209,11 @@ load_identity_file(char *filename, int userprovided)

/*
* try keys in the following order:
* 1. agent keys that are found in the config file
* 2. other agent keys
* 3. keys that are only listed in the config file
* 1. certificates listed in the config file
* 2. other input certificates
* 3. agent keys that are found in the config file
* 4. other agent keys
* 5. keys that are only listed in the config file
*/
static void
pubkey_prepare(Authctxt *authctxt)
@@ -1236,6 +1267,18 @@ pubkey_prepare(Authctxt *authctxt)
free(id);
}
}
/* list of certificates specified by user */
for (i = 0; i < options.num_certificate_files; i++) {
key = options.certificates[i];
if (!key_is_cert(key) || key->cert == NULL ||
key->cert->type != SSH2_CERT_TYPE_USER)
continue;
id = xcalloc(1, sizeof(*id));
id->key = key;
id->filename = xstrdup(options.certificate_files[i]);
id->userprovided = options.certificate_file_userprovided[i];
TAILQ_INSERT_TAIL(preferred, id, next);
}
/* list of keys supported by the agent */
if ((r = ssh_get_authentication_socket(&agent_fd)) != 0) {
if (r != SSH_ERR_AGENT_NOT_PRESENT)