Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Overhaul curl's usage of CAs. #1431

Merged
merged 18 commits into from
Apr 14, 2021
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
18 commits
Select commit Hold shift + click to select a range
5e31d97
Overhaul curl's usage of CAs.
bbockelm Mar 18, 2021
75f631e
Add support for certfile directive for TPC handler.
bbockelm Mar 18, 2021
c84668f
Provide a pure-environment override for the XrdTpc cadir.
bbockelm Mar 18, 2021
399d5a7
XrdTpc: Switch update variables to std::atomics.
bbockelm Mar 19, 2021
1fe8f5d
XrdTpc: Remove deprecated readdir_r.
bbockelm Mar 19, 2021
5793ac7
Remove use of smart pointers.
bbockelm Mar 25, 2021
97deb89
XrdTpc: Pass filename to parsing / exporting functions.
bbockelm Mar 28, 2021
2719b4b
XrdTpc: Use XrdSysFD functions where possible for CLOEXEC protection.
bbockelm Mar 28, 2021
380f476
XrdTpc: If NSS hack is needed and fails, do not startup server.
bbockelm Mar 28, 2021
5f49669
XrdTls: Move temp CA generator code into core XrdTls.
bbockelm Mar 28, 2021
ab5fad4
XrdTpc: Remove XrdTpcNSSSupport implementation.
bbockelm Mar 28, 2021
1eb60a5
XrdTls: HACK - temporarily link crypto files into XrdUtils.
bbockelm Mar 28, 2021
c3dc4c1
XrdTls: Extend XrdCryptosslX509Crl to load / write CRLs to a FILE*
bbockelm Mar 28, 2021
342ba6c
XrdTls: HACK - add CRLs to XrdUtils. Revert when we understand linki…
bbockelm Mar 28, 2021
399fc03
XrdTls: Add CRL concatenation support to TempCA manager.
bbockelm Mar 28, 2021
7d3a823
XrdTls: Remove XrdTlsTempCA from its dedicated namespace.
bbockelm Mar 30, 2021
639e6e3
XrdTls: Convert TempCA loader to a separate thread.
bbockelm Apr 4, 2021
87b341c
XrdTls: Refactor temp CA code to use ADMINPATH directory.
bbockelm Apr 13, 2021
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
105 changes: 88 additions & 17 deletions src/XrdTls/XrdTlsTempCA.cc
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
#include <stdlib.h>
#include <fcntl.h>
#include <dirent.h>
#include <sys/poll.h>

#include <unordered_set>
#include <memory>
Expand All @@ -49,7 +50,15 @@
namespace {

typedef std::unique_ptr<FILE, decltype(&fclose)> file_smart_ptr;



static uint64_t monotonic_time_s() {
struct timespec tp;
clock_gettime(CLOCK_MONOTONIC, &tp);
return tp.tv_sec + (tp.tv_nsec >= 500000000);
}


class CASet {
public:
CASet(int output_fd, XrdSysError &err)
Expand Down Expand Up @@ -234,7 +243,48 @@ XrdTlsTempCA::XrdTlsTempCA(XrdSysError *err, std::string ca_dir)
: m_log(*err),
m_ca_dir(ca_dir)
{
Maintenance();
// Setup communication pipes; we write one byte to the child to tell it to shutdown;
// it'll write one byte back to acknowledge before our destructor exits.
int pipes[2];
if (-1 == XrdSysFD_Pipe(pipes)) {
m_log.Emsg("XrdTlsTempCA", "Failed to create communication pipes", strerror(errno));
return;
}
m_maintenance_pipe_r = pipes[0];
m_maintenance_pipe_w = pipes[1];
if (-1 == XrdSysFD_Pipe(pipes)) {
m_log.Emsg("XrdTlsTempCA", "Failed to create communication pipes", strerror(errno));
return;
}
m_maintenance_thread_pipe_r = pipes[0];
m_maintenance_thread_pipe_w = pipes[1];
if (!Maintenance()) {return;}

pthread_t tid;
auto rc = XrdSysThread::Run(&tid, XrdTlsTempCA::MaintenanceThread,
static_cast<void*>(this), 0, "CA/CRL refresh");
if (rc) {
m_log.Emsg("XrdTlsTempCA", "Failed to launch CA monitoring thread");
m_ca_file.reset();
}
}


XrdTlsTempCA::~XrdTlsTempCA()
{
char indicator[1];
if (m_maintenance_pipe_w >= 0) {
indicator[0] = '1';
int rval;
do {rval = write(m_maintenance_pipe_w, indicator, 1);} while (rval != -1 || errno == EINTR);
if (m_maintenance_thread_pipe_r >= 0) {
do {rval = read(m_maintenance_thread_pipe_r, indicator, 1);} while (rval != -1 || errno == EINTR);
close(m_maintenance_thread_pipe_r);
close(m_maintenance_thread_pipe_w);
}
close(m_maintenance_pipe_r);
close(m_maintenance_pipe_w);
}
}


Expand Down Expand Up @@ -291,25 +341,46 @@ XrdTlsTempCA::Maintenance()
}
closedir(dirp);

m_next_update.store(time(NULL) + 900, std::memory_order_relaxed);
m_ca_file.reset(new_file.release());
return true;
}


