XRootD
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()
Definition: XrdCryptoAux.cc:77

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();
364  if (k->status == XrdCryptoRSA::kComplete) {
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)
Definition: XrdBwmTrace.hh:54
#define EPNAME(x)
Definition: XrdBwmTrace.hh:56
int fclose(FILE *stream)
#define fopen(a, b)
Definition: XrdPosix.hh:49
ERSAStatus status
Definition: XrdCryptoRSA.hh:58
virtual XrdCryptoRSAdata Opaque()
Definition: XrdCryptoRSA.cc:51
XrdCryptoX509 * End() const
XrdCryptoX509 * SearchBySubject(const char *subject, ESearchMode mode=kExact)
virtual XrdCryptoX509data Opaque()
virtual XrdCryptoRSA * PKI()
virtual const char * Issuer()
EX509Type type

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();
238  if (k->status == XrdCryptoRSA::kComplete) {
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
Definition: XrdSutBucket.hh:47
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(), and fopen.

Referenced by XrdCryptosslFactory::X509ParseFile().

+ 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
58  gErrVerifyChain = 0;
59 
60  if (ok != 0) {
61 
62  // Error analysis
63  gErrVerifyChain = 1;
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().