added public methods is_ca() and is_valid()
authorAndreas Steffen <andreas.steffen@strongswan.org>
Fri, 9 Jun 2006 05:47:00 +0000 (05:47 -0000)
committerAndreas Steffen <andreas.steffen@strongswan.org>
Fri, 9 Jun 2006 05:47:00 +0000 (05:47 -0000)
src/libstrongswan/crypto/x509.c
src/libstrongswan/crypto/x509.h

index 3eb4a96..6899abe 100755 (executable)
@@ -44,7 +44,7 @@
 
 #define CERT_WARNING_INTERVAL  30      /* days */
 
-logger_t *logger;
+static logger_t *logger;
 
 /**
  * Different kinds of generalNames
@@ -144,12 +144,16 @@ struct private_x509_t {
         */
        chunk_t authKeySerialNumber;
        
+       /**
+        * CA basic constraints flag
+        */
+       bool isCA;
+
        u_char authority_flags;
        chunk_t tbsCertificate;
        /*   signature */
        int sigAlg;
        chunk_t subjectPublicKey;
-       bool isCA;
        bool isOcspSigner; /* ocsp */
        chunk_t accessLocation; /* ocsp */
        /* signatureAlgorithm */
@@ -373,7 +377,7 @@ static const chunk_t ASN1_subjectAltName_oid = chunk_from_buf(ASN1_subjectAltNam
 /**
  * compare two X.509 x509s by comparing their signatures
  */
-static bool equals(private_x509_t *this, private_x509_t *other)
+static bool equals(const private_x509_t *this, const private_x509_t *other)
 {
        return chunk_equals(this->signature, other->signature);
 }
@@ -400,7 +404,7 @@ static bool parse_basicConstraints(chunk_t blob, int level0)
                if (objectID == BASIC_CONSTRAINTS_CA)
                {
                        isCA = object.len && *object.ptr;
-                       logger->log(logger, CONTROL|LEVEL1, "  %s", isCA ? "TRUE" : "FALSE");
+                       logger->log(logger, CONTROL|LEVEL2, "  %s", isCA ? "TRUE" : "FALSE");
                }
                objectID++;
        }
@@ -498,7 +502,7 @@ static identification_t *parse_generalName(chunk_t blob, int level0)
                if (id_type != ID_ANY)
                {
                        identification_t *gn = identification_create_from_encoding(id_type, object);
-                       logger->log(logger, CONTROL|LEVEL1, "  '%s'", gn->get_string(gn));
+                       logger->log(logger, CONTROL|LEVEL2, "  '%s'", gn->get_string(gn));
                        return gn;
         }
                objectID++;
