Skip to content

Commit

Permalink
Overhaul curl's usage of CAs.
Browse files Browse the repository at this point in the history
For the NSS backend, this PR will periodically parse all CAs in
the CA directory and concatenate the unique CAs into a single file.

The result is:
- Drastically fewer memory leaks in the libnss backend for libcurl.
- Far faster parsing of CAs (1 file to read versus ~1200).
- Avoids a bug where NSS tries to parse CRLs as a CA.
  • Loading branch information
bbockelm committed Mar 18, 2021
1 parent 6e91d86 commit 5e31d97
Show file tree
Hide file tree
Showing 8 changed files with 454 additions and 23 deletions.
62 changes: 45 additions & 17 deletions src/XrdCrypto/XrdCryptosslAux.cc
Original file line number Diff line number Diff line change
Expand Up @@ -297,6 +297,26 @@ XrdSutBucket *XrdCryptosslX509ExportChain(XrdCryptoX509Chain *chain,
return bck;
}

//____________________________________________________________________________
int XrdCryptosslX509ToFile(XrdCryptoX509 *x509, FILE *file)
{
// Dump a single X509 certificate to a file in PEM format.
EPNAME("X509ChainToFile");

// Check inputs
if (!x509 || !file) {
DEBUG("Invalid inputs");
return -1;
}

if (PEM_write_X509(file, (X509 *)x509->Opaque()) != 1) {
DEBUG("error while writing certificate");
return -1;
}

return 0;
}

//____________________________________________________________________________
int XrdCryptosslX509ChainToFile(XrdCryptoX509Chain *ch, const char *fn)
{
Expand Down Expand Up @@ -433,6 +453,26 @@ int XrdCryptosslX509ParseStack(XrdTlsPeerCerts* pc, XrdCryptoX509Chain *chain)
//____________________________________________________________________________
int XrdCryptosslX509ParseFile(const char *fname,
XrdCryptoX509Chain *chain)
{
EPNAME("X509ParseFile");

//
// Open file and read the content:
// it should contain blocks on information in PEM form
FILE *fcer = fopen(fname, "r");
if (!fcer) {
DEBUG("unable to open file (errno: "<<errno<<")");
return 0;
}

auto retval = XrdCryptosslX509ParseFile(fcer, chain);
fclose(fcer);
return retval;
}

//____________________________________________________________________________
int XrdCryptosslX509ParseFile(FILE *fcer,
XrdCryptoX509Chain *chain)
{
// Parse content of file 'fname' and add X509 certificates to
// chain (which must be initialized by the caller).
Expand All @@ -441,9 +481,9 @@ int XrdCryptosslX509ParseFile(const char *fname,
EPNAME("X509ParseFile");
int nci = 0;

// Make sure we got a file to import
if (!fname) {
DEBUG("file name undefined: can do nothing");
// Make sure we got a valid file
if (!fcer) {
DEBUG("FILE object undefined: can do nothing");
return nci;
}

Expand All @@ -453,15 +493,6 @@ int XrdCryptosslX509ParseFile(const char *fname,
return nci;
}

//
// Open file and read the content:
// it should contain blocks on information in PEM form
FILE *fcer = fopen(fname, "r");
if (!fcer) {
DEBUG("unable to open file (errno: "<<errno<<")");
return nci;
}

// Now read out certificates and add them to the chain
X509 *xcer = 0;
while (PEM_read_X509(fcer, &xcer, 0, 0)) {
Expand All @@ -485,9 +516,9 @@ int XrdCryptosslX509ParseFile(const char *fname,
rewind(fcer);
RSA *rsap = 0;
if (!PEM_read_RSAPrivateKey(fcer, &rsap, 0, 0)) {
DEBUG("no RSA private key found in file "<<fname);
DEBUG("no RSA private key found in file");
} else {
DEBUG("found a RSA private key in file "<<fname);
DEBUG("found a RSA private key in file");
// We need to complete the key: we save it temporarly
// to a bio and check all the private keys of the
// loaded certificates
Expand Down Expand Up @@ -538,9 +569,6 @@ int XrdCryptosslX509ParseFile(const char *fname,
}
}

// We can close the file now
fclose(fcer);

// We are done
return nci;
}
Expand Down
4 changes: 4 additions & 0 deletions src/XrdCrypto/XrdCryptosslAux.hh
Original file line number Diff line number Diff line change
Expand Up @@ -59,8 +59,12 @@ bool XrdCryptosslX509VerifyChain(XrdCryptoX509Chain *chain, int &errcode);
XrdSutBucket *XrdCryptosslX509ExportChain(XrdCryptoX509Chain *c, bool key = 0);
// chain export to file (proxy file creation)
int XrdCryptosslX509ChainToFile(XrdCryptoX509Chain *c, const char *fn);
// export single certificate to file
extern "C" int XrdCryptosslX509ToFile(XrdCryptoX509 *x509, FILE *file);
// certificates from file parsing
int XrdCryptosslX509ParseFile(const char *fname, XrdCryptoX509Chain *c);
// certificates from FILE object
extern "C" int XrdCryptosslX509ParseFile(FILE *file, XrdCryptoX509Chain *c);
// certificates from bucket parsing
int XrdCryptosslX509ParseBucket(XrdSutBucket *b, XrdCryptoX509Chain *c);
// certificates from STACK_OF(X509*)
Expand Down
1 change: 1 addition & 0 deletions src/XrdTpc.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ if( BUILD_TPC )
MODULE
XrdTpc/XrdTpcConfigure.cc
XrdTpc/XrdTpcMultistream.cc
XrdTpc/XrdTpcNSSSupport.cc XrdTpc/XrdTpcNSSSupport.hh
XrdTpc/XrdTpcCurlMulti.cc XrdTpc/XrdTpcCurlMulti.hh
XrdTpc/XrdTpcState.cc XrdTpc/XrdTpcState.hh
XrdTpc/XrdTpcStream.cc XrdTpc/XrdTpcStream.hh
Expand Down
3 changes: 3 additions & 0 deletions src/XrdTpc/XrdTpcConfigure.cc
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,9 @@ bool TPCHandler::Configure(const char *configfn, XrdOucEnv *myEnv)
return false;
}
m_cadir = val;
if (XrdTpcNSSSupport::NeedsNSSHack()) {
m_nss_hack.reset(new XrdTpcNSSSupport(&m_log, m_cadir));
}

void *sfs_raw_ptr;
if ((sfs_raw_ptr = myEnv->GetPtr("XrdSfsFileSystem*"))) {
Expand Down
Loading

0 comments on commit 5e31d97

Please sign in to comment.