XRootD
Loading...
Searching...
No Matches
XrdCryptosslAux.cc File Reference
#include <ctime>
#include <cerrno>
#include <cstdlib>
#include <sys/types.h>
#include <sys/stat.h>
#include "XrdCrypto/XrdCryptoX509Chain.hh"
#include "XrdCrypto/XrdCryptosslAux.hh"
#include "XrdCrypto/XrdCryptosslRSA.hh"
#include "XrdCrypto/XrdCryptosslX509.hh"
#include "XrdCrypto/XrdCryptosslTrace.hh"
#include "XrdTls/XrdTlsPeerCerts.hh"
#include <openssl/pem.h>
Include dependency graph for XrdCryptosslAux.cc:

Go to the source code of this file.

Functions

time_t XrdCryptosslASN1toUTC (const ASN1_TIME *tsn1)
int XrdCryptosslKDFun (const char *pass, int plen, const char *salt, int slen, char *key, int klen)
int XrdCryptosslKDFunLen ()
void XrdCryptosslNameOneLine (X509_NAME *nm, XrdOucString &s)
int XrdCryptosslX509ChainToFile (XrdCryptoX509Chain *ch, const char *fn)
XrdSutBucketXrdCryptosslX509ExportChain (XrdCryptoX509Chain *chain, bool withprivatekey)
int XrdCryptosslX509ParseBucket (XrdSutBucket *b, XrdCryptoX509Chain *chain)
int XrdCryptosslX509ParseFile (const char *fname, XrdCryptoX509Chain *chain, const char *fkey)
int XrdCryptosslX509ParseFile (FILE *fcer, XrdCryptoX509Chain *chain, const char *fname, const char *fkey)
int XrdCryptosslX509ParseStack (XrdTlsPeerCerts *pc, XrdCryptoX509Chain *chain)
int XrdCryptosslX509ToFile (XrdCryptoX509 *x509, FILE *file, const char *fname)
int XrdCryptosslX509VerifyCB (int ok, X509_STORE_CTX *ctx)
bool XrdCryptosslX509VerifyCert (XrdCryptoX509 *cert, XrdCryptoX509 *ref)
bool XrdCryptosslX509VerifyChain (XrdCryptoX509Chain *chain, int &errcode)

Variables

static int gErrVerifyChain = 0
XrdOucTracesslTrace = 0

Function Documentation

◆ XrdCryptosslASN1toUTC()

time_t XrdCryptosslASN1toUTC ( const ASN1_TIME * tsn1)

Definition at line 675 of file XrdCryptosslAux.cc.

676{
677 // Function to convert from ASN1 time format into UTC
678 // since Epoch (Jan 1, 1970)
679 // Return -1 if something went wrong
680 time_t etime = -1;
681// EPNAME("ASN1toUTC");
682
683 //
684 // Make sure there is something to convert
685 if (!tsn1) return etime;
686
687 //
688 // Parse the input string: here we basically cut&paste from GRIDSITE
689 // They finally use timegm to convert to UTC seconds, which is less
690 // standard and seems to give an offset of 3600 secs.
691 // Our result is in agreement with 'date +%s`.
692 struct tm ltm;
693 char zz;
694 if ((sscanf((const char *)(tsn1->data),
695 "%02d%02d%02d%02d%02d%02d%c",
696 &(ltm.tm_year), &(ltm.tm_mon), &(ltm.tm_mday),
697 &(ltm.tm_hour), &(ltm.tm_min), &(ltm.tm_sec),
698 &zz) != 7) || (zz != 'Z')) {
699 // Try GeneralizedTime
700 if ((sscanf((const char *)(tsn1->data),
701 "%04d%02d%02d%02d%02d%02d%c",
702 &(ltm.tm_year), &(ltm.tm_mon), &(ltm.tm_mday),
703 &(ltm.tm_hour), &(ltm.tm_min), &(ltm.tm_sec),
704 &zz) != 7) || (zz != 'Z')) {
705 return -1;
706 }
707 }
708 // Init also the ones not used by mktime
709 ltm.tm_wday = 0; // day of the week
710 ltm.tm_yday = 0; // day in the year
711 ltm.tm_isdst = 0; // we will correct with an offset without dst
712 //
713 // Renormalize some values (year should be modulo 1900), honouring all cases
714 if (ltm.tm_year < 50) {
715 ltm.tm_year += 2000;
716 } else if (ltm.tm_year < 100) {
717 ltm.tm_year += 1900;
718 }
719 ltm.tm_year -= 1900;
720 //
721 // month should in [0, 11]
722 (ltm.tm_mon)--;
723 //
724 // Calculate as if the UTC stamp was a localtime with no dst
725 etime = mktime(&ltm);
726 // Correct to UTC
727 etime += XrdCryptoTZCorr();
728 // Notify, if requested
729// DEBUG(" UTC: "<<etime<<" isdst: "<<ltm.tm_isdst);
730 //
731 // We are done
732 return etime;
733}
time_t XrdCryptoTZCorr()

