diff options
-rw-r--r-- | man/ipsec.secrets.5.in | 21 | ||||
-rw-r--r-- | src/libcharon/plugins/stroke/stroke_cred.c | 107 |
2 files changed, 109 insertions, 19 deletions
diff --git a/man/ipsec.secrets.5.in b/man/ipsec.secrets.5.in index 319d4856b..ee20c9670 100644 --- a/man/ipsec.secrets.5.in +++ b/man/ipsec.secrets.5.in @@ -91,6 +91,9 @@ defines an RSA private key .B ECDSA defines an ECDSA private key .TP +.B P12 +defines a PKCS#12 container +.TP .B EAP defines EAP credentials .TP @@ -133,16 +136,26 @@ Similarly, a character sequence beginning with .B 0s is interpreted as Base64 encoded binary data. .TP -.B [ <selectors> ] : RSA <private key file> [ <passphrase> | %prompt ] +.B : RSA <private key file> [ <passphrase> | %prompt ] .TQ -.B [ <selectors> ] : ECDSA <private key file> [ <passphrase> | %prompt ] +.B : ECDSA <private key file> [ <passphrase> | %prompt ] For the private key file both absolute paths or paths relative to \fI/etc/ipsec.d/private\fP are accepted. If the private key file is encrypted, the \fIpassphrase\fP must be defined. Instead of a passphrase .B %prompt -can be used which then causes the daemons to ask the user for the password +can be used which then causes the daemon to ask the user for the password whenever it is required to decrypt the key. .TP +.B : P12 <PKCS#12 file> [ <passphrase> | %prompt ] +For the PKCS#12 file both absolute paths or paths relative to +\fI/etc/ipsec.d/private\fP are accepted. If the container is +encrypted, the \fIpassphrase\fP must be defined. Instead of a passphrase +.B %prompt +can be used which then causes the daemon to ask the user for the password +whenever it is required to decrypt the container. Private keys, client and CA +certificates are extracted from the container. To use such a client certificate +in a connection set leftid to one of the subjects of the certificate. +.TP .B <user id> : EAP <secret> The format of \fIsecret\fP is the same as that of \fBPSK\fP secrets. .br @@ -165,7 +178,7 @@ key. The slot number defines the slot on the token, the module name refers to the module name defined in strongswan.conf(5). Instead of specifying the pin code statically, .B %prompt -can be specified, which causes the daemons to ask the user for the pin code. +can be specified, which causes the daemon to ask the user for the pin code. .LP .SH FILES diff --git a/src/libcharon/plugins/stroke/stroke_cred.c b/src/libcharon/plugins/stroke/stroke_cred.c index f24082ee3..703410016 100644 --- a/src/libcharon/plugins/stroke/stroke_cred.c +++ b/src/libcharon/plugins/stroke/stroke_cred.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2008-2012 Tobias Brunner + * Copyright (C) 2008-2013 Tobias Brunner * Copyright (C) 2008 Martin Willi * Hochschule fuer Technik Rapperswil * @@ -32,6 +32,7 @@ #include <credentials/certificates/x509.h> #include <credentials/certificates/crl.h> #include <credentials/certificates/ac.h> +#include <credentials/containers/pkcs12.h> #include <credentials/sets/mem_cred.h> #include <credentials/sets/callback_cred.h> #include <collections/linked_list.h> @@ -72,7 +73,7 @@ struct private_stroke_cred_t { /** * ignore missing CA basic constraint (i.e. treat all certificates in - * ipsec.conf ca sections and ipsec.d/cacert as CA certificates) + * ipsec.conf ca sections and ipsec.d/cacerts as CA certificates) */ bool force_ca_cert; @@ -225,7 +226,7 @@ METHOD(stroke_cred_t, load_ca, certificate_t*, cert->destroy(cert); return NULL; } - DBG1(DBG_CFG, " loaded ca certificate \"%Y\" from '%s", + DBG1(DBG_CFG, " loaded ca certificate \"%Y\" from '%s'", cert->get_subject(cert), filename); return this->creds->add_cert_ref(this->creds, TRUE, cert); } @@ -821,15 +822,14 @@ static bool load_pin(mem_cred_t *secrets, chunk_t line, int line_nr, } /** - * Load a private key + * Load a private key or PKCS#12 container from a file */ -static bool load_private(mem_cred_t *secrets, chunk_t line, int line_nr, - FILE *prompt, key_type_t key_type) +static bool load_from_file(chunk_t line, int line_nr, FILE *prompt, + char *path, int type, int subtype, + void **result) { - char path[PATH_MAX]; chunk_t filename; chunk_t secret = chunk_empty; - private_key_t *key; err_t ugh = extract_value(&filename, &line); @@ -846,12 +846,12 @@ static bool load_private(mem_cred_t *secrets, chunk_t line, int line_nr, if (*filename.ptr == '/') { /* absolute path name */ - snprintf(path, sizeof(path), "%.*s", (int)filename.len, filename.ptr); + snprintf(path, PATH_MAX, "%.*s", (int)filename.len, filename.ptr); } else { /* relative path name */ - snprintf(path, sizeof(path), "%s/%.*s", PRIVATE_KEY_DIR, + snprintf(path, PATH_MAX, "%s/%.*s", PRIVATE_KEY_DIR, (int)filename.len, filename.ptr); } @@ -877,6 +877,7 @@ static bool load_private(mem_cred_t *secrets, chunk_t line, int line_nr, free(secret.ptr); if (!prompt) { + *result = NULL; return TRUE; } /* use callback credential set to prompt for the passphrase */ @@ -886,8 +887,8 @@ static bool load_private(mem_cred_t *secrets, chunk_t line, int line_nr, cb = callback_cred_create_shared((void*)passphrase_cb, &pp_data); lib->credmgr->add_local_set(lib->credmgr, &cb->set, FALSE); - key = lib->creds->create(lib->creds, CRED_PRIVATE_KEY, key_type, - BUILD_FROM_FILE, path, BUILD_END); + *result = lib->creds->create(lib->creds, type, subtype, + BUILD_FROM_FILE, path, BUILD_END); lib->credmgr->remove_local_set(lib->credmgr, &cb->set); cb->destroy(cb); @@ -903,12 +904,29 @@ static bool load_private(mem_cred_t *secrets, chunk_t line, int line_nr, mem->add_shared(mem, shared, NULL); lib->credmgr->add_local_set(lib->credmgr, &mem->set, FALSE); - key = lib->creds->create(lib->creds, CRED_PRIVATE_KEY, key_type, - BUILD_FROM_FILE, path, BUILD_END); + *result = lib->creds->create(lib->creds, type, subtype, + BUILD_FROM_FILE, path, BUILD_END); lib->credmgr->remove_local_set(lib->credmgr, &mem->set); mem->destroy(mem); } + return TRUE; +} + +/** + * Load a private key + */ +static bool load_private(mem_cred_t *secrets, chunk_t line, int line_nr, + FILE *prompt, key_type_t key_type) +{ + char path[PATH_MAX]; + private_key_t *key; + + if (!load_from_file(line, line_nr, prompt, path, CRED_PRIVATE_KEY, + key_type, (void**)&key)) + { + return FALSE; + } if (key) { DBG1(DBG_CFG, " loaded %N private key from '%s'", @@ -923,6 +941,58 @@ static bool load_private(mem_cred_t *secrets, chunk_t line, int line_nr, } /** + * Load a PKCS#12 container + */ +static bool load_pkcs12(mem_cred_t *secrets, chunk_t line, int line_nr, + FILE *prompt) +{ + enumerator_t *enumerator; + char path[PATH_MAX]; + certificate_t *cert; + private_key_t *key; + pkcs12_t *pkcs12; + + if (!load_from_file(line, line_nr, prompt, path, CRED_CONTAINER, + CONTAINER_PKCS12, (void**)&pkcs12)) + { + return FALSE; + } + if (!pkcs12) + { + DBG1(DBG_CFG, " loading credentials from '%s' failed", path); + return TRUE; + } + enumerator = pkcs12->create_cert_enumerator(pkcs12); + while (enumerator->enumerate(enumerator, &cert)) + { + x509_t *x509 = (x509_t*)cert; + + if (x509->get_flags(x509) & X509_CA) + { + DBG1(DBG_CFG, " loaded ca certificate \"%Y\" from '%s'", + cert->get_subject(cert), path); + } + else + { + DBG1(DBG_CFG, " loaded certificate \"%Y\" from '%s'", + cert->get_subject(cert), path); + } + secrets->add_cert(secrets, TRUE, cert->get_ref(cert)); + } + enumerator->destroy(enumerator); + enumerator = pkcs12->create_key_enumerator(pkcs12); + while (enumerator->enumerate(enumerator, &key)) + { + DBG1(DBG_CFG, " loaded %N private key from '%s'", + key_type_names, key->get_type(key), path); + secrets->add_key(secrets, key->get_ref(key)); + } + enumerator->destroy(enumerator); + pkcs12->container.destroy(&pkcs12->container); + return TRUE; +} + +/** * Load a shared key */ static bool load_shared(mem_cred_t *secrets, chunk_t line, int line_nr, @@ -1140,6 +1210,13 @@ static void load_secrets(private_stroke_cred_t *this, mem_cred_t *secrets, break; } } + else if (match("P12", &token)) + { + if (!load_pkcs12(secrets, line, line_nr, prompt)) + { + break; + } + } else if (match("PIN", &token)) { if (!load_pin(secrets, line, line_nr, prompt)) @@ -1160,7 +1237,7 @@ static void load_secrets(private_stroke_cred_t *this, mem_cred_t *secrets, else { DBG1(DBG_CFG, "line %d: token must be either " - "RSA, ECDSA, PSK, EAP, XAUTH or PIN", line_nr); + "RSA, ECDSA, P12, PIN, PSK, EAP, XAUTH or NTLM", line_nr); break; } } |