8 #include <openssl/x509v3.h>
9 #include <openssl/pem.h>
12 #include "wvx509mgr.h"
16 static 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); \
24 static 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;
60 int i = X509_get_ext_by_NID(ca.cert, NID_subject_key_identifier, -1);
61 if ((i >= 0) && (ext = X509_get_ext(ca.cert, i)))
62 ikeyid =
static_cast<ASN1_OCTET_STRING *
>(X509V3_EXT_d2i(ext));
66 AUTHORITY_KEYID *akeyid = AUTHORITY_KEYID_new();
67 akeyid->issuer = NULL;
68 akeyid->serial = NULL;
69 akeyid->keyid = ikeyid;
70 ext = X509V3_EXT_i2d(NID_authority_key_identifier, 0, akeyid);
71 X509_CRL_add_ext(crl, ext, -1);
72 X509_EXTENSION_free(ext);
73 AUTHORITY_KEYID_free(akeyid);
97 CHECK_CRL_EXISTS_GET(
"if CRL is signed by CA",
false);
99 EVP_PKEY *pkey = X509_get_pubkey(cacert.cert);
100 int result = X509_CRL_verify(crl, pkey);
104 debug(
"There was an error (%s) determining whether or not we were "
105 "signed by CA '%s'\n", wvssl_errstr(), cacert.
get_subject());
108 bool issigned = (result > 0);
110 debug(
"CRL was%s signed by CA %s\n", issigned ?
"" :
" NOT",
119 CHECK_CRL_EXISTS_GET(
"if CRL is issued by CA",
false);
124 debug(
"CRL issuer '%s' matches subject '%s' of cert. We can say "
125 "that it appears to be issued by this CA.\n",
128 debug(
"CRL issuer '%s' doesn't match subject '%s' of cert. Doesn't "
129 "appear to be issued by this CA.\n", name,
138 CHECK_CRL_EXISTS_GET(
"if CRL has expired",
false);
140 if (X509_cmp_current_time(X509_CRL_get_nextUpdate(crl)) < 0)
142 debug(
"CRL appears to be expired.\n");
146 debug(
"CRL appears not to be expired.\n");
151 bool WvCRL::has_critical_extensions()
const
153 CHECK_CRL_EXISTS_GET(
"if CRL has critical extensions",
false);
155 int critical = X509_CRL_get_ext_by_critical(crl, 1, 0);
156 return (critical > 0);
162 CHECK_CRL_EXISTS_GET(
"CRL's AKI", WvString::null);
164 AUTHORITY_KEYID *aki = NULL;
167 aki =
static_cast<AUTHORITY_KEYID *
>(
168 X509_CRL_get_ext_d2i(crl, NID_authority_key_identifier,
172 char *tmp = hex_to_string(aki->keyid->data, aki->keyid->length);
176 AUTHORITY_KEYID_free(aki);
181 return WvString::null;
187 CHECK_CRL_EXISTS_GET(
"CRL's issuer", WvString::null);
189 char *name = X509_NAME_oneline(X509_CRL_get_issuer(crl), 0, 0);
208 if (mode == CRLFileDER || mode == CRLFilePEM)
213 debug(WvLog::Warning,
"Tried to encode CRL, but CRL is blank!\n");
217 BIO *bufbio = BIO_new(BIO_s_mem());
222 debug(
"Dumping CRL in PEM format.\n");
223 PEM_write_bio_X509_CRL(bufbio, crl);
226 debug(
"Dumping CRL in DER format.\n");
227 i2d_X509_CRL_bio(bufbio, crl);
230 debug(
"Tried to dump CRL in unknown format!\n");
234 BIO_get_mem_ptr(bufbio, &bm);
235 buf.put(bm->data, bm->length);
244 debug(
"Replacing already existant CRL.\n");
249 if (mode == CRLFileDER)
251 BIO *bio = BIO_new(BIO_s_file());
253 if (BIO_read_filename(bio, str.cstr()) <= 0)
255 debug(WvLog::Warning,
"Import CRL from '%s': %s\n",
256 str, wvssl_errstr());
261 if (!(crl = d2i_X509_CRL_bio(bio, NULL)))
262 debug(WvLog::Warning,
"Read CRL from '%s': %s\n",
263 str, wvssl_errstr());
268 else if (mode == CRLFilePEM)
270 FILE * fp = fopen(str,
"rb");
274 debug(WvLog::Warning,
276 str, strerror(errnum));
280 if (!(crl = PEM_read_X509_CRL(fp, NULL, NULL, NULL)))
281 debug(WvLog::Warning,
"Import CRL from '%s': %s\n",
282 str, wvssl_errstr());
299 debug(
"Replacing already existant CRL.\n");
304 if (mode == CRLFileDER || mode == CRLFilePEM)
310 BIO *bufbio = BIO_new(BIO_s_mem());
311 BIO_write(bufbio, buf.
get(buf.
used()), buf.
used());
315 debug(
"Decoding CRL from PEM format.\n");
316 crl = PEM_read_bio_X509_CRL(bufbio, NULL, NULL, NULL);
318 else if (mode == CRLDER)
320 debug(
"Decoding CRL from DER format.\n");
321 crl = d2i_X509_CRL_bio(bufbio, NULL);
324 debug(WvLog::Warning,
"Attempted to decode unknown format.\n");
327 debug(WvLog::Warning,
"Couldn't decode CRL.\n");
337 debug(
"Checking to see if certificate with name '%s' and serial "
344 debug(WvLog::Error,
"Given certificate to check revocation status, "
345 "but certificate is blank. Declining.\n");
353 CHECK_CRL_EXISTS_GET(
"if certificate is revoked in CRL",
false);
357 ASN1_INTEGER *serial = serial_to_int(serial_number);
360 X509_REVOKED *revoked_entry = NULL;
361 int idx = X509_CRL_get0_by_serial(crl, &revoked_entry, serial);
362 ASN1_INTEGER_free(serial);
363 if (idx >= 1 || revoked_entry)
365 debug(
"Certificate is revoked.\n");
370 debug(
"Certificate is not revoked.\n");
375 debug(WvLog::Warning,
"Can't convert serial number to ASN1 format. "
376 "Saying it's not revoked.\n");
379 debug(WvLog::Warning,
"Serial number for certificate is blank.\n");
381 debug(
"Certificate is not revoked (or could not determine whether it "
393 return NO_VALID_SIGNATURE;
399 if (has_critical_extensions())
401 debug(
"CRL has unhandled critical extensions.\n");
402 return UNHANDLED_CRITICAL_EXTENSIONS;
411 CHECK_CRL_EXISTS_GET(
"number of certificates in CRL", 0);
413 STACK_OF(X509_REVOKED) *rev;
414 rev = X509_CRL_get_REVOKED(crl);
415 int certcount = sk_X509_REVOKED_num(rev);
428 debug(WvLog::Warning,
"Tried to add certificate to CRL, but CRL is "
435 ASN1_INTEGER *serial = serial_to_int(cert.
get_serial());
436 X509_REVOKED *revoked = X509_REVOKED_new();
437 ASN1_GENERALIZEDTIME *now = ASN1_GENERALIZEDTIME_new();
438 X509_REVOKED_set_serialNumber(revoked, serial);
439 X509_gmtime_adj(now, 0);
440 X509_REVOKED_set_revocationDate(revoked, now);
442 X509_CRL_add0_revoked(crl, revoked);
443 ASN1_GENERALIZEDTIME_free(now);
444 ASN1_INTEGER_free(serial);
448 debug(WvLog::Warning,
"Tried to add a certificate to the CRL, but "
449 "certificate is either bad or broken.\n");