References XrdCryptoTZCorr().

Referenced by XrdCryptosslX509Crl::LastUpdate(), XrdCryptosslX509Crl::NextUpdate(), XrdCryptosslX509::NotAfter(), and XrdCryptosslX509::NotBefore().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ XrdCryptosslKDFun()

int XrdCryptosslKDFun ( const char * pass,
int plen,
const char * salt,
int slen,
char * key,
int klen )

Definition at line 78 of file XrdCryptosslAux.cc.

80{
81 // Password-Based Key Derivation Function 2, specified in PKCS #5
82 // Following (J.Viega, M.Messier, "Secure programming Cookbook", p.141),
83 // the default number of iterations is set to 10000 .
84 // It can be specified at the beginning of the salt using a construct
85 // like this: salt = "$$<number_of_iterations>$<effective_salt>"
86
87 klen = (klen <= 0) ? 24 : klen;
88
89 // Defaults
90 char *realsalt = (char *)salt;
91 int realslen = slen;
92 int it = 10000;
93 //
94 // Extract iteration number from salt, if any
95 char *ibeg = (char *)memchr(salt+1,'$',slen-1);
96 if (ibeg) {
97 char *del = 0;
98 int newit = strtol(ibeg+1, &del, 10);
99 if (newit > 0 && del[0] == '$' && errno != ERANGE) {
100 // found iteration number
101 it = newit;
102 realsalt = del+1;
103 realslen = slen - (int)(realsalt-salt);
104 }
105 }
106
107 PKCS5_PBKDF2_HMAC_SHA1(pass, plen,
108 (unsigned char *)realsalt, realslen, it,
109 klen, (unsigned char *)key);
110 return klen;
111}

Referenced by XrdCryptosslFactory::KDFun().

Here is the caller graph for this function:

◆ XrdCryptosslKDFunLen()

int XrdCryptosslKDFunLen ( )

Definition at line 71 of file XrdCryptosslAux.cc.

72{
73 // default buffer length
74 return kSslKDFunDefLen;
75}
#define kSslKDFunDefLen

References kSslKDFunDefLen.

Referenced by XrdCryptosslFactory::KDFunLen().

Here is the caller graph for this function:

◆ XrdCryptosslNameOneLine()

void XrdCryptosslNameOneLine ( X509_NAME * nm,
XrdOucString & s )

Definition at line 736 of file XrdCryptosslAux.cc.

737{
738 // Function to convert X509_NAME into a one-line human readable string
739
740#ifndef USEX509NAMEONELINE
741 BIO *mbio = BIO_new(BIO_s_mem());
742 X509_NAME_print_ex(mbio, nm, 0, XN_FLAG_SEP_MULTILINE);
743 char *data = 0;
744 long len = BIO_get_mem_data(mbio, &data);
745 s = "/";
746 s.insert(data, 1, len);
747 BIO_free(mbio);
748 s.replace("\n", "/");
749#else
750 char *xn = X509_NAME_oneline(nm, 0, 0);
751 s = xn;
752 OPENSSL_free(xn);
753#endif
754
755 // Done
756 return;
757}
void insert(const int i, int start=-1)
int replace(const char *s1, const char *s2, int from=0, int to=-1)

References XrdOucString::insert(), and XrdOucString::replace().

Referenced by XrdCryptosslX509::Issuer(), XrdCryptosslX509Crl::Issuer(), XrdCryptosslX509::Subject(), and XrdCryptosslX509Req::Subject().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ XrdCryptosslX509ChainToFile()

