8#include <openssl/x509v3.h>
9#include <openssl/pem.h>
16static const char * warning_str_get =
"Tried to determine %s, but CRL is blank!\n";
17#define CHECK_CRL_EXISTS_GET(x, y) \
19 debug(WvLog::Warning, warning_str_get, x); \
24static ASN1_INTEGER * serial_to_int(WvStringParm serial)
29 BN_dec2bn(&bn, serial);
30 ASN1_INTEGER *retval = ASN1_INTEGER_new();
31 retval = BN_to_ASN1_INTEGER(bn, retval);
41 : debug(
"X509 CRL",
WvLog::Debug5)
48 : debug(
"X509 CRL",
WvLog::Debug5)
50 assert(crl = X509_CRL_new());
54 X509_CRL_set_version(crl, 1);
55 X509_CRL_set_issuer_name(crl, X509_get_issuer_name(ca.cert));
58 ASN1_OCTET_STRING *ikeyid = NULL;
59 const X509_EXTENSION *src_ext;
61 int i = X509_get_ext_by_NID(ca.cert, NID_subject_key_identifier, -1);
62 if ((i >= 0) && (src_ext = X509_get_ext(ca.cert, i)))
63 ikeyid =
static_cast<ASN1_OCTET_STRING *
>(X509V3_EXT_d2i(
const_cast<X509_EXTENSION *
>(src_ext)));
67 AUTHORITY_KEYID *akeyid = AUTHORITY_KEYID_new();
68 akeyid->issuer = NULL;
69 akeyid->serial = NULL;
70 akeyid->keyid = ikeyid;
71 ext = X509V3_EXT_i2d(NID_authority_key_identifier, 0, akeyid);
72 X509_CRL_add_ext(crl, ext, -1);
73 X509_EXTENSION_free(ext);
74 AUTHORITY_KEYID_free(akeyid);
98 CHECK_CRL_EXISTS_GET(
"if CRL is signed by CA",
false);
100 EVP_PKEY *pkey = X509_get_pubkey(cacert.cert);
101 int result = X509_CRL_verify(crl, pkey);
105 debug(
"There was an error (%s) determining whether or not we were "
106 "signed by CA '%s'\n", wvssl_errstr(), cacert.
get_subject());
109 bool issigned = (result > 0);
111 debug(
"CRL was%s signed by CA %s\n", issigned ?
"" :
" NOT",
120 CHECK_CRL_EXISTS_GET(
"if CRL is issued by CA",
false);
125 debug(
"CRL issuer '%s' matches subject '%s' of cert. We can say "
126 "that it appears to be issued by this CA.\n",
129 debug(
"CRL issuer '%s' doesn't match subject '%s' of cert. Doesn't "
130 "appear to be issued by this CA.\n", name,
139 CHECK_CRL_EXISTS_GET(
"if CRL has expired",
false);
141 if (X509_cmp_current_time(X509_CRL_get_nextUpdate(crl)) < 0)
143 debug(
"CRL appears to be expired.\n");
147 debug(
"CRL appears not to be expired.\n");
152bool WvCRL::has_critical_extensions()
const
154 CHECK_CRL_EXISTS_GET(
"if CRL has critical extensions",
false);
156 int critical = X509_CRL_get_ext_by_critical(crl, 1, 0);
157 return (critical > 0);
163 CHECK_CRL_EXISTS_GET(
"CRL's AKI", WvString::null);
165 AUTHORITY_KEYID *aki = NULL;
168 aki =
static_cast<AUTHORITY_KEYID *
>(
169 X509_CRL_get_ext_d2i(crl, NID_authority_key_identifier,
173 char *tmp = hex_to_string(ASN1_STRING_get0_data(aki->keyid), ASN1_STRING_length(aki->keyid));
177 AUTHORITY_KEYID_free(aki);
182 return WvString::null;
188 CHECK_CRL_EXISTS_GET(
"CRL's issuer", WvString::null);
190 char *name = X509_NAME_oneline(X509_CRL_get_issuer(crl), 0, 0);
209 if (mode == CRLFileDER || mode == CRLFilePEM)
214 debug(WvLog::Warning,
"Tried to encode CRL, but CRL is blank!\n");
218 BIO *bufbio = BIO_new(BIO_s_mem());
223 debug(
"Dumping CRL in PEM format.\n");
224 PEM_write_bio_X509_CRL(bufbio, crl);
227 debug(
"Dumping CRL in DER format.\n");
228 i2d_X509_CRL_bio(bufbio, crl);
231 debug(
"Tried to dump CRL in unknown format!\n");
235 BIO_get_mem_ptr(bufbio, &bm);
236 buf.put(bm->data, bm->length);
245 debug(
"Replacing already existant CRL.\n");
250 if (mode == CRLFileDER)
252 BIO *bio = BIO_new(BIO_s_file());
254 if (BIO_read_filename(bio, str.
cstr()) <= 0)
256 debug(WvLog::Warning,
"Import CRL from '%s': %s\n",
257 str, wvssl_errstr());
262 if (!(crl = d2i_X509_CRL_bio(bio, NULL)))
263 debug(WvLog::Warning,
"Read CRL from '%s': %s\n",
264 str, wvssl_errstr());
269 else if (mode == CRLFilePEM)
271 FILE * fp = fopen(str,
"rb");
275 debug(WvLog::Warning,
277 str, strerror(errnum));
281 if (!(crl = PEM_read_X509_CRL(fp, NULL, NULL, NULL)))
282 debug(WvLog::Warning,
"Import CRL from '%s': %s\n",
283 str, wvssl_errstr());
300 debug(
"Replacing already existant CRL.\n");
305 if (mode == CRLFileDER || mode == CRLFilePEM)
311 BIO *bufbio = BIO_new(BIO_s_mem());
312 BIO_write(bufbio, buf.
get(buf.
used()), buf.
used());
316 debug(
"Decoding CRL from PEM format.\n");
317 crl = PEM_read_bio_X509_CRL(bufbio, NULL, NULL, NULL);
319 else if (mode == CRLDER)
321 debug(
"Decoding CRL from DER format.\n");
322 crl = d2i_X509_CRL_bio(bufbio, NULL);
325 debug(WvLog::Warning,
"Attempted to decode unknown format.\n");
328 debug(WvLog::Warning,
"Couldn't decode CRL.\n");
338 debug(
"Checking to see if certificate with name '%s' and serial "
339 "number '%s' is revoked.\n", cert.get_subject(),
345 debug(WvLog::Error,
"Given certificate to check revocation status, "
346 "but certificate is blank. Declining.\n");
354 CHECK_CRL_EXISTS_GET(
"if certificate is revoked in CRL",
false);
358 ASN1_INTEGER *serial = serial_to_int(serial_number);
361 X509_REVOKED *revoked_entry = NULL;
362 int idx = X509_CRL_get0_by_serial(crl, &revoked_entry, serial);
363 ASN1_INTEGER_free(serial);
364 if (idx >= 1 || revoked_entry)
366 debug(
"Certificate is revoked.\n");
371 debug(
"Certificate is not revoked.\n");
376 debug(WvLog::Warning,
"Can't convert serial number to ASN1 format. "
377 "Saying it's not revoked.\n");
380 debug(WvLog::Warning,
"Serial number for certificate is blank.\n");
382 debug(
"Certificate is not revoked (or could not determine whether it "
394 return NO_VALID_SIGNATURE;
400 if (has_critical_extensions())
402 debug(
"CRL has unhandled critical extensions.\n");
403 return UNHANDLED_CRITICAL_EXTENSIONS;
412 CHECK_CRL_EXISTS_GET(
"number of certificates in CRL", 0);
414 STACK_OF(X509_REVOKED) *rev;
415 rev = X509_CRL_get_REVOKED(crl);
416 int certcount = sk_X509_REVOKED_num(rev);
429 debug(WvLog::Warning,
"Tried to add certificate to CRL, but CRL is "
436 ASN1_INTEGER *serial = serial_to_int(cert.get_serial());
437 X509_REVOKED *revoked = X509_REVOKED_new();
438 ASN1_GENERALIZEDTIME *now = ASN1_GENERALIZEDTIME_new();
439 X509_REVOKED_set_serialNumber(revoked, serial);
440 X509_gmtime_adj(now, 0);
441 X509_REVOKED_set_revocationDate(revoked, now);
443 X509_CRL_add0_revoked(crl, revoked);
444 ASN1_GENERALIZEDTIME_free(now);
445 ASN1_INTEGER_free(serial);
449 debug(WvLog::Warning,
"Tried to add a certificate to the CRL, but "
450 "certificate is either bad or broken.\n");
const T * get(size_t count)
Reads exactly the specified number of elements and returns a pointer to a storage location owned by t...
size_t used() const
Returns the number of elements in the buffer currently available for reading.
WvString getstr()
Returns the entire buffer as a null-terminated WvString.
void putstr(WvStringParm str)
Copies a WvString into the buffer, excluding the null-terminator.
void decode(const DumpMode mode, WvStringParm encoded)
Load the information from the format requested by mode into the class - this overwrites the CRL.
WvCRL()
Initialize a blank (null) CRL object.
Valid validate(const WvX509 &cacert) const
Checks to see that a CRL is signed and issued by a CA certificate, and that it has not expired.
bool expired() const
Checks to see if the CRL is expired (i.e.: the present time is past the nextUpdate extension).
bool signedbyca(const WvX509 &cacert) const
Check the CRL in crl against the CA certificate in cert.
bool isok() const
Do we have any errors... convenience function.
void addcert(const WvX509 &cert)
Add the certificate specified by cert to the CRL.
bool issuedbyca(const WvX509 &cacert) const
Check the issuer name of the CRL in crl against the CA certificate in cert.
WvString encode(const DumpMode mode) const
Return the information requested by mode as a WvString.
Valid
Type for validate() method: ERROR = there was an error that happened.
int numcerts() const
Counts the number of certificates in this CRL.
bool isrevoked(const WvX509 &cert) const
Is the certificate in cert revoked?
WvString get_issuer() const
Get the CRL Issuer.
DumpMode
Type for the encode() and decode() methods: CRLPEM = PEM Encoded X.509 CRL CRLDER = DER Encoded X....
WvString get_aki() const
Get the Authority key Info.
virtual ~WvCRL()
Destructor.
const char * cstr() const
return a (const char *) for this string.
A WvLog stream accepts log messages from applications and forwards them to all registered WvLogRcv's.
WvString is an implementation of a simple and efficient printable-string class.
bool signcrl(WvCRL &unsignedcrl) const
Sign the CRL with the rsa key associated with this class.
X509 Class to handle certificates and their related functions.
WvString get_subject() const
get and set the Subject field of the certificate