45#include <openssl/bn.h>
46#include <openssl/pem.h>
48#if OPENSSL_VERSION_NUMBER < 0x10100000L
49#define X509_REVOKED_get0_revocationDate(x) (x)->revocationDate
50#define X509_REVOKED_get0_serialNumber(x) (x)->serialNumber
51#define X509_CRL_get0_lastUpdate X509_CRL_get_lastUpdate
52#define X509_CRL_get0_nextUpdate X509_CRL_get_nextUpdate
60 EPNAME(
"X509Crl::XrdCryptosslX509Crl_file");
65 DEBUG(
"could not initialize the CRL from "<<cf);
69 if (InitFromURI(cf, 0) != 0) {
70 DEBUG(
"could not initialize the CRL from URI"<<cf);
80 EPNAME(
"X509Crl::XrdCryptosslX509Crl_file");
83 DEBUG(
"could not initialize the CRL from " << cf);
96 EPNAME(
"X509Crl::XrdCryptosslX509Crl_CA");
100 DEBUG(
"the CA certificate is undefined or not CA! ("<<cacert<<
")");
105 X509_EXTENSION *crlext = (X509_EXTENSION *) cacert->
GetExtension(
"crlDistributionPoints");
107 DEBUG(
"extension 'crlDistributionPoints' not found in the CA certificate");
112 BIO *bext = BIO_new(BIO_s_mem());
113 ASN1_OBJECT *obj = X509_EXTENSION_get_object(crlext);
114 i2a_ASN1_OBJECT(bext, obj);
115 X509V3_EXT_print(bext, crlext, 0, 4);
118 int lbio = (int) BIO_get_mem_data(bext, &cbio);
119 char *buf = (
char *) malloc(lbio+1);
121 memcpy(buf, cbio, lbio);
128 DEBUG(
"URI string: "<< uris);
132 while ((from = uris.
tokenize(uri, from,
' ')) != -1) {
156int XrdCryptosslX509Crl::Init(
const char *cf)
164 DEBUG(
"file name undefined");
169 if (
stat(cf, &st) != 0) {
170 if (errno == ENOENT) {
171 DEBUG(
"file "<<cf<<
" does not exist - do nothing");
173 DEBUG(
"cannot stat file "<<cf<<
" (errno: "<<errno<<
")");
179 FILE *fc =
fopen(cf,
"r");
181 DEBUG(
"cannot open file "<<cf<<
" (errno: "<<errno<<
")");
185 auto rval = Init(fc, cf);
196int XrdCryptosslX509Crl::Init(FILE *fc,
const char *cf)
204 if (!PEM_read_X509_CRL(fc, &crl, 0, 0)) {
205 DEBUG(
"Unable to load CRL from file");
211 DEBUG(
"CRL successfully loaded from "<< cf);
228int XrdCryptosslX509Crl::InitFromURI(
const char *uri,
const char *hash)
233 EPNAME(
"X509Crl::InitFromURI");
237 DEBUG(
"uri undefined");
242 int isl = u.rfind(
'/');
243 if (isl !=
STR_NPOS) h.assign(u, isl + 1);
245 if (h ==
"") h =
"hashtmp";
249 if (outtmp.length() <= 0) outtmp =
"/tmp";
250 if (!outtmp.endswith(
"/")) outtmp +=
"/";
261 DEBUG(
"executing ... "<<cmd);
262 if (system(cmd.c_str()) == -1) {
263 DEBUG(
"'system' could not fork to execute command '"<<cmd<<
"'");
267 if (
stat(outtmp.c_str(), &st) != 0) {
268 DEBUG(
"did not manage to get the CRL file from "<<uri);
274 int needsopenssl = GetFileType(outtmp.c_str());
275 if (needsopenssl < 0) {
276 DEBUG(
"did not manage to coorectly parse "<<outtmp);
280 if (needsopenssl > 0) {
282 outpem.
replace(
".crltmp",
".pem");
283 cmd =
"openssl crl -inform DER -in ";
290 DEBUG(
"executing ... "<<cmd);
291 if (system(cmd.c_str()) == -1) {
292 DEBUG(
"system: problem executing: "<<cmd);
297 if (
unlink(outtmp.c_str()) != 0) {
298 DEBUG(
"problems removing "<<outtmp);
304 DEBUG(
"did not manage to change format from DER to PEM ("<<outpem<<
")");
309 if (Init(outpem.
c_str()) != 0) {
310 DEBUG(
"could not initialize the CRL from "<<outpem);
329 DEBUG(
"CRL object invalid; cannot write to a file");
333 if (PEM_write_X509_CRL(fh, crl) == 0) {
334 DEBUG(
"Unable to write CRL to file");
340 DEBUG(
"CRL successfully written to file");
346int XrdCryptosslX509Crl::GetFileType(
const char *crlfn)
353 if (!crlfn || strlen(crlfn) <= 0) {
354 PRINT(
"file name undefined!");
358 char line[1024] = {0};
359 FILE *f =
fopen(crlfn,
"r");
361 PRINT(
"could not open file "<<crlfn<<
" - errno: "<<(
int)errno);
366 while (fgets(line, 1024, f)) {
368 if (line[0] ==
'\n')
continue;
370 if (strstr(line,
"BEGIN X509 CRL")) rc = 0;
382 return X509_CRL_get_ext_by_critical(crl,1,-1) != -1;
386int XrdCryptosslX509Crl::LoadCache()
394 DEBUG(
"CRL undefined");
399#if OPENSSL_VERSION_NUMBER >= 0x10000000L
400 STACK_OF(X509_REVOKED *) rsk = X509_CRL_get_REVOKED(crl);
402 STACK_OF(X509_REVOKED *) *rsk = X509_CRL_get_REVOKED(crl);
405 DEBUG(
"could not get stack of revoked instances");
410#if OPENSSL_VERSION_NUMBER >= 0x10000000L
411 nrevoked = sk_X509_REVOKED_num(rsk);
413 nrevoked = sk_num(rsk);
415 DEBUG(nrevoked <<
"certificates have been revoked");
417 DEBUG(
"no valid certificate has been revoked - nothing to do");
424 for (; i < nrevoked; i++ ){
425#if OPENSSL_VERSION_NUMBER >= 0x10000000L
426 X509_REVOKED *rev = sk_X509_REVOKED_value(rsk,i);
428 X509_REVOKED *rev = (X509_REVOKED *)sk_value(rsk,i);
431 BIGNUM *bn = BN_new();
433 tagser = BN_bn2hex(bn);
435 TRACE(
Dump,
"certificate with serial number: "<<tagser<<
436 " has been revoked");
441 DEBUG(
"problems getting entry in the cache");
449 OPENSSL_free(tagser);
464 if (lastupdate < 0) {
480 if (nextupdate < 0) {
494 EPNAME(
"X509Crl::Issuer");
497 if (issuer.
length() <= 0) {
501 DEBUG(
"WARNING: no CRL available - cannot extract issuer name");
502 return (
const char *)0;
510 return (issuer.
length() > 0) ? issuer.
c_str() : (
const char *)0;
519 EPNAME(
"X509::IssuerHash");
521#if (OPENSSL_VERSION_NUMBER >= 0x10000000L && !defined(__APPLE__))
524 if (issueroldhash.
length() <= 0) {
527 char chash[30] = {0};
528 snprintf(chash,
sizeof(chash),
529 "%08lx.0",X509_NAME_hash_old(X509_CRL_get_issuer(crl)));
530 issueroldhash = chash;
532 DEBUG(
"WARNING: no certificate available - cannot extract issuer hash (md5)");
536 return (issueroldhash.
length() > 0) ? issueroldhash.
c_str() : (
const char *)0;
543 if (issuerhash.
length() <= 0) {
547 char chash[30] = {0};
548 snprintf(chash,
sizeof(chash),
549 "%08lx.0",X509_NAME_hash(X509_CRL_get_issuer(crl)));
552 DEBUG(
"WARNING: no certificate available - cannot extract issuer hash (default)");
557 return (issuerhash.
length() > 0) ? issuerhash.
c_str() : (
const char *)0;
570 X509 *r = ref ? (X509 *)(ref->
Opaque()) : 0;
571 EVP_PKEY *rk = r ? X509_get_pubkey(r) : 0;
576 return (X509_CRL_verify(crl, rk) > 0);
587 int now = (when > 0) ? when : time(0);
591 DEBUG(
"WARNING: CRL is expired: you should download the updated one");
596 DEBUG(
"No certificate in the list");
601 char tagser[20] = {0};
602 sprintf(tagser,
"%x",serialnumber);
608 if (now > cent->
mtime) {
609 DEBUG(
"certificate "<<tagser<<
" has been revoked");
628 int now = (when > 0) ? when : time(0);
632 DEBUG(
"WARNING: CRL is expired: you should download the updated one");
637 DEBUG(
"No certificate in the list");
645 if (now > cent->
mtime) {
646 DEBUG(
"certificate "<<sernum<<
" has been revoked");
665 char stbeg[256] = {0};
667 localtime_r(&tbeg,&tst);
668 asctime_r(&tst,stbeg);
669 stbeg[strlen(stbeg)-1] = 0;
670 char stend[256] = {0};
672 localtime_r(&tend,&tst);
673 asctime_r(&tst,stend);
674 stend[strlen(stend)-1] = 0;
676 PRINT(
"+++++++++++++++ X509 CRL dump +++++++++++++++++++++++");
684 PRINT(
"+ Validity: (expired!)");
686 PRINT(
"+ Validity:");
688 PRINT(
"+ LastUpdate: "<<tbeg<<
" UTC - "<<stbeg);
689 PRINT(
"+ NextUpdate: "<<tend<<
" UTC - "<<stend);
691 PRINT(
"+ Number of revoked certificates: "<<nrevoked);
693 PRINT(
"+++++++++++++++++++++++++++++++++++++++++++++++++");
void XrdCryptosslNameOneLine(X509_NAME *nm, XrdOucString &s)
time_t XrdCryptosslASN1toUTC(const ASN1_TIME *tsn1)
#define X509_REVOKED_get0_serialNumber(x)
#define X509_CRL_get0_nextUpdate
#define X509_CRL_get0_lastUpdate
#define X509_REVOKED_get0_revocationDate(x)
virtual bool IsExpired(int when=0)
const char * IssuerHash()
virtual XrdCryptoX509data GetExtension(const char *oid)
virtual XrdCryptoX509data Opaque()
virtual const char * SubjectHash(int)
XrdCryptosslX509Crl(const char *crlf, int opt=0)
virtual ~XrdCryptosslX509Crl()
bool hasCriticalExtension()
bool IsRevoked(int serialnumber, int when=0)
const char * ParentFile()
bool Verify(XrdCryptoX509 *ref)
int replace(const char *s1, const char *s2, int from=0, int to=-1)
int tokenize(XrdOucString &tok, int from, char del=':')
const char * c_str() const
XrdSutCacheEntry * Get(const char *tag)