int XrdCryptosslX509ChainToFile ( XrdCryptoX509Chain * ch,
const char * fn )

Definition at line 307 of file XrdCryptosslAux.cc.

308{
309 // Dump non-CA content of chain 'c' into file 'fn'
310 EPNAME("X509ChainToFile");
311
312 // Check inputs
313 if (!ch || !fn) {
314 DEBUG("Invalid inputs");
315 return -1;
316 }
317
318 // We proceed only if we can lock for write
319 FILE *fp = fopen(fn,"w");
320 if (!fp) {
321 DEBUG("cannot open file to save chain (file: "<<fn<<")");
322 return -1;
323 }
324 int ifp = fileno(fp);
325 if (ifp == -1) {
326 DEBUG("got invalid file descriptor (file: "<<fn<<")");
327 fclose(fp);
328 return -1;
329 }
330
331 // We need to lock from now on
333
334 // If not successful, return
335 if (!fl.IsValid()) {
336 DEBUG("could not lock file: "<<fn<<")");
337 fclose(fp);
338 return -1;
339 }
340
341 // Set permissions to 0600
342 if (fchmod(ifp, 0600) == -1) {
343 DEBUG("cannot set permissions on file: "<<fn<<" (errno: "<<errno<<")");
344 fclose(fp);
345 return -1;
346 }
347
348 // Reorder the chain
349 ch->Reorder();
350
351 // Write the last cert first
352 XrdCryptoX509 *c = ch->End();
353 if (PEM_write_X509(fp, (X509 *)c->Opaque()) != 1) {
354 DEBUG("error while writing proxy certificate");
355 fclose(fp);
356 return -1;
357 }
358 // Write its private key, if any
359 XrdCryptoRSA *k = c->PKI();
361 if (PEM_write_PrivateKey(fp, (EVP_PKEY *)(k->Opaque()),
362 0, 0, 0, 0, 0) != 1) {
363 DEBUG("error while writing proxy private key");
364 fclose(fp);
365 return -1;
366 }
367 }
368 // Now write all other certificates
369 while ((c = ch->SearchBySubject(c->Issuer())) && c->type != XrdCryptoX509::kCA) {
370 // Write to file
371 if (PEM_write_X509(fp, (X509 *)c->Opaque()) != 1) {
372 DEBUG("error while writing proxy certificate");
373 fclose(fp);
374 return -1;
375 }
376 }
377 } // Unlocks the file
378
379 // CLose the file
380 fclose(fp);
381 //
382 // We are done
383 return 0;
384}
#define DEBUG(x)
#define EPNAME(x)
int fclose(FILE *stream)
#define fopen(a, b)
Definition XrdPosix.hh:54
ERSAStatus status
virtual XrdCryptoRSAdata Opaque()
XrdCryptoX509 * End() const
XrdCryptoX509 * SearchBySubject(const char *subject, ESearchMode mode=kExact)
virtual XrdCryptoX509data Opaque()
virtual XrdCryptoRSA * PKI()
virtual const char * Issuer()

References DEBUG, XrdCryptoX509Chain::End(), EPNAME, fclose(), fopen, XrdCryptoX509::Issuer(), XrdSutFileLocker::IsValid(), XrdCryptoX509::kCA, XrdCryptoRSA::kComplete, XrdSutFileLocker::kExcl, XrdCryptoRSA::Opaque(), XrdCryptoX509::Opaque(), XrdCryptoX509::PKI(), XrdCryptoX509Chain::Reorder(), XrdCryptoX509Chain::SearchBySubject(), XrdCryptoRSA::status, and XrdCryptoX509::type.

Referenced by XrdCryptosslFactory::X509ChainToFile().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ XrdCryptosslX509ExportChain()

XrdSutBucket * XrdCryptosslX509ExportChain ( XrdCryptoX509Chain * chain,
bool withprivatekey )

Definition at line 194 of file XrdCryptosslAux.cc.

