added public methods is_ca() and is_valid()
This commit is contained in:
@@ -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;
|
||||
char buf[TIMETOA_BUF];
|
||||
|
||||
time_t current_time = time(NULL);
|
||||
|
||||
time(¤t_time);
|
||||
|
||||
if (cert->notAfter < *until)
|
||||
timetoa(buf, BUF_LEN, &this->notBefore, TRUE);
|
||||
logger->log(logger, CONTROL|LEVEL1, " not before : %s", buf);
|
||||
timetoa(buf, BUF_LEN, ¤t_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;
|
||||
}
|
||||
if (current_time < cert->notBefore)
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user