swanctl: Generalize private key decryption to support other credential types

This commit is contained in:
Martin Willi
2015-03-18 13:34:22 +01:00
parent 84738b1aed
commit a1fb5251e0
+97 -55
View File
@@ -60,7 +60,7 @@ static bool load_cert(vici_conn_t *conn, command_format_options_t format,
} }
else else
{ {
printf("loaded %s certificate '%s'\n", type, dir); printf("loaded %s certificate from '%s'\n", type, dir);
} }
vici_free_res(res); vici_free_res(res);
return ret; return ret;
@@ -113,7 +113,14 @@ static bool load_key(vici_conn_t *conn, command_format_options_t format,
req = vici_begin("load-key"); req = vici_begin("load-key");
vici_add_key_valuef(req, "type", "%s", type); if (streq(type, "pkcs8"))
{ /* as used by vici */
vici_add_key_valuef(req, "type", "any");
}
else
{
vici_add_key_valuef(req, "type", "%s", type);
}
vici_add_key_value(req, "data", data.ptr, data.len); vici_add_key_value(req, "data", data.ptr, data.len);
res = vici_submit(req, conn); res = vici_submit(req, conn);
@@ -135,12 +142,42 @@ static bool load_key(vici_conn_t *conn, command_format_options_t format,
} }
else else
{ {
printf("loaded %s key '%s'\n", type, dir); printf("loaded %s key from '%s'\n", type, dir);
} }
vici_free_res(res); vici_free_res(res);
return ret; return ret;
} }
/**
* Load a private key of any type to vici
*/
static bool load_key_anytype(vici_conn_t *conn, command_format_options_t format,
char *path, private_key_t *private)
{
bool loaded = FALSE;
chunk_t encoding;
if (!private->get_encoding(private, PRIVKEY_ASN1_DER, &encoding))
{
fprintf(stderr, "encoding private key from '%s' failed\n", path);
return FALSE;
}
switch (private->get_type(private))
{
case KEY_RSA:
loaded = load_key(conn, format, path, "rsa", encoding);
break;
case KEY_ECDSA:
loaded = load_key(conn, format, path, "ecdsa", encoding);
break;
default:
fprintf(stderr, "unsupported key type in '%s'\n", path);
break;
}
chunk_clear(&encoding);
return loaded;
}
/** /**
* Callback function to prompt for private key passwords * Callback function to prompt for private key passwords
*/ */
@@ -174,61 +211,81 @@ CALLBACK(password_cb, shared_key_t*,
} }
/** /**
* Try to parse a potentially encrypted private key using password prompt * Determine credential type and subtype from a type string
*/ */
static private_key_t* decrypt_key(char *name, char *type, chunk_t encoding) static bool determine_credtype(char *type, credential_type_t *credtype,
int *subtype)
{ {
key_type_t kt = KEY_ANY; struct {
private_key_t *private; char *type;
credential_type_t credtype;
int subtype;
} map[] = {
{ "pkcs8", CRED_PRIVATE_KEY, KEY_ANY, },
{ "rsa", CRED_PRIVATE_KEY, KEY_RSA, },
{ "ecdsa", CRED_PRIVATE_KEY, KEY_ECDSA, },
};
int i;
for (i = 0; i < countof(map); i++)
{
if (streq(map[i].type, type))
{
*credtype = map[i].credtype;
*subtype = map[i].subtype;
return TRUE;
}
}
return FALSE;
}
/**
* Try to parse a potentially encrypted credential using password prompt
*/
static void* decrypt(char *name, char *type, chunk_t encoding)
{
credential_type_t credtype;
int subtype;
void *cred;
callback_cred_t *cb; callback_cred_t *cb;
char buf[128]; char buf[128];
if (streq(type, "rsa")) if (!determine_credtype(type, &credtype, &subtype))
{ {
kt = KEY_RSA; return NULL;
}
else if (streq(type, "ecdsa"))
{
kt = KEY_ECDSA;
} }
snprintf(buf, sizeof(buf), "Password for '%s': ", name); snprintf(buf, sizeof(buf), "Password for %s file '%s': ", type, name);
cb = callback_cred_create_shared(password_cb, buf); cb = callback_cred_create_shared(password_cb, buf);
lib->credmgr->add_set(lib->credmgr, &cb->set); lib->credmgr->add_set(lib->credmgr, &cb->set);
private = lib->creds->create(lib->creds, CRED_PRIVATE_KEY, kt, cred = lib->creds->create(lib->creds, credtype, subtype,
BUILD_BLOB_PEM, encoding, BUILD_END); BUILD_BLOB_PEM, encoding, BUILD_END);
lib->credmgr->remove_set(lib->credmgr, &cb->set); lib->credmgr->remove_set(lib->credmgr, &cb->set);
cb->destroy(cb); cb->destroy(cb);
return private; return cred;
} }
/** /**
* Try to parse a potentially encrypted private key using configured secret * Try to parse a potentially encrypted credential using configured secret
*/ */
static private_key_t* decrypt_key_with_config(settings_t *cfg, char *name, static void* decrypt_with_config(settings_t *cfg, char *name, char *type,
char *type, chunk_t encoding) chunk_t encoding)
{ key_type_t kt = KEY_ANY; {
credential_type_t credtype;
int subtype;
enumerator_t *enumerator, *secrets; enumerator_t *enumerator, *secrets;
char *section, *key, *value, *file, buf[128]; char *section, *key, *value, *file, buf[128];
shared_key_t *shared; shared_key_t *shared;
private_key_t *private = NULL; void *cred = NULL;
mem_cred_t *mem = NULL; mem_cred_t *mem = NULL;
if (streq(type, "rsa")) if (!determine_credtype(type, &credtype, &subtype))
{ {
kt = KEY_RSA; return NULL;
}
else if (streq(type, "ecdsa"))
{
kt = KEY_ECDSA;
}
else
{
type = "pkcs8";
} }
/* load all secrets for this key type */ /* load all secrets for this key type */
@@ -265,12 +322,12 @@ static private_key_t* decrypt_key_with_config(settings_t *cfg, char *name,
{ {
lib->credmgr->add_local_set(lib->credmgr, &mem->set, FALSE); lib->credmgr->add_local_set(lib->credmgr, &mem->set, FALSE);
private = lib->creds->create(lib->creds, CRED_PRIVATE_KEY, kt, cred = lib->creds->create(lib->creds, credtype, subtype,
BUILD_BLOB_PEM, encoding, BUILD_END); BUILD_BLOB_PEM, encoding, BUILD_END);
lib->credmgr->remove_local_set(lib->credmgr, &mem->set); lib->credmgr->remove_local_set(lib->credmgr, &mem->set);
if (!private) if (!cred)
{ {
fprintf(stderr, "configured decryption secret for '%s' invalid\n", fprintf(stderr, "configured decryption secret for '%s' invalid\n",
name); name);
@@ -279,7 +336,7 @@ static private_key_t* decrypt_key_with_config(settings_t *cfg, char *name,
mem->destroy(mem); mem->destroy(mem);
} }
return private; return cred;
} }
/** /**
@@ -292,30 +349,15 @@ static bool load_encrypted_key(vici_conn_t *conn,
{ {
private_key_t *private; private_key_t *private;
bool loaded = FALSE; bool loaded = FALSE;
chunk_t encoding;
private = decrypt_key_with_config(cfg, rel, type, data); private = decrypt_with_config(cfg, rel, type, data);
if (!private && !noprompt) if (!private && !noprompt)
{ {
private = decrypt_key(rel, type, data); private = decrypt(rel, type, data);
} }
if (private) if (private)
{ {
if (private->get_encoding(private, PRIVKEY_ASN1_DER, &encoding)) loaded = load_key_anytype(conn, format, path, private);
{
switch (private->get_type(private))
{
case KEY_RSA:
loaded = load_key(conn, format, path, "rsa", encoding);
break;
case KEY_ECDSA:
loaded = load_key(conn, format, path, "ecdsa", encoding);
break;
default:
break;
}
chunk_clear(&encoding);
}
private->destroy(private); private->destroy(private);
} }
return loaded; return loaded;
@@ -510,7 +552,7 @@ int load_creds_cfg(vici_conn_t *conn, command_format_options_t format,
load_keys(conn, format, noprompt, cfg, "rsa", SWANCTL_RSADIR); load_keys(conn, format, noprompt, cfg, "rsa", SWANCTL_RSADIR);
load_keys(conn, format, noprompt, cfg, "ecdsa", SWANCTL_ECDSADIR); load_keys(conn, format, noprompt, cfg, "ecdsa", SWANCTL_ECDSADIR);
load_keys(conn, format, noprompt, cfg, "any", SWANCTL_PKCS8DIR); load_keys(conn, format, noprompt, cfg, "pkcs8", SWANCTL_PKCS8DIR);
enumerator = cfg->create_section_enumerator(cfg, "secrets"); enumerator = cfg->create_section_enumerator(cfg, "secrets");
while (enumerator->enumerate(enumerator, &section)) while (enumerator->enumerate(enumerator, &section))