196{
197 // Export non-CA content of 'chain' into a bucket for transfer.
198 EPNAME("X509ExportChain");
199 XrdSutBucket *bck = 0;
200
201 // Make sure we got something to export
202 if (!chain || chain->Size() <= 0) {
203 DEBUG("chain undefined or empty: nothing to export");
204 return bck;
205 }
206
207 // Do not export CA selfsigned certificates
208 if (chain->Size() == 1 && chain->Begin()->type == XrdCryptoX509::kCA &&
209 !strcmp(chain->Begin()->IssuerHash(),chain->Begin()->SubjectHash())) {
210 DEBUG("chain contains only a CA certificate: nothing to export");
211 return bck;
212 }
213
214 // Now we create a bio_mem to serialize the certificates
215 BIO *bmem = BIO_new(BIO_s_mem());
216 if (!bmem) {
217 DEBUG("unable to create BIO for memory operations");
218 return bck;
219 }
220
221 // Reorder the chain
222 chain->Reorder();
223
224 // Write the last cert first
225 XrdCryptoX509 *c = chain->End();
226 if (!PEM_write_bio_X509(bmem, (X509 *)c->Opaque())) {
227 DEBUG("error while writing proxy certificate");
228 BIO_free(bmem);
229 return bck;
230 }
231 // Write its private key, if any and if asked
232 if (withprivatekey) {
233 XrdCryptoRSA *k = c->PKI();
235 if (!PEM_write_bio_PrivateKey(bmem, (EVP_PKEY *)(k->Opaque()),
236 0, 0, 0, 0, 0)) {
237 DEBUG("error while writing proxy private key");
238 BIO_free(bmem);
239 return bck;
240 }
241 }
242 }
243 // Now write all other certificates (except selfsigned CAs ...)
244 while ((c = chain->SearchBySubject(c->Issuer()))) {
245 if (c->type == XrdCryptoX509::kCA) {
246 DEBUG("Encountered CA in chain; breaking. Subject: " << c->Subject());
247 break;
248 }
249 if (strcmp(c->IssuerHash(), c->SubjectHash())) {
250 // Write to bucket
251 if (!PEM_write_bio_X509(bmem, (X509 *)c->Opaque())) {
252 DEBUG("error while writing proxy certificate");
253 BIO_free(bmem);
254 return bck;
255 }
256 } else {
257 DEBUG("Encountered self-signed CA in chain; breaking. Subject: " << c->Subject());
258 break;
259 }
260 }
261
262 // Extract pointer to BIO data and length of segment
263 char *bdata = 0;
264 int blen = BIO_get_mem_data(bmem, &bdata);
265 DEBUG("BIO data: "<<blen<<" bytes at 0x"<<(int *)bdata);
266
267 // create the bucket now
268 bck = new XrdSutBucket(0, 0, kXRS_x509);
269 if (bck) {
270 // Fill bucket
271 bck->SetBuf(bdata, blen);
272 DEBUG("result of serialization: "<<bck->size<<" bytes");
273 } else {
274 DEBUG("unable to create bucket for serialized format");
275 BIO_free(bmem);
276 return bck;
277 }
278 //
279 // Free BIO
280 BIO_free(bmem);
281 //
282 // We are done
283 return bck;
284}
@ kXRS_x509
Definition XrdSutAux.hh:79
XrdCryptoX509 * Begin()
virtual const char * Subject()
virtual const char * SubjectHash(int)
virtual const char * IssuerHash(int)
kXR_int32 size
int SetBuf(const char *nb=0, int ns=0)

References XrdCryptoX509Chain::Begin(), DEBUG, XrdCryptoX509Chain::End(), EPNAME, XrdCryptoX509::Issuer(), XrdCryptoX509::IssuerHash(), XrdCryptoX509::kCA, XrdCryptoRSA::kComplete, kXRS_x509, XrdCryptoRSA::Opaque(), XrdCryptoX509::Opaque(), XrdCryptoX509::PKI(), XrdCryptoX509Chain::Reorder(), XrdCryptoX509Chain::SearchBySubject(), XrdSutBucket::SetBuf(), XrdCryptoX509Chain::Size(), XrdSutBucket::size, XrdCryptoRSA::status, XrdCryptoX509::Subject(), XrdCryptoX509::SubjectHash(), and XrdCryptoX509::type.

Referenced by XrdCryptosslFactory::X509ExportChain().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ XrdCryptosslX509ParseBucket()

int XrdCryptosslX509ParseBucket ( XrdSutBucket * b,
XrdCryptoX509Chain * chain )

Definition at line 567 of file XrdCryptosslAux.cc.

