From: Martin Willi Date: Wed, 11 Mar 2015 15:23:56 +0000 (+0100) Subject: swanctl: Support loading PKCS#12 containers from a pkcs12 swanctl directory X-Git-Tag: 5.3.0rc1~29^2~1 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=54cdf847ccf1eee2608291a36a19c078df485a2d;p=thirdparty%2Fstrongswan.git swanctl: Support loading PKCS#12 containers from a pkcs12 swanctl directory --- diff --git a/src/swanctl/Makefile.am b/src/swanctl/Makefile.am index b84d705879..f4f9fdf7e6 100644 --- a/src/swanctl/Makefile.am +++ b/src/swanctl/Makefile.am @@ -65,4 +65,5 @@ install-data-local: swanctl.conf test -e "$(DESTDIR)$(swanctldir)/rsa" || $(INSTALL) -d -m 750 "$(DESTDIR)$(swanctldir)/rsa" || true test -e "$(DESTDIR)$(swanctldir)/ecdsa" || $(INSTALL) -d -m 750 "$(DESTDIR)$(swanctldir)/ecdsa" || true test -e "$(DESTDIR)$(swanctldir)/pkcs8" || $(INSTALL) -d -m 750 "$(DESTDIR)$(swanctldir)/pkcs8" || true + test -e "$(DESTDIR)$(swanctldir)/pkcs12" || $(INSTALL) -d -m 750 "$(DESTDIR)$(swanctldir)/pkcs12" || true test -e "$(DESTDIR)$(swanctldir)/swanctl.conf" || $(INSTALL) -m 640 $(srcdir)/swanctl.conf $(DESTDIR)$(swanctldir)/swanctl.conf || true diff --git a/src/swanctl/commands/load_creds.c b/src/swanctl/commands/load_creds.c index db94f49591..2579a5231b 100644 --- a/src/swanctl/commands/load_creds.c +++ b/src/swanctl/commands/load_creds.c @@ -25,6 +25,7 @@ #include #include +#include /** * Load a single certificate over vici @@ -224,6 +225,7 @@ static bool determine_credtype(char *type, credential_type_t *credtype, { "pkcs8", CRED_PRIVATE_KEY, KEY_ANY, }, { "rsa", CRED_PRIVATE_KEY, KEY_RSA, }, { "ecdsa", CRED_PRIVATE_KEY, KEY_ECDSA, }, + { "pkcs12", CRED_CONTAINER, CONTAINER_PKCS12, }, }; int i; @@ -402,6 +404,114 @@ static void load_keys(vici_conn_t *conn, command_format_options_t format, } } +/** + * Load credentials from a PKCS#12 container over vici + */ +static bool load_pkcs12(vici_conn_t *conn, command_format_options_t format, + char *path, pkcs12_t *p12) +{ + enumerator_t *enumerator; + certificate_t *cert; + private_key_t *private; + chunk_t encoding; + bool loaded = TRUE; + + enumerator = p12->create_cert_enumerator(p12); + while (loaded && enumerator->enumerate(enumerator, &cert)) + { + loaded = FALSE; + if (cert->get_encoding(cert, CERT_ASN1_DER, &encoding)) + { + loaded = load_cert(conn, format, path, "x509", encoding); + if (loaded) + { + fprintf(stderr, " %Y\n", cert->get_subject(cert)); + } + free(encoding.ptr); + } + else + { + fprintf(stderr, "encoding certificate from '%s' failed\n", path); + } + } + enumerator->destroy(enumerator); + + enumerator = p12->create_key_enumerator(p12); + while (loaded && enumerator->enumerate(enumerator, &private)) + { + loaded = load_key_anytype(conn, format, path, private); + } + enumerator->destroy(enumerator); + + return loaded; +} + +/** + * Try to decrypt and load credentials from a container + */ +static bool load_encrypted_container(vici_conn_t *conn, + command_format_options_t format, settings_t *cfg, char *rel, + char *path, char *type, bool noprompt, chunk_t data) +{ + container_t *container; + bool loaded = FALSE; + + container = decrypt_with_config(cfg, rel, type, data); + if (!container && !noprompt) + { + container = decrypt(rel, type, data); + } + if (container) + { + switch (container->get_type(container)) + { + case CONTAINER_PKCS12: + loaded = load_pkcs12(conn, format, path, (pkcs12_t*)container); + break; + default: + break; + } + container->destroy(container); + } + return loaded; +} + +/** + * Load credential containers from a directory + */ +static void load_containers(vici_conn_t *conn, command_format_options_t format, + bool noprompt, settings_t *cfg, char *type, char *dir) +{ + enumerator_t *enumerator; + struct stat st; + chunk_t *map; + char *path, *rel; + + enumerator = enumerator_create_directory(dir); + if (enumerator) + { + while (enumerator->enumerate(enumerator, &rel, &path, &st)) + { + if (S_ISREG(st.st_mode)) + { + map = chunk_map(path, FALSE); + if (map) + { + load_encrypted_container(conn, format, cfg, rel, path, + type, noprompt, *map); + chunk_unmap(map); + } + else + { + fprintf(stderr, "mapping '%s' failed: %s, skipped\n", + path, strerror(errno)); + } + } + } + enumerator->destroy(enumerator); + } +} + /** * Load a single secret over VICI */ @@ -422,6 +532,7 @@ static bool load_secret(vici_conn_t *conn, settings_t *cfg, "rsa", "ecdsa", "pkcs8", + "pkcs12", }; for (i = 0; i < countof(types); i++) @@ -554,6 +665,8 @@ int load_creds_cfg(vici_conn_t *conn, command_format_options_t format, load_keys(conn, format, noprompt, cfg, "ecdsa", SWANCTL_ECDSADIR); load_keys(conn, format, noprompt, cfg, "pkcs8", SWANCTL_PKCS8DIR); + load_containers(conn, format, noprompt, cfg, "pkcs12", SWANCTL_PKCS12DIR); + enumerator = cfg->create_section_enumerator(cfg, "secrets"); while (enumerator->enumerate(enumerator, §ion)) { diff --git a/src/swanctl/swanctl.h b/src/swanctl/swanctl.h index bd7e003787..cb570cd340 100644 --- a/src/swanctl/swanctl.h +++ b/src/swanctl/swanctl.h @@ -66,4 +66,9 @@ */ #define SWANCTL_PKCS8DIR SWANCTLDIR "/pkcs8" +/** + * Directory for PKCS#12 containers + */ +#define SWANCTL_PKCS12DIR SWANCTLDIR "/pkcs12" + #endif /** SWANCTL_H_ @}*/ diff --git a/src/swanctl/swanctl.opt b/src/swanctl/swanctl.opt index 454d4a51a8..b6ef175463 100644 --- a/src/swanctl/swanctl.opt +++ b/src/swanctl/swanctl.opt @@ -775,6 +775,15 @@ secrets.pkcs8.file = secrets.pkcs8.secret Value of decryption passphrase for PKCS#8 key. +secrets.pkcs12 { # } + PKCS#12 decryption passphrase for a container in the _pkcs12_ folder. + +secrets.pkcs12.file = + File name in the _pkcs12_ folder for which this passphrase should be used. + +secrets.pkcs12.secret + Value of decryption passphrase for PKCS#12 container. + pools { # } Section defining named pools.