Bugzilla – Attachment 2887 Details for
Bug 2377
Add ssh-agent support to ssh-keygen
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Requests
|
Help
|
New Account
|
Log In
[x]
|
Forgot Password
Login:
[x]
[patch]
ssh-keygen: Add ssh-agent support for key signing (adapted to master branch)
bug2377-master-010359b.patch (text/plain), 8.51 KB, created by
Riccardo Coccioli
on 2016-11-07 21:53:41 AEDT
(
hide
)
Description:
ssh-keygen: Add ssh-agent support for key signing (adapted to master branch)
Filename:
MIME Type:
Creator:
Riccardo Coccioli
Created:
2016-11-07 21:53:41 AEDT
Size:
8.51 KB
patch
obsolete
>commit c563610eaa1c5968145e5b0bd791c9618dcc748d >Author: Meghana Bhat <mebhat@akamai.com> >Date: Sat Nov 5 01:08:33 2016 +0100 > > ssh-keygen: Add ssh-agent support for key signing > > Communicate with the ssh-agent to sign certificates if agent is present > and is loaded with the specified certificate authority. > In order for the agent to sign, the certificate authority public key > must be alongside the private key with the same file name but a .pub > extension. > > This patch addresses the bug at: > https://bugzilla.mindrot.org/show_bug.cgi?id=2377 > > Patch developed against 7.1p by Meghana Bhat <mebhat@akamai.com>. > Patch adapted to master branch at 5ee3fb5 (post 7.3p1) by Riccardo > Coccioli <rcoccioli@wikimedia.org>. > >diff --git a/authfd.c b/authfd.c >index a634bcb..f587fba 100644 >--- a/authfd.c >+++ b/authfd.c >@@ -121,7 +121,7 @@ ssh_get_authentication_socket(int *fdp) > } > > /* Communicate with agent: send request and read reply */ >-static int >+int > ssh_request_reply(int sock, struct sshbuf *request, struct sshbuf *reply) > { > int r; >diff --git a/authfd.h b/authfd.h >index 4b417e3..e8fde8c 100644 >--- a/authfd.h >+++ b/authfd.h >@@ -42,6 +42,7 @@ int ssh_decrypt_challenge(int sock, struct sshkey* key, BIGNUM *challenge, > int ssh_agent_sign(int sock, struct sshkey *key, > u_char **sigp, size_t *lenp, > const u_char *data, size_t datalen, const char *alg, u_int compat); >+int ssh_request_reply(int sock, struct sshbuf *request, struct sshbuf *reply); > > /* Messages for the authentication agent connection. */ > #define SSH_AGENTC_REQUEST_RSA_IDENTITIES 1 >diff --git a/ssh-keygen.c b/ssh-keygen.c >index 2a7939b..ba270d0 100644 >--- a/ssh-keygen.c >+++ b/ssh-keygen.c >@@ -57,6 +57,7 @@ > #include "atomicio.h" > #include "krl.h" > #include "digest.h" >+#include "authfd.h" > > #ifdef WITH_OPENSSL > # define DEFAULT_KEY_TYPE_NAME "rsa" >@@ -1579,28 +1580,94 @@ load_pkcs11_key(char *path) > #endif /* ENABLE_PKCS11 */ > } > >+static int >+do_agent_sign(int agent_fd, struct sshkey *k, struct sshkey *ca_pk, >+ u_char *ca_blob, size_t ca_len) >+{ >+ u_char type; >+ u_char *sig; >+ size_t slen; >+ struct sshbuf *msg, *cert_blob; >+ u_int flags = 0; >+ int ret = 0, r = 0; >+ >+ cert_blob = k->cert->certblob; /* for readability */ >+ if ((msg = sshbuf_new()) == NULL) >+ fatal("%s: sshbuf_new failed", __func__); >+ if ((r = sshkey_cert_prepare_sign(k, ca_pk)) != 0) >+ ret = -1; >+ >+ if (ret == 0) { >+ if ((r = sshbuf_put_u8(msg, SSH2_AGENTC_SIGN_REQUEST)) != 0 || >+ (r = sshbuf_put_string(msg, ca_blob, ca_len)) != 0 || >+ (r = sshbuf_put_string(msg, sshbuf_ptr(cert_blob), >+ sshbuf_len(cert_blob))) != 0 || >+ (r = sshbuf_put_u32(msg, flags)) != 0) >+ fatal("%s: buffer error: %s", __func__, ssh_err(r)); >+ if ((r = ssh_request_reply(agent_fd, msg, msg)) != 0) >+ ret = -1; >+ else if ((r = sshbuf_get_u8(msg, &type)) != 0) >+ fatal("%s: buffer error: %s", __func__, ssh_err(r)); >+ else if ((type == SSH_AGENT_FAILURE) || (type == SSH2_AGENT_FAILURE)) >+ ret = -1; >+ else if ((r = sshbuf_get_string(msg, &sig, &slen)) != 0 || >+ (r = sshbuf_put_string(cert_blob, sig, slen)) != 0) >+ fatal("%s: buffer error: %s", __func__, ssh_err(r)); >+ else >+ free(sig); >+ } >+ >+ sshbuf_free(msg); >+ return ret; >+} >+ > static void > do_ca_sign(struct passwd *pw, int argc, char **argv) > { >- int r, i, fd; >+ int r, i, fd, agent_fd; > u_int n; >- struct sshkey *ca, *public; >+ struct sshkey *ca, *ca_pk, *public; > char valid[64], *otmp, *tmp, *cp, *out, *comment, **plist = NULL; > FILE *f; >+ u_char *ca_blob; >+ size_t ca_len; >+ /* flag indicating whether to try the ssh-agent to sign certificates */ >+ int try_agent = 0; > > #ifdef ENABLE_PKCS11 > pkcs11_init(1); > #endif >+ >+ /* load pubkey of CA first (ca_blob), if it works, try getting agent socket */ > tmp = tilde_expand_filename(ca_key_path, pw->pw_uid); >- if (pkcs11provider != NULL) { >- if ((ca = load_pkcs11_key(tmp)) == NULL) >- fatal("No PKCS#11 key matching %s found", ca_key_path); >- } else >- ca = load_identity(tmp); >- free(tmp); >+ >+ if ((r = sshkey_load_public(tmp, &ca_pk, NULL)) == 0 && >+ (r = sshkey_to_blob(ca_pk, &ca_blob, &ca_len)) == 0) { >+ switch (r = ssh_get_authentication_socket(&agent_fd)) { >+ case SSH_ERR_SUCCESS: >+ try_agent = 1; >+ ca = NULL; >+ break; >+ case SSH_ERR_AGENT_NOT_PRESENT: >+ debug("Couldn't open connection to agent"); >+ break; >+ default: >+ debug("Error connecting to agent"); >+ break; >+ } >+ } >+ >+ if (!try_agent) { >+ if (pkcs11provider != NULL) { >+ if ((ca = load_pkcs11_key(tmp)) == NULL) >+ fatal("No PKCS#11 key matching %s found", ca_key_path); >+ } else >+ ca = load_identity(tmp); >+ free(tmp); >+ } > > if (key_type_name != NULL && >- sshkey_type_from_name(key_type_name) != ca->type) { >+ sshkey_type_from_name(key_type_name) != ca->type) { > fatal("CA key type %s doesn't match specified %s", > sshkey_ssh_name(ca), key_type_name); > } >@@ -1618,7 +1685,7 @@ do_ca_sign(struct passwd *pw, int argc, char **argv) > } > free(otmp); > } >- >+ > tmp = tilde_expand_filename(argv[i], pw->pw_uid); > if ((r = sshkey_load_public(tmp, &public, &comment)) != 0) > fatal("%s: unable to open \"%s\": %s", >@@ -1642,12 +1709,27 @@ do_ca_sign(struct passwd *pw, int argc, char **argv) > prepare_options_buf(public->cert->critical, OPTIONS_CRITICAL); > prepare_options_buf(public->cert->extensions, > OPTIONS_EXTENSIONS); >- if ((r = sshkey_from_private(ca, >- &public->cert->signature_key)) != 0) >- fatal("key_from_private (ca key): %s", ssh_err(r)); > >- if ((r = sshkey_certify(public, ca, key_type_name)) != 0) >- fatal("Couldn't certify key %s: %s", tmp, ssh_err(r)); >+ if (try_agent && >+ (r = do_agent_sign(agent_fd, public, ca_pk, ca_blob, ca_len)) != 0) { >+ try_agent = 0; >+ otmp = tilde_expand_filename(ca_key_path, pw->pw_uid); >+ if (pkcs11provider != NULL) { >+ if ((ca = load_pkcs11_key(otmp)) == NULL) >+ fatal("No PKCS#11 key matching %s found", ca_key_path); >+ } else >+ ca = load_identity(otmp); >+ free(otmp); >+ } >+ >+ if (!try_agent) { >+ if ((r = sshkey_from_private(ca, >+ &public->cert->signature_key)) != 0) >+ fatal("key_from_private (ca key): %s", ssh_err(r)); >+ >+ if ((r = sshkey_certify(public, ca, key_type_name)) != 0) >+ fatal("Couldn't certify key %s: %s", tmp, ssh_err(r)); >+ } > > if ((cp = strrchr(tmp, '.')) != NULL && strcmp(cp, ".pub") == 0) > *cp = '\0'; >diff --git a/sshkey.c b/sshkey.c >index c01da6c..d43f681 100644 >--- a/sshkey.c >+++ b/sshkey.c >@@ -2369,13 +2369,13 @@ sshkey_drop_cert(struct sshkey *k) > return 0; > } > >-/* Sign a certified key, (re-)generating the signed certblob. */ >+/* Prepare a certificate blob for CA signing. */ > int >-sshkey_certify(struct sshkey *k, struct sshkey *ca, const char *alg) >+sshkey_cert_prepare_sign(struct sshkey *k, struct sshkey *ca) > { > struct sshbuf *principals = NULL; >- u_char *ca_blob = NULL, *sig_blob = NULL, nonce[32]; >- size_t i, ca_len, sig_len; >+ u_char *ca_blob = NULL, nonce[32]; >+ size_t i, ca_len; > int ret = SSH_ERR_INTERNAL_ERROR; > struct sshbuf *cert; > >@@ -2458,6 +2458,29 @@ sshkey_certify(struct sshkey *k, struct sshkey *ca, const char *alg) > (ret = sshbuf_put_string(cert, NULL, 0)) != 0 || /* Reserved */ > (ret = sshbuf_put_string(cert, ca_blob, ca_len)) != 0) > goto out; >+ ret = 0; >+ out: >+ if (ret != 0) >+ sshbuf_reset(cert); >+ if (ca_blob != NULL) >+ free(ca_blob); >+ if (principals != NULL) >+ sshbuf_free(principals); >+ return ret; >+} >+ >+/* Sign a certified key, (re-)generating the signed certblob. */ >+int >+sshkey_certify(struct sshkey *k, struct sshkey *ca, const char *alg) >+{ >+ u_char *sig_blob = NULL; >+ size_t sig_len; >+ int ret = SSH_ERR_INTERNAL_ERROR; >+ struct sshbuf *cert; >+ >+ cert = k->cert->certblob; /* for readability */ >+ if ((ret = sshkey_cert_prepare_sign(k, ca)) != 0) >+ goto out; > > /* Sign the whole mess */ > if ((ret = sshkey_sign(ca, &sig_blob, &sig_len, sshbuf_ptr(cert), >@@ -2472,8 +2495,6 @@ sshkey_certify(struct sshkey *k, struct sshkey *ca, const char *alg) > if (ret != 0) > sshbuf_reset(cert); > free(sig_blob); >- free(ca_blob); >- sshbuf_free(principals); > return ret; > } > >diff --git a/sshkey.h b/sshkey.h >index f393638..53018c2 100644 >--- a/sshkey.h >+++ b/sshkey.h >@@ -137,6 +137,7 @@ int sshkey_type_is_cert(int); > int sshkey_type_plain(int); > int sshkey_to_certified(struct sshkey *); > int sshkey_drop_cert(struct sshkey *); >+int sshkey_cert_prepare_sign(struct sshkey *, struct sshkey *); > int sshkey_certify(struct sshkey *, struct sshkey *, const char *); > int sshkey_cert_copy(const struct sshkey *, struct sshkey *); > int sshkey_cert_check_authority(const struct sshkey *, int, int,
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Actions:
View
|
Diff
Attachments on
bug 2377
:
2690
|
2692
|
2887
|
2983