568{
569 // Import certificate(s) from bucket b adding them to 'chain'
570 // (which must be initialized by the caller).
571 EPNAME("X509ParseBucket");
572 int nci = 0;
573
574 // Make sure we got something to import
575 if (!b || b->size <= 0) {
576 DEBUG("bucket undefined or empty: can do nothing");
577 return nci;
578 }
579
580 // Make sure we got a chain where to add the certificates
581 if (!chain) {
582 DEBUG("chain undefined: can do nothing");
583 return nci;
584 }
585 //
586 // Now we create a bio_mem to store the certificates
587 BIO *bmem = BIO_new(BIO_s_mem());
588 if (!bmem) {
589 DEBUG("unable to create BIO to import certificates");
590 return nci;
591 }
592
593 // Write data to BIO
594 if (BIO_write(bmem,(const void *)(b->buffer),b->size) != b->size) {
595 DEBUG("problems writing data to BIO");
596 BIO_free(bmem);
597 return nci;
598 }
599
600 // Get certificates from BIO
601 X509 *xcer = 0;
602 while (PEM_read_bio_X509(bmem, &xcer, 0, 0)) {
603 //
604 // Create container and add to the list
605 XrdCryptoX509 *c = new XrdCryptosslX509(xcer);
606 if (c) {
607 chain->PushBack(c);
608 nci++;
609 DEBUG("certificate added to the chain - ord: "<<chain->Size());
610 } else {
611 DEBUG("could not create certificate: memory exhausted?");
612 BIO_free(bmem);
613 return nci;
614 }
615 // reset cert otherwise the next one is not fetched
616 xcer = 0;
617 }
618
619 // If we found something, and we are asked to extract a key,
620 // refill the BIO and search again for the key (this is mandatory
621 // as read operations modify the BIO contents; a read-only BIO
622 // may be more efficient)
623 if (nci && BIO_write(bmem,(const void *)(b->buffer),b->size) == b->size) {
624 EVP_PKEY *rsa = 0;
625 if (!PEM_read_bio_PrivateKey(bmem, &rsa, 0, 0)) {
626 DEBUG("no RSA private key found in bucket");
627 } else {
628 DEBUG("found a RSA private key in bucket");
629 // We need to complete the key
630 // check all the public keys of the loaded certificates
631 if (rsa) {
632 // Loop over the chain certificates
633 XrdCryptoX509 *cert = chain->Begin();
634 while (cert && cert->Opaque()) {
635 if (cert->type != XrdCryptoX509::kCA) {
636 // Get the public key
637 EVP_PKEY *evpp = X509_get_pubkey((X509 *)(cert->Opaque()));
638 if (evpp) {
639 // Test consistency
640#if OPENSSL_VERSION_NUMBER < 0x30000000L
641 int rc = EVP_PKEY_cmp(evpp, rsa);
642#else
643 int rc = EVP_PKEY_eq(evpp, rsa);
644#endif
645 EVP_PKEY_free(evpp);
646 if (rc == 1) {
647 // Update PKI in certificate; also tests if the key is complete
648 cert->SetPKI((XrdCryptoX509data)rsa);
649 if (cert->PKI()->status == XrdCryptoRSA::kComplete) {
650 DEBUG("RSA key completed");
651 break;
652 }
653 }
654 }
655 }
656 // Get next
657 cert = chain->Next();
658 }
659 if (!cert)
660 EVP_PKEY_free(rsa);
661 }
662 else
663 EVP_PKEY_free(rsa);
664 }
665 }
666
667 // Cleanup
668 BIO_free(bmem);
669
670 // We are done
671 return nci;
672}
void * XrdCryptoX509data
XrdCryptoX509 * Next()
void PushBack(XrdCryptoX509 *c)
virtual void SetPKI(XrdCryptoX509data pki)

References XrdCryptoX509Chain::Begin(), XrdSutBucket::buffer, DEBUG, EPNAME, XrdCryptoX509::kCA, XrdCryptoRSA::kComplete, XrdCryptoX509Chain::Next(), XrdCryptoX509::Opaque(), XrdCryptoX509::PKI(), XrdCryptoX509Chain::PushBack(), XrdCryptoX509::SetPKI(), XrdCryptoX509Chain::Size(), XrdSutBucket::size, XrdCryptoRSA::status, and XrdCryptoX509::type.