@@ -649,7 +653,7 @@ static void parse_authorityInfoAccess(chunk_t blob, int level0, chunk_t *accessL
                                                {
                                                        if (asn1_length(&object) == ASN1_INVALID_LENGTH)
                                                                return;
-                                                       logger->log(logger, CONTROL|LEVEL1, "  '%.*s'",(int)object.len, object.ptr);
+                                                       logger->log(logger, CONTROL|LEVEL2, "  '%.*s'",(int)object.len, object.ptr);
                                                        /* only HTTP(S) URIs accepted */
                                                        if (strncasecmp(object.ptr, "http", 4) == 0)
                                                        {
@@ -729,7 +733,7 @@ static void parse_crlDistributionPoints(chunk_t blob, int level0, linked_list_t
 
 
 /**
- * Parses an X.509v3 x509
+ * Parses an X.509v3 certificate
  */
 bool parse_x509cert(chunk_t blob, u_int level0, private_x509_t *cert)
 {
@@ -758,7 +762,7 @@ bool parse_x509cert(chunk_t blob, u_int level0, private_x509_t *cert)
                                break;
                        case X509_OBJ_VERSION:
                                cert->version = (object.len) ? (1+(u_int)*object.ptr) : 1;
-                               logger->log(logger, CONTROL|LEVEL1, "  v%d", cert->version);
+                               logger->log(logger, CONTROL|LEVEL2, "  v%d", cert->version);
                                break;
                        case X509_OBJ_SERIAL_NUMBER:
                                cert->serialNumber = object;
@@ -807,7 +811,7 @@ bool parse_x509cert(chunk_t blob, u_int level0, private_x509_t *cert)
                                break;
                        case X509_OBJ_CRITICAL:
                                critical = object.len && *object.ptr;
-                               logger->log(logger, ERROR|LEVEL1, "  %s", critical ? "TRUE" : "FALSE");
+                               logger->log(logger, ERROR|LEVEL2, "  %s", critical ? "TRUE" : "FALSE");
                                break;
                        case X509_OBJ_EXTN_VALUE:
                        {
@@ -861,37 +865,46 @@ bool parse_x509cert(chunk_t blob, u_int level0, private_x509_t *cert)
 }
 
 /**
- * verify the validity of a x509 by
- * checking the notBefore and notAfter dates
+ * Implements x509_t.is_valid
  */
-err_t check_validity(const private_x509_t *cert, time_t *until)
+static err_t is_valid(const private_x509_t *this, time_t *until)
 {
-       time_t current_time;
-       
-       time(&current_time);
+       char buf[TIMETOA_BUF];
+
+       time_t current_time = time(NULL);
        
-       if (cert->notAfter < *until) 
-       {
-               *until = cert->notAfter;
-       }
-       if (current_time < cert->notBefore)
+       timetoa(buf, BUF_LEN, &this->notBefore, TRUE);
+       logger->log(logger, CONTROL|LEVEL1, "  not before  : %s", buf);
+       timetoa(buf, BUF_LEN, &current_time, TRUE);
+       logger->log(logger, CONTROL|LEVEL1, "  current time: %s", buf);
+       timetoa(buf, BUF_LEN, &this->notAfter, TRUE);
+       logger->log(logger, CONTROL|LEVEL1, "  not after   : %s", buf);
+
+       if (until != NULL
+       && (*until == UNDEFINED_TIME || this->notAfter < *until)) 
        {
-               return "x509 is not valid yet";
-       }
-       if (current_time > cert->notAfter)
-       {
-               return "x509 has expired";
-       }
-       else
-       {
-               return NULL;
+               *until = this->notAfter;
        }
+       if (current_time < this->notBefore)
+               return "is not valid yet";
+       if (current_time > this->notAfter)
+               return "has expired";
+       logger->log(logger, CONTROL|LEVEL1, "  certificate is valid", buf);
+       return NULL;
+}
+
+/**
+ * Implements x509_t.is_ca
+ */
+static bool is_ca(const private_x509_t *this)
+{
+       return this->isCA;
 }
 
 /**
  * Implements x509_t.equals_subjectAltName
  */
-static bool equals_subjectAltName(private_x509_t *this, identification_t *id)
+static bool equals_subjectAltName(const private_x509_t *this, identification_t *id)
 {
        bool found = FALSE;
        iterator_t *iterator = this->subjectAltNames->create_iterator(this->subjectAltNames, TRUE);
@@ -914,7 +927,7 @@ static bool equals_subjectAltName(private_x509_t *this, identification_t *id)
 /**
  * Implements x509_t.get_public_key
  */
-static rsa_public_key_t *get_public_key(private_x509_t *this)
+static rsa_public_key_t *get_public_key(const private_x509_t *this)
 {
        return this->public_key->clone(this->public_key);
 }
@@ -922,7 +935,7 @@ static rsa_public_key_t *get_public_key(private_x509_t *this)
 /**
  * Implements x509_t.get_subject
  */
-static identification_t *get_subject(private_x509_t *this)
+static identification_t *get_subject(const private_x509_t *this)
 {
        return this->subject;
 }
@@ -930,7 +943,7 @@ static identification_t *get_subject(private_x509_t *this)
 /**
  * Implements x509_t.get_issuer
  */
-static identification_t *get_issuer(private_x509_t *this)
+static identification_t *get_issuer(const private_x509_t *this)
 {
        return this->issuer;
 }
@@ -966,10 +979,10 @@ static void destroy(private_x509_t *this)
        free(this);
 }
 
-/** checks if the expiration date has been reached and
- *  warns during the warning_interval of the imminent
- *  expiry. strict=TRUE declares a fatal error,
 strict=FALSE issues a warning upon expiry.
+/**
+ * checks if the expiration date has been reached and warns during the
+  * warning_interval of the imminent expiration.
 * strict=TRUE declares a fatal error, strict=FALSE issues a warning upon expiry.
  */
 char* check_expiry(time_t expiration_date, int warning_interval, bool strict)
 {
@@ -1012,27 +1025,29 @@ char* check_expiry(time_t expiration_date, int warning_interval, bool strict)
 /**
  * log certificate
  */
-static void log_certificate(private_x509_t *this, logger_t *logger, bool utc, bool has_key)
+static void log_certificate(const private_x509_t *this, logger_t *logger, bool utc, bool has_key)
 {
        identification_t *subject = this->subject;
        identification_t *issuer = this->issuer;
        rsa_public_key_t *pubkey = this->public_key;
 
        char buf[BUF_LEN];
-    time_t now;
 
     /* determine the current time */
-    time(&now);
+    time_t now = time(NULL);
 
        timetoa(buf, BUF_LEN, &this->installed, utc);
        logger->log(logger, CONTROL, "%s", buf);
        logger->log(logger, CONTROL, "       subject: '%s'", subject->get_string(subject));
        logger->log(logger, CONTROL, "       issuer:  '%s'", issuer->get_string(issuer));
+       
        chunk_to_hex(buf, BUF_LEN, this->serialNumber);
        logger->log(logger, CONTROL, "       serial:   %s", buf);
+       
        timetoa(buf, BUF_LEN, &this->notBefore, utc);
        logger->log(logger, CONTROL, "       validity: not before %s %s", buf,
                                (this->notBefore < now)? "ok":"fatal (not valid yet)");
+       
        timetoa(buf, BUF_LEN, &this->notAfter, utc);
        logger->log(logger, CONTROL, "                 not after  %s %s", buf,
                        check_expiry(this->notAfter, CERT_WARNING_INTERVAL, TRUE));
@@ -1066,15 +1081,6 @@ x509_t *x509_create_from_chunk(chunk_t chunk)
 {
        private_x509_t *this = malloc_thing(private_x509_t);
        
-       /* public functions */
-       this->public.equals = (bool (*) (x509_t*,x509_t*))equals;
-       this->public.equals_subjectAltName = (bool (*) (x509_t*,identification_t*))equals_subjectAltName;
-       this->public.destroy = (void (*) (x509_t*))destroy;
-       this->public.get_public_key = (rsa_public_key_t* (*) (x509_t*))get_public_key;
-       this->public.get_subject = (identification_t* (*) (x509_t*))get_subject;
-       this->public.get_issuer = (identification_t* (*) (x509_t*))get_issuer;
-       this->public.log_certificate = (void (*) (x509_t*,logger_t*,bool,bool))log_certificate;
-       
        /* initialize */
        this->subjectPublicKey = CHUNK_INITIALIZER;
        this->public_key = NULL;
@@ -1086,22 +1092,34 @@ x509_t *x509_create_from_chunk(chunk_t chunk)
        this->authKeyID = CHUNK_INITIALIZER;
        this->authKeySerialNumber = CHUNK_INITIALIZER;
        
+       /* public functions */
+       this->public.equals = (bool (*) (const x509_t*,const x509_t*))equals;
+       this->public.equals_subjectAltName = (bool (*) (const x509_t*,identification_t*))equals_subjectAltName;
+       this->public.is_valid = (err_t (*) (const x509_t*,time_t*))is_valid;
+       this->public.is_ca = (bool (*) (const x509_t*))is_ca;
+       this->public.destroy = (void (*) (x509_t*))destroy;
+       this->public.get_public_key = (rsa_public_key_t* (*) (const x509_t*))get_public_key;
+       this->public.get_subject = (identification_t* (*) (const x509_t*))get_subject;
+       this->public.get_issuer = (identification_t* (*) (const x509_t*))get_issuer;
+       this->public.log_certificate = (void (*) (const x509_t*,logger_t*,bool,bool))log_certificate;
+
        /* we do not use a per-instance logger right now, since its not always accessible */
        logger = logger_manager->get_logger(logger_manager, ASN1);
        
-       if (!is_asn1(chunk) || !parse_x509cert(chunk, 0, this))
+       if (!parse_x509cert(chunk, 0, this))
        {
                destroy(this);
                return NULL;
        }
-       
+
+       /* extract public key from certificate */
        this->public_key = rsa_public_key_create_from_chunk(this->subjectPublicKey);
        if (this->public_key == NULL)
        {
                destroy(this);
                return NULL;
        }
-       
+
        return &this->public;
 }
 
index 7f96936..5828819 100755 (executable)
@@ -54,7 +54,7 @@ struct x509_t {
         * @param this                          calling object
         * @return                                      public_key
         */
-       rsa_public_key_t *(*get_public_key) (x509_t *this);
+       rsa_public_key_t *(*get_public_key) (const x509_t *this);
                
        /**
         * @brief Get the certificate issuers ID.
@@ -65,7 +65,7 @@ struct x509_t {
         * @param this                          calling object
         * @return                                      issuers ID
         */
-       identification_t *(*get_issuer) (x509_t *this);
+       identification_t *(*get_issuer) (const x509_t *this);
                
        /**
         * @brief Get the subjects ID.
@@ -76,7 +76,7 @@ struct x509_t {
         * @param this                          calling object
         * @return                                      subjects ID
         */
-       identification_t *(*get_subject) (x509_t *this);
+       identification_t *(*get_subject) (const x509_t *this);
        
        /**
         * @brief Check if a certificate is valid.
@@ -86,14 +86,14 @@ struct x509_t {
         * 
         * @todo implement!
         */
-       bool (*verify) (x509_t *this, rsa_public_key_t *signer);
+       bool (*verify) (const x509_t *this, rsa_public_key_t *signer);
        
        /**
         * @brief Get the key identifier of the public key.
         * 
         * @todo implement!
         */
-       chunk_t (*get_subject_key_identifier) (x509_t *this);
+       chunk_t (*get_subject_key_identifier) (const x509_t *this);
        
        /**
         * @brief Compare two certificates.
@@ -102,18 +102,35 @@ struct x509_t {
         * 
         * @param this                  first cert for compare
         * @param other                 second cert for compare
-        * @return                              TRUE if signature is equal
+        * @return                      TRUE if signature is equal
         */
-       bool (*equals) (x509_t *this, x509_t *that);
+       bool (*equals) (const x509_t *this, const x509_t *that);
        
        /**
         * @brief Checks if the certificate contains a subjectAltName equal to id.
         * 
         * @param this                  certificate being examined
         * @param id                    id which is being compared to the subjectAltNames
-        * @return                              TRUE if a match is found
+        * @return                      TRUE if a match is found
         */
-       bool (*equals_subjectAltName) (x509_t *this, identification_t *id);
+       bool (*equals_subjectAltName) (const x509_t *this, identification_t *id);
+
+       /**
+        * @brief Checks the validity interval of the certificate
+        * 
+        * @param this                  certificate being examined
+        * @param until                 until = min(until, notAfter)
+        * @return                      NULL if the certificate is valid
+        */
+       err_t (*is_valid) (const x509_t *this, time_t *until);
+       
+       /**
+        * @brief Returns the CA basic constraints flag
+        * 
+        * @param this                  certificate being examined
+        * @return                      TRUE if the CA flag is set
+        */
+       bool (*is_ca) (const x509_t *this);
        
        /**
         * @brief Destroys the certificate.
@@ -130,7 +147,7 @@ struct x509_t {
         * @param utc                   log dates either in UTC or local time
         * @param has_key               a matching private key is available
         */
-        void (*log_certificate) (x509_t *this, logger_t *logger, bool utc, bool has_key);
+        void (*log_certificate) (const x509_t *this, logger_t *logger, bool utc, bool has_key);
 };
 
 /**