bool
XrdTlsTempCA::NeedsMaintenance()
{
return time(NULL) > m_next_update.load(std::memory_order_relaxed);
}


std::shared_ptr<XrdTlsTempCA::TempCAGuard>
XrdTlsTempCA::getHandle()
void *XrdTlsTempCA::MaintenanceThread(void *myself_raw)
{
if (NeedsMaintenance()) {
Maintenance();
}

return m_ca_file;
auto myself = static_cast<XrdTlsTempCA *>(myself_raw);

auto now = monotonic_time_s();
auto next_update = now + m_update_interval;
while (true) {
now = monotonic_time_s();
auto remaining = next_update - now;
struct pollfd fds;
fds.fd = myself->m_maintenance_pipe_r;
fds.events = POLLIN;
auto rval = poll(&fds, 1, remaining*1000);
if (rval == -1) {
if (rval == EINTR) continue;
else break;
} else if (rval == 0) { // timeout! Let's run maintenance.
if (myself->Maintenance()) {
next_update = monotonic_time_s() + m_update_interval;
} else {
next_update = monotonic_time_s() + m_update_interval_failure;
}
} else { // FD ready; let's shutdown
if (fds.revents & POLLIN) {
char indicator[1];
do {rval = read(myself->m_maintenance_pipe_r, indicator, 1);} while (rval != -1 || errno == EINTR);
}
}
}
if (errno) {
myself->m_log.Emsg("Maintenance", "Failed to poll for events from parent object");
}
char indicator = '1';
int rval;
do {rval = write(myself->m_maintenance_thread_pipe_w, &indicator, 1);} while (rval != -1 || errno == EINTR);

return nullptr;
}
23 changes: 17 additions & 6 deletions src/XrdTls/XrdTlsTempCA.hh
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,6 @@
/* specific prior written permission of the institution or contributor. */
/******************************************************************************/

#include <atomic>
#include <string>
#include <memory>

Expand All @@ -46,14 +45,15 @@ public:
class TempCAGuard;

XrdTlsTempCA(XrdSysError *log, std::string ca_dir);
~XrdTlsTempCA();

/**
* Return a handle to the current CA file. The shared_ptr
* *must* be kept alive while the CA file is in use; if it
* goes out of scope, the corresponding temporary file may
* be garbage collected.
*/
std::shared_ptr<TempCAGuard> getHandle();
std::shared_ptr<TempCAGuard> getHandle() {return m_ca_file;}

/**
* Returns true if object is valid.
Expand Down Expand Up @@ -97,13 +97,24 @@ private:
bool Maintenance();

/**
* Returns true if we need to run the CA maintenance
* routine.
* Thread managing the invocation of the CA maintenance routines
*/
bool NeedsMaintenance();
static void *MaintenanceThread(void *myself_raw);

std::atomic<time_t> m_next_update{0};
/**
* Read and write ends of a pipe to communicate between the parent
* object and the maintenance thread.
*/
int m_maintenance_pipe_r{-1};
int m_maintenance_pipe_w{-1};
int m_maintenance_thread_pipe_r{-1};
int m_maintenance_thread_pipe_w{-1};
XrdSysError &m_log;
const std::string m_ca_dir;
std::shared_ptr<TempCAGuard> m_ca_file;

// After success, how long to wait until the next CA reload.
static constexpr unsigned m_update_interval = 900;
// After failure, how long to wait until the next CA reload.
static constexpr unsigned m_update_interval_failure = 10;
};