Referenced by XrdCryptosslFactory::X509ParseBucket(), and XrdSecgsiAuthzKey().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ XrdCryptosslX509ParseFile() [1/2]

int XrdCryptosslX509ParseFile ( const char * fname,
XrdCryptoX509Chain * chain,
const char * fkey )

Definition at line 436 of file XrdCryptosslAux.cc.

438{
439 EPNAME("X509ParseFile");
440
441 //
442 // Open file and read the content:
443 // it should contain blocks on information in PEM form
444 FILE *fcer = fopen(fname, "r");
445 if (!fcer) {
446 DEBUG("unable to open file (errno: "<<errno<<")");
447 return 0;
448 }
449
450 auto retval = XrdCryptosslX509ParseFile(fcer, chain, fname, fkey);
451 fclose(fcer);
452 return retval;
453}
int XrdCryptosslX509ParseFile(const char *fname, XrdCryptoX509Chain *chain, const char *fkey)

References DEBUG, EPNAME, fclose(), fopen, and XrdCryptosslX509ParseFile().

Referenced by XrdCryptosslFactory::X509ParseFile(), and XrdCryptosslX509ParseFile().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ XrdCryptosslX509ParseFile() [2/2]

int XrdCryptosslX509ParseFile ( FILE * fcer,
XrdCryptoX509Chain * chain,
const char * fname,
const char * fkey )

Definition at line 456 of file XrdCryptosslAux.cc.

459{
460 // Parse content of file 'fname' and add X509 certificates to
461 // chain (which must be initialized by the caller).
462 // If a private key matching the public key of one of the certificates
463 // is found in the file, the certificate key is completed.
464 EPNAME("X509ParseFile");
465 int nci = 0;
466
467 // Make sure we got a valid file
468 if (!fcer) {
469 DEBUG("FILE object undefined: can do nothing");
470 return nci;
471 }
472
473 // Make sure we got a chain where to add the certificates
474 if (!chain) {
475 DEBUG("chain undefined: can do nothing");
476 return nci;
477 }
478
479 // Now read out certificates and add them to the chain
480 X509 *xcer = 0;
481 while (PEM_read_X509(fcer, &xcer, 0, 0)) {
482 // Add it to the chain
483 XrdCryptoX509 *c = new XrdCryptosslX509(xcer);
484 if (c) {
485 chain->PushBack(c);
486 nci++;
487 DEBUG("certificate for '"<<c->Subject()<<"'added to the chain - ord: "<<chain->Size());
488 } else {
489 DEBUG("could not create certificate: memory exhausted?");
490 fclose(fcer);
491 return nci;
492 }
493 xcer = 0;
494 }
495
496 // If we found something, and we are asked to extract a key,
497 // rewind and look for it
498 if (nci) {
499 FILE *fcersave = 0;
500 if (!fkey) {
501 // Look in the same file, after rewinding
502 rewind(fcer);
503 } else {
504 // We can close the file now
505 fcersave = fcer;
506 // Open key file
507 fcer = fopen(fkey, "r");
508 if (!fcer) {
509 DEBUG("unable to open key file (errno: "<<errno<<")");
510 fcer = fcersave;
511 return nci;
512 }
513 }
514 EVP_PKEY *rsa = 0;
515 if (!PEM_read_PrivateKey(fcer, &rsa, 0, 0)) {
516 DEBUG("no RSA private key found in file " << fname);
517 } else {
518 DEBUG("found a RSA private key in file " << fname);
519 // We need to complete the key
520 // check all the public keys of the loaded certificates
521 if (rsa) {
522 // Loop over the chain certificates
523 XrdCryptoX509 *cert = chain->Begin();
524 while (cert && cert->Opaque()) {
525 if (cert->type != XrdCryptoX509::kCA) {
526 // Get the public key
527 EVP_PKEY *evpp = X509_get_pubkey((X509 *)(cert->Opaque()));
528 if (evpp) {
529 // Test consistency
530#if OPENSSL_VERSION_NUMBER < 0x30000000L
531 int rc = EVP_PKEY_cmp(evpp, rsa);
532#else
533 int rc = EVP_PKEY_eq(evpp, rsa);
534#endif
535 EVP_PKEY_free(evpp);
536 if (rc == 1) {
537 // Update PKI in certificate; also tests if the key is complete
538 cert->SetPKI((XrdCryptoX509data)rsa);
539 if (cert->PKI()->status == XrdCryptoRSA::kComplete) {
540 DEBUG("RSA key completed");
541 break;
542 }
543 }
544 }
545 }
546 // Get next
547 cert = chain->Next();
548 }
549 if (!cert)
550 EVP_PKEY_free(rsa);
551 }
552 else
553 EVP_PKEY_free(rsa);
554 }
555 if (fkey) {
556 // Re-establish original fcer pointer
557 fclose(fcer);
558 fcer = fcersave;
559 }
560 }
561
562 // We are done
563 return nci;
564}

