added public methods is_ca() and is_valid()

This commit is contained in:
Andreas Steffen
2006-06-09 05:47:00 +00:00
parent 5407d563b7
commit a612f2dd00
2 changed files with 97 additions and 62 deletions
+67 -49
View File
@@ -44,7 +44,7 @@
#define CERT_WARNING_INTERVAL 30 /* days */ #define CERT_WARNING_INTERVAL 30 /* days */
logger_t *logger; static logger_t *logger;
/** /**
* Different kinds of generalNames * Different kinds of generalNames
@@ -144,12 +144,16 @@ struct private_x509_t {
*/ */
chunk_t authKeySerialNumber; chunk_t authKeySerialNumber;
/**
* CA basic constraints flag
*/
bool isCA;
u_char authority_flags; u_char authority_flags;
chunk_t tbsCertificate; chunk_t tbsCertificate;
/* signature */ /* signature */
int sigAlg; int sigAlg;
chunk_t subjectPublicKey; chunk_t subjectPublicKey;
bool isCA;
bool isOcspSigner; /* ocsp */ bool isOcspSigner; /* ocsp */
chunk_t accessLocation; /* ocsp */ chunk_t accessLocation; /* ocsp */
/* signatureAlgorithm */ /* 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 * 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); 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) if (objectID == BASIC_CONSTRAINTS_CA)
{ {
isCA = object.len && *object.ptr; isCA = object.len && *object.ptr;
logger->log(logger, CONTROL|LEVEL1, " %s", isCA ? "TRUE" : "FALSE"); logger->log(logger, CONTROL|LEVEL2, " %s", isCA ? "TRUE" : "FALSE");
} }
objectID++; objectID++;
} }
@@ -498,7 +502,7 @@ static identification_t *parse_generalName(chunk_t blob, int level0)
if (id_type != ID_ANY) if (id_type != ID_ANY)
{ {
identification_t *gn = identification_create_from_encoding(id_type, object); 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; return gn;
} }
objectID++; objectID++;
@@ -649,7 +653,7 @@ static void parse_authorityInfoAccess(chunk_t blob, int level0, chunk_t *accessL
{ {
if (asn1_length(&object) == ASN1_INVALID_LENGTH) if (asn1_length(&object) == ASN1_INVALID_LENGTH)
return; 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 */ /* only HTTP(S) URIs accepted */
if (strncasecmp(object.ptr, "http", 4) == 0) 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) 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; break;
case X509_OBJ_VERSION: case X509_OBJ_VERSION:
cert->version = (object.len) ? (1+(u_int)*object.ptr) : 1; 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; break;
case X509_OBJ_SERIAL_NUMBER: case X509_OBJ_SERIAL_NUMBER:
cert->serialNumber = object; cert->serialNumber = object;
@@ -807,7 +811,7 @@ bool parse_x509cert(chunk_t blob, u_int level0, private_x509_t *cert)
break; break;
case X509_OBJ_CRITICAL: case X509_OBJ_CRITICAL:
critical = object.len && *object.ptr; critical = object.len && *object.ptr;
logger->log(logger, ERROR|LEVEL1, " %s", critical ? "TRUE" : "FALSE"); logger->log(logger, ERROR|LEVEL2, " %s", critical ? "TRUE" : "FALSE");
break; break;
case X509_OBJ_EXTN_VALUE: 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 * Implements x509_t.is_valid
* checking the notBefore and notAfter dates
*/ */
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; char buf[TIMETOA_BUF];
time(&current_time); time_t current_time = time(NULL);
if (cert->notAfter < *until) 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))
{ {
*until = cert->notAfter; *until = this->notAfter;
}
if (current_time < cert->notBefore)
{
return "x509 is not valid yet";
}
if (current_time > cert->notAfter)
{
return "x509 has expired";
}
else
{
return NULL;
} }
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 * 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; bool found = FALSE;
iterator_t *iterator = this->subjectAltNames->create_iterator(this->subjectAltNames, TRUE); 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 * 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); 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 * 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; return this->subject;
} }
@@ -930,7 +943,7 @@ static identification_t *get_subject(private_x509_t *this)
/** /**
* Implements x509_t.get_issuer * 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; return this->issuer;
} }
@@ -966,10 +979,10 @@ static void destroy(private_x509_t *this)
free(this); free(this);
} }
/** checks if the expiration date has been reached and /**
* warns during the warning_interval of the imminent * checks if the expiration date has been reached and warns during the
* expiry. strict=TRUE declares a fatal error, * warning_interval of the imminent expiration.
* strict=FALSE issues a warning upon expiry. * 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) 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 * 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 *subject = this->subject;
identification_t *issuer = this->issuer; identification_t *issuer = this->issuer;
rsa_public_key_t *pubkey = this->public_key; rsa_public_key_t *pubkey = this->public_key;
char buf[BUF_LEN]; char buf[BUF_LEN];
time_t now;
/* determine the current time */ /* determine the current time */
time(&now); time_t now = time(NULL);
timetoa(buf, BUF_LEN, &this->installed, utc); timetoa(buf, BUF_LEN, &this->installed, utc);
logger->log(logger, CONTROL, "%s", buf); logger->log(logger, CONTROL, "%s", buf);
logger->log(logger, CONTROL, " subject: '%s'", subject->get_string(subject)); logger->log(logger, CONTROL, " subject: '%s'", subject->get_string(subject));
logger->log(logger, CONTROL, " issuer: '%s'", issuer->get_string(issuer)); logger->log(logger, CONTROL, " issuer: '%s'", issuer->get_string(issuer));
chunk_to_hex(buf, BUF_LEN, this->serialNumber); chunk_to_hex(buf, BUF_LEN, this->serialNumber);
logger->log(logger, CONTROL, " serial: %s", buf); logger->log(logger, CONTROL, " serial: %s", buf);
timetoa(buf, BUF_LEN, &this->notBefore, utc); timetoa(buf, BUF_LEN, &this->notBefore, utc);
logger->log(logger, CONTROL, " validity: not before %s %s", buf, logger->log(logger, CONTROL, " validity: not before %s %s", buf,
(this->notBefore < now)? "ok":"fatal (not valid yet)"); (this->notBefore < now)? "ok":"fatal (not valid yet)");
timetoa(buf, BUF_LEN, &this->notAfter, utc); timetoa(buf, BUF_LEN, &this->notAfter, utc);
logger->log(logger, CONTROL, " not after %s %s", buf, logger->log(logger, CONTROL, " not after %s %s", buf,
check_expiry(this->notAfter, CERT_WARNING_INTERVAL, TRUE)); 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); 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 */ /* initialize */
this->subjectPublicKey = CHUNK_INITIALIZER; this->subjectPublicKey = CHUNK_INITIALIZER;
this->public_key = NULL; this->public_key = NULL;
@@ -1086,15 +1092,27 @@ x509_t *x509_create_from_chunk(chunk_t chunk)
this->authKeyID = CHUNK_INITIALIZER; this->authKeyID = CHUNK_INITIALIZER;
this->authKeySerialNumber = 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 */ /* we do not use a per-instance logger right now, since its not always accessible */
logger = logger_manager->get_logger(logger_manager, ASN1); 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); destroy(this);
return NULL; return NULL;
} }
/* extract public key from certificate */
this->public_key = rsa_public_key_create_from_chunk(this->subjectPublicKey); this->public_key = rsa_public_key_create_from_chunk(this->subjectPublicKey);
if (this->public_key == NULL) if (this->public_key == NULL)
{ {
+27 -10
View File
@@ -54,7 +54,7 @@ struct x509_t {
* @param this calling object * @param this calling object
* @return public_key * @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. * @brief Get the certificate issuers ID.
@@ -65,7 +65,7 @@ struct x509_t {
* @param this calling object * @param this calling object
* @return issuers ID * @return issuers ID
*/ */
identification_t *(*get_issuer) (x509_t *this); identification_t *(*get_issuer) (const x509_t *this);
/** /**
* @brief Get the subjects ID. * @brief Get the subjects ID.
@@ -76,7 +76,7 @@ struct x509_t {
* @param this calling object * @param this calling object
* @return subjects ID * @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. * @brief Check if a certificate is valid.
@@ -86,14 +86,14 @@ struct x509_t {
* *
* @todo implement! * @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. * @brief Get the key identifier of the public key.
* *
* @todo implement! * @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. * @brief Compare two certificates.
@@ -102,18 +102,35 @@ struct x509_t {
* *
* @param this first cert for compare * @param this first cert for compare
* @param other second 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. * @brief Checks if the certificate contains a subjectAltName equal to id.
* *
* @param this certificate being examined * @param this certificate being examined
* @param id id which is being compared to the subjectAltNames * @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. * @brief Destroys the certificate.
@@ -130,7 +147,7 @@ struct x509_t {
* @param utc log dates either in UTC or local time * @param utc log dates either in UTC or local time
* @param has_key a matching private key is available * @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);
}; };
/** /**