From 8372b8fc54c62915c3e18dbecd04f6d4ebbccfb7 Mon Sep 17 00:00:00 2001 From: Tobias Brunner Date: Mon, 1 Apr 2013 14:47:09 +0200 Subject: [PATCH 01/14] charon-cmd: Load pubkey plugin to load raw keys --- configure.in | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configure.in b/configure.in index 06829755f..818d48561 100644 --- a/configure.in +++ b/configure.in @@ -961,7 +961,7 @@ ADD_PLUGIN([nonce], [s charon nm cmd]) ADD_PLUGIN([x509], [s charon openac scepclient pki scripts attest nm cmd]) ADD_PLUGIN([revocation], [s charon nm cmd]) ADD_PLUGIN([constraints], [s charon nm cmd]) -ADD_PLUGIN([pubkey], [s charon]) +ADD_PLUGIN([pubkey], [s charon cmd]) ADD_PLUGIN([pkcs1], [s charon openac scepclient pki scripts manager medsrv attest nm cmd]) ADD_PLUGIN([pkcs7], [s scepclient pki]) ADD_PLUGIN([pkcs8], [s charon openac scepclient pki scripts manager medsrv attest nm cmd]) From 4dc50bf9de08e08abd6fbc85434c3f34a01e601f Mon Sep 17 00:00:00 2001 From: Tobias Brunner Date: Mon, 1 Apr 2013 14:48:02 +0200 Subject: [PATCH 02/14] charon-cmd: Use loose matching of gateway identity --- src/charon-cmd/cmd/cmd_connection.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/charon-cmd/cmd/cmd_connection.c b/src/charon-cmd/cmd/cmd_connection.c index 965b72bc0..0aedf76ce 100644 --- a/src/charon-cmd/cmd/cmd_connection.c +++ b/src/charon-cmd/cmd/cmd_connection.c @@ -180,6 +180,7 @@ static void add_auth_cfg(private_cmd_connection_t *this, peer_cfg_t *peer_cfg, { id = identification_create_from_string(this->host); } + auth->add(auth, AUTH_RULE_IDENTITY_LOOSE, TRUE); } auth->add(auth, AUTH_RULE_IDENTITY, id); peer_cfg->add_auth_cfg(peer_cfg, auth, local); From ee7b73832c97c12932641ba61c52211810afde00 Mon Sep 17 00:00:00 2001 From: Tobias Brunner Date: Mon, 1 Apr 2013 14:51:09 +0200 Subject: [PATCH 03/14] charon-cmd: Add --agent option to authenticate using ssh-agent(1) The socket path is read from the SSH_AUTH_SOCK environment variable. So using this with sudo might require the -E command line (or an appropriate sudoers config) to preserve the environment. --- src/charon-cmd/cmd/cmd_connection.c | 1 + src/charon-cmd/cmd/cmd_creds.c | 68 +++++++++++++++++++++++++++++ src/charon-cmd/cmd/cmd_options.c | 2 + src/charon-cmd/cmd/cmd_options.h | 1 + 4 files changed, 72 insertions(+) diff --git a/src/charon-cmd/cmd/cmd_connection.c b/src/charon-cmd/cmd/cmd_connection.c index 0aedf76ce..8b42befe9 100644 --- a/src/charon-cmd/cmd/cmd_connection.c +++ b/src/charon-cmd/cmd/cmd_connection.c @@ -387,6 +387,7 @@ METHOD(cmd_connection_t, handle, bool, this->identity = arg; break; case CMD_OPT_RSA: + case CMD_OPT_AGENT: this->key_seen = TRUE; break; case CMD_OPT_LOCAL_TS: diff --git a/src/charon-cmd/cmd/cmd_creds.c b/src/charon-cmd/cmd/cmd_creds.c index b70490915..178b77d49 100644 --- a/src/charon-cmd/cmd/cmd_creds.c +++ b/src/charon-cmd/cmd/cmd_creds.c @@ -47,6 +47,16 @@ struct private_cmd_creds_t { * Already prompted for password? */ bool prompted; + + /** + * Provide keys via ssh-agent + */ + bool agent; + + /** + * Local identity + */ + char *identity; }; /** @@ -119,6 +129,54 @@ static void load_key(private_cmd_creds_t *this, key_type_t type, char *path) this->creds->add_key(this->creds, privkey); } +/** + * Load a private and public key via ssh-agent + */ +static void load_agent(private_cmd_creds_t *this) +{ + private_key_t *privkey; + public_key_t *pubkey; + identification_t *id; + certificate_t *cert; + char *agent; + + agent = getenv("SSH_AUTH_SOCK"); + if (!agent) + { + DBG1(DBG_CFG, "ssh-agent socket not found"); + exit(1); + } + + privkey = lib->creds->create(lib->creds, CRED_PRIVATE_KEY, + KEY_RSA, BUILD_AGENT_SOCKET, agent, BUILD_END); + if (!privkey) + { + DBG1(DBG_CFG, "failed to load private key from ssh-agent"); + exit(1); + } + pubkey = privkey->get_public_key(privkey); + if (!pubkey) + { + DBG1(DBG_CFG, "failed to load public key from ssh-agent"); + privkey->destroy(privkey); + exit(1); + } + id = identification_create_from_string(this->identity); + cert = lib->creds->create(lib->creds, CRED_CERTIFICATE, + CERT_TRUSTED_PUBKEY, BUILD_PUBLIC_KEY, pubkey, + BUILD_SUBJECT, id, BUILD_END); + pubkey->destroy(pubkey); + id->destroy(id); + if (!cert) + { + DBG1(DBG_CFG, "failed to create certificate for ssh-agent public key"); + privkey->destroy(privkey); + exit(1); + } + this->creds->add_cert(this->creds, TRUE, cert); + this->creds->add_key(this->creds, privkey); +} + METHOD(cmd_creds_t, handle, bool, private_cmd_creds_t *this, cmd_option_type_t opt, char *arg) { @@ -130,9 +188,19 @@ METHOD(cmd_creds_t, handle, bool, case CMD_OPT_RSA: load_key(this, KEY_RSA, arg); break; + case CMD_OPT_IDENTITY: + this->identity = arg; + break; + case CMD_OPT_AGENT: + this->agent = TRUE; + break; default: return FALSE; } + if (this->agent && this->identity) + { + load_agent(this); + } return TRUE; } diff --git a/src/charon-cmd/cmd/cmd_options.c b/src/charon-cmd/cmd/cmd_options.c index 312d12964..6b7df6d93 100644 --- a/src/charon-cmd/cmd/cmd_options.c +++ b/src/charon-cmd/cmd/cmd_options.c @@ -35,6 +35,8 @@ cmd_option_t cmd_options[CMD_OPT_COUNT] = { "trusted certificate, for authentication or trust chain validation" }, { CMD_OPT_RSA, "rsa", required_argument, "path", "RSA private key to use for authentication" }, + { CMD_OPT_AGENT, "agent", no_argument, "", + "use SSH agent for authentication"}, { CMD_OPT_LOCAL_TS, "local-ts", required_argument, "subnet", "additional traffic selector to propose for our side" }, { CMD_OPT_REMOTE_TS, "remote-ts", required_argument, "subnet", diff --git a/src/charon-cmd/cmd/cmd_options.h b/src/charon-cmd/cmd/cmd_options.h index addbb50d8..a14896f83 100644 --- a/src/charon-cmd/cmd/cmd_options.h +++ b/src/charon-cmd/cmd/cmd_options.h @@ -35,6 +35,7 @@ enum cmd_option_type_t { CMD_OPT_REMOTE_IDENTITY, CMD_OPT_CERT, CMD_OPT_RSA, + CMD_OPT_AGENT, CMD_OPT_LOCAL_TS, CMD_OPT_REMOTE_TS, CMD_OPT_PROFILE, From c0bbddfa42bfc9838a634873f44e733d9251ada6 Mon Sep 17 00:00:00 2001 From: Tobias Brunner Date: Mon, 1 Apr 2013 13:51:37 +0200 Subject: [PATCH 04/14] Try to load raw keys from ipsec.conf as PKCS#1 blob first The DNSKEY builder is quite eager and parses pretty much anything as RSA key, so this has to be done before. --- src/libcharon/plugins/stroke/stroke_cred.c | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/src/libcharon/plugins/stroke/stroke_cred.c b/src/libcharon/plugins/stroke/stroke_cred.c index eda746f7e..6c47a7b06 100644 --- a/src/libcharon/plugins/stroke/stroke_cred.c +++ b/src/libcharon/plugins/stroke/stroke_cred.c @@ -291,17 +291,24 @@ METHOD(stroke_cred_t, load_pubkey, certificate_t*, } else if (strncaseeq(filename, "0x", 2) || strncaseeq(filename, "0s", 2)) { - chunk_t printable_key, rfc3110_key; + chunk_t printable_key, raw_key; public_key_t *key; printable_key = chunk_create(filename + 2, strlen(filename) - 2); - rfc3110_key = strncaseeq(filename, "0x", 2) ? + raw_key = strncaseeq(filename, "0x", 2) ? chunk_from_hex(printable_key, NULL) : chunk_from_base64(printable_key, NULL); - key = lib->creds->create(lib->creds, CRED_PUBLIC_KEY, KEY_RSA, - BUILD_BLOB_DNSKEY, rfc3110_key, + key = lib->creds->create(lib->creds, CRED_PUBLIC_KEY, KEY_ANY, + BUILD_BLOB_ASN1_DER, raw_key, BUILD_END); - free(rfc3110_key.ptr); + if (!key) + { /* try RFC 3110 format (as it accepts nearly any blob, the above has + * to be tried first) */ + key = lib->creds->create(lib->creds, CRED_PUBLIC_KEY, KEY_RSA, + BUILD_BLOB_DNSKEY, raw_key, + BUILD_END); + } + chunk_free(&raw_key); if (key) { cert = lib->creds->create(lib->creds, CRED_CERTIFICATE, From 584d656b774ca11f415d0ea0257dbf4558326562 Mon Sep 17 00:00:00 2001 From: Tobias Brunner Date: Mon, 1 Apr 2013 15:20:39 +0200 Subject: [PATCH 05/14] Add sshkey plugin stub that will parse RFC 4253 public keys --- configure.in | 4 ++ src/libstrongswan/Makefile.am | 7 ++ src/libstrongswan/plugins/sshkey/Makefile.am | 15 ++++ .../plugins/sshkey/sshkey_plugin.c | 72 +++++++++++++++++++ .../plugins/sshkey/sshkey_plugin.h | 42 +++++++++++ 5 files changed, 140 insertions(+) create mode 100644 src/libstrongswan/plugins/sshkey/Makefile.am create mode 100644 src/libstrongswan/plugins/sshkey/sshkey_plugin.c create mode 100644 src/libstrongswan/plugins/sshkey/sshkey_plugin.h diff --git a/configure.in b/configure.in index 818d48561..49a91647b 100644 --- a/configure.in +++ b/configure.in @@ -130,6 +130,7 @@ ARG_DISBL_SET([pkcs7], [disable PKCS7 container support plugin.]) ARG_DISBL_SET([pkcs8], [disable PKCS8 private key decoding plugin.]) ARG_DISBL_SET([pgp], [disable PGP key decoding plugin.]) ARG_DISBL_SET([dnskey], [disable DNS RR key decoding plugin.]) +ARG_DISBL_SET([sshkey], [disable SSH key decoding plugin.]) ARG_ENABL_SET([ipseckey], [enable IPSECKEY authentication plugin.]) ARG_DISBL_SET([pem], [disable PEM decoding plugin.]) ARG_DISBL_SET([hmac], [disable HMAC crypto implementation plugin.]) @@ -967,6 +968,7 @@ ADD_PLUGIN([pkcs7], [s scepclient pki]) ADD_PLUGIN([pkcs8], [s charon openac scepclient pki scripts manager medsrv attest nm cmd]) ADD_PLUGIN([pgp], [s charon]) ADD_PLUGIN([dnskey], [s charon]) +ADD_PLUGIN([sshkey], [s charon]) ADD_PLUGIN([ipseckey], [c charon]) ADD_PLUGIN([pem], [s charon openac scepclient pki scripts manager medsrv attest nm cmd]) ADD_PLUGIN([padlock], [s charon]) @@ -1097,6 +1099,7 @@ AM_CONDITIONAL(USE_PKCS7, test x$pkcs7 = xtrue) AM_CONDITIONAL(USE_PKCS8, test x$pkcs8 = xtrue) AM_CONDITIONAL(USE_PGP, test x$pgp = xtrue) AM_CONDITIONAL(USE_DNSKEY, test x$dnskey = xtrue) +AM_CONDITIONAL(USE_SSHKEY, test x$sshkey = xtrue) AM_CONDITIONAL(USE_PEM, test x$pem = xtrue) AM_CONDITIONAL(USE_HMAC, test x$hmac = xtrue) AM_CONDITIONAL(USE_CMAC, test x$cmac = xtrue) @@ -1291,6 +1294,7 @@ AC_CONFIG_FILES([ src/libstrongswan/plugins/pkcs8/Makefile src/libstrongswan/plugins/pgp/Makefile src/libstrongswan/plugins/dnskey/Makefile + src/libstrongswan/plugins/sshkey/Makefile src/libstrongswan/plugins/pem/Makefile src/libstrongswan/plugins/curl/Makefile src/libstrongswan/plugins/unbound/Makefile diff --git a/src/libstrongswan/Makefile.am b/src/libstrongswan/Makefile.am index ce6df2855..b5a4b9bab 100644 --- a/src/libstrongswan/Makefile.am +++ b/src/libstrongswan/Makefile.am @@ -315,6 +315,13 @@ if MONOLITHIC endif endif +if USE_SSHKEY + SUBDIRS += plugins/sshkey +if MONOLITHIC + libstrongswan_la_LIBADD += plugins/sshkey/libstrongswan-sshkey.la +endif +endif + if USE_PEM SUBDIRS += plugins/pem if MONOLITHIC diff --git a/src/libstrongswan/plugins/sshkey/Makefile.am b/src/libstrongswan/plugins/sshkey/Makefile.am new file mode 100644 index 000000000..108a5f3a3 --- /dev/null +++ b/src/libstrongswan/plugins/sshkey/Makefile.am @@ -0,0 +1,15 @@ + +INCLUDES = -I$(top_srcdir)/src/libstrongswan + +AM_CFLAGS = -rdynamic + +if MONOLITHIC +noinst_LTLIBRARIES = libstrongswan-sshkey.la +else +plugin_LTLIBRARIES = libstrongswan-sshkey.la +endif + +libstrongswan_sshkey_la_SOURCES = \ + sshkey_plugin.h sshkey_plugin.c + +libstrongswan_sshkey_la_LDFLAGS = -module -avoid-version diff --git a/src/libstrongswan/plugins/sshkey/sshkey_plugin.c b/src/libstrongswan/plugins/sshkey/sshkey_plugin.c new file mode 100644 index 000000000..3d90db6db --- /dev/null +++ b/src/libstrongswan/plugins/sshkey/sshkey_plugin.c @@ -0,0 +1,72 @@ +/* + * Copyright (C) 2013 Tobias Brunner + * Hochschule fuer Technik Rapperswil + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. See . + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + */ + +#include "sshkey_plugin.h" + +#include + +typedef struct private_sshkey_plugin_t private_sshkey_plugin_t; + +/** + * private data of sshkey_plugin + */ +struct private_sshkey_plugin_t { + + /** + * public functions + */ + sshkey_plugin_t public; +}; + +METHOD(plugin_t, get_name, char*, + private_sshkey_plugin_t *this) +{ + return "sshkey"; +} + +METHOD(plugin_t, get_features, int, + private_sshkey_plugin_t *this, plugin_feature_t *features[]) +{ + static plugin_feature_t f[] = { + }; + *features = f; + return countof(f); +} + +METHOD(plugin_t, destroy, void, + private_sshkey_plugin_t *this) +{ + free(this); +} + +/* + * see header file + */ +plugin_t *sshkey_plugin_create() +{ + private_sshkey_plugin_t *this; + + INIT(this, + .public = { + .plugin = { + .get_name = _get_name, + .get_features = _get_features, + .destroy = _destroy, + }, + }, + ); + + return &this->public.plugin; +} diff --git a/src/libstrongswan/plugins/sshkey/sshkey_plugin.h b/src/libstrongswan/plugins/sshkey/sshkey_plugin.h new file mode 100644 index 000000000..2b9095a98 --- /dev/null +++ b/src/libstrongswan/plugins/sshkey/sshkey_plugin.h @@ -0,0 +1,42 @@ +/* + * Copyright (C) 2013 Tobias Brunner + * Hochschule fuer Technik Rapperswil + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. See . + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + */ + +/** + * @defgroup sshkey_p sshkey + * @ingroup plugins + * + * @defgroup sshkey_plugin sshkey_plugin + * @{ @ingroup sshkey_p + */ + +#ifndef SSHKEY_PLUGIN_H_ +#define SSHKEY_PLUGIN_H_ + +#include + +typedef struct sshkey_plugin_t sshkey_plugin_t; + +/** + * Plugin providing RFC 4253 public key decoding functions. + */ +struct sshkey_plugin_t { + + /** + * implements plugin interface + */ + plugin_t plugin; +}; + +#endif /** SSHKEY_PLUGIN_H_ @}*/ From cc4408abcb47fa48a2dc633ebd9f2a8bf1144caf Mon Sep 17 00:00:00 2001 From: Tobias Brunner Date: Mon, 1 Apr 2013 16:02:00 +0200 Subject: [PATCH 06/14] sshkey: Added builder for SSHKEY RSA keys --- src/libstrongswan/credentials/builder.c | 1 + src/libstrongswan/credentials/builder.h | 2 + src/libstrongswan/plugins/sshkey/Makefile.am | 3 +- .../plugins/sshkey/sshkey_builder.c | 83 +++++++++++++++++++ .../plugins/sshkey/sshkey_builder.h | 51 ++++++++++++ .../plugins/sshkey/sshkey_plugin.c | 3 + 6 files changed, 142 insertions(+), 1 deletion(-) create mode 100644 src/libstrongswan/plugins/sshkey/sshkey_builder.c create mode 100644 src/libstrongswan/plugins/sshkey/sshkey_builder.h diff --git a/src/libstrongswan/credentials/builder.c b/src/libstrongswan/credentials/builder.c index f5858382f..6710dfb54 100644 --- a/src/libstrongswan/credentials/builder.c +++ b/src/libstrongswan/credentials/builder.c @@ -24,6 +24,7 @@ ENUM(builder_part_names, BUILD_FROM_FILE, BUILD_END, "BUILD_BLOB_PEM", "BUILD_BLOB_PGP", "BUILD_BLOB_DNSKEY", + "BUILD_BLOB_SSHKEY", "BUILD_BLOB_ALGID_PARAMS", "BUILD_KEY_SIZE", "BUILD_SIGNING_KEY", diff --git a/src/libstrongswan/credentials/builder.h b/src/libstrongswan/credentials/builder.h index 740041aac..5ab462fa8 100644 --- a/src/libstrongswan/credentials/builder.h +++ b/src/libstrongswan/credentials/builder.h @@ -59,6 +59,8 @@ enum builder_part_t { BUILD_BLOB_PGP, /** DNS public key blob (RFC 4034, RSA specifc RFC 3110), chunk_t */ BUILD_BLOB_DNSKEY, + /** SSH public key blob (RFC 4253), chunk_t */ + BUILD_BLOB_SSHKEY, /** parameters from algorithmIdentifier (ASN.1 blob), chunk_t */ BUILD_BLOB_ALGID_PARAMS, /** key size in bits, as used for key generation, u_int */ diff --git a/src/libstrongswan/plugins/sshkey/Makefile.am b/src/libstrongswan/plugins/sshkey/Makefile.am index 108a5f3a3..8101726b6 100644 --- a/src/libstrongswan/plugins/sshkey/Makefile.am +++ b/src/libstrongswan/plugins/sshkey/Makefile.am @@ -10,6 +10,7 @@ plugin_LTLIBRARIES = libstrongswan-sshkey.la endif libstrongswan_sshkey_la_SOURCES = \ - sshkey_plugin.h sshkey_plugin.c + sshkey_plugin.h sshkey_plugin.c \ + sshkey_builder.h sshkey_builder.c libstrongswan_sshkey_la_LDFLAGS = -module -avoid-version diff --git a/src/libstrongswan/plugins/sshkey/sshkey_builder.c b/src/libstrongswan/plugins/sshkey/sshkey_builder.c new file mode 100644 index 000000000..31c7b2164 --- /dev/null +++ b/src/libstrongswan/plugins/sshkey/sshkey_builder.c @@ -0,0 +1,83 @@ +/* + * Copyright (C) 2013 Tobias Brunner + * Hochschule fuer Technik Rapperswil + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. See . + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + */ + +#include "sshkey_builder.h" + +#include +#include + +/** + * Load a generic public key from an SSH key blob + */ +static sshkey_public_key_t *parse_public_key(chunk_t blob) +{ + bio_reader_t *reader; + chunk_t format; + + reader = bio_reader_create(blob); + if (!reader->read_data32(reader, &format)) + { + DBG1(DBG_LIB, "invalid key format in SSH key"); + reader->destroy(reader); + return NULL; + } + if (chunk_equals(format, chunk_from_str("ssh-rsa"))) + { + chunk_t n, e; + + if (!reader->read_data32(reader, &e) || + !reader->read_data32(reader, &n)) + { + DBG1(DBG_LIB, "invalid RSA key in SSH key"); + reader->destroy(reader); + return NULL; + } + reader->destroy(reader); + return lib->creds->create(lib->creds, CRED_PUBLIC_KEY, KEY_RSA, + BUILD_RSA_MODULUS, n, BUILD_RSA_PUB_EXP, e, BUILD_END); + } + DBG1(DBG_LIB, "unsupported SSH key format %.*s", (int)format.len, + format.ptr); + reader->destroy(reader); + return NULL; +} + +/** + * See header. + */ +sshkey_public_key_t *sshkey_public_key_load(key_type_t type, va_list args) +{ + chunk_t blob = chunk_empty; + + while (TRUE) + { + switch (va_arg(args, builder_part_t)) + { + case BUILD_BLOB_SSHKEY: + blob = va_arg(args, chunk_t); + continue; + case BUILD_END: + break; + default: + return NULL; + } + break; + } + if (blob.ptr && type == KEY_ANY) + { + return parse_public_key(blob); + } + return NULL; +} diff --git a/src/libstrongswan/plugins/sshkey/sshkey_builder.h b/src/libstrongswan/plugins/sshkey/sshkey_builder.h new file mode 100644 index 000000000..e4c7a90d0 --- /dev/null +++ b/src/libstrongswan/plugins/sshkey/sshkey_builder.h @@ -0,0 +1,51 @@ +/* + * Copyright (C) 2013 Tobias Brunner + * Hochschule fuer Technik Rapperswil + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. See . + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + */ + +/** + * @defgroup sshky_public_key sshky_public_key + * @{ @ingroup sshkey_p + */ + +#ifndef SSHKEY_BUILDER_H_ +#define SSHKEY_BUILDER_H_ + +#include +#include + +typedef struct sshkey_public_key_t sshkey_public_key_t; + +/** + * Public key implementation supporting RFC 4253 decoding. + */ +struct sshkey_public_key_t { + + /** + * Implements public_key_t interface. + */ + public_key_t interface; +}; + +/** + * Load a public key in RFC 4253 format. + * + * Takes a BUILD_BLOB_SSHKEY to parse the public key. + * + * @param type type of the key, must be KEY_ANY + * @param args builder_part_t argument list + * @return built key, NULL on failure + */ +sshkey_public_key_t *sshkey_public_key_load(key_type_t type, va_list args); + +#endif /** SSHKEY_BUILDER_H_ @}*/ diff --git a/src/libstrongswan/plugins/sshkey/sshkey_plugin.c b/src/libstrongswan/plugins/sshkey/sshkey_plugin.c index 3d90db6db..fe6252671 100644 --- a/src/libstrongswan/plugins/sshkey/sshkey_plugin.c +++ b/src/libstrongswan/plugins/sshkey/sshkey_plugin.c @@ -16,6 +16,7 @@ #include "sshkey_plugin.h" #include +#include "sshkey_builder.h" typedef struct private_sshkey_plugin_t private_sshkey_plugin_t; @@ -40,6 +41,8 @@ METHOD(plugin_t, get_features, int, private_sshkey_plugin_t *this, plugin_feature_t *features[]) { static plugin_feature_t f[] = { + PLUGIN_REGISTER(PUBKEY, sshkey_public_key_load, FALSE), + PLUGIN_PROVIDE(PUBKEY, KEY_ANY), }; *features = f; return countof(f); From fa1d3d39dc50ce8f8ce55f838edb02b3ffd07bbe Mon Sep 17 00:00:00 2001 From: Tobias Brunner Date: Mon, 1 Apr 2013 16:28:28 +0200 Subject: [PATCH 07/14] left|rightrsasigkey accepts SSH keys but the key format has to be specified explicitly The default is now PKCS#1. With the dns: and ssh: prefixes other formats can be selected. --- man/ipsec.conf.5.in | 12 +++++-- src/libcharon/plugins/stroke/stroke_cred.c | 34 ++++++++++++------- .../net2net-rsa/hosts/moon/etc/ipsec.conf | 4 +-- .../net2net-rsa/hosts/sun/etc/ipsec.conf | 4 +-- .../rw-dnssec/hosts/carol/etc/ipsec.conf | 2 +- .../ikev2/rw-dnssec/hosts/dave/etc/ipsec.conf | 2 +- 6 files changed, 37 insertions(+), 21 deletions(-) diff --git a/man/ipsec.conf.5.in b/man/ipsec.conf.5.in index e778ab773..a8933531c 100644 --- a/man/ipsec.conf.5.in +++ b/man/ipsec.conf.5.in @@ -756,9 +756,15 @@ None of the kernel backends currently supports opaque or port ranges and uses for policy installation instead. .TP .BR leftrsasigkey " = | " -the left participant's public key for RSA signature authentication, in RFC 2537 -format using hex (0x prefix) or base64 (0s prefix) encoding. Also accepted is -the path to a file containing the public key in PEM or DER encoding. +the left participant's public key for RSA signature authentication, in PKCS#1 +format using hex (0x prefix) or base64 (0s prefix) encoding. With the optional +.B dns: +or +.B ssh: +prefix in front of 0x or 0s, the public key is expected to be in either +the RFC 3110 or RFC 4253 public key format, respectively. +Also accepted is the path to a file containing the public key in PEM or DER +encoding. .TP .BR leftsendcert " = never | no | " ifasked " | always | yes" Accepted values are diff --git a/src/libcharon/plugins/stroke/stroke_cred.c b/src/libcharon/plugins/stroke/stroke_cred.c index 6c47a7b06..bee16c581 100644 --- a/src/libcharon/plugins/stroke/stroke_cred.c +++ b/src/libcharon/plugins/stroke/stroke_cred.c @@ -284,12 +284,30 @@ METHOD(stroke_cred_t, load_pubkey, certificate_t*, { certificate_t *cert; char path[PATH_MAX]; + builder_part_t build_part; + key_type_t build_type = KEY_ANY; if (streq(filename, "%dns")) { - + return NULL; } - else if (strncaseeq(filename, "0x", 2) || strncaseeq(filename, "0s", 2)) + if (strncaseeq(filename, "dns:", 4)) + { /* RFC 3110 format */ + build_part = BUILD_BLOB_DNSKEY; + /* not a complete RR */ + build_type = KEY_RSA; + filename += 4; + } + else if (strncaseeq(filename, "ssh:", 4)) + { /* SSH key */ + build_part = BUILD_BLOB_SSHKEY; + filename += 4; + } + else + { /* try PKCS#1 by default */ + build_part = BUILD_BLOB_ASN1_DER; + } + if (strncaseeq(filename, "0x", 2) || strncaseeq(filename, "0s", 2)) { chunk_t printable_key, raw_key; public_key_t *key; @@ -298,16 +316,8 @@ METHOD(stroke_cred_t, load_pubkey, certificate_t*, raw_key = strncaseeq(filename, "0x", 2) ? chunk_from_hex(printable_key, NULL) : chunk_from_base64(printable_key, NULL); - key = lib->creds->create(lib->creds, CRED_PUBLIC_KEY, KEY_ANY, - BUILD_BLOB_ASN1_DER, raw_key, - BUILD_END); - if (!key) - { /* try RFC 3110 format (as it accepts nearly any blob, the above has - * to be tried first) */ - key = lib->creds->create(lib->creds, CRED_PUBLIC_KEY, KEY_RSA, - BUILD_BLOB_DNSKEY, raw_key, - BUILD_END); - } + key = lib->creds->create(lib->creds, CRED_PUBLIC_KEY, build_type, + build_part, raw_key, BUILD_END); chunk_free(&raw_key); if (key) { diff --git a/testing/tests/ikev2/net2net-rsa/hosts/moon/etc/ipsec.conf b/testing/tests/ikev2/net2net-rsa/hosts/moon/etc/ipsec.conf index 9cac82eaf..a2cb928bd 100644 --- a/testing/tests/ikev2/net2net-rsa/hosts/moon/etc/ipsec.conf +++ b/testing/tests/ikev2/net2net-rsa/hosts/moon/etc/ipsec.conf @@ -13,12 +13,12 @@ conn net-net left=PH_IP_MOON leftsubnet=10.1.0.0/16 leftid=@moon.strongswan.org - leftrsasigkey=0sAQN+mkeECF5Bm7XnDkkkfmgny/TZndTkN1XzFZWB7nJroM3cTk3zMtdSPX8hY9GQxVGWSsmUBq7mGA5Qx39JpRNpyzxW7wRcMbwqDquG1PRfblLzV1ixdXOGSLUNaXonqDI/h5fCkqTuZtLbE4q3Pf4PmQAwzWVWaTZQ1gXXqUqKlN6218Hm2vbvNRE/CBHuFMmaCz11jckvaPvcqBLZzRTx9b/Mi+qD6xT7k9RpYHmtaGCJ95ed1bY6SZkapgHWu88/3M6bxCzD0KOA3oFbwlkHkFyaGWFB2+fc7L6BfYq0wr/d84tQdOxEn3BwLTrVKo7+6AxDrMi0I+blD2nd9cxj + leftrsasigkey=dns:0sAQN+mkeECF5Bm7XnDkkkfmgny/TZndTkN1XzFZWB7nJroM3cTk3zMtdSPX8hY9GQxVGWSsmUBq7mGA5Qx39JpRNpyzxW7wRcMbwqDquG1PRfblLzV1ixdXOGSLUNaXonqDI/h5fCkqTuZtLbE4q3Pf4PmQAwzWVWaTZQ1gXXqUqKlN6218Hm2vbvNRE/CBHuFMmaCz11jckvaPvcqBLZzRTx9b/Mi+qD6xT7k9RpYHmtaGCJ95ed1bY6SZkapgHWu88/3M6bxCzD0KOA3oFbwlkHkFyaGWFB2+fc7L6BfYq0wr/d84tQdOxEn3BwLTrVKo7+6AxDrMi0I+blD2nd9cxj leftauth=pubkey leftfirewall=yes right=PH_IP_SUN rightsubnet=10.2.0.0/16 rightid=@sun.strongswan.org - rightrsasigkey=0sAQOiSuR9e/WMZFOxK3IdaFBOT2DGoObFDJURejqLcjMpmY2yVbA9Lpc+AEGKxqjb37WG6sVo3fBCDBOAhgmMw9s0b6DTSeXaIQloqW1M8IC+xe1fT+F0BsW1ttaEN0WTF5H+J+a4/arYg4HyiA+sjoqHagnCVPM15Rm5mkmg913XmSCgtkenD4WUq+NfPLuOcggqTjHAAoGD0doswRa3sebyqHQNAb32PXW9ecKi9ExcPrdr5hR5uNXRMYGumBtoxcE6xEvCM/sPRK1hbyynixc5nfMQ5Ymb4mdCUotUGaCyKDa4pF58sYgP6xpd/HXMXGdRP+KxqA4sfes46gp8UuJT + rightrsasigkey=dns:0sAQOiSuR9e/WMZFOxK3IdaFBOT2DGoObFDJURejqLcjMpmY2yVbA9Lpc+AEGKxqjb37WG6sVo3fBCDBOAhgmMw9s0b6DTSeXaIQloqW1M8IC+xe1fT+F0BsW1ttaEN0WTF5H+J+a4/arYg4HyiA+sjoqHagnCVPM15Rm5mkmg913XmSCgtkenD4WUq+NfPLuOcggqTjHAAoGD0doswRa3sebyqHQNAb32PXW9ecKi9ExcPrdr5hR5uNXRMYGumBtoxcE6xEvCM/sPRK1hbyynixc5nfMQ5Ymb4mdCUotUGaCyKDa4pF58sYgP6xpd/HXMXGdRP+KxqA4sfes46gp8UuJT rightauth=pubkey auto=add diff --git a/testing/tests/ikev2/net2net-rsa/hosts/sun/etc/ipsec.conf b/testing/tests/ikev2/net2net-rsa/hosts/sun/etc/ipsec.conf index 3a89b4088..1c483fb87 100644 --- a/testing/tests/ikev2/net2net-rsa/hosts/sun/etc/ipsec.conf +++ b/testing/tests/ikev2/net2net-rsa/hosts/sun/etc/ipsec.conf @@ -13,10 +13,10 @@ conn net-net left=PH_IP_SUN leftsubnet=10.2.0.0/16 leftid=@sun.strongswan.org - leftrsasigkey=0sAQOiSuR9e/WMZFOxK3IdaFBOT2DGoObFDJURejqLcjMpmY2yVbA9Lpc+AEGKxqjb37WG6sVo3fBCDBOAhgmMw9s0b6DTSeXaIQloqW1M8IC+xe1fT+F0BsW1ttaEN0WTF5H+J+a4/arYg4HyiA+sjoqHagnCVPM15Rm5mkmg913XmSCgtkenD4WUq+NfPLuOcggqTjHAAoGD0doswRa3sebyqHQNAb32PXW9ecKi9ExcPrdr5hR5uNXRMYGumBtoxcE6xEvCM/sPRK1hbyynixc5nfMQ5Ymb4mdCUotUGaCyKDa4pF58sYgP6xpd/HXMXGdRP+KxqA4sfes46gp8UuJT + leftrsasigkey=dns:0sAQOiSuR9e/WMZFOxK3IdaFBOT2DGoObFDJURejqLcjMpmY2yVbA9Lpc+AEGKxqjb37WG6sVo3fBCDBOAhgmMw9s0b6DTSeXaIQloqW1M8IC+xe1fT+F0BsW1ttaEN0WTF5H+J+a4/arYg4HyiA+sjoqHagnCVPM15Rm5mkmg913XmSCgtkenD4WUq+NfPLuOcggqTjHAAoGD0doswRa3sebyqHQNAb32PXW9ecKi9ExcPrdr5hR5uNXRMYGumBtoxcE6xEvCM/sPRK1hbyynixc5nfMQ5Ymb4mdCUotUGaCyKDa4pF58sYgP6xpd/HXMXGdRP+KxqA4sfes46gp8UuJT leftfirewall=yes right=PH_IP_MOON rightsubnet=10.1.0.0/16 rightid=@moon.strongswan.org - rightrsasigkey=0sAQN+mkeECF5Bm7XnDkkkfmgny/TZndTkN1XzFZWB7nJroM3cTk3zMtdSPX8hY9GQxVGWSsmUBq7mGA5Qx39JpRNpyzxW7wRcMbwqDquG1PRfblLzV1ixdXOGSLUNaXonqDI/h5fCkqTuZtLbE4q3Pf4PmQAwzWVWaTZQ1gXXqUqKlN6218Hm2vbvNRE/CBHuFMmaCz11jckvaPvcqBLZzRTx9b/Mi+qD6xT7k9RpYHmtaGCJ95ed1bY6SZkapgHWu88/3M6bxCzD0KOA3oFbwlkHkFyaGWFB2+fc7L6BfYq0wr/d84tQdOxEn3BwLTrVKo7+6AxDrMi0I+blD2nd9cxj + rightrsasigkey=dns:0sAQN+mkeECF5Bm7XnDkkkfmgny/TZndTkN1XzFZWB7nJroM3cTk3zMtdSPX8hY9GQxVGWSsmUBq7mGA5Qx39JpRNpyzxW7wRcMbwqDquG1PRfblLzV1ixdXOGSLUNaXonqDI/h5fCkqTuZtLbE4q3Pf4PmQAwzWVWaTZQ1gXXqUqKlN6218Hm2vbvNRE/CBHuFMmaCz11jckvaPvcqBLZzRTx9b/Mi+qD6xT7k9RpYHmtaGCJ95ed1bY6SZkapgHWu88/3M6bxCzD0KOA3oFbwlkHkFyaGWFB2+fc7L6BfYq0wr/d84tQdOxEn3BwLTrVKo7+6AxDrMi0I+blD2nd9cxj auto=add diff --git a/testing/tests/ikev2/rw-dnssec/hosts/carol/etc/ipsec.conf b/testing/tests/ikev2/rw-dnssec/hosts/carol/etc/ipsec.conf index 70deaa036..baf5b61ae 100644 --- a/testing/tests/ikev2/rw-dnssec/hosts/carol/etc/ipsec.conf +++ b/testing/tests/ikev2/rw-dnssec/hosts/carol/etc/ipsec.conf @@ -13,7 +13,7 @@ conn home left=%any leftsourceip=%config leftid=carol.strongswan.org - leftrsasigkey="0sAwEAAdBdWU+BF7x4lyo+xHnr4UAOU89yQQuT5vdPoXzx6kRPsjYAuuktgXR+SaLkQHw/YRgDPSKj5nzmmlOQf/rWRr+8O2q+C92aUICmkNvZGamo5w2WlOMZ6T5dk2Hv+QM6xT/GzWyVr1dMYu/7tywD1Bw7aW/HqkRESDu6q95VWu+Lzg6XlxCNEez0YsZrN/fC6BL2qzKAqMBbIHFW8OOnh+nEY4IF5AzkZnFrw12GI72Z882pw97lyKwZhSz/GMQFBJx+rnNdw5P1IJwTlG5PUdoDCte/Mcr1iiA+zOovx55x1GoGxduoXWU5egrf1MtalRf9Pc8Xr4q3WEKTAmsZrVE=" + leftrsasigkey="dns:0sAwEAAdBdWU+BF7x4lyo+xHnr4UAOU89yQQuT5vdPoXzx6kRPsjYAuuktgXR+SaLkQHw/YRgDPSKj5nzmmlOQf/rWRr+8O2q+C92aUICmkNvZGamo5w2WlOMZ6T5dk2Hv+QM6xT/GzWyVr1dMYu/7tywD1Bw7aW/HqkRESDu6q95VWu+Lzg6XlxCNEez0YsZrN/fC6BL2qzKAqMBbIHFW8OOnh+nEY4IF5AzkZnFrw12GI72Z882pw97lyKwZhSz/GMQFBJx+rnNdw5P1IJwTlG5PUdoDCte/Mcr1iiA+zOovx55x1GoGxduoXWU5egrf1MtalRf9Pc8Xr4q3WEKTAmsZrVE=" leftauth=pubkey leftfirewall=yes right=moon.strongswan.org diff --git a/testing/tests/ikev2/rw-dnssec/hosts/dave/etc/ipsec.conf b/testing/tests/ikev2/rw-dnssec/hosts/dave/etc/ipsec.conf index 24ffdd3b1..45d85e265 100644 --- a/testing/tests/ikev2/rw-dnssec/hosts/dave/etc/ipsec.conf +++ b/testing/tests/ikev2/rw-dnssec/hosts/dave/etc/ipsec.conf @@ -13,7 +13,7 @@ conn home left=%any leftsourceip=%config leftid=dave.strongswan.org - leftrsasigkey="0sAwEAAcAH8lNvBVjmg0XT7wF6F1tzQ055f5uXRI5yClmFrqdswFA7jWO04jmvlduD2wr2X4Ng6dlBkSwSEhVkOgrzIYj8UgQT6BZF/44uYjyTYr4bV2SVML9U/a1lYxBhBazpSdfeKJWkdxwjcJCqolZ719mwiyrQn2P2G7qH10YgRuifpFcMs8jkMiIgpzevSMMc0OwhQPNyO5R0LEoUIy4dQJ9rU8GKqmPmk/pdPQaAjpSNuCc1Y9M9vZrETs/XHmBCZXCIWJiz5VOHZ+r073E3Gef9ibMuTj9g2XLvFhdDfU26FK9GkfuOwnWnhVK66diq9xw9Qqynk+8K0J4a81Paq3U=" + leftrsasigkey="dns:0sAwEAAcAH8lNvBVjmg0XT7wF6F1tzQ055f5uXRI5yClmFrqdswFA7jWO04jmvlduD2wr2X4Ng6dlBkSwSEhVkOgrzIYj8UgQT6BZF/44uYjyTYr4bV2SVML9U/a1lYxBhBazpSdfeKJWkdxwjcJCqolZ719mwiyrQn2P2G7qH10YgRuifpFcMs8jkMiIgpzevSMMc0OwhQPNyO5R0LEoUIy4dQJ9rU8GKqmPmk/pdPQaAjpSNuCc1Y9M9vZrETs/XHmBCZXCIWJiz5VOHZ+r073E3Gef9ibMuTj9g2XLvFhdDfU26FK9GkfuOwnWnhVK66diq9xw9Qqynk+8K0J4a81Paq3U=" leftauth=pubkey leftfirewall=yes right=moon.strongswan.org From 87692be21536a586e5245cdda795134b7cfb2895 Mon Sep 17 00:00:00 2001 From: Tobias Brunner Date: Mon, 1 Apr 2013 16:42:53 +0200 Subject: [PATCH 08/14] Load any type (RSA/ECDSA) of public key via left|rightsigkey --- man/ipsec.conf.5.in | 10 ++++---- src/libcharon/plugins/stroke/stroke_config.c | 3 +-- src/libcharon/plugins/stroke/stroke_cred.c | 24 ++++++++++--------- src/libcharon/plugins/stroke/stroke_cred.h | 7 +++--- src/starter/keywords.h | 6 ++--- src/starter/keywords.txt | 6 +++-- .../net2net-dnssec/hosts/moon/etc/ipsec.conf | 2 +- .../net2net-dnssec/hosts/sun/etc/ipsec.conf | 2 +- .../net2net-pubkey/hosts/moon/etc/ipsec.conf | 4 ++-- .../net2net-pubkey/hosts/sun/etc/ipsec.conf | 4 ++-- .../net2net-rsa/hosts/moon/etc/ipsec.conf | 4 ++-- .../net2net-rsa/hosts/sun/etc/ipsec.conf | 4 ++-- .../rw-dnssec/hosts/carol/etc/ipsec.conf | 2 +- .../ikev2/rw-dnssec/hosts/dave/etc/ipsec.conf | 2 +- .../ikev2/rw-dnssec/hosts/moon/etc/ipsec.conf | 2 +- 15 files changed, 43 insertions(+), 39 deletions(-) diff --git a/man/ipsec.conf.5.in b/man/ipsec.conf.5.in index a8933531c..4ee884bcc 100644 --- a/man/ipsec.conf.5.in +++ b/man/ipsec.conf.5.in @@ -755,14 +755,16 @@ None of the kernel backends currently supports opaque or port ranges and uses .B %any for policy installation instead. .TP -.BR leftrsasigkey " = | " -the left participant's public key for RSA signature authentication, in PKCS#1 -format using hex (0x prefix) or base64 (0s prefix) encoding. With the optional +.BR leftsigkey " = | " +the left participant's public key for public key signature authentication, +in PKCS#1 format using hex (0x prefix) or base64 (0s prefix) encoding. With the +optional .B dns: or .B ssh: prefix in front of 0x or 0s, the public key is expected to be in either -the RFC 3110 or RFC 4253 public key format, respectively. +the RFC 3110 (not the full RR, only RSA key part) or RFC 4253 public key format, +respectively. Also accepted is the path to a file containing the public key in PEM or DER encoding. .TP diff --git a/src/libcharon/plugins/stroke/stroke_config.c b/src/libcharon/plugins/stroke/stroke_config.c index 86f0fe431..988129f03 100644 --- a/src/libcharon/plugins/stroke/stroke_config.c +++ b/src/libcharon/plugins/stroke/stroke_config.c @@ -489,8 +489,7 @@ static auth_cfg_t *build_auth_cfg(private_stroke_config_t *this, pubkey = end->rsakey; if (pubkey && !streq(pubkey, "") && !streq(pubkey, "%cert")) { - certificate = this->cred->load_pubkey(this->cred, KEY_RSA, pubkey, - identity); + certificate = this->cred->load_pubkey(this->cred, pubkey, identity); if (certificate) { cfg->add(cfg, AUTH_RULE_SUBJECT_CERT, certificate); diff --git a/src/libcharon/plugins/stroke/stroke_cred.c b/src/libcharon/plugins/stroke/stroke_cred.c index bee16c581..f24082ee3 100644 --- a/src/libcharon/plugins/stroke/stroke_cred.c +++ b/src/libcharon/plugins/stroke/stroke_cred.c @@ -279,13 +279,13 @@ METHOD(stroke_cred_t, load_peer, certificate_t*, } METHOD(stroke_cred_t, load_pubkey, certificate_t*, - private_stroke_cred_t *this, key_type_t type, char *filename, - identification_t *identity) + private_stroke_cred_t *this, char *filename, identification_t *identity) { certificate_t *cert; + public_key_t *key; char path[PATH_MAX]; builder_part_t build_part; - key_type_t build_type = KEY_ANY; + key_type_t type = KEY_ANY; if (streq(filename, "%dns")) { @@ -294,8 +294,8 @@ METHOD(stroke_cred_t, load_pubkey, certificate_t*, if (strncaseeq(filename, "dns:", 4)) { /* RFC 3110 format */ build_part = BUILD_BLOB_DNSKEY; - /* not a complete RR */ - build_type = KEY_RSA; + /* not a complete RR, only RSA supported */ + type = KEY_RSA; filename += 4; } else if (strncaseeq(filename, "ssh:", 4)) @@ -310,13 +310,12 @@ METHOD(stroke_cred_t, load_pubkey, certificate_t*, if (strncaseeq(filename, "0x", 2) || strncaseeq(filename, "0s", 2)) { chunk_t printable_key, raw_key; - public_key_t *key; printable_key = chunk_create(filename + 2, strlen(filename) - 2); raw_key = strncaseeq(filename, "0x", 2) ? chunk_from_hex(printable_key, NULL) : chunk_from_base64(printable_key, NULL); - key = lib->creds->create(lib->creds, CRED_PUBLIC_KEY, build_type, + key = lib->creds->create(lib->creds, CRED_PUBLIC_KEY, type, build_part, raw_key, BUILD_END); chunk_free(&raw_key); if (key) @@ -326,6 +325,7 @@ METHOD(stroke_cred_t, load_pubkey, certificate_t*, BUILD_PUBLIC_KEY, key, BUILD_SUBJECT, identity, BUILD_END); + type = key->get_type(key); key->destroy(key); if (cert) { @@ -335,8 +335,7 @@ METHOD(stroke_cred_t, load_pubkey, certificate_t*, return cert; } } - DBG1(DBG_CFG, " loading %N public key for \"%Y\" failed", - key_type_names, type, identity); + DBG1(DBG_CFG, " loading public key for \"%Y\" failed", identity); } else { @@ -357,12 +356,15 @@ METHOD(stroke_cred_t, load_pubkey, certificate_t*, if (cert) { cert = this->creds->add_cert_ref(this->creds, TRUE, cert); + key = cert->get_public_key(cert); + type = key->get_type(key); + key->destroy(key); DBG1(DBG_CFG, " loaded %N public key for \"%Y\" from '%s'", key_type_names, type, identity, filename); return cert; } - DBG1(DBG_CFG, " loading %N public key for \"%Y\" from '%s' failed", - key_type_names, type, identity, filename); + DBG1(DBG_CFG, " loading public key for \"%Y\" from '%s' failed", + identity, filename); } return NULL; } diff --git a/src/libcharon/plugins/stroke/stroke_cred.h b/src/libcharon/plugins/stroke/stroke_cred.h index c37d05808..f6fbb96d3 100644 --- a/src/libcharon/plugins/stroke/stroke_cred.h +++ b/src/libcharon/plugins/stroke/stroke_cred.h @@ -68,13 +68,12 @@ struct stroke_cred_t { /** * Load a raw public key and serve it through the credential_set. * - * @param type type of the raw public key (RSA or ECDSA) - * @param filename file to load raw public key from + * @param filename encoding or file to load raw public key from * @param identity identity of the raw public key owner * @return reference to loaded raw public key, or NULL */ - certificate_t* (*load_pubkey)(stroke_cred_t *this, key_type_t type, - char *filename, identification_t *identity); + certificate_t* (*load_pubkey)(stroke_cred_t *this, char *filename, + identification_t *identity); /** * Add a shared secret to serve through the credential_set. diff --git a/src/starter/keywords.h b/src/starter/keywords.h index 4a96a418c..83ce4a7dd 100644 --- a/src/starter/keywords.h +++ b/src/starter/keywords.h @@ -108,7 +108,7 @@ typedef enum { KW_AUTH2, KW_ID, KW_ID2, - KW_RSASIGKEY, + KW_SIGKEY, KW_CERT, KW_CERT2, KW_CERTPOLICY, @@ -137,7 +137,7 @@ typedef enum { KW_LEFTAUTH2, KW_LEFTID, KW_LEFTID2, - KW_LEFTRSASIGKEY, + KW_LEFTSIGKEY, KW_LEFTCERT, KW_LEFTCERT2, KW_LEFTCERTPOLICY, @@ -166,7 +166,7 @@ typedef enum { KW_RIGHTAUTH2, KW_RIGHTID, KW_RIGHTID2, - KW_RIGHTRSASIGKEY, + KW_RIGHTSIGKEY, KW_RIGHTCERT, KW_RIGHTCERT2, KW_RIGHTCERTPOLICY, diff --git a/src/starter/keywords.txt b/src/starter/keywords.txt index cd964b0e3..20d35ded0 100644 --- a/src/starter/keywords.txt +++ b/src/starter/keywords.txt @@ -96,7 +96,8 @@ leftauth, KW_LEFTAUTH leftauth2, KW_LEFTAUTH2 leftid, KW_LEFTID leftid2, KW_LEFTID2 -leftrsasigkey, KW_LEFTRSASIGKEY +leftsigkey, KW_LEFTSIGKEY +leftrsasigkey, KW_LEFTSIGKEY leftcert, KW_LEFTCERT leftcert2, KW_LEFTCERT2 leftcertpolicy, KW_LEFTCERTPOLICY @@ -120,7 +121,8 @@ rightauth, KW_RIGHTAUTH rightauth2, KW_RIGHTAUTH2 rightid, KW_RIGHTID rightid2, KW_RIGHTID2 -rightrsasigkey, KW_RIGHTRSASIGKEY +rightsigkey, KW_RIGHTSIGKEY +rightrsasigkey, KW_RIGHTSIGKEY rightcert, KW_RIGHTCERT rightcert2, KW_RIGHTCERT2 rightcertpolicy, KW_RIGHTCERTPOLICY diff --git a/testing/tests/ikev2/net2net-dnssec/hosts/moon/etc/ipsec.conf b/testing/tests/ikev2/net2net-dnssec/hosts/moon/etc/ipsec.conf index 6c11645f9..ea10eb0a3 100644 --- a/testing/tests/ikev2/net2net-dnssec/hosts/moon/etc/ipsec.conf +++ b/testing/tests/ikev2/net2net-dnssec/hosts/moon/etc/ipsec.conf @@ -14,7 +14,7 @@ conn net-net left=PH_IP_MOON leftid=moon.strongswan.org leftsubnet=10.1.0.0/16 - leftrsasigkey=moonPub.der + leftsigkey=moonPub.der leftauth=pubkey leftfirewall=yes right=sun.strongswan.org diff --git a/testing/tests/ikev2/net2net-dnssec/hosts/sun/etc/ipsec.conf b/testing/tests/ikev2/net2net-dnssec/hosts/sun/etc/ipsec.conf index 76e41cd47..9e310050d 100644 --- a/testing/tests/ikev2/net2net-dnssec/hosts/sun/etc/ipsec.conf +++ b/testing/tests/ikev2/net2net-dnssec/hosts/sun/etc/ipsec.conf @@ -14,7 +14,7 @@ conn net-net left=PH_IP_SUN leftid=sun.strongswan.org leftsubnet=10.2.0.0/16 - leftrsasigkey=sunPub.der + leftsigkey=sunPub.der leftauth=pubkey leftfirewall=yes right=moon.strongswan.org diff --git a/testing/tests/ikev2/net2net-pubkey/hosts/moon/etc/ipsec.conf b/testing/tests/ikev2/net2net-pubkey/hosts/moon/etc/ipsec.conf index 29d15a6b5..bcc6d5b69 100644 --- a/testing/tests/ikev2/net2net-pubkey/hosts/moon/etc/ipsec.conf +++ b/testing/tests/ikev2/net2net-pubkey/hosts/moon/etc/ipsec.conf @@ -13,12 +13,12 @@ conn net-net left=PH_IP_MOON leftsubnet=10.1.0.0/16 leftid=@moon.strongswan.org - leftrsasigkey=moonPub.der + leftsigkey=moonPub.der leftauth=pubkey leftfirewall=yes right=PH_IP_SUN rightsubnet=10.2.0.0/16 rightid=@sun.strongswan.org - rightrsasigkey=sunPub.der + rightsigkey=sunPub.der rightauth=pubkey auto=add diff --git a/testing/tests/ikev2/net2net-pubkey/hosts/sun/etc/ipsec.conf b/testing/tests/ikev2/net2net-pubkey/hosts/sun/etc/ipsec.conf index c60cf918f..4fe2e67de 100644 --- a/testing/tests/ikev2/net2net-pubkey/hosts/sun/etc/ipsec.conf +++ b/testing/tests/ikev2/net2net-pubkey/hosts/sun/etc/ipsec.conf @@ -13,10 +13,10 @@ conn net-net left=PH_IP_SUN leftsubnet=10.2.0.0/16 leftid=@sun.strongswan.org - leftrsasigkey=sunPub.der + leftsigkey=sunPub.der leftfirewall=yes right=PH_IP_MOON rightsubnet=10.1.0.0/16 rightid=@moon.strongswan.org - rightrsasigkey=moonPub.der + rightsigkey=moonPub.der auto=add diff --git a/testing/tests/ikev2/net2net-rsa/hosts/moon/etc/ipsec.conf b/testing/tests/ikev2/net2net-rsa/hosts/moon/etc/ipsec.conf index a2cb928bd..c0ee06240 100644 --- a/testing/tests/ikev2/net2net-rsa/hosts/moon/etc/ipsec.conf +++ b/testing/tests/ikev2/net2net-rsa/hosts/moon/etc/ipsec.conf @@ -13,12 +13,12 @@ conn net-net left=PH_IP_MOON leftsubnet=10.1.0.0/16 leftid=@moon.strongswan.org - leftrsasigkey=dns:0sAQN+mkeECF5Bm7XnDkkkfmgny/TZndTkN1XzFZWB7nJroM3cTk3zMtdSPX8hY9GQxVGWSsmUBq7mGA5Qx39JpRNpyzxW7wRcMbwqDquG1PRfblLzV1ixdXOGSLUNaXonqDI/h5fCkqTuZtLbE4q3Pf4PmQAwzWVWaTZQ1gXXqUqKlN6218Hm2vbvNRE/CBHuFMmaCz11jckvaPvcqBLZzRTx9b/Mi+qD6xT7k9RpYHmtaGCJ95ed1bY6SZkapgHWu88/3M6bxCzD0KOA3oFbwlkHkFyaGWFB2+fc7L6BfYq0wr/d84tQdOxEn3BwLTrVKo7+6AxDrMi0I+blD2nd9cxj + leftsigkey=dns:0sAQN+mkeECF5Bm7XnDkkkfmgny/TZndTkN1XzFZWB7nJroM3cTk3zMtdSPX8hY9GQxVGWSsmUBq7mGA5Qx39JpRNpyzxW7wRcMbwqDquG1PRfblLzV1ixdXOGSLUNaXonqDI/h5fCkqTuZtLbE4q3Pf4PmQAwzWVWaTZQ1gXXqUqKlN6218Hm2vbvNRE/CBHuFMmaCz11jckvaPvcqBLZzRTx9b/Mi+qD6xT7k9RpYHmtaGCJ95ed1bY6SZkapgHWu88/3M6bxCzD0KOA3oFbwlkHkFyaGWFB2+fc7L6BfYq0wr/d84tQdOxEn3BwLTrVKo7+6AxDrMi0I+blD2nd9cxj leftauth=pubkey leftfirewall=yes right=PH_IP_SUN rightsubnet=10.2.0.0/16 rightid=@sun.strongswan.org - rightrsasigkey=dns:0sAQOiSuR9e/WMZFOxK3IdaFBOT2DGoObFDJURejqLcjMpmY2yVbA9Lpc+AEGKxqjb37WG6sVo3fBCDBOAhgmMw9s0b6DTSeXaIQloqW1M8IC+xe1fT+F0BsW1ttaEN0WTF5H+J+a4/arYg4HyiA+sjoqHagnCVPM15Rm5mkmg913XmSCgtkenD4WUq+NfPLuOcggqTjHAAoGD0doswRa3sebyqHQNAb32PXW9ecKi9ExcPrdr5hR5uNXRMYGumBtoxcE6xEvCM/sPRK1hbyynixc5nfMQ5Ymb4mdCUotUGaCyKDa4pF58sYgP6xpd/HXMXGdRP+KxqA4sfes46gp8UuJT + rightsigkey=dns:0sAQOiSuR9e/WMZFOxK3IdaFBOT2DGoObFDJURejqLcjMpmY2yVbA9Lpc+AEGKxqjb37WG6sVo3fBCDBOAhgmMw9s0b6DTSeXaIQloqW1M8IC+xe1fT+F0BsW1ttaEN0WTF5H+J+a4/arYg4HyiA+sjoqHagnCVPM15Rm5mkmg913XmSCgtkenD4WUq+NfPLuOcggqTjHAAoGD0doswRa3sebyqHQNAb32PXW9ecKi9ExcPrdr5hR5uNXRMYGumBtoxcE6xEvCM/sPRK1hbyynixc5nfMQ5Ymb4mdCUotUGaCyKDa4pF58sYgP6xpd/HXMXGdRP+KxqA4sfes46gp8UuJT rightauth=pubkey auto=add diff --git a/testing/tests/ikev2/net2net-rsa/hosts/sun/etc/ipsec.conf b/testing/tests/ikev2/net2net-rsa/hosts/sun/etc/ipsec.conf index 1c483fb87..b089e9f48 100644 --- a/testing/tests/ikev2/net2net-rsa/hosts/sun/etc/ipsec.conf +++ b/testing/tests/ikev2/net2net-rsa/hosts/sun/etc/ipsec.conf @@ -13,10 +13,10 @@ conn net-net left=PH_IP_SUN leftsubnet=10.2.0.0/16 leftid=@sun.strongswan.org - leftrsasigkey=dns:0sAQOiSuR9e/WMZFOxK3IdaFBOT2DGoObFDJURejqLcjMpmY2yVbA9Lpc+AEGKxqjb37WG6sVo3fBCDBOAhgmMw9s0b6DTSeXaIQloqW1M8IC+xe1fT+F0BsW1ttaEN0WTF5H+J+a4/arYg4HyiA+sjoqHagnCVPM15Rm5mkmg913XmSCgtkenD4WUq+NfPLuOcggqTjHAAoGD0doswRa3sebyqHQNAb32PXW9ecKi9ExcPrdr5hR5uNXRMYGumBtoxcE6xEvCM/sPRK1hbyynixc5nfMQ5Ymb4mdCUotUGaCyKDa4pF58sYgP6xpd/HXMXGdRP+KxqA4sfes46gp8UuJT + leftsigkey=dns:0sAQOiSuR9e/WMZFOxK3IdaFBOT2DGoObFDJURejqLcjMpmY2yVbA9Lpc+AEGKxqjb37WG6sVo3fBCDBOAhgmMw9s0b6DTSeXaIQloqW1M8IC+xe1fT+F0BsW1ttaEN0WTF5H+J+a4/arYg4HyiA+sjoqHagnCVPM15Rm5mkmg913XmSCgtkenD4WUq+NfPLuOcggqTjHAAoGD0doswRa3sebyqHQNAb32PXW9ecKi9ExcPrdr5hR5uNXRMYGumBtoxcE6xEvCM/sPRK1hbyynixc5nfMQ5Ymb4mdCUotUGaCyKDa4pF58sYgP6xpd/HXMXGdRP+KxqA4sfes46gp8UuJT leftfirewall=yes right=PH_IP_MOON rightsubnet=10.1.0.0/16 rightid=@moon.strongswan.org - rightrsasigkey=dns:0sAQN+mkeECF5Bm7XnDkkkfmgny/TZndTkN1XzFZWB7nJroM3cTk3zMtdSPX8hY9GQxVGWSsmUBq7mGA5Qx39JpRNpyzxW7wRcMbwqDquG1PRfblLzV1ixdXOGSLUNaXonqDI/h5fCkqTuZtLbE4q3Pf4PmQAwzWVWaTZQ1gXXqUqKlN6218Hm2vbvNRE/CBHuFMmaCz11jckvaPvcqBLZzRTx9b/Mi+qD6xT7k9RpYHmtaGCJ95ed1bY6SZkapgHWu88/3M6bxCzD0KOA3oFbwlkHkFyaGWFB2+fc7L6BfYq0wr/d84tQdOxEn3BwLTrVKo7+6AxDrMi0I+blD2nd9cxj + rightsigkey=dns:0sAQN+mkeECF5Bm7XnDkkkfmgny/TZndTkN1XzFZWB7nJroM3cTk3zMtdSPX8hY9GQxVGWSsmUBq7mGA5Qx39JpRNpyzxW7wRcMbwqDquG1PRfblLzV1ixdXOGSLUNaXonqDI/h5fCkqTuZtLbE4q3Pf4PmQAwzWVWaTZQ1gXXqUqKlN6218Hm2vbvNRE/CBHuFMmaCz11jckvaPvcqBLZzRTx9b/Mi+qD6xT7k9RpYHmtaGCJ95ed1bY6SZkapgHWu88/3M6bxCzD0KOA3oFbwlkHkFyaGWFB2+fc7L6BfYq0wr/d84tQdOxEn3BwLTrVKo7+6AxDrMi0I+blD2nd9cxj auto=add diff --git a/testing/tests/ikev2/rw-dnssec/hosts/carol/etc/ipsec.conf b/testing/tests/ikev2/rw-dnssec/hosts/carol/etc/ipsec.conf index baf5b61ae..082b18a7f 100644 --- a/testing/tests/ikev2/rw-dnssec/hosts/carol/etc/ipsec.conf +++ b/testing/tests/ikev2/rw-dnssec/hosts/carol/etc/ipsec.conf @@ -13,7 +13,7 @@ conn home left=%any leftsourceip=%config leftid=carol.strongswan.org - leftrsasigkey="dns:0sAwEAAdBdWU+BF7x4lyo+xHnr4UAOU89yQQuT5vdPoXzx6kRPsjYAuuktgXR+SaLkQHw/YRgDPSKj5nzmmlOQf/rWRr+8O2q+C92aUICmkNvZGamo5w2WlOMZ6T5dk2Hv+QM6xT/GzWyVr1dMYu/7tywD1Bw7aW/HqkRESDu6q95VWu+Lzg6XlxCNEez0YsZrN/fC6BL2qzKAqMBbIHFW8OOnh+nEY4IF5AzkZnFrw12GI72Z882pw97lyKwZhSz/GMQFBJx+rnNdw5P1IJwTlG5PUdoDCte/Mcr1iiA+zOovx55x1GoGxduoXWU5egrf1MtalRf9Pc8Xr4q3WEKTAmsZrVE=" + leftsigkey="dns:0sAwEAAdBdWU+BF7x4lyo+xHnr4UAOU89yQQuT5vdPoXzx6kRPsjYAuuktgXR+SaLkQHw/YRgDPSKj5nzmmlOQf/rWRr+8O2q+C92aUICmkNvZGamo5w2WlOMZ6T5dk2Hv+QM6xT/GzWyVr1dMYu/7tywD1Bw7aW/HqkRESDu6q95VWu+Lzg6XlxCNEez0YsZrN/fC6BL2qzKAqMBbIHFW8OOnh+nEY4IF5AzkZnFrw12GI72Z882pw97lyKwZhSz/GMQFBJx+rnNdw5P1IJwTlG5PUdoDCte/Mcr1iiA+zOovx55x1GoGxduoXWU5egrf1MtalRf9Pc8Xr4q3WEKTAmsZrVE=" leftauth=pubkey leftfirewall=yes right=moon.strongswan.org diff --git a/testing/tests/ikev2/rw-dnssec/hosts/dave/etc/ipsec.conf b/testing/tests/ikev2/rw-dnssec/hosts/dave/etc/ipsec.conf index 45d85e265..a68f981d1 100644 --- a/testing/tests/ikev2/rw-dnssec/hosts/dave/etc/ipsec.conf +++ b/testing/tests/ikev2/rw-dnssec/hosts/dave/etc/ipsec.conf @@ -13,7 +13,7 @@ conn home left=%any leftsourceip=%config leftid=dave.strongswan.org - leftrsasigkey="dns:0sAwEAAcAH8lNvBVjmg0XT7wF6F1tzQ055f5uXRI5yClmFrqdswFA7jWO04jmvlduD2wr2X4Ng6dlBkSwSEhVkOgrzIYj8UgQT6BZF/44uYjyTYr4bV2SVML9U/a1lYxBhBazpSdfeKJWkdxwjcJCqolZ719mwiyrQn2P2G7qH10YgRuifpFcMs8jkMiIgpzevSMMc0OwhQPNyO5R0LEoUIy4dQJ9rU8GKqmPmk/pdPQaAjpSNuCc1Y9M9vZrETs/XHmBCZXCIWJiz5VOHZ+r073E3Gef9ibMuTj9g2XLvFhdDfU26FK9GkfuOwnWnhVK66diq9xw9Qqynk+8K0J4a81Paq3U=" + leftsigkey="dns:0sAwEAAcAH8lNvBVjmg0XT7wF6F1tzQ055f5uXRI5yClmFrqdswFA7jWO04jmvlduD2wr2X4Ng6dlBkSwSEhVkOgrzIYj8UgQT6BZF/44uYjyTYr4bV2SVML9U/a1lYxBhBazpSdfeKJWkdxwjcJCqolZ719mwiyrQn2P2G7qH10YgRuifpFcMs8jkMiIgpzevSMMc0OwhQPNyO5R0LEoUIy4dQJ9rU8GKqmPmk/pdPQaAjpSNuCc1Y9M9vZrETs/XHmBCZXCIWJiz5VOHZ+r073E3Gef9ibMuTj9g2XLvFhdDfU26FK9GkfuOwnWnhVK66diq9xw9Qqynk+8K0J4a81Paq3U=" leftauth=pubkey leftfirewall=yes right=moon.strongswan.org diff --git a/testing/tests/ikev2/rw-dnssec/hosts/moon/etc/ipsec.conf b/testing/tests/ikev2/rw-dnssec/hosts/moon/etc/ipsec.conf index a199a4824..74ddc6e01 100644 --- a/testing/tests/ikev2/rw-dnssec/hosts/moon/etc/ipsec.conf +++ b/testing/tests/ikev2/rw-dnssec/hosts/moon/etc/ipsec.conf @@ -14,7 +14,7 @@ conn rw leftsubnet=10.1.0.0/16 leftid=moon.strongswan.org leftauth=pubkey - leftrsasigkey=moonPub.der + leftsigkey=moonPub.der leftfirewall=yes right=%any rightauth=pubkey From dd9e366814475f22bf22ef874cf68f8691e19c81 Mon Sep 17 00:00:00 2001 From: Tobias Brunner Date: Mon, 1 Apr 2013 18:16:17 +0200 Subject: [PATCH 09/14] sshkey: Add support for ECDSA keys --- .../plugins/sshkey/sshkey_builder.c | 70 +++++++++++++++++++ 1 file changed, 70 insertions(+) diff --git a/src/libstrongswan/plugins/sshkey/sshkey_builder.c b/src/libstrongswan/plugins/sshkey/sshkey_builder.c index 31c7b2164..986e860d9 100644 --- a/src/libstrongswan/plugins/sshkey/sshkey_builder.c +++ b/src/libstrongswan/plugins/sshkey/sshkey_builder.c @@ -15,9 +15,45 @@ #include "sshkey_builder.h" +#include +#include #include #include +#define ECDSA_PREFIX "ecdsa-sha2-" + +/** + * Parse an EC domain parameter identifier as defined in RFC 5656 + */ +static chunk_t parse_ec_identifier(chunk_t identifier) +{ + chunk_t oid = chunk_empty; + + if (chunk_equals(identifier, chunk_from_str("nistp256"))) + { + oid = asn1_build_known_oid(OID_PRIME256V1); + } + else if (chunk_equals(identifier, chunk_from_str("nistp384"))) + { + oid = asn1_build_known_oid(OID_SECT384R1); + } + else if (chunk_equals(identifier, chunk_from_str("nistp521"))) + { + oid = asn1_build_known_oid(OID_SECT521R1); + } + else + { + char ascii[64]; + + if (snprintf(ascii, sizeof(ascii), "%.*s", (int)identifier.len, + identifier.ptr) < sizeof(ascii)) + { + oid = asn1_wrap(ASN1_OID, "m", asn1_oid_from_string(ascii)); + } + } + return oid; +} + /** * Load a generic public key from an SSH key blob */ @@ -48,6 +84,40 @@ static sshkey_public_key_t *parse_public_key(chunk_t blob) return lib->creds->create(lib->creds, CRED_PUBLIC_KEY, KEY_RSA, BUILD_RSA_MODULUS, n, BUILD_RSA_PUB_EXP, e, BUILD_END); } + else if (format.len > strlen(ECDSA_PREFIX) && + strneq(format.ptr, ECDSA_PREFIX, strlen(ECDSA_PREFIX))) + { + chunk_t ec_blob, identifier, q, oid, encoded; + sshkey_public_key_t *key; + + ec_blob = reader->peek(reader); + reader->destroy(reader); + reader = bio_reader_create(ec_blob); + if (!reader->read_data32(reader, &identifier) || + !reader->read_data32(reader, &q)) + { + DBG1(DBG_LIB, "invalid ECDSA key in SSH key"); + reader->destroy(reader); + return NULL; + } + oid = parse_ec_identifier(identifier); + if (!oid.ptr) + { + DBG1(DBG_LIB, "invalid ECDSA key identifier in SSH key"); + reader->destroy(reader); + return NULL; + } + reader->destroy(reader); + /* build key from subjectPublicKeyInfo */ + encoded = asn1_wrap(ASN1_SEQUENCE, "mm", + asn1_wrap(ASN1_SEQUENCE, "mm", + asn1_build_known_oid(OID_EC_PUBLICKEY), oid), + asn1_bitstring("c", q)); + key = lib->creds->create(lib->creds, CRED_PUBLIC_KEY, + KEY_ECDSA, BUILD_BLOB_ASN1_DER, encoded, BUILD_END); + chunk_free(&encoded); + return key; + } DBG1(DBG_LIB, "unsupported SSH key format %.*s", (int)format.len, format.ptr); reader->destroy(reader); From e07e489d5f4738b9c340b30ab8d83d3d2d59017c Mon Sep 17 00:00:00 2001 From: Tobias Brunner Date: Mon, 1 Apr 2013 19:47:23 +0200 Subject: [PATCH 10/14] agent: Use sshkey plugin to parse keys, adds support for ECDSA --- configure.in | 2 +- src/charon-cmd/cmd/cmd_creds.c | 4 +- .../plugins/agent/agent_plugin.c | 2 + .../plugins/agent/agent_private_key.c | 122 ++++++++++-------- 4 files changed, 71 insertions(+), 59 deletions(-) diff --git a/configure.in b/configure.in index 49a91647b..dd16633a7 100644 --- a/configure.in +++ b/configure.in @@ -968,7 +968,7 @@ ADD_PLUGIN([pkcs7], [s scepclient pki]) ADD_PLUGIN([pkcs8], [s charon openac scepclient pki scripts manager medsrv attest nm cmd]) ADD_PLUGIN([pgp], [s charon]) ADD_PLUGIN([dnskey], [s charon]) -ADD_PLUGIN([sshkey], [s charon]) +ADD_PLUGIN([sshkey], [s charon nm cmd]) ADD_PLUGIN([ipseckey], [c charon]) ADD_PLUGIN([pem], [s charon openac scepclient pki scripts manager medsrv attest nm cmd]) ADD_PLUGIN([padlock], [s charon]) diff --git a/src/charon-cmd/cmd/cmd_creds.c b/src/charon-cmd/cmd/cmd_creds.c index 178b77d49..31e578995 100644 --- a/src/charon-cmd/cmd/cmd_creds.c +++ b/src/charon-cmd/cmd/cmd_creds.c @@ -148,7 +148,7 @@ static void load_agent(private_cmd_creds_t *this) } privkey = lib->creds->create(lib->creds, CRED_PRIVATE_KEY, - KEY_RSA, BUILD_AGENT_SOCKET, agent, BUILD_END); + KEY_ANY, BUILD_AGENT_SOCKET, agent, BUILD_END); if (!privkey) { DBG1(DBG_CFG, "failed to load private key from ssh-agent"); @@ -200,6 +200,8 @@ METHOD(cmd_creds_t, handle, bool, if (this->agent && this->identity) { load_agent(this); + /* only do this once */ + this->agent = FALSE; } return TRUE; } diff --git a/src/libstrongswan/plugins/agent/agent_plugin.c b/src/libstrongswan/plugins/agent/agent_plugin.c index 980a140b9..322ded48c 100644 --- a/src/libstrongswan/plugins/agent/agent_plugin.c +++ b/src/libstrongswan/plugins/agent/agent_plugin.c @@ -42,7 +42,9 @@ METHOD(plugin_t, get_features, int, { static plugin_feature_t f[] = { PLUGIN_REGISTER(PRIVKEY, agent_private_key_open, FALSE), + PLUGIN_PROVIDE(PRIVKEY, KEY_ANY), PLUGIN_PROVIDE(PRIVKEY, KEY_RSA), + PLUGIN_PROVIDE(PRIVKEY, KEY_ECDSA), }; *features = f; return countof(f); diff --git a/src/libstrongswan/plugins/agent/agent_private_key.c b/src/libstrongswan/plugins/agent/agent_private_key.c index 42c78c172..8a3fb150a 100644 --- a/src/libstrongswan/plugins/agent/agent_private_key.c +++ b/src/libstrongswan/plugins/agent/agent_private_key.c @@ -49,10 +49,15 @@ struct private_agent_private_key_t { int socket; /** - * key identity blob in ssh format + * public key encoded in SSH format */ chunk_t key; + /** + * public key + */ + public_key_t *pubkey; + /** * keysize in bytes */ @@ -163,7 +168,7 @@ static bool read_key(private_agent_private_key_t *this, public_key_t *pubkey) { int len; char buf[2048]; - chunk_t blob, key, type, n; + chunk_t blob, key; len = htonl(1); buf[0] = SSH_AGENT_ID_REQUEST; @@ -193,34 +198,40 @@ static bool read_key(private_agent_private_key_t *this, public_key_t *pubkey) { break; } - this->key = key; - type = read_string(&key); - if (!type.len || !strneq("ssh-rsa", type.ptr, type.len)) - { - break; - } - read_string(&key); - n = read_string(&key); - if (n.len <= 512/8) - { - break;; - } - if (pubkey && !private_key_belongs_to(&this->public.key, pubkey)) + this->pubkey = lib->creds->create(lib->creds, CRED_PUBLIC_KEY, KEY_ANY, + BUILD_BLOB_SSHKEY, key, BUILD_END); + if (!this->pubkey) { continue; } - this->key_size = n.len; - if (n.ptr[0] == 0) + if (pubkey && !private_key_belongs_to(&this->public.key, pubkey)) { - this->key_size--; + this->pubkey->destroy(this->pubkey); + this->pubkey = NULL; + continue; } - this->key = chunk_clone(this->key); + this->key = chunk_clone(key); return TRUE; } - this->key = chunk_empty; return FALSE; } +static bool scheme_supported(private_agent_private_key_t *this, + signature_scheme_t scheme) +{ + switch (this->pubkey->get_type(this->pubkey)) + { + case KEY_RSA: + return scheme == SIGN_RSA_EMSA_PKCS1_SHA1; + case KEY_ECDSA: + return scheme == SIGN_ECDSA_256 || + scheme == SIGN_ECDSA_384 || + scheme == SIGN_ECDSA_521; + default: + return FALSE; + } +} + METHOD(private_key_t, sign, bool, private_agent_private_key_t *this, signature_scheme_t scheme, chunk_t data, chunk_t *signature) @@ -229,7 +240,7 @@ METHOD(private_key_t, sign, bool, char buf[2048]; chunk_t blob; - if (scheme != SIGN_RSA_EMSA_PKCS1_SHA1) + if (!scheme_supported(this, scheme)) { DBG1(DBG_LIB, "signature scheme %N not supported by ssh-agent", signature_scheme_names, scheme); @@ -279,23 +290,40 @@ METHOD(private_key_t, sign, bool, } /* parse length */ blob = read_string(&blob); - /* skip sig type */ - read_string(&blob); - /* parse length */ - blob = read_string(&blob); - if (!blob.len) - { - DBG1(DBG_LIB, "received invalid ssh-agent signature response"); - return FALSE; + /* check sig type */ + if (chunk_equals(read_string(&blob), chunk_from_str("ssh-rsa"))) + { /* for RSA the signature has no special encoding */ + blob = read_string(&blob); + if (blob.len) + { + *signature = chunk_clone(blob); + return TRUE; + } } - *signature = chunk_clone(blob); - return TRUE; + else + { /* anything else is treated as ECSDA for now */ + blob = read_string(&blob); + if (blob.len) + { + chunk_t r, s; + + r = read_string(&blob); + s = read_string(&blob); + if (r.len && s.len) + { + *signature = chunk_cat("cc", r, s); + return TRUE; + } + } + } + DBG1(DBG_LIB, "received invalid ssh-agent signature response"); + return FALSE; } METHOD(private_key_t, get_type, key_type_t, private_agent_private_key_t *this) { - return KEY_RSA; + return this->pubkey->get_type(this->pubkey); } METHOD(private_key_t, decrypt, bool, @@ -309,21 +337,13 @@ METHOD(private_key_t, decrypt, bool, METHOD(private_key_t, get_keysize, int, private_agent_private_key_t *this) { - return this->key_size * 8; + return this->pubkey->get_keysize(this->pubkey); } METHOD(private_key_t, get_public_key, public_key_t*, private_agent_private_key_t *this) { - chunk_t key, n, e; - - key = this->key; - read_string(&key); - e = read_string(&key); - n = read_string(&key); - - return lib->creds->create(lib->creds, CRED_PUBLIC_KEY, KEY_RSA, - BUILD_RSA_MODULUS, n, BUILD_RSA_PUB_EXP, e, BUILD_END); + return this->pubkey->get_ref(this->pubkey); } METHOD(private_key_t, get_encoding, bool, @@ -336,19 +356,7 @@ METHOD(private_key_t, get_encoding, bool, METHOD(private_key_t, get_fingerprint, bool, private_agent_private_key_t *this, cred_encoding_type_t type, chunk_t *fp) { - chunk_t n, e, key; - - if (lib->encoding->get_cache(lib->encoding, type, this, fp)) - { - return TRUE; - } - key = this->key; - read_string(&key); - e = read_string(&key); - n = read_string(&key); - - return lib->encoding->encode(lib->encoding, type, this, fp, - CRED_PART_RSA_MODULUS, n, CRED_PART_RSA_PUB_EXP, e, CRED_PART_END); + return this->pubkey->get_fingerprint(this->pubkey, type, fp); } METHOD(private_key_t, get_ref, private_key_t*, @@ -364,8 +372,8 @@ METHOD(private_key_t, destroy, void, if (ref_put(&this->ref)) { close(this->socket); - free(this->key.ptr); - lib->encoding->clear_cache(lib->encoding, this); + chunk_free(&this->key); + DESTROY_IF(this->pubkey); free(this); } } From 410abbd35ff850fd5cbf95a7a922289710cf23f5 Mon Sep 17 00:00:00 2001 From: Tobias Brunner Date: Tue, 7 May 2013 14:08:20 +0200 Subject: [PATCH 11/14] charon-cmd: Properly initialize options with no additional lines --- src/charon-cmd/cmd/cmd_options.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/src/charon-cmd/cmd/cmd_options.c b/src/charon-cmd/cmd/cmd_options.c index 6b7df6d93..f25719a51 100644 --- a/src/charon-cmd/cmd/cmd_options.c +++ b/src/charon-cmd/cmd/cmd_options.c @@ -22,25 +22,25 @@ */ cmd_option_t cmd_options[CMD_OPT_COUNT] = { { CMD_OPT_HELP, "help", no_argument, "", - "print this usage information and exit" }, + "print this usage information and exit", {}}, { CMD_OPT_VERSION, "version", no_argument, "", - "show version information and exit" }, + "show version information and exit", {}}, { CMD_OPT_HOST, "host", required_argument, "hostname", - "DNS name or address to connect to" }, + "DNS name or address to connect to", {}}, { CMD_OPT_IDENTITY, "identity", required_argument, "identity", - "identity the client uses for the IKE exchange" }, + "identity the client uses for the IKE exchange", {}}, { CMD_OPT_REMOTE_IDENTITY, "remote-identity", required_argument, "identity", - "server identity to expect, defaults to host" }, + "server identity to expect, defaults to host", {}}, { CMD_OPT_CERT, "cert", required_argument, "path", - "trusted certificate, for authentication or trust chain validation" }, + "trusted certificate, for authentication or trust chain validation", {}}, { CMD_OPT_RSA, "rsa", required_argument, "path", - "RSA private key to use for authentication" }, + "RSA private key to use for authentication", {}}, { CMD_OPT_AGENT, "agent", no_argument, "", - "use SSH agent for authentication"}, + "use SSH agent for authentication", {}}, { CMD_OPT_LOCAL_TS, "local-ts", required_argument, "subnet", - "additional traffic selector to propose for our side" }, + "additional traffic selector to propose for our side", {}}, { CMD_OPT_REMOTE_TS, "remote-ts", required_argument, "subnet", - "remote traffic selector to propose for remote side" }, + "remote traffic selector to propose for remote side", {}}, { CMD_OPT_PROFILE, "profile", required_argument, "name", "authentication profile to use, where name is one of:", { "ikev2-pub: IKEv2 with public key client authentication", From efb4cb0bf9ab2abd209072041e04160f8b09ae5d Mon Sep 17 00:00:00 2001 From: Tobias Brunner Date: Tue, 7 May 2013 14:53:27 +0200 Subject: [PATCH 12/14] charon-cmd: Stop processing options if an argument is missing or an option not recognized --- src/charon-cmd/charon-cmd.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/charon-cmd/charon-cmd.c b/src/charon-cmd/charon-cmd.c index 5f27255a9..a77794abe 100644 --- a/src/charon-cmd/charon-cmd.c +++ b/src/charon-cmd/charon-cmd.c @@ -282,6 +282,9 @@ static void handle_arguments(int argc, char *argv[]) { continue; } + /* fall-through */ + case '?': + /* missing argument, unrecognized option */ usage(stderr, NULL, argv[0]); exit(1); } From 6a6d0ea7cd7b313b8f4d2f85f42a66a2f6e78b57 Mon Sep 17 00:00:00 2001 From: Tobias Brunner Date: Tue, 7 May 2013 15:04:02 +0200 Subject: [PATCH 13/14] charon-cmd: --agent optionally takes the path to an ssh-agent socket If not given it is read from the SSH_AUTH_SOCK environment variable. --- src/charon-cmd/cmd/cmd_connection.c | 3 +++ src/charon-cmd/cmd/cmd_creds.c | 28 ++++++++++++++-------------- src/charon-cmd/cmd/cmd_options.c | 9 +++++++-- 3 files changed, 24 insertions(+), 16 deletions(-) diff --git a/src/charon-cmd/cmd/cmd_connection.c b/src/charon-cmd/cmd/cmd_connection.c index 8b42befe9..9c25df907 100644 --- a/src/charon-cmd/cmd/cmd_connection.c +++ b/src/charon-cmd/cmd/cmd_connection.c @@ -1,4 +1,7 @@ /* + * Copyright (C) 2013 Tobias Brunner + * Hochschule fuer Technik Rapperswil + * * Copyright (C) 2013 Martin Willi * Copyright (C) 2013 revosec AG * diff --git a/src/charon-cmd/cmd/cmd_creds.c b/src/charon-cmd/cmd/cmd_creds.c index 31e578995..98337db55 100644 --- a/src/charon-cmd/cmd/cmd_creds.c +++ b/src/charon-cmd/cmd/cmd_creds.c @@ -1,4 +1,7 @@ /* + * Copyright (C) 2013 Tobias Brunner + * Hochschule fuer Technik Rapperswil + * * Copyright (C) 2013 Martin Willi * Copyright (C) 2013 revosec AG * @@ -49,9 +52,9 @@ struct private_cmd_creds_t { bool prompted; /** - * Provide keys via ssh-agent + * Path to ssh-agent socket */ - bool agent; + char *agent; /** * Local identity @@ -138,17 +141,9 @@ static void load_agent(private_cmd_creds_t *this) public_key_t *pubkey; identification_t *id; certificate_t *cert; - char *agent; - agent = getenv("SSH_AUTH_SOCK"); - if (!agent) - { - DBG1(DBG_CFG, "ssh-agent socket not found"); - exit(1); - } - - privkey = lib->creds->create(lib->creds, CRED_PRIVATE_KEY, - KEY_ANY, BUILD_AGENT_SOCKET, agent, BUILD_END); + privkey = lib->creds->create(lib->creds, CRED_PRIVATE_KEY, KEY_ANY, + BUILD_AGENT_SOCKET, this->agent, BUILD_END); if (!privkey) { DBG1(DBG_CFG, "failed to load private key from ssh-agent"); @@ -192,7 +187,12 @@ METHOD(cmd_creds_t, handle, bool, this->identity = arg; break; case CMD_OPT_AGENT: - this->agent = TRUE; + this->agent = arg ?: getenv("SSH_AUTH_SOCK"); + if (!this->agent) + { + DBG1(DBG_CFG, "no ssh-agent socket defined"); + exit(1); + } break; default: return FALSE; @@ -201,7 +201,7 @@ METHOD(cmd_creds_t, handle, bool, { load_agent(this); /* only do this once */ - this->agent = FALSE; + this->agent = NULL; } return TRUE; } diff --git a/src/charon-cmd/cmd/cmd_options.c b/src/charon-cmd/cmd/cmd_options.c index f25719a51..06d0996cc 100644 --- a/src/charon-cmd/cmd/cmd_options.c +++ b/src/charon-cmd/cmd/cmd_options.c @@ -1,4 +1,7 @@ /* + * Copyright (C) 2013 Tobias Brunner + * Hochschule fuer Technik Rapperswil + * * Copyright (C) 2013 Martin Willi * Copyright (C) 2013 revosec AG * @@ -35,8 +38,10 @@ cmd_option_t cmd_options[CMD_OPT_COUNT] = { "trusted certificate, for authentication or trust chain validation", {}}, { CMD_OPT_RSA, "rsa", required_argument, "path", "RSA private key to use for authentication", {}}, - { CMD_OPT_AGENT, "agent", no_argument, "", - "use SSH agent for authentication", {}}, + { CMD_OPT_AGENT, "agent", optional_argument, "socket", + "use SSH agent for authentication. If socket is not specified", { + "it is read from the SSH_AUTH_SOCK environment variable", + }}, { CMD_OPT_LOCAL_TS, "local-ts", required_argument, "subnet", "additional traffic selector to propose for our side", {}}, { CMD_OPT_REMOTE_TS, "remote-ts", required_argument, "subnet", From 4d38a698b81f9d223142eb04c666472e1d1343ed Mon Sep 17 00:00:00 2001 From: Tobias Brunner Date: Tue, 7 May 2013 15:05:12 +0200 Subject: [PATCH 14/14] charon-cmd: Changed formatting of optional arguments in usage information Optional arguments have to be specified with = after the option. --- src/charon-cmd/charon-cmd.c | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/src/charon-cmd/charon-cmd.c b/src/charon-cmd/charon-cmd.c index a77794abe..f898fd650 100644 --- a/src/charon-cmd/charon-cmd.c +++ b/src/charon-cmd/charon-cmd.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2006-2012 Tobias Brunner + * Copyright (C) 2006-2013 Tobias Brunner * Copyright (C) 2005-2013 Martin Willi * Copyright (C) 2006 Daniel Roethlisberger * Copyright (C) 2005 Jan Hutter @@ -199,7 +199,8 @@ static void segv_handler(int signal) */ static void usage(FILE *out, char *msg, char *binary) { - int i, line, pre, post, padto = 0, spacing = 2; + char *pre, *post; + int i, line, padto = 0, spacing = 2; for (i = 0; i < CMD_OPT_COUNT; i++) { @@ -218,19 +219,20 @@ static void usage(FILE *out, char *msg, char *binary) switch (cmd_options[i].has_arg) { case required_argument: - pre = '<'; - post = '>'; + pre = " <"; + post = ">"; break; case optional_argument: - pre = '['; - post = ']'; + pre = "[="; + post = "]"; break; case no_argument: default: - pre = post = ' '; + pre = " "; + post = " "; break; } - fprintf(out, " --%s %c%s%c %-*s%s\n", + fprintf(out, " --%s%s%s%s %-*s%s\n", cmd_options[i].name, pre, cmd_options[i].arg, post, padto - strlen(cmd_options[i].name) - strlen(cmd_options[i].arg), "",