#include "command.h"
#include "swanctl.h"
+#include <credentials/sets/mem_cred.h>
#include <credentials/sets/callback_cred.h>
/**
}
/**
- * Try to parse a potentially encrypted private key
+ * Try to parse a potentially encrypted private key using password prompt
*/
static private_key_t* decrypt_key(char *name, char *type, chunk_t encoding)
{
return private;
}
+/**
+ * Try to parse a potentially encrypted private key using configured secret
+ */
+static private_key_t* decrypt_key_with_config(settings_t *cfg, char *name,
+ char *type, chunk_t encoding)
+{ key_type_t kt = KEY_ANY;
+ enumerator_t *enumerator, *secrets;
+ char *section, *key, *value, *file, buf[128];
+ shared_key_t *shared;
+ private_key_t *private = NULL;
+ mem_cred_t *mem = NULL;
+
+ if (streq(type, "rsa"))
+ {
+ kt = KEY_RSA;
+ }
+ else if (streq(type, "ecdsa"))
+ {
+ kt = KEY_ECDSA;
+ }
+ else
+ {
+ type = "pkcs8";
+ }
+
+ /* load all secrets for this key type */
+ enumerator = cfg->create_section_enumerator(cfg, "secrets");
+ while (enumerator->enumerate(enumerator, §ion))
+ {
+ if (strpfx(section, type))
+ {
+ file = cfg->get_str(cfg, "secrets.%s.file", NULL, section);
+ if (file && strcaseeq(file, name))
+ {
+ snprintf(buf, sizeof(buf), "secrets.%s", section);
+ secrets = cfg->create_key_value_enumerator(cfg, buf);
+ while (secrets->enumerate(secrets, &key, &value))
+ {
+ if (strpfx(key, "secret"))
+ {
+ if (!mem)
+ {
+ mem = mem_cred_create();
+ }
+ shared = shared_key_create(SHARED_PRIVATE_KEY_PASS,
+ chunk_clone(chunk_from_str(value)));
+ mem->add_shared(mem, shared, NULL);
+ }
+ }
+ secrets->destroy(secrets);
+ }
+ }
+ }
+ enumerator->destroy(enumerator);
+
+ if (mem)
+ {
+ lib->credmgr->add_local_set(lib->credmgr, &mem->set, FALSE);
+
+ private = lib->creds->create(lib->creds, CRED_PRIVATE_KEY, kt,
+ BUILD_BLOB_PEM, encoding, BUILD_END);
+
+ lib->credmgr->remove_local_set(lib->credmgr, &mem->set);
+
+ if (!private)
+ {
+ fprintf(stderr, "configured decryption secret for '%s' invalid\n",
+ name);
+ }
+
+ mem->destroy(mem);
+ }
+
+ return private;
+}
+
/**
* Try to decrypt and load a private key
*/
-static bool load_encrypted_key(vici_conn_t *conn, command_format_options_t format,
- char *rel, char *path, char *type, chunk_t data)
+static bool load_encrypted_key(vici_conn_t *conn,
+ command_format_options_t format, settings_t *cfg,
+ char *rel, char *path, char *type, bool noprompt,
+ chunk_t data)
{
private_key_t *private;
bool loaded = FALSE;
chunk_t encoding;
- private = decrypt_key(rel, type, data);
+ private = decrypt_key_with_config(cfg, rel, type, data);
+ if (!private && !noprompt)
+ {
+ private = decrypt_key(rel, type, data);
+ }
if (private)
{
- if (private->get_encoding(private, PRIVKEY_ASN1_DER,
- &encoding))
+ if (private->get_encoding(private, PRIVKEY_ASN1_DER, &encoding))
{
switch (private->get_type(private))
{
* Load private keys from a directory
*/
static void load_keys(vici_conn_t *conn, command_format_options_t format,
- bool noprompt, char *type, char *dir)
+ bool noprompt, settings_t *cfg, char *type, char *dir)
{
enumerator_t *enumerator;
struct stat st;
map = chunk_map(path, FALSE);
if (map)
{
- if (noprompt ||
- !load_encrypted_key(conn, format, rel, path, type, *map))
+ if (!load_encrypted_key(conn, format, cfg, rel, path, type,
+ noprompt, *map))
{
load_key(conn, format, path, type, *map);
}
"eap",
"xauth",
"ike",
+ "rsa",
+ "ecdsa",
+ "pkcs8",
};
for (i = 0; i < countof(types); i++)
fprintf(stderr, "ignoring unsupported secret '%s'\n", section);
return FALSE;
}
+ if (!streq(type, "eap") && !streq(type, "xauth") && !streq(type, "ike"))
+ { /* skip non-shared secrets */
+ return TRUE;
+ }
value = cfg->get_str(cfg, "secrets.%s.secret", NULL, section);
if (!value)
}
}
- load_certs(conn, format, "x509", SWANCTL_X509DIR);
- load_certs(conn, format, "x509ca", SWANCTL_X509CADIR);
- load_certs(conn, format, "x509aa", SWANCTL_X509AADIR);
- load_certs(conn, format, "x509crl", SWANCTL_X509CRLDIR);
- load_certs(conn, format, "x509ac", SWANCTL_X509ACDIR);
-
- load_keys(conn, format, noprompt, "rsa", SWANCTL_RSADIR);
- load_keys(conn, format, noprompt, "ecdsa", SWANCTL_ECDSADIR);
- load_keys(conn, format, noprompt, "any", SWANCTL_PKCS8DIR);
-
cfg = settings_create(SWANCTL_CONF);
if (!cfg)
{
return EINVAL;
}
+ load_certs(conn, format, "x509", SWANCTL_X509DIR);
+ load_certs(conn, format, "x509ca", SWANCTL_X509CADIR);
+ load_certs(conn, format, "x509aa", SWANCTL_X509AADIR);
+ load_certs(conn, format, "x509crl", SWANCTL_X509CRLDIR);
+ load_certs(conn, format, "x509ac", SWANCTL_X509ACDIR);
+
+ load_keys(conn, format, noprompt, cfg, "rsa", SWANCTL_RSADIR);
+ load_keys(conn, format, noprompt, cfg, "ecdsa", SWANCTL_ECDSADIR);
+ load_keys(conn, format, noprompt, cfg, "any", SWANCTL_PKCS8DIR);
+
enumerator = cfg->create_section_enumerator(cfg, "secrets");
while (enumerator->enumerate(enumerator, §ion))
{
failures. Use trap policies to reliably re-create failed CHILD_SAs.
secrets { # }
- Section defining secrets for IKE and EAP/XAuth authentication.
+ Section defining secrets for IKE/EAP/XAuth authentication and private
+ key decryption.
- Section defining secrets for IKE and EAP/XAuth authentication. The
- **secrets** section takes sub-sections having a specific prefix which
- defines the secret type.
+ Section defining secrets for IKE/EAP/XAuth authentication and private key
+ decryption. The **secrets** section takes sub-sections having a specific
+ prefix which defines the secret type.
+
+ It is not recommended to define any private key decryption passphrases,
+ as then there is no real security benefit in having encrypted keys. Either
+ store the key unencrypted, or enter the keys manually when loading
+ credentials.
secrets.eap<suffix> { # }
EAP secret section for a specific secret.
may be specified, each having an _id_ prefix, if a secret is shared between
multiple peers.
+secrets.rsa<suffix> { # }
+ Private key decryption passphrase for a key in the _rsa_ folder.
+
+secrets.rsa<suffix>.file =
+ File name in the _rsa_ folder for which this passphrase should be used.
+
+secrets.rsa<suffix>.secret
+ Value of decryption passphrase for RSA key.
+
+secrets.ecdsa<suffix> { # }
+ Private key decryption passphrase for a key in the _ecdsa_ folder.
+
+secrets.ecdsa<suffix>.file =
+ File name in the _ecdsa_ folder for which this passphrase should be used.
+
+secrets.ecdsa<suffix>.secret
+ Value of decryption passphrase for ECDSA key.
+
+secrets.pkcs8<suffix> { # }
+ Private key decryption passphrase for a key in the _pkcs8_ folder.
+
+secrets.pkcs8<suffix>.file =
+ File name in the _pkcs8_ folder for which this passphrase should be used.
+
+secrets.pkcs8<suffix>.secret
+ Value of decryption passphrase for PKCS#8 key.
+
pools { # }
Section defining named pools.