References XrdCryptoX509Chain::Begin(), DEBUG, EPNAME, fclose(), fopen, XrdCryptoX509::kCA, XrdCryptoRSA::kComplete, XrdCryptoX509Chain::Next(), XrdCryptoX509::Opaque(), XrdCryptoX509::PKI(), XrdCryptoX509Chain::PushBack(), XrdCryptoX509::SetPKI(), XrdCryptoX509Chain::Size(), XrdCryptoRSA::status, XrdCryptoX509::Subject(), and XrdCryptoX509::type.

Here is the call graph for this function:

◆ XrdCryptosslX509ParseStack()

int XrdCryptosslX509ParseStack ( XrdTlsPeerCerts * pc,
XrdCryptoX509Chain * chain )

Definition at line 387 of file XrdCryptosslAux.cc.

388{
389 EPNAME("X509ParseStack");
390 int nci = 0;
391 // Make sure we got a chain where to add the certificates
392 if (!chain) {
393 DEBUG("chain undefined: can do nothing");
394 return nci;
395 }
396
397 if (pc->hasCert()) {
398 XrdCryptoX509 *c = new XrdCryptosslX509(pc->getCert());
399
400 if (c) {
401 chain->PushBack(c);
402 nci ++;
403 }
404 }
405
406 if (!pc->hasChain()) {
407 return nci;
408 }
409
410 STACK_OF(X509) *pChain = pc->getChain();
411
412 for (int i=0; i < sk_X509_num(pChain); i++) {
413 X509 *cert = sk_X509_value(pChain, i);
414 XrdCryptoX509 *c = new XrdCryptosslX509(cert);
415
416 if (c) {
417 // The SSL_get_peer_chain method does not increment the
418 // refcount; the XrdCryptoX509 object assumes it owns
419 // the X509* but also does not increment the refcount.
420 // Hence, we increment manually.
421 X509_up_ref(cert);
422 chain->PushBack(c);
423 } else {
424 X509_free(cert);
425 DEBUG("could not create certificate: memory exhausted?");
426 chain->Reorder();
427 return nci;
428 }
429 nci ++;
430 }
431 chain->Reorder();
432 return nci;
433}
X509 * getCert(bool upref=true)

References DEBUG, EPNAME, XrdTlsPeerCerts::getCert(), XrdTlsPeerCerts::hasCert(), XrdTlsPeerCerts::hasChain(), XrdCryptoX509Chain::PushBack(), and XrdCryptoX509Chain::Reorder().

Referenced by XrdCryptosslFactory::X509ParseStack().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ XrdCryptosslX509ToFile()

int XrdCryptosslX509ToFile ( XrdCryptoX509 * x509,
FILE * file,
const char * fname )

Definition at line 287 of file XrdCryptosslAux.cc.

288{
289 // Dump a single X509 certificate to a file in PEM format.
290 EPNAME("X509ChainToFile");
291
292 // Check inputs
293 if (!x509 || !file) {
294 DEBUG("Invalid inputs");
295 return -1;
296 }
297
298 if (PEM_write_X509(file, (X509 *)x509->Opaque()) != 1) {
299 DEBUG("error while writing certificate " << fname);
300 return -1;
301 }
302
303 return 0;
304}

References DEBUG, EPNAME, and XrdCryptoX509::Opaque().

Here is the call graph for this function:

◆ XrdCryptosslX509VerifyCB()

int XrdCryptosslX509VerifyCB ( int ok,
X509_STORE_CTX * ctx )

