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 683 of file XrdCryptosslAux.cc.

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

745{
746 // Function to convert X509_NAME into a one-line human readable string
747
748#ifndef USEX509NAMEONELINE
749 BIO *mbio = BIO_new(BIO_s_mem());
750 X509_NAME_print_ex(mbio, nm, 0, XN_FLAG_SEP_MULTILINE);
751 char *data = 0;
752 long len = BIO_get_mem_data(mbio, &data);
753 s = "/";
754 s.insert(data, 1, len);
755 BIO_free(mbio);
756 s.replace("\n", "/");
757#else
758 char *xn = X509_NAME_oneline(nm, 0, 0);
759 s = xn;
760 OPENSSL_free(xn);
761#endif
762
763 // Done
764 return;
765}
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 311 of file XrdCryptosslAux.cc.

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

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

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

446{
447 EPNAME("X509ParseFile");
448
449 //
450 // Open file and read the content:
451 // it should contain blocks on information in PEM form
452 FILE *fcer = fopen(fname, "r");
453 if (!fcer) {
454 DEBUG("unable to open file (errno: "<<errno<<")");
455 return 0;
456 }
457
458 auto retval = XrdCryptosslX509ParseFile(fcer, chain, fname, fkey);
459 fclose(fcer);
460 return retval;
461}
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 464 of file XrdCryptosslAux.cc.

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

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 391 of file XrdCryptosslAux.cc.

392{
393 EPNAME("X509ParseStack");
394 int nci = 0;
395 // Make sure we got a chain where to add the certificates
396 if (!chain) {
397 DEBUG("chain undefined: can do nothing");
398 return nci;
399 }
400
401 if (pc->hasCert()) {
402 XrdCryptoX509 *c = new XrdCryptosslX509(pc->getCert());
403
404 if (c) {
405 chain->PushBack(c);
406 nci ++;
407 }
408 }
409
410 if (!pc->hasChain()) {
411 return nci;
412 }
413
414 STACK_OF(X509) *pChain = pc->getChain();
415
416 for (int i=0; i < sk_X509_num(pChain); i++) {
417 X509 *cert = sk_X509_value(pChain, i);
418 XrdCryptoX509 *c = new XrdCryptosslX509(cert);
419
420 if (c) {
421 // The SSL_get_peer_chain method does not increment the
422 // refcount; the XrdCryptoX509 object assumes it owns
423 // the X509* but also does not increment the refcount.
424 // Hence, we increment manually.
425#if OPENSSL_VERSION_NUMBER < 0x010100000L
426 CRYPTO_add(&(cert->references), 1, CRYPTO_LOCK_X509);
427#else
428 X509_up_ref(cert);
429#endif
430 chain->PushBack(c);
431 } else {
432 X509_free(cert);
433 DEBUG("could not create certificate: memory exhausted?");
434 chain->Reorder();
435 return nci;
436 }
437 nci ++;
438 }
439 chain->Reorder();
440 return nci;
441}
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 291 of file XrdCryptosslAux.cc.

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

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 OPENSSL_VERSION_NUMBER >= 0x10000000L
167 if (sk_X509_num(stk) != chain->Size() - 1)
168#else /* OPENSSL */
169 if (sk_num(stk) != chain->Size() - 1)
170#endif /* OPENSSL */
171 return 0;
172
173 // Create a store ctx ...
174 X509_STORE_CTX *ctx = X509_STORE_CTX_new();
175 if (!ctx)
176 return 0;
177
178 // ... and initialize it
179 X509_STORE_CTX_init(ctx, store, cref, stk);
180
181 // verify ?
182 bool verify_ok = (X509_verify_cert(ctx) == 1);
183
184 // Fill error code, if any
185 errcode = 0;
186 if (!verify_ok)
187 errcode = gErrVerifyChain;
188
189 // Free context, stack, and store
190 X509_STORE_CTX_free(ctx);
191 sk_X509_pop_free(stk, X509_free);
192 X509_STORE_free(store);
193
194 return verify_ok;
195}

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().