removed unused gmp.h to build libstrongswan without libgmp
[strongswan.git] / src / libstrongswan / plugins / x509 / x509_cert.c
index 6a0be36..f427734 100644 (file)
@@ -23,7 +23,6 @@
 
 #include "x509_cert.h"
 
-#include <gmp.h>
 #include <sys/stat.h>
 #include <unistd.h>
 #include <string.h>
@@ -66,9 +65,9 @@ struct private_x509_cert_t {
        x509_cert_t public;
 
        /**
-        * DER encoded X.509 certificate
+        * X.509 certificate encoding in ASN.1 DER format
         */
-       chunk_t certificate;
+       chunk_t encoding;
 
        /**
         * X.509 certificate body over which signature is computed
@@ -498,7 +497,7 @@ static identification_t *parse_generalName(chunk_t blob, int level0)
 /**
  * extracts one or several GNs and puts them into a chained list
  */
-void parse_generalNames(chunk_t blob, int level0, bool implicit, linked_list_t *list)
+void x509_parse_generalNames(chunk_t blob, int level0, bool implicit, linked_list_t *list)
 {
        asn1_ctx_t ctx;
        chunk_t object;
@@ -581,7 +580,7 @@ identification_t* x509_parse_authorityKeyIdentifier(chunk_t blob, int level0,
                        }
                        case AUTH_KEY_ID_CERT_ISSUER:
                        {
-                               /* TODO: parse_generalNames(object, level+1, TRUE); */
+                               /* TODO: x509_parse_generalNames(object, level+1, TRUE); */
                                break;
                        }
                        case AUTH_KEY_ID_CERT_SERIAL:
@@ -708,7 +707,7 @@ static void parse_crlDistributionPoints(chunk_t blob, int level0,
                }
                if (objectID == CRL_DIST_POINTS_FULLNAME)
                {       /* append extracted generalNames to existing chained list */
-                       parse_generalNames(object, level+1, TRUE, list);
+                       x509_parse_generalNames(object, level+1, TRUE, list);
        
                        while (list->remove_last(list, (void**)&id) == SUCCESS)
                        {
@@ -735,11 +734,11 @@ static bool parse_certificate(private_x509_cert_t *this)
        u_int level;
        int objectID = 0;
        int extn_oid = OID_UNKNOWN;
-       int key_alg = 0;
-       int sig_alg = 0;
+       int key_alg = OID_UNKNOWN;
+       int sig_alg = OID_UNKNOWN;
        chunk_t subjectPublicKey = chunk_empty;
        
-       asn1_init(&ctx, this->certificate, 0, FALSE, FALSE);
+       asn1_init(&ctx, this->encoding, 0, FALSE, FALSE);
        while (objectID < X509_OBJ_ROOF)
        {
                if (!extract_object(certObjects, &objectID, &object, &level, &ctx))
@@ -817,7 +816,7 @@ static bool parse_certificate(private_x509_cert_t *this)
                                                this->subjectKeyID = parse_keyIdentifier(object, level, FALSE);
                                                break;
                                        case OID_SUBJECT_ALT_NAME:
-                                               parse_generalNames(object, level, FALSE, this->subjectAltNames);
+                                               x509_parse_generalNames(object, level, FALSE, this->subjectAltNames);
                                                break;
                                        case OID_BASIC_CONSTRAINTS:
                                                if (parse_basicConstraints(object, level))
@@ -932,8 +931,7 @@ static id_match_t has_issuer(private_x509_cert_t *this, identification_t *issuer
 /**
  * Implementation of certificate_t.issued_by
  */
-static bool issued_by(private_x509_cert_t *this, certificate_t *issuer,
-                                         bool sigcheck)
+static bool issued_by(private_x509_cert_t *this, certificate_t *issuer)
 {
        public_key_t *key;
        signature_scheme_t scheme;
@@ -962,10 +960,6 @@ static bool issued_by(private_x509_cert_t *this, certificate_t *issuer,
        {
                return FALSE;
        }
-       if (!sigcheck)
-       {
-               return TRUE;
-       }
        /* TODO: generic OID to scheme mapper? */
        switch (this->algorithm)
        {
@@ -1073,7 +1067,7 @@ static bool is_newer(certificate_t *this, certificate_t *that)
  */
 static chunk_t get_encoding(private_x509_cert_t *this)
 {
-       return chunk_clone(this->certificate);
+       return chunk_clone(this->encoding);
 }
 
 /**
@@ -1157,15 +1151,15 @@ static void destroy(private_x509_cert_t *this)
                DESTROY_IF(this->subject);
                DESTROY_IF(this->public_key);
                DESTROY_IF(this->authKeyIdentifier);
-               chunk_free(&this->certificate);
+               chunk_free(&this->encoding);
                free(this);
        }
 }
 
 /**
- * load x509 certificate from a chunk
+ * create an empty but initialized X.509 certificate
  */
-static private_x509_cert_t *load(chunk_t chunk)
+static private_x509_cert_t* create_empty(void)
 {
        private_x509_cert_t *this = malloc_thing(private_x509_cert_t);
        
@@ -1174,7 +1168,7 @@ static private_x509_cert_t *load(chunk_t chunk)
        this->public.interface.interface.get_issuer = (identification_t* (*)(certificate_t *this))get_issuer;
        this->public.interface.interface.has_subject = (id_match_t (*)(certificate_t*, identification_t *subject))has_subject;
        this->public.interface.interface.has_issuer = (id_match_t (*)(certificate_t*, identification_t *issuer))has_issuer;
-       this->public.interface.interface.issued_by = (bool (*)(certificate_t *this, certificate_t *issuer,bool))issued_by;
+       this->public.interface.interface.issued_by = (bool (*)(certificate_t *this, certificate_t *issuer))issued_by;
        this->public.interface.interface.get_public_key = (public_key_t* (*)(certificate_t *this))get_public_key;
        this->public.interface.interface.get_validity = (bool (*)(certificate_t*, time_t *when, time_t *, time_t*))get_validity;
        this->public.interface.interface.is_newer = (bool (*)(certificate_t*,certificate_t*))is_newer;
@@ -1189,7 +1183,7 @@ static private_x509_cert_t *load(chunk_t chunk)
        this->public.interface.create_crl_uri_enumerator = (enumerator_t* (*)(x509_t*))create_crl_uri_enumerator;
        this->public.interface.create_ocsp_uri_enumerator = (enumerator_t* (*)(x509_t*))create_ocsp_uri_enumerator;
 
-       this->certificate = chunk;
+       this->encoding = chunk_empty;
        this->public_key = NULL;
        this->subject = NULL;
        this->issuer = NULL;
@@ -1201,21 +1195,58 @@ static private_x509_cert_t *load(chunk_t chunk)
        this->authKeySerialNumber = chunk_empty;
        this->flags = 0;
        this->ref = 1;
-       
+
+       return this;
+}
+
+/**
+ * create an X.509 certificate from a chunk
+ */
+static private_x509_cert_t *create_from_chunk(chunk_t chunk)
+{
+       private_x509_cert_t *this = create_empty();
+
+       this->encoding = chunk;
        if (!parse_certificate(this))
        {
                destroy(this);
                return NULL;
        }
-       
+
        /* check if the certificate is self-signed */
-       if (issued_by(this, &this->public.interface.interface, TRUE))
+       if (issued_by(this, &this->public.interface.interface))
        {
                this->flags |= X509_SELF_SIGNED;
        }
        return this;
 }
 
+/**
+ * create an X.509 certificate from a file
+ */
+static private_x509_cert_t *create_from_file(char *path)
+{
+       bool pgp = FALSE;
+       chunk_t chunk;
+       private_x509_cert_t *this;
+       
+       if (!pem_asn1_load_file(path, NULL, &chunk, &pgp))
+       {
+               return NULL;
+       }
+
+       this = create_from_chunk(chunk);
+
+       if (this == NULL)
+       {
+               DBG1("  could not parse loaded certificate file '%s'",path);
+               return NULL;
+       }
+       DBG1("  loaded certificate file '%s'",  path);
+       return this;
+
+}
+
 typedef struct private_builder_t private_builder_t;
 /**
  * Builder implementation for certificate loading
@@ -1232,14 +1263,24 @@ struct private_builder_t {
 /**
  * Implementation of builder_t.build
  */
-static x509_cert_t *build(private_builder_t *this)
+static private_x509_cert_t *build(private_builder_t *this)
 {
-       private_x509_cert_t *cert;
-       
-       cert = this->cert;
-       cert->flags |= this->flags;
+       private_x509_cert_t *cert = this->cert;
+       x509_flag_t flags = this->flags;
+
        free(this);
-       return &cert->public;
+       if (cert == NULL)
+       {
+               return NULL;
+       }
+       if ((flags & X509_CA) && !(cert->flags & X509_CA))
+       {
+               DBG1("  ca certificate must have ca basic constraint set, discarded");
+               destroy(cert);
+               return NULL;
+       }
+       cert->flags |= flags;
+       return cert;
 }
 
 /**
@@ -1252,20 +1293,15 @@ static void add(private_builder_t *this, builder_part_t part, ...)
        va_start(args, part);
        switch (part)
        {
+               case BUILD_FROM_FILE:
+                       this->cert = create_from_file(va_arg(args, char*));
+                       break;
                case BUILD_BLOB_ASN1_DER:
-               {
-                       if (this->cert)
-                       {
-                               destroy(this->cert);
-                       }
-                       this->cert = load(va_arg(args, chunk_t));
+                       this->cert = create_from_chunk(va_arg(args, chunk_t));
                        break;
-               }
                case BUILD_X509_FLAG:
-               {
                        this->flags = va_arg(args, x509_flag_t);
                        break;
-               }
                default:
                        DBG1("ignoring unsupported build part %N", builder_part_names, part);
                        break;