diff options
-rw-r--r-- | configure.in | 17 | ||||
-rw-r--r-- | src/libstrongswan/Makefile.am | 4 | ||||
-rw-r--r-- | src/libstrongswan/credentials/builder.c | 4 | ||||
-rw-r--r-- | src/libstrongswan/credentials/builder.h | 10 | ||||
-rw-r--r-- | src/libstrongswan/credentials/credential_factory.c | 10 | ||||
-rw-r--r-- | src/libstrongswan/plugins/pem/Makefile.am | 12 | ||||
-rw-r--r-- | src/libstrongswan/plugins/pem/pem_builder.c | 490 | ||||
-rw-r--r-- | src/libstrongswan/plugins/pem/pem_builder.h | 52 | ||||
-rw-r--r-- | src/libstrongswan/plugins/pem/pem_plugin.c | 97 | ||||
-rw-r--r-- | src/libstrongswan/plugins/pem/pem_plugin.h | 47 | ||||
-rw-r--r-- | src/libstrongswan/plugins/pubkey/pubkey_public_key.c | 9 | ||||
-rwxr-xr-x | src/medsrv/controller/peer_controller.c | 5 |
12 files changed, 746 insertions, 11 deletions
diff --git a/configure.in b/configure.in index 04dfe868b..97bd331b1 100644 --- a/configure.in +++ b/configure.in @@ -288,6 +288,17 @@ AC_ARG_ENABLE( ) AC_ARG_ENABLE( + [pem], + AS_HELP_STRING([--disable-pem],[disable PEM decoding plugin. (default is NO).]), + [if test x$enableval = xyes; then + pem=true + else + pem=false + fi], + pem=true +) + +AC_ARG_ENABLE( [hmac], AS_HELP_STRING([--disable-hmac],[disable HMAC crypto implementation plugin. (default is NO).]), [if test x$enableval = xyes; then @@ -1181,6 +1192,10 @@ if test x$pubkey = xtrue; then libstrongswan_plugins=${libstrongswan_plugins}" pubkey" pluto_plugins=${pluto_plugins}" pubkey" fi +if test x$pem = xtrue; then + libstrongswan_plugins=${libstrongswan_plugins}" pem" + pluto_plugins=${pluto_plugins}" pem" +fi if test x$mysql = xtrue; then libstrongswan_plugins=${libstrongswan_plugins}" mysql" fi @@ -1237,6 +1252,7 @@ AM_CONDITIONAL(USE_GMP, test x$gmp = xtrue) AM_CONDITIONAL(USE_RANDOM, test x$random = xtrue) AM_CONDITIONAL(USE_X509, test x$x509 = xtrue) AM_CONDITIONAL(USE_PUBKEY, test x$pubkey = xtrue) +AM_CONDITIONAL(USE_PEM, test x$pem = xtrue) AM_CONDITIONAL(USE_HMAC, test x$hmac = xtrue) AM_CONDITIONAL(USE_XCBC, test x$xcbc = xtrue) AM_CONDITIONAL(USE_MYSQL, test x$mysql = xtrue) @@ -1331,6 +1347,7 @@ AC_OUTPUT( src/libstrongswan/plugins/xcbc/Makefile src/libstrongswan/plugins/x509/Makefile src/libstrongswan/plugins/pubkey/Makefile + src/libstrongswan/plugins/pem/Makefile src/libstrongswan/plugins/curl/Makefile src/libstrongswan/plugins/ldap/Makefile src/libstrongswan/plugins/mysql/Makefile diff --git a/src/libstrongswan/Makefile.am b/src/libstrongswan/Makefile.am index ee6996558..1777daa06 100644 --- a/src/libstrongswan/Makefile.am +++ b/src/libstrongswan/Makefile.am @@ -162,6 +162,10 @@ if USE_PUBKEY SUBDIRS += plugins/pubkey endif +if USE_PEM + SUBDIRS += plugins/pem +endif + if USE_CURL SUBDIRS += plugins/curl endif diff --git a/src/libstrongswan/credentials/builder.c b/src/libstrongswan/credentials/builder.c index 701cbcde3..8a799d3cd 100644 --- a/src/libstrongswan/credentials/builder.c +++ b/src/libstrongswan/credentials/builder.c @@ -19,9 +19,11 @@ ENUM(builder_part_names, BUILD_FROM_FILE, BUILD_END, "BUILD_FROM_FILE", "BUILD_AGENT_SOCKET", "BUILD_BLOB_ASN1_DER", - "BUILD_BLOB_ASN1_PEM", + "BUILD_BLOB_PEM", "BUILD_BLOB_PGP", "BUILD_BLOB_RFC_3110", + "BUILD_PASSPHRASE", + "BUILD_PASSPHRASE_CALLBACK", "BUILD_KEY_SIZE", "BUILD_SIGNING_KEY", "BUILD_SIGNING_CERT", diff --git a/src/libstrongswan/credentials/builder.h b/src/libstrongswan/credentials/builder.h index 01ccf2a5c..9c73f6e7c 100644 --- a/src/libstrongswan/credentials/builder.h +++ b/src/libstrongswan/credentials/builder.h @@ -44,12 +44,18 @@ enum builder_part_t { BUILD_AGENT_SOCKET, /** DER encoded ASN.1 blob, chunk_t */ BUILD_BLOB_ASN1_DER, - /** PEM encoded ASN.1 blob, null terminated char* */ - BUILD_BLOB_ASN1_PEM, + /** PEM encoded ASN.1/PGP blob, chunk_t */ + BUILD_BLOB_PEM, /** OpenPGP key blob, chunk_t */ BUILD_BLOB_PGP, /** RFC 3110 DNS public key blob, chunk_t */ BUILD_BLOB_RFC_3110, + /** passphrase for e.g. PEM decryption, chunk_t */ + BUILD_PASSPHRASE, + /** passphrase callback, chunk_t(*fn)(void *user, int try), void *user. + * The callback is invoked until the returned passphrase is accepted, or + * a zero-length passphrase is returned. Try starts at 1. */ + BUILD_PASSPHRASE_CALLBACK, /** key size in bits, as used for key generation, u_int */ BUILD_KEY_SIZE, /** private key to use for signing, private_key_t* */ diff --git a/src/libstrongswan/credentials/credential_factory.c b/src/libstrongswan/credentials/credential_factory.c index e55df0398..38bbc672a 100644 --- a/src/libstrongswan/credentials/credential_factory.c +++ b/src/libstrongswan/credentials/credential_factory.c @@ -142,7 +142,7 @@ static void* create(private_credential_factory_t *this, credential_type_t type, builder_t *builder; builder_part_t part; va_list args; - void* construct = NULL; + void* construct = NULL, *fn, *data; enumerator = create_builder_enumerator(this, type, subtype); while (enumerator->enumerate(enumerator, &builder)) @@ -155,9 +155,11 @@ static void* create(private_credential_factory_t *this, credential_type_t type, { case BUILD_END: break; + case BUILD_BLOB_PEM: case BUILD_BLOB_ASN1_DER: case BUILD_BLOB_PGP: case BUILD_BLOB_RFC_3110: + case BUILD_PASSPHRASE: case BUILD_SERIAL: builder->add(builder, part, va_arg(args, chunk_t)); continue; @@ -171,7 +173,6 @@ static void* create(private_credential_factory_t *this, credential_type_t type, case BUILD_NOT_AFTER_TIME: builder->add(builder, part, va_arg(args, time_t)); continue; - case BUILD_BLOB_ASN1_PEM: case BUILD_FROM_FILE: case BUILD_AGENT_SOCKET: case BUILD_SIGNING_KEY: @@ -188,6 +189,11 @@ static void* create(private_credential_factory_t *this, credential_type_t type, case BUILD_SMARTCARD_PIN: builder->add(builder, part, va_arg(args, void*)); continue; + case BUILD_PASSPHRASE_CALLBACK: + fn = va_arg(args, void*); + data = va_arg(args, void*); + builder->add(builder, part, fn, data); + continue; /* no default to get a compiler warning */ } break; diff --git a/src/libstrongswan/plugins/pem/Makefile.am b/src/libstrongswan/plugins/pem/Makefile.am new file mode 100644 index 000000000..98f356aaf --- /dev/null +++ b/src/libstrongswan/plugins/pem/Makefile.am @@ -0,0 +1,12 @@ + +INCLUDES = -I$(top_srcdir)/src/libstrongswan + +AM_CFLAGS = -rdynamic + +plugin_LTLIBRARIES = libstrongswan-pem.la + +libstrongswan_pem_la_SOURCES = pem_plugin.h pem_plugin.c \ + pem_builder.c pem_builder.h + +libstrongswan_pem_la_LDFLAGS = -module -avoid-version + diff --git a/src/libstrongswan/plugins/pem/pem_builder.c b/src/libstrongswan/plugins/pem/pem_builder.c new file mode 100644 index 000000000..d5bd1bd2d --- /dev/null +++ b/src/libstrongswan/plugins/pem/pem_builder.c @@ -0,0 +1,490 @@ +/* + * Copyright (C) 2009 Martin Willi + * Copyright (C) 2001-2008 Andreas Steffen + * 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 <http://www.fsf.org/copyleft/gpl.txt>. + * + * 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 "pem_builder.h" + +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> +#include <errno.h> +#include <string.h> +#include <stddef.h> +#include <sys/types.h> + +#include <debug.h> +#include <library.h> +#include <utils/lexparser.h> +#include <crypto/hashers/hasher.h> +#include <crypto/crypters/crypter.h> + +#define PKCS5_SALT_LEN 8 /* bytes */ + +typedef struct private_builder_t private_builder_t; + +/** + * Builder implementation for PEM decoding + */ +struct private_builder_t { + /** implements the builder interface */ + builder_t public; + /** credential type we are building */ + credential_type_t type; + /** subtype (keytype, certtype) of the credential we build */ + int subtype; + /** PEM encoding of the credential */ + chunk_t pem; + /** PEM decryption passphrase, if given */ + chunk_t passphrase; + /** supplied callback to read passphrase */ + chunk_t (*cb)(void *data, int try); + /** user data to callback */ + void *data; +}; + +/** + * check the presence of a pattern in a character string, skip if found + */ +static bool present(char* pattern, chunk_t* ch) +{ + u_int len = strlen(pattern); + + if (ch->len >= len && strneq(ch->ptr, pattern, len)) + { + *ch = chunk_skip(*ch, len); + return TRUE; + } + return FALSE; +} + +/** + * find a boundary of the form -----tag name----- + */ +static bool find_boundary(char* tag, chunk_t *line) +{ + chunk_t name = chunk_empty; + + if (!present("-----", line) || + !present(tag, line) || + *line->ptr != ' ') + { + return FALSE; + } + *line = chunk_skip(*line, 1); + + /* extract name */ + name.ptr = line->ptr; + while (line->len > 0) + { + if (present("-----", line)) + { + DBG2(" -----%s %.*s-----", tag, (int)name.len, name.ptr); + return TRUE; + } + line->ptr++; line->len--; name.len++; + } + return FALSE; +} + +/* + * decrypts a passphrase protected encrypted data block + */ +static status_t pem_decrypt(chunk_t *blob, encryption_algorithm_t alg, + size_t key_size, chunk_t iv, chunk_t passphrase) +{ + hasher_t *hasher; + crypter_t *crypter; + chunk_t salt = { iv.ptr, PKCS5_SALT_LEN }; + chunk_t hash; + chunk_t decrypted; + chunk_t key = {alloca(key_size), key_size}; + u_int8_t padding, *last_padding_pos, *first_padding_pos; + + /* build key from passphrase and IV */ + hasher = lib->crypto->create_hasher(lib->crypto, HASH_MD5); + if (hasher == NULL) + { + DBG1(" MD5 hash algorithm not available"); + return NOT_SUPPORTED; + } + hash.len = hasher->get_hash_size(hasher); + hash.ptr = alloca(hash.len); + hasher->get_hash(hasher, passphrase, NULL); + hasher->get_hash(hasher, salt, hash.ptr); + memcpy(key.ptr, hash.ptr, hash.len); + + if (key.len > hash.len) + { + hasher->get_hash(hasher, hash, NULL); + hasher->get_hash(hasher, passphrase, NULL); + hasher->get_hash(hasher, salt, hash.ptr); + memcpy(key.ptr + hash.len, hash.ptr, key.len - hash.len); + } + hasher->destroy(hasher); + + /* decrypt blob */ + crypter = lib->crypto->create_crypter(lib->crypto, alg, key_size); + if (crypter == NULL) + { + DBG1(" %N encryption algorithm not available", + encryption_algorithm_names, alg); + return NOT_SUPPORTED; + } + crypter->set_key(crypter, key); + + if (iv.len != crypter->get_block_size(crypter) || + blob->len % iv.len) + { + crypter->destroy(crypter); + DBG1(" data size is not multiple of block size"); + return PARSE_ERROR; + } + crypter->decrypt(crypter, *blob, iv, &decrypted); + crypter->destroy(crypter); + memcpy(blob->ptr, decrypted.ptr, blob->len); + chunk_free(&decrypted); + + /* determine amount of padding */ + last_padding_pos = blob->ptr + blob->len - 1; + padding = *last_padding_pos; + if (padding > blob->len) + { + first_padding_pos = blob->ptr; + } + else + { + first_padding_pos = last_padding_pos - padding; + } + /* check the padding pattern */ + while (--last_padding_pos > first_padding_pos) + { + if (*last_padding_pos != padding) + { + DBG1(" invalid passphrase"); + return INVALID_ARG; + } + } + /* remove padding */ + blob->len -= padding; + return SUCCESS; +} + +/** + * Converts a PEM encoded file into its binary form (RFC 1421, RFC 934) + */ +status_t pem_to_bin(chunk_t *blob, private_builder_t *this, bool *pgp) +{ + typedef enum { + PEM_PRE = 0, + PEM_MSG = 1, + PEM_HEADER = 2, + PEM_BODY = 3, + PEM_POST = 4, + PEM_ABORT = 5 + } state_t; + + encryption_algorithm_t alg = ENCR_UNDEFINED; + size_t key_size = 0; + bool encrypted = FALSE; + state_t state = PEM_PRE; + chunk_t src = *blob; + chunk_t dst = *blob; + chunk_t line = chunk_empty; + chunk_t iv = chunk_empty; + chunk_t passphrase; + int try = 0; + u_char iv_buf[HASH_SIZE_MD5]; + + dst.len = 0; + iv.ptr = iv_buf; + iv.len = 0; + + while (fetchline(&src, &line)) + { + if (state == PEM_PRE) + { + if (find_boundary("BEGIN", &line)) + { + state = PEM_MSG; + } + continue; + } + else + { + if (find_boundary("END", &line)) + { + state = PEM_POST; + break; + } + if (state == PEM_MSG) + { + state = PEM_HEADER; + if (memchr(line.ptr, ':', line.len) == NULL) + { + state = PEM_BODY; + } + } + if (state == PEM_HEADER) + { + err_t ugh = NULL; + chunk_t name = chunk_empty; + chunk_t value = chunk_empty; + + /* an empty line separates HEADER and BODY */ + if (line.len == 0) + { + state = PEM_BODY; + continue; + } + + /* we are looking for a parameter: value pair */ + DBG2(" %.*s", (int)line.len, line.ptr); + ugh = extract_parameter_value(&name, &value, &line); + if (ugh != NULL) + { + continue; + } + if (match("Proc-Type", &name) && *value.ptr == '4') + { + encrypted = TRUE; + } + else if (match("DEK-Info", &name)) + { + chunk_t dek; + + if (!extract_token(&dek, ',', &value)) + { + dek = value; + } + if (match("DES-EDE3-CBC", &dek)) + { + alg = ENCR_3DES; + key_size = 24; + } + else if (match("AES-128-CBC", &dek)) + { + alg = ENCR_AES_CBC; + key_size = 16; + } + else if (match("AES-192-CBC", &dek)) + { + alg = ENCR_AES_CBC; + key_size = 24; + } + else if (match("AES-256-CBC", &dek)) + { + alg = ENCR_AES_CBC; + key_size = 32; + } + else + { + DBG1(" encryption algorithm '%.s' not supported", + dek.len, dek.ptr); + return NOT_SUPPORTED; + } + eat_whitespace(&value); + iv = chunk_from_hex(value, iv.ptr); + } + } + else /* state is PEM_BODY */ + { + chunk_t data; + + /* remove any trailing whitespace */ + if (!extract_token(&data ,' ', &line)) + { + data = line; + } + + /* check for PGP armor checksum */ + if (*data.ptr == '=') + { + *pgp = TRUE; + data.ptr++; + data.len--; + DBG2(" armor checksum: %.*s", (int)data.len, data.ptr); + continue; + } + + if (blob->len - dst.len < data.len / 4 * 3) + { + state = PEM_ABORT; + } + data = chunk_from_base64(data, dst.ptr); + + dst.ptr += data.len; + dst.len += data.len; + } + } + } + /* set length to size of binary blob */ + blob->len = dst.len; + + if (state != PEM_POST) + { + DBG1(" file coded in unknown format, discarded"); + return PARSE_ERROR; + } + if (!encrypted) + { + return SUCCESS; + } + if (!this->cb) + { + DBG1(" missing passphrase"); + return INVALID_ARG; + } + while (TRUE) + { + passphrase = this->cb(this->data, ++try); + if (!passphrase.len || !passphrase.ptr) + { + return INVALID_ARG; + } + switch (pem_decrypt(blob, alg, key_size, iv, passphrase)) + { + case INVALID_ARG: + /* bad passphrase, retry */ + continue; + case SUCCESS: + return SUCCESS; + default: + return FAILED; + } + } +} + +/** + * Implementation of builder_t.build + */ +static void *build(private_builder_t *this) +{ + bool pgp = FALSE; + void *cred = NULL; + chunk_t blob; + builder_part_t part = BUILD_BLOB_ASN1_DER; + + if (!this->pem.ptr) + { + free(this); + return NULL; + } + blob = chunk_clone(this->pem); + if (pem_to_bin(&blob, this, &pgp) == SUCCESS) + { + if (pgp) + { + part = BUILD_BLOB_PGP; + } + cred = lib->creds->create(lib->creds, this->type, this->subtype, + part, blob, BUILD_END); + } + chunk_clear(&blob); + free(this); + return cred; +} + +/** + * passphrase callback to use if passphrase given + */ +static chunk_t given_passphrase_cb(chunk_t *passphrase, int try) +{ + if (try > 1) + { /* try only once for given passphrases */ + return chunk_empty; + } + return *passphrase; +} + +/** + * Implementation of builder_t.add + */ +static void add(private_builder_t *this, builder_part_t part, ...) +{ + va_list args; + + switch (part) + { + case BUILD_BLOB_PEM: + va_start(args, part); + this->pem = va_arg(args, chunk_t); + va_end(args); + break; + case BUILD_PASSPHRASE: + va_start(args, part); + this->passphrase = va_arg(args, chunk_t); + va_end(args); + if (this->passphrase.len && this->passphrase.ptr) + { + this->cb = (void*)given_passphrase_cb; + this->data = &this->passphrase; + } + break; + case BUILD_PASSPHRASE_CALLBACK: + va_start(args, part); + this->cb = va_arg(args, chunk_t(*)(void*,int)); + this->data = va_arg(args, void*); + va_end(args); + break; + default: + builder_cancel(&this->public); + break; + } +} + +/** + * Generic PEM builder. + */ +static builder_t *pem_builder(credential_type_t type, int subtype) +{ + private_builder_t *this = malloc_thing(private_builder_t); + + this->public.add = (void(*)(builder_t *this, builder_part_t part, ...))add; + this->public.build = (void*(*)(builder_t *this))build; + + this->type = type; + this->subtype = subtype; + this->pem = chunk_empty; + this->passphrase = chunk_empty; + this->cb = NULL; + this->data = NULL; + + return &this->public; +} + +/** + * Private key PEM builder. + */ +builder_t *private_key_pem_builder(key_type_t type) +{ + return pem_builder(CRED_PRIVATE_KEY, type); +} + +/** + * Public key PEM builder. + */ +builder_t *public_key_pem_builder(key_type_t type) +{ + return pem_builder(CRED_PUBLIC_KEY, type); +} + +/** + * Certificate PEM builder. + */ +builder_t *certificate_pem_builder(certificate_type_t type) +{ + return pem_builder(CRED_CERTIFICATE, type); +} + diff --git a/src/libstrongswan/plugins/pem/pem_builder.h b/src/libstrongswan/plugins/pem/pem_builder.h new file mode 100644 index 000000000..a473a2784 --- /dev/null +++ b/src/libstrongswan/plugins/pem/pem_builder.h @@ -0,0 +1,52 @@ +/* + * Copyright (C) 2009 Martin Willi + * 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 <http://www.fsf.org/copyleft/gpl.txt>. + * + * 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 pem_builder pem_builder + * @{ @ingroup pem_p + */ + +#ifndef PEM_PRIVATE_KEY_H_ +#define PEM_PRIVATE_KEY_H_ + +#include <credentials/certificates/certificate.h> +#include <credentials/credential_factory.h> + +/** + * Builder for PEM encoded private keys of all kind. + * + * @param type type of the key + * @return builder instance + */ +builder_t *private_key_pem_builder(key_type_t type); + +/** + * Builder for PEM encoded public keys of all kind. + * + * @param type type of the key + * @return builder instance + */ +builder_t *public_key_pem_builder(key_type_t type); + +/** + * Builder for PEM encoded certificates of all kind. + * + * @param type type of the key + * @return builder instance + */ +builder_t *certificate_pem_builder(certificate_type_t type); + +#endif /** PEM_PRIVATE_KEY_H_ @}*/ + diff --git a/src/libstrongswan/plugins/pem/pem_plugin.c b/src/libstrongswan/plugins/pem/pem_plugin.c new file mode 100644 index 000000000..c8505047b --- /dev/null +++ b/src/libstrongswan/plugins/pem/pem_plugin.c @@ -0,0 +1,97 @@ +/* + * Copyright (C) 2009 Martin Willi + * 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 <http://www.fsf.org/copyleft/gpl.txt>. + * + * 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 "pem_plugin.h" + +#include <library.h> +#include "pem_builder.h" + +typedef struct private_pem_plugin_t private_pem_plugin_t; + +/** + * private data of pem_plugin + */ +struct private_pem_plugin_t { + + /** + * public functions + */ + pem_plugin_t public; +}; + +/** + * Implementation of pem_plugin_t.pemtroy + */ +static void destroy(private_pem_plugin_t *this) +{ + lib->creds->remove_builder(lib->creds, + (builder_constructor_t)private_key_pem_builder); + lib->creds->remove_builder(lib->creds, + (builder_constructor_t)public_key_pem_builder); + lib->creds->remove_builder(lib->creds, + (builder_constructor_t)certificate_pem_builder); + free(this); +} + +/* + * see header file + */ +plugin_t *plugin_create() +{ + private_pem_plugin_t *this = malloc_thing(private_pem_plugin_t); + + this->public.plugin.destroy = (void(*)(plugin_t*))destroy; + + /* register private key PEM decoding builders */ + lib->creds->add_builder(lib->creds, CRED_PRIVATE_KEY, KEY_ANY, + (builder_constructor_t)private_key_pem_builder); + lib->creds->add_builder(lib->creds, CRED_PRIVATE_KEY, KEY_RSA, + (builder_constructor_t)private_key_pem_builder); + lib->creds->add_builder(lib->creds, CRED_PRIVATE_KEY, KEY_ECDSA, + (builder_constructor_t)private_key_pem_builder); + lib->creds->add_builder(lib->creds, CRED_PRIVATE_KEY, KEY_DSA, + (builder_constructor_t)private_key_pem_builder); + + /* register public key PEM decoding builders */ + lib->creds->add_builder(lib->creds, CRED_PUBLIC_KEY, KEY_ANY, + (builder_constructor_t)public_key_pem_builder); + lib->creds->add_builder(lib->creds, CRED_PUBLIC_KEY, KEY_RSA, + (builder_constructor_t)public_key_pem_builder); + lib->creds->add_builder(lib->creds, CRED_PUBLIC_KEY, KEY_ECDSA, + (builder_constructor_t)public_key_pem_builder); + lib->creds->add_builder(lib->creds, CRED_PUBLIC_KEY, KEY_DSA, + (builder_constructor_t)public_key_pem_builder); + + /* register certificate PEM decoding builders */ + lib->creds->add_builder(lib->creds, CRED_CERTIFICATE, CERT_ANY, + (builder_constructor_t)certificate_pem_builder); + lib->creds->add_builder(lib->creds, CRED_CERTIFICATE, CERT_X509, + (builder_constructor_t)certificate_pem_builder); + lib->creds->add_builder(lib->creds, CRED_CERTIFICATE, CERT_X509_CRL, + (builder_constructor_t)certificate_pem_builder); + lib->creds->add_builder(lib->creds, CRED_CERTIFICATE, CERT_X509_OCSP_REQUEST, + (builder_constructor_t)certificate_pem_builder); + lib->creds->add_builder(lib->creds, CRED_CERTIFICATE, CERT_X509_OCSP_RESPONSE, + (builder_constructor_t)certificate_pem_builder); + lib->creds->add_builder(lib->creds, CRED_CERTIFICATE, CERT_X509_AC, + (builder_constructor_t)certificate_pem_builder); + lib->creds->add_builder(lib->creds, CRED_CERTIFICATE, CERT_TRUSTED_PUBKEY, + (builder_constructor_t)certificate_pem_builder); + lib->creds->add_builder(lib->creds, CRED_CERTIFICATE, CERT_PGP, + (builder_constructor_t)certificate_pem_builder); + + return &this->public.plugin; +} + diff --git a/src/libstrongswan/plugins/pem/pem_plugin.h b/src/libstrongswan/plugins/pem/pem_plugin.h new file mode 100644 index 000000000..6d39160f9 --- /dev/null +++ b/src/libstrongswan/plugins/pem/pem_plugin.h @@ -0,0 +1,47 @@ +/* + * Copyright (C) 2009 Martin Willi + * 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 <http://www.fsf.org/copyleft/gpl.txt>. + * + * 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 pem_p pem + * @ingroup plugins + * + * @defgroup pem_plugin pem_plugin + * @{ @ingroup pem_p + */ + +#ifndef PEM_PLUGIN_H_ +#define PEM_PLUGIN_H_ + +#include <plugins/plugin.h> + +typedef struct pem_plugin_t pem_plugin_t; + +/** + * Plugin providing support to load credentials in PEM format + */ +struct pem_plugin_t { + + /** + * implements plugin interface + */ + plugin_t plugin; +}; + +/** + * Create a pem_plugin instance. + */ +plugin_t *plugin_create(); + +#endif /** PEM_PLUGIN_H_ @}*/ diff --git a/src/libstrongswan/plugins/pubkey/pubkey_public_key.c b/src/libstrongswan/plugins/pubkey/pubkey_public_key.c index 6d3ae66ab..afe200fec 100644 --- a/src/libstrongswan/plugins/pubkey/pubkey_public_key.c +++ b/src/libstrongswan/plugins/pubkey/pubkey_public_key.c @@ -137,14 +137,13 @@ static void add(private_builder_t *this, builder_part_t part, ...) va_end(args); return; } - case BUILD_BLOB_ASN1_PEM: + case BUILD_BLOB_PEM: { bool pgp; - char *pem; - + va_start(args, part); - pem = va_arg(args, char *); - blob = chunk_clone(chunk_create(pem, strlen(pem))); + blob = va_arg(args, chunk_t); + blob = chunk_clone(blob); if (pem_to_bin(&blob, chunk_empty, &pgp) == SUCCESS) { this->key = pubkey_public_key_load(chunk_clone(blob)); diff --git a/src/medsrv/controller/peer_controller.c b/src/medsrv/controller/peer_controller.c index 01ba0c8cc..5166a420c 100755 --- a/src/medsrv/controller/peer_controller.c +++ b/src/medsrv/controller/peer_controller.c @@ -122,15 +122,18 @@ static bool parse_public_key(private_peer_controller_t *this, { public_key_t *public; identification_t *id; + chunk_t blob; if (!public_key || *public_key == '\0') { request->setf(request, "error=Public key is missing."); return FALSE; } + blob = chunk_clone(chunk_create(public_key, strlen(public_key))); public = lib->creds->create(lib->creds, CRED_PUBLIC_KEY, KEY_ANY, - BUILD_BLOB_ASN1_PEM, public_key, + BUILD_BLOB_PEM, blob, BUILD_END); + chunk_free(&blob); if (!public) { request->setf(request, "error=Parsing public key failed."); |