Commit 623e11df authored by Eric Cano's avatar Eric Cano
Browse files

CASTOR-4739: tapeserverd should support localfile, rfio, xroot and rados...

CASTOR-4739: tapeserverd should support localfile, rfio, xroot and rados striper access for disk files

After testing Xroot access, realised that we need to add a signature in the opaque data of the
Xroot URL. A signature using OpenSSL, as used in other places of the project was implemented,
but did not pass the memory leak and race condition tests. As discussed with the rest of the team,
OpenSSL is not to be trusted and has poor quality memory managment. The CryptoPP library, also part
of the SLC6 distribution has been tested as well, and it output validated (on a few example) with
OpenSSL's. CryptoPP can be used instead of OpenSSL, and has been put in place. This commit still contains
the OpenSSL for reference. The next commit will remove it.
parent 52825408
......@@ -60,6 +60,8 @@ void DiskReadTask::execute(log::LogContext& lc, diskFile::DiskFileFactory & file
std::auto_ptr<tape::diskFile::ReadFile> sourceFile(
fileFactory.createReadFile(m_migratedFile->path()));
log::ScopedParamContainer URLcontext(lc);
URLcontext.add("actualURL", sourceFile->URL());
if(migratingFileSize != sourceFile->size()){
throw castor::exception::Exception("Mismtach between size given by the client "
"and the real one");
......@@ -68,7 +70,7 @@ void DiskReadTask::execute(log::LogContext& lc, diskFile::DiskFileFactory & file
m_stats.openingTime+=localTime.secs(utils::Timer::resetCounter);
LogContext::ScopedParam sp(lc, Param("filePath",m_migratedFile->path()));
lc.log(LOG_INFO,"Opened file on disk for migration ");
lc.log(LOG_INFO,"Opened disk file for read");
while(migratingFileSize>0){
......
......@@ -24,6 +24,7 @@
#include "castor/tape/tapeserver/daemon/DiskReadThreadPool.hpp"
#include "castor/tape/tapeserver/daemon/MigrationTaskInjector.hpp"
#include "castor/tape/tapeserver/daemon/MigrationReportPacker.hpp"
#include "castor/common/CastorConfiguration.hpp"
#include <memory>
#include <sstream>
......@@ -37,7 +38,10 @@ namespace daemon {
//------------------------------------------------------------------------------
DiskReadThreadPool::DiskReadThreadPool(int nbThread, uint64_t maxFilesReq,uint64_t maxBytesReq,
castor::log::LogContext lc, const std::string & remoteFileProtocol) :
m_diskFileFactory(remoteFileProtocol), m_lc(lc),m_maxFilesReq(maxFilesReq),
m_diskFileFactory(remoteFileProtocol,
castor::common::CastorConfiguration::getConfig().
getConfEntString("XROOT", "PrivateKey", "/opt/xrootd/keys/key.pem")),
m_lc(lc),m_maxFilesReq(maxFilesReq),
m_maxBytesReq(maxBytesReq), m_nbActiveThread(0) {
for(int i=0; i<nbThread; i++) {
DiskReadWorkerThread * thr = new DiskReadWorkerThread(*this);
......
......@@ -57,7 +57,7 @@ namespace unitTests{
MockRecallReportPacker report(client,lc);
EXPECT_CALL(report,reportFailedJob(_,_,_));
RecallMemoryManager mm(10,100,lc);
DiskFileFactory fileFactory("RFIO");
DiskFileFactory fileFactory("RFIO","");
castor::tape::tapegateway::FileToRecallStruct file;
file.setPath("/dev/null");
......
......@@ -21,6 +21,7 @@
* @author Castor Dev team, castor-dev@cern.ch
*****************************************************************************/
#include "castor/tape/tapeserver/daemon/DiskWriteThreadPool.hpp"
#include "castor/common/CastorConfiguration.hpp"
#include "castor/tape/utils/Timer.hpp"
#include "log.h"
#include <memory>
......@@ -34,9 +35,12 @@ namespace daemon {
// constructor
//------------------------------------------------------------------------------
DiskWriteThreadPool::DiskWriteThreadPool(int nbThread,
RecallReportPacker& report,castor::log::LogContext lc,
const std::string & remoteFileProtocol):
m_diskFileFactory(remoteFileProtocol),m_reporter(report),m_lc(lc)
RecallReportPacker& report,castor::log::LogContext lc,
const std::string & remoteFileProtocol):
m_diskFileFactory(remoteFileProtocol,
castor::common::CastorConfiguration::getConfig().
getConfEntString("XROOT", "PrivateKey", "/opt/xrootd/keys/key.pem")),
m_reporter(report),m_lc(lc)
{
m_lc.pushOrReplace(castor::log::Param("threadCount", nbThread));
for(int i=0; i<nbThread; i++) {
......
/******************************************************************************
*
* This file is part of the Castor project.
* See http://castor.web.cern.ch/castor
*
* Copyright (C) 2003 CERN
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
*
*
*
* @author Castor Dev team, castor-dev@cern.ch
*****************************************************************************/
#include "castor/tape/tapeserver/exception/OpenSSL.hpp"
#include <openssl/err.h>
castor::tape::server::exception::OpenSSL::OpenSSL( const std::string & what) {
std::stringstream w;
if (what.size())
w << what << " ";
// Dump the OpenSSL error stack
// (open SSL maintains a stack of errors per thread)
while (unsigned long SSLError = ::ERR_get_error()) {
// SSL errors are stored in at least 120 char buffers
const size_t len = 200;
char buff[len];
::ERR_error_string_n(SSLError, buff, len);
w << "[" << buff << "]";
}
// Flush the SSL error queue
::ERR_clear_error();
getMessage().str(w.str());
}
/******************************************************************************
*
* This file is part of the Castor project.
* See http://castor.web.cern.ch/castor
*
* Copyright (C) 2003 CERN
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
*
*
*
* @author Castor Dev team, castor-dev@cern.ch
*****************************************************************************/
#pragma once
#include "castor/exception/Exception.hpp"
namespace castor {
namespace tape {
namespace server {
namespace exception {
/**
* A class retrieving OpenSSL errors codes and turning them into a string.
* Comes with exception launchers
*/
class OpenSSL: public castor::exception::Exception {
public:
OpenSSL(const std::string & context);
virtual ~OpenSSL() throw() {};
template<class T>
static void throwOnNULL(const T * ptr, std::string context = "") {
if (!ptr) throw OpenSSL(context);
}
template<class T>
static void throwOnZero(const T val, std::string context = "") {
if (!val) throw OpenSSL(context);
}
};
}}}}
......@@ -25,7 +25,7 @@
#include "XrootCl.hpp"
#include <sstream>
castor::exception::XrootCl::XrootCl(const XrdCl::XRootDStatus& status, const std::string & what) {
castor::tape::server::exception::XrootCl::XrootCl(const XrdCl::XRootDStatus& status, const std::string & what) {
std::stringstream w;
if (what.size())
w << what << " ";
......@@ -33,7 +33,7 @@ castor::exception::XrootCl::XrootCl(const XrdCl::XRootDStatus& status, const std
getMessage().str(w.str());
}
void castor::exception::XrootCl::throwOnError(const XrdCl::XRootDStatus& status, std::string context)
void castor::tape::server::exception::XrootCl::throwOnError(const XrdCl::XRootDStatus& status, std::string context)
{
if (!status.IsOK()) {
throw XrootCl(status, context);
......
......@@ -28,6 +28,8 @@
#include <xrootd/XrdCl/XrdClXRootDResponses.hh>
namespace castor {
namespace tape {
namespace server {
namespace exception {
/**
* A class turning the XrootCl (xroot 4 object client) error codes
......@@ -42,5 +44,4 @@ namespace exception {
protected:
XrdCl::XRootDStatus m_status;
};
}
}
}}}}
find_package (xrootd REQUIRED)
include_directories (${XROOTD_INCLUDE_DIR})
add_library(File File.cpp DiskFile.cpp Structures.cpp ../exception/XrootCl.cpp)
target_link_libraries (File castorrfio XrdCl)
add_library(File
File.cpp
DiskFile.cpp
Structures.cpp
OpenSSLLocker.cpp
../exception/XrootCl.cpp
../exception/OpenSSL.cpp)
target_link_libraries (File castorrfio XrdCl cryptopp)
/******************************************************************************
*
* This file is part of the Castor project.
* See http://castor.web.cern.ch/castor
*
* Copyright (C) 2003 CERN
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
*
*
* @author Castor Dev team, castor-dev@cern.ch
*****************************************************************************/
#include <gtest/gtest.h>
#include "castor/server/Threading.hpp"
#include "castor/tape/tapeserver/file/DiskFileImplementations.hpp"
#include <cryptopp/base64.h>
#include <cryptopp/osrng.h>
#include <openssl/pem.h>
namespace unitTests {
class CryptoPPThread: public castor::server::Thread {
public:
void setKey(const CryptoPP::RSA::PrivateKey & key) { m_key = key; }
private:
virtual void run() {
for (int i=0; i<100; i++) {
std::string payload = "Some payload... And some more...";
std::string signature = castor::tape::diskFile::CryptoPPSigner::sign(
payload, m_key);
}
}
CryptoPP::RSA::PrivateKey m_key;
};
class PEMKeyString {
public:
PEMKeyString(const std::string & keyString) {
// Import the key
const std::string HEADER = "-----BEGIN RSA PRIVATE KEY-----";
const std::string FOOTER = "-----END RSA PRIVATE KEY-----";
size_t pos1, pos2;
pos1 = keyString.find(HEADER);
if(pos1 == std::string::npos)
throw castor::exception::Exception(
"In DiskFileFactory::xrootCryptoPPPrivateKey, PEM header not found");
pos2 = keyString.find(FOOTER, pos1+1);
if(pos2 == std::string::npos)
throw castor::exception::Exception(
"In DiskFileFactory::xrootCryptoPPPrivateKey, PEM footer not found");
// Start position and length
pos1 = pos1 + HEADER.length();
pos2 = pos2 - pos1;
std::string keystr = keyString.substr(pos1, pos2);
// Base64 decode, place in a ByteQueue
CryptoPP::ByteQueue queue;
CryptoPP::Base64Decoder decoder;
decoder.Attach(new CryptoPP::Redirector(queue));
decoder.Put((const byte*)keystr.data(), keystr.length());
decoder.MessageEnd();
// Get the key
m_key.BERDecodePrivateKey(queue, false /*paramsPresent*/, queue.MaxRetrievable());
// BERDecodePrivateKey is a void function. Here's the only check
// we have regarding the DER bytes consumed.
if(!queue.IsEmpty())
throw castor::exception::Exception(
"In DiskFileFactory::xrootCryptoPPPrivateKey, garbage at end of key");
CryptoPP::AutoSeededRandomPool prng;
bool valid = m_key.Validate(prng, 3);
if(!valid)
throw castor::exception::Exception(
"In DiskFileFactory::xrootCryptoPPPrivateKey, RSA private key is not valid");
}
operator CryptoPP::RSA::PrivateKey() {
return m_key;
}
private:
CryptoPP::RSA::PrivateKey m_key;
};
// A random key from a bare "openssl genrsa".
std::string somePrivateKey =
"-----BEGIN RSA PRIVATE KEY-----\n"
"MIICXQIBAAKBgQDMGFBHGra0lHWyXA9oiwaMSPqKjv7tNuxAL3oUe+SbXBUJX6Nh\n"
"oMh/uo71jSQpyEozxkTsHkwNCMAPq+fBlsjGFHoNkiAjH68zwzCILM3XDQx5+ztH\n"
"e1att+niTVzLgrBy8R729Vgyvv/ToghLdwrJ+witd1YNPHHoZH5amLsHLwIDAQAB\n"
"AoGBAJ7y0JKP23sHpCIkUFu66n6W14jRlPhprdTPJOSPGJtmO3vxX+zIq13OjUfv\n"
"hBqGQkPQRh0d+1yrU+jgmL3MEM/OYJRm0iKAom3x28a9Rn2c+6tr7synBJMT3b8t\n"
"c5ShEGU2diNR3VrjyRDLQplaWY+1txLp+5jZ86C10M5y22QBAkEA9hYkGHJ0q9B6\n"
"16bHJvEUE8VbdFdZBPCE5HmJBoambFBeQgseuxi9fY3byrVvrRKgn8t7tocz0Ans\n"
"8ND+QTWAUQJBANRRHpBv13JmmBN0SK57rw3bDz27CnDbCMN2/omC1Ykb1g3L+JvU\n"
"VupF4zHo54VXIMXwRVQ8dSmTLxYEVMepr38CQC3Y/iyX1mjUVK6s4dm9fJIaaOmK\n"
"BInJDdlLU14l5Ae2CXmgfL864sLrlRF1MDM8jzR2QrxFAEA4OS68oUIg56ECQQCR\n"
"W0gVkrxpshuDliT8b+kVD1iL5rXrNcn2KE1zT4Np7wjJQU/fP6yRj29QCCgZfeEO\n"
"IsUUOp/r6rxd0nFIkL95AkA3oztzUVis7R4g5gO9UXCJzhlIY7y67coAbBHrqiHa\n"
"QeMkZnkN4sib4C4U2GanmAI05U05AIjDgp9lx3EYSulY\n"
"-----END RSA PRIVATE KEY-----\n";
TEST(castor_CryptoPP, multiThreading) {
// Read the key
PEMKeyString privateKey(somePrivateKey);
// Run the threads
std::vector<CryptoPPThread> m_threads;
m_threads.resize(10);
for (std::vector<CryptoPPThread>::iterator i=m_threads.begin();
i!=m_threads.end(); i++) {
i->setKey(privateKey);
i->start();
}
for (std::vector<CryptoPPThread>::iterator i=m_threads.begin();
i!=m_threads.end(); i++)
i->wait();
}
TEST(castor_CryptoPP, agreesWithOpenSSL) {
// Import the key for Open SSL
BIO * BIObuf = BIO_new(BIO_s_mem());
BIO_write(BIObuf, somePrivateKey.c_str(), somePrivateKey.size());
EVP_PKEY * OSSLKey;
OSSLKey = PEM_read_bio_PrivateKey(BIObuf, NULL, NULL, NULL);
BIO_free(BIObuf);
// We need one reference locker per thread for proper cleanup
std::auto_ptr<castor::tape::diskFile::OpenSSLLockerRef> lockerRef(
castor::tape::diskFile::OpenSSLLockerRefFactory());
// Import the key for CryptoPP
PEMKeyString CryptoPPKey(somePrivateKey);
std::string msg("Any random message will do!");
std::string osslSign(castor::tape::diskFile::OpenSSLSigner::sign(msg,OSSLKey));
std::string CryptoPPSign(castor::tape::diskFile::CryptoPPSigner::sign(msg,CryptoPPKey));
std::cout << CryptoPPSign << std::endl;
ASSERT_EQ(osslSign,CryptoPPSign);
// A few examples generated with openssl's command line:
// string=`dd if=/dev/urandom bs=40 count=1 2>/dev/null | openssl enc -base64 | tr -d 'n\'`
// echo $string
// openssl dgst -sha1 -sign ~/testRSAPrivate.pem | openssl enc -base64 | tr -d '\n' ; echo
//
// ~/testRSAPrivate.pem contains the same content as the variable somePrivateKey.
ASSERT_EQ("O8nSHzVPXyNRGRu8vaQ+CrqJjlv28qdsiFCTjlmeMFgc/aEnlJq+2b2q5al7BiHmPAFOd6fUkvn8xlFBm9IUlPFENhPLuMKJGqRSBndE7At0t+/vbS9UVnKiuOjrFepXo8JOvbt7lpqfp3jBwrQE5OZpOT92Nh8GXlpiCksvoxI=",
castor::tape::diskFile::CryptoPPSigner::sign("rsoCb+KBj9j9Xk6wr5Cgh+TVuI3eDZHTzD9z8pTFjBPEjdyfiTFIeQ==",CryptoPPKey));
ASSERT_EQ("uf8Cgkwtmh9K1VFLfeIfkZFQMd/pfSGCHNYPByH0nm0COPHNQAkYEI38ez9DS43fsIBVU9Gdrs0x50dVIntzawgzDrjp8YJIeARJF73he8M+6/FUgWJumNMoDE8fdvgiBaCFTv4+di5vtSb/abKVfqY9IbUPSDByxYjDKKI0OF0=",
castor::tape::diskFile::CryptoPPSigner::sign("MtvFsd09F8UQNpwsULF6eMyVkRDIU+uAvBXyJs/LoNM5HrjoJgZrig==",CryptoPPKey));
ASSERT_EQ("EzSR5Fd1kfmdrVhCiYgoWQ7E1MSdv8OYng3L7LepCfS9OStlEFTkJcMezt4VRqUZnarlcIZ0yPAvrmOUscjrAOAbqA0rMYKsvHnAwd19RaH54QZhtRCDwMloxpuLmUC1cmyJ/PAdRoMYCoHiMVr7yQw0CnVJ5168MUe5o0v3swY=",
castor::tape::diskFile::CryptoPPSigner::sign("v3lPb49U+Zz+DNdzoTf2R8AU+AFP+/9/7nLlJV1+HNf3Z+Nzl/HuiQ==",CryptoPPKey));
EVP_PKEY_free(OSSLKey);
}
}
This diff is collapsed.
......@@ -24,6 +24,10 @@
#pragma once
#include "castor/tape/tapeserver/utils/Regex.hpp"
#include <openssl/evp.h>
#include <cryptopp/rsa.h>
#include "castor/tape/tapeserver/file/OpenSSLLocker.hpp"
#include <memory>
/*
* This file only contains the interface declaration of the base classes
* the real implementation, which depends on many includes is hidden in
......@@ -49,9 +53,11 @@ namespace castor {
class DiskFileFactory {
typedef castor::tape::utils::Regex Regex;
public:
DiskFileFactory(const std::string & remoteFileProtocol);
DiskFileFactory(const std::string & remoteFileProtocol,
const std::string & xrootPrivateKey);
ReadFile * createReadFile(const std::string & path);
WriteFile * createWriteFile(const std::string & path);
~DiskFileFactory();
private:
Regex m_NoURLLocalFile;
Regex m_NoURLRemoteFile;
......@@ -61,6 +67,15 @@ namespace castor {
Regex m_URLXrootFile;
Regex m_URLCephFile;
std::string m_remoteFileProtocol;
std::auto_ptr<OpenSSLLockerRef> m_openSSLLocker;
std::string m_xrootPrivateKeyFile;
EVP_PKEY *m_xrootOpenSSLPrivateKey;
CryptoPP::RSA::PrivateKey m_xrootCryptoPPPrivateKey;
bool m_xrootCryptoPPPrivateKeyLoaded;
/** Return the private key. Read it from the file if necessary. */
EVP_PKEY* xrootOpenSSLPrivateKey();
const CryptoPP::RSA::PrivateKey & xrootCryptoPPPrivateKey();
};
class ReadFile {
......@@ -77,12 +92,23 @@ namespace castor {
* @param size: size of the buffer
* @return The amount of data actually copied. Zero at end of file.
*/
virtual size_t read(void *data, const size_t size) = 0;
virtual size_t read(void *data, const size_t size) const = 0;
/**
* Destructor of the ReadFile class. It closes the corresponding file descriptor.
*/
virtual ~ReadFile() throw() {}
/**
* File protocol and path for logging
*/
virtual std::string URL() const { return m_URL; }
protected:
/**
* Storage for the URL
*/
std::string m_URL;
};
class WriteFile {
......@@ -103,6 +129,17 @@ namespace castor {
* Destructor of the WriteFile class.
*/
virtual ~WriteFile() throw() {}
/**
* File protocol and path for logging
*/
virtual std::string URL() const { return m_URL; }
protected:
/**
* Storage for the URL
*/
std::string m_URL;
};
} //end of namespace diskFile
......
......@@ -212,7 +212,7 @@ namespace UnitTests {
const uint32_t block_size = 1024;
char data1[block_size];
char data2[block_size];
castor::tape::diskFile::DiskFileFactory fileFactory("RFIO");
castor::tape::diskFile::DiskFileFactory fileFactory("RFIO","");
{
std::auto_ptr<castor::tape::diskFile::ReadFile> rf(
fileFactory.createReadFile("localhost:/etc/fstab"));
......
/******************************************************************************
*
* This file is part of the Castor project.
* See http://castor.web.cern.ch/castor
*
* Copyright (C) 2003 CERN
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
*
*
* @author Castor Dev team, castor-dev@cern.ch
*****************************************************************************/
#include <openssl/crypto.h>
#include "castor/tape/tapeserver/file/OpenSSLLocker.hpp"
#include "castor/server/Mutex.hpp"
#include "castor/server/MutexLocker.hpp"
#include <sys/types.h>
#include <sys/syscall.h>
#include <unistd.h>
#include <vector>
#include "castor/exception/Exception.hpp"
#include "castor/log/SyslogLogger.hpp"
#include <openssl/err.h>
#include <openssl/evp.h>
extern "C" {
void castorTapeOpenSSLLockingCallback(int mode, int n, const char * file, int line);
void castorTapeOpenSSLThreadIdCallback(CRYPTO_THREADID * threadId);
}
namespace castor {
namespace tape {
namespace diskFile {
/**
* A singleton implementing and registering the minimal callbacks for thread
* safe operations of OpenSSL. It is designed to be instantiated late in
* the tape session. The file factory will do it. The class will then
* "register" itself in a static pointer, which is needed as the OpenSSL callbacks
* do not provide a void* context pointer.
*
* We do this so that the main process for not have statically allocated mutexes,
* which could give side effects to initial forking.
*/
class OpenSSLLocker {
public:
OpenSSLLocker () {
if (gOpenSSLLocker) {
throw castor::exception::Exception("Attempt to instantiate several OpenSSLLockers");
} else {
gOpenSSLLocker = this;
}
// In the current implementation of OpenSSL, CRYPTO_num_locks returns
// CRYPTO_NUM_LOCKS, which is 41. a pretty reasonable number.
// Just resize the array
m_mutexes.resize(::CRYPTO_num_locks());
::CRYPTO_set_locking_callback(castorTapeOpenSSLLockingCallback);
::CRYPTO_THREADID_set_callback(castorTapeOpenSSLThreadIdCallback);
// Also load the crypto error messages
::ERR_load_crypto_strings();
}
~OpenSSLLocker() {
// According to Network Security with OpenSSL, Chapter 4, we can unset the
// callbacks
::CRYPTO_THREADID_set_callback(NULL);
::CRYPTO_set_locking_callback(NULL);
// Cleanup OpenSSL's structures
//::CONF_modules_free();
//::ENGINE_cleanup();
//::CONF_modules_unload(1);
::ERR_free_strings();
::EVP_cleanup();
::CRYPTO_cleanup_all_ex_data();
gOpenSSLLocker = NULL;
}
void lockingCallback(int mode, int n, const char * file, int line) throw () {
try {
if (n < 0 || (size_t)n >= m_mutexes.size())
throw castor::exception::Exception("In castor::tape::diskFile::OpenSSLLocker: index overflow");
if (mode & CRYPTO_LOCK) {
m_mutexes[n].lock();
} else {
m_mutexes[n].unlock();
}
} catch (castor::exception::Exception & e) {
// Simple handling for the moment: log and die. IF not sufficient we will
// have to use SSL's error system to push errors to the caller.
// See https://www.openssl.org/docs/crypto/err.html
castor::log::SyslogLogger sl("tapeserverd");
sl(LOG_EMERG, e.what());
abort();
} catch (...) {
castor::log::SyslogLogger sl("tapeserverd");
castor::exception::Exception e("Unknown exception in castor::tape::diskFile::OpenSSLLocker");
sl(LOG_EMERG, e.what());
abort();
}
}
static OpenSSLLocker * gOpenSSLLocker;
static castor::server::Mutex gCreationMutex;
static int gRefCount;
private:
std::vector<castor::server::Mutex> m_mutexes;
};
struct OpenSSLLockerRef {
OpenSSLLockerRef() {
castor::server::MutexLocker ml(&OpenSSLLocker::gCreationMutex);