added file loading support to pem plugin, using mmap()
authorMartin Willi <martin@strongswan.org>
Wed, 12 Aug 2009 11:26:02 +0000 (13:26 +0200)
committerMartin Willi <martin@strongswan.org>
Wed, 26 Aug 2009 09:23:48 +0000 (11:23 +0200)
src/libstrongswan/plugins/pem/pem_builder.c

index d5bd1bd..dd335cc 100644 (file)
 #include <errno.h>
 #include <string.h>
 #include <stddef.h>
 #include <errno.h>
 #include <string.h>
 #include <stddef.h>
+#include <fcntl.h>
 #include <sys/types.h>
 #include <sys/types.h>
+#include <sys/mman.h>
+#include <sys/stat.h>
 
 #include <debug.h>
 #include <library.h>
 #include <utils/lexparser.h>
 
 #include <debug.h>
 #include <library.h>
 #include <utils/lexparser.h>
+#include <asn1/asn1.h>
 #include <crypto/hashers/hasher.h>
 #include <crypto/crypters/crypter.h>
 
 #include <crypto/hashers/hasher.h>
 #include <crypto/crypters/crypter.h>
 
@@ -44,6 +48,8 @@ struct private_builder_t {
        credential_type_t type;
        /** subtype (keytype, certtype) of the credential we build */
        int subtype;
        credential_type_t type;
        /** subtype (keytype, certtype) of the credential we build */
        int subtype;
+       /** path to file, if we are reading from a file */
+       char *file;
        /** PEM encoding of the credential */
        chunk_t pem;
        /** PEM decryption passphrase, if given */
        /** PEM encoding of the credential */
        chunk_t pem;
        /** PEM decryption passphrase, if given */
@@ -367,31 +373,83 @@ status_t pem_to_bin(chunk_t *blob, private_builder_t *this, bool *pgp)
 }
 
 /**
 }
 
 /**
- * Implementation of builder_t.build
+ * build the credential from a blob
  */
  */
-static void *build(private_builder_t *this)
+static void *build_from_blob(private_builder_t *this, chunk_t blob)
 {
 {
+       void *cred = NULL;
        bool pgp = FALSE;
        bool pgp = FALSE;
+       
+       blob = chunk_clone(blob);
+       if (!is_asn1(blob))
+       {
+               if (pem_to_bin(&blob, this, &pgp) != SUCCESS)
+               {
+                       chunk_clear(&blob);
+                       return NULL;
+               }
+       }
+       cred = lib->creds->create(lib->creds, this->type, this->subtype,
+                                                         pgp ? BUILD_BLOB_PGP : BUILD_BLOB_ASN1_DER, blob,
+                                                         BUILD_END);
+       chunk_clear(&blob);
+       return cred;
+}
+
+/**
+ * build the credential from a file
+ */
+static void *build_from_file(private_builder_t *this, char *file)
+{
        void *cred = NULL;
        void *cred = NULL;
-       chunk_t blob;
-       builder_part_t part = BUILD_BLOB_ASN1_DER;
+       struct stat sb;
+       void *addr;
+       int fd;
        
        
-       if (!this->pem.ptr)
+       fd = open(file, O_RDONLY);
+       if (fd == -1)
        {
        {
-               free(this);
+               DBG1("  opening '%s' failed: %s", file, strerror(errno));
                return NULL;
        }
                return NULL;
        }
-       blob = chunk_clone(this->pem);
-       if (pem_to_bin(&blob, this, &pgp) == SUCCESS)
+       
+       if (fstat(fd, &sb) == -1)
        {
        {
-               if (pgp)
-               {
-                       part = BUILD_BLOB_PGP;
-               }
-               cred = lib->creds->create(lib->creds, this->type, this->subtype,
-                                                                 part, blob, BUILD_END);
+               DBG1("  getting file size of '%s' failed: %s", file, strerror(errno));
+               close(fd);
+               return NULL;
+       }
+       
+       addr = mmap(NULL, sb.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
+       if (addr == MAP_FAILED)
+       {
+               DBG1("  mapping '%s' failed: %s", file, strerror(errno));
+               close(fd);
+               return NULL;
+       }
+       
+       cred = build_from_blob(this, chunk_create(addr, sb.st_size));
+       
+       munmap(addr, sb.st_size);
+       close(fd);
+       return cred;
+}
+
+/**
+ * Implementation of builder_t.build
+ */
+static void *build(private_builder_t *this)
+{
+       void *cred = NULL;
+       
+       if (this->pem.ptr)
+       {
+               cred = build_from_blob(this, this->pem);
+       }
+       else if (this->file)
+       {
+               cred = build_from_file(this, this->file);
        }
        }
-       chunk_clear(&blob);
        free(this);
        return cred;
 }
        free(this);
        return cred;
 }
@@ -417,6 +475,11 @@ static void add(private_builder_t *this, builder_part_t part, ...)
        
        switch (part)
        {
        
        switch (part)
        {
+               case BUILD_FROM_FILE:
+                       va_start(args, part);
+                       this->file = va_arg(args, char*);
+                       va_end(args);
+                       break;
                case BUILD_BLOB_PEM:
                        va_start(args, part);
                        this->pem = va_arg(args, chunk_t);
                case BUILD_BLOB_PEM:
                        va_start(args, part);
                        this->pem = va_arg(args, chunk_t);
@@ -456,6 +519,7 @@ static builder_t *pem_builder(credential_type_t type, int subtype)
        
        this->type = type;
        this->subtype = subtype;
        
        this->type = type;
        this->subtype = subtype;
+       this->file = NULL;
        this->pem = chunk_empty;
        this->passphrase = chunk_empty;
        this->cb = NULL;
        this->pem = chunk_empty;
        this->passphrase = chunk_empty;
        this->cb = NULL;