aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--configure.in17
-rw-r--r--src/libstrongswan/Makefile.am4
-rw-r--r--src/libstrongswan/credentials/builder.c4
-rw-r--r--src/libstrongswan/credentials/builder.h10
-rw-r--r--src/libstrongswan/credentials/credential_factory.c10
-rw-r--r--src/libstrongswan/plugins/pem/Makefile.am12
-rw-r--r--src/libstrongswan/plugins/pem/pem_builder.c490
-rw-r--r--src/libstrongswan/plugins/pem/pem_builder.h52
-rw-r--r--src/libstrongswan/plugins/pem/pem_plugin.c97
-rw-r--r--src/libstrongswan/plugins/pem/pem_plugin.h47
-rw-r--r--src/libstrongswan/plugins/pubkey/pubkey_public_key.c9
-rwxr-xr-xsrc/medsrv/controller/peer_controller.c5
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.");