Definition at line 53 of file XrdCryptosslAux.cc.

54{
55 // Verify callback function
56
57 // Reset global error
59
60 if (ok != 0) {
61
62 // Error analysis
64 }
65
66 // We are done
67 return ok;
68}
static int gErrVerifyChain

References gErrVerifyChain.

◆ XrdCryptosslX509VerifyCert()

bool XrdCryptosslX509VerifyCert ( XrdCryptoX509 * cert,
XrdCryptoX509 * ref )

Definition at line 114 of file XrdCryptosslAux.cc.

115{
116 // Verify signature of cert using public key of ref
117
118 // Input must make sense
119 X509 *c = cert ? (X509 *)(cert->Opaque()) : 0;
120 X509 *r = ref ? (X509 *)(ref->Opaque()) : 0;
121 EVP_PKEY *rk = r ? X509_get_pubkey(r) : 0;
122 if (!c || !rk) return 0;
123
124 // Ok: we can verify
125 return (X509_verify(c, rk) > 0);
126}

References XrdCryptoX509::Opaque().

Referenced by XrdCryptosslFactory::X509VerifyCert().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ XrdCryptosslX509VerifyChain()

bool XrdCryptosslX509VerifyChain ( XrdCryptoX509Chain * chain,
int & errcode )

Definition at line 129 of file XrdCryptosslAux.cc.

130{
131 // Verifies crossed signatures of X509 certificate 'chain'
132 // In case of failure, and error code is returned in errcode.
133
134 // Make sure we got a potentially meaningful chain
135 if (!chain || chain->Size() <= 1)
136 return 0;
137
138 // Create a store
139 X509_STORE *store = X509_STORE_new();
140 if (!store)
141 return 0;
142
143 // Set the verify callback function
144 X509_STORE_set_verify_cb_func(store, 0);
145
146 // Add the first (the CA) certificate
147 XrdCryptoX509 *cert = chain->Begin();
148 if (cert->type != XrdCryptoX509::kCA && cert->Opaque())
149 return 0;
150 X509_STORE_add_cert(store, (X509 *)(cert->Opaque()));
151
152 // Create a stack
153 STACK_OF(X509) *stk = sk_X509_new_null();
154 if (!stk)
155 return 0;
156
157 // Fill it with chain we have
158 X509 *cref = 0;
159 while ((cert = chain->Next()) && cert->Opaque()) {
160 if (!cref)
161 cref = (X509 *)(cert->Opaque());
162 sk_X509_push(stk, (X509 *)(cert->Opaque()));
163 }
164
165 // Make sure all the certificates have been inserted
166 if (sk_X509_num(stk) != chain->Size() - 1)
167 return 0;
168
169 // Create a store ctx ...
170 X509_STORE_CTX *ctx = X509_STORE_CTX_new();
171 if (!ctx)
172 return 0;
173
174 // ... and initialize it
175 X509_STORE_CTX_init(ctx, store, cref, stk);
176
177 // verify ?
178 bool verify_ok = (X509_verify_cert(ctx) == 1);
179
180 // Fill error code, if any
181 errcode = 0;
182 if (!verify_ok)
183 errcode = gErrVerifyChain;
184
185 // Free context, stack, and store
186 X509_STORE_CTX_free(ctx);
187 sk_X509_pop_free(stk, X509_free);
188 X509_STORE_free(store);
189
190 return verify_ok;
191}

References XrdCryptoX509Chain::Begin(), gErrVerifyChain, XrdCryptoX509::kCA, XrdCryptoX509Chain::Next(), XrdCryptoX509::Opaque(), XrdCryptoX509Chain::Size(), and XrdCryptoX509::type.

Referenced by XrdCryptosslFactory::X509VerifyChain().

Here is the call graph for this function:
Here is the caller graph for this function:

Variable Documentation

◆ gErrVerifyChain

int gErrVerifyChain = 0
static

Definition at line 49 of file XrdCryptosslAux.cc.

Referenced by XrdCryptosslX509VerifyCB(), and XrdCryptosslX509VerifyChain().

◆ sslTrace

XrdOucTrace* sslTrace = 0

Definition at line 50 of file XrdCryptosslAux.cc.

Referenced by XrdCryptosslFactory::SetTrace().