5 #define __STDC_FORMAT_MACROS
38 const string &progname,
39 const string &search_path,
43 , search_path_(search_path)
68 const int retval = pthread_mutex_destroy(&
lock_);
74 Send(
string(
"{\"cvmfs_authz_v1\":{") +
"\"msgid\":"
96 retval = waitpid(
pid_, &statloc, WNOHANG);
99 "authz helper %s unresponsive, killing",
progname_.c_str());
100 retval = kill(
pid_, SIGKILL);
103 (void)waitpid(
pid_, &statloc, 0);
106 (void)waitpid(
pid_, &statloc, WNOHANG);
110 }
while (retval == 0);
118 "authz helper %s enters fail state, no more authorization",
142 char *argv[] = {argv0, NULL};
144 const bool strip_prefix =
true;
146 "CVMFS_AUTHZ_", strip_prefix);
148 for (
unsigned i = 0; i < authz_env.size(); ++i)
149 envp.push_back(
strdupa(authz_env[i].c_str()));
150 envp.push_back(
strdupa(
"CVMFS_AUTHZ_HELPER=yes"));
151 envp.push_back(NULL);
154 int max_fd = sysconf(_SC_OPEN_MAX);
157 std::vector<int> open_fds;
158 DIR *dirp = opendir(
"/proc/self/fd");
162 const std::string name(dirent->d_name);
163 uint64_t name_uint64;
169 open_fds.push_back(static_cast<int>(name_uint64));
176 const pid_t pid = fork();
179 int retval = dup2(pipe_send[0], 0);
181 retval = dup2(pipe_recv[1], 1);
184 for (
int fd = 2; fd < max_fd; fd++)
187 for (
unsigned i = 0; i < open_fds.size(); ++i)
193 struct sigaction signal_handler;
194 signal_handler.sa_handler = SIG_DFL;
198 execve(argv0, argv, &envp[0]);
199 syslog(LOG_USER | LOG_ERR,
"failed to start authz helper %s (%d)", argv0,
208 signal(SIGPIPE, SIG_IGN);
243 string pure_membership;
245 string json_msg = string(
"{\"cvmfs_authz_v1\":{") +
"\"msgid\":"
250 +
"\"membership\":\"" +
Base64(pure_membership) +
"\"}}";
251 retval =
Send(json_msg) &&
Recv(&json_msg);
272 string pure_membership;
275 if (!sanitizer.
IsValid(authz_schema)) {
277 authz_schema.c_str());
281 string exe_path =
search_path_ +
"/cvmfs_" + authz_schema +
"_helper";
295 string json_debug_log;
297 json_debug_log =
",\"debug_log\":\"" + debug_log +
"\"";
298 string json_msg = string(
"{") +
"\"cvmfs_authz_v1\":{"
299 +
"\"msgid\":" +
StringifyInt(0) +
"," +
"\"revision\":0,"
300 +
"\"fqrn\":\"" +
fqrn_ +
"\"," +
"\"syslog_facility\":"
303 + json_debug_log +
"}}";
304 bool retval =
Send(json_msg);
308 retval =
Recv(&json_msg);
321 const int retval = pthread_mutex_init(&
lock_, NULL);
333 header.length = msg.length();
334 const unsigned raw_length =
sizeof(header) + msg.length();
335 unsigned char *raw_msg =
reinterpret_cast<unsigned char *
>(
337 memcpy(raw_msg, &header,
sizeof(header));
338 memcpy(raw_msg +
sizeof(header), msg.data(), header.length);
363 assert(binary_msg != NULL);
366 if (!json_document.
IsValid()) {
368 "invalid json from authz helper %s: %s",
progname_.c_str(),
375 json_document->
root(),
"cvmfs_authz_v1", JSON_OBJECT);
376 if (json_authz == NULL) {
378 "\"cvmfs_authz_v1\" not found in json from authz helper %s: %s",
385 || (binary_msg->
msgid != expected_msgid)) {
407 if (json_msgid == NULL) {
409 "\"msgid\" not found in json from authz helper %s",
415 if ((json_msgid->int_value < 0)
418 "invalid \"msgid\" in json from authz helper %s: %d",
419 progname_.c_str(), json_msgid->int_value);
437 if (json_status == NULL) {
439 "\"status\" not found in json from authz helper %s",
444 if ((json_status->int_value < 0)
449 json_status->int_value);
453 if (json_ttl == NULL) {
462 if (json_token != NULL) {
465 const bool valid_base64 =
Debase64(json_token->string_value, &token_binary);
468 "invalid Base64 in 'x509_proxy' from authz helper %s",
473 const unsigned size = token_binary.size();
485 if (json_token != NULL) {
487 const unsigned size = strlen(json_token->string_value);
496 "Got a bearer_token from authz_helper. "
497 "Setting token type to kTokenBearer");
501 "bearer_token was in returned JSON from Authz helper,"
502 " but of size 0 from authz helper %s",
511 "No auth token found in returned JSON from Authz helper %s",
523 if (json_revision == NULL) {
525 "\"revision\" not found in json from authz helper %s",
531 if (json_revision->int_value < 0) {
533 "invalid \"revision\" in json from authz helper %s: %d",
534 progname_.c_str(), json_revision->int_value);
547 if (retval != static_cast<int>(
sizeof(version))) {
553 "authz helper uses unknown protocol version %u", version);
560 if (retval != static_cast<int>(
sizeof(length))) {
568 while (nbytes < length) {
569 const unsigned remaining = length - nbytes;
573 "read failure from authz helper %s",
progname_.c_str());
578 msg->append(buf, retval);
586 string *authz_schema,
587 string *pure_membership) {
588 vector<string> components =
SplitString(membership,
'%');
589 *authz_schema = components[0];
590 if (components.size() < 2) {
593 *pure_membership =
"";
597 components.erase(components.begin());
AuthzExternalMsgIds msgid
AuthzExternalFetcher(const std::string &fqrn, const std::string &progname, const std::string &search_path, OptionsManager *options_manager)
static JSON * SearchInObject(const JSON *json_object, const std::string &name, const json_type type)
static const unsigned kChildTimeout
string JoinStrings(const vector< string > &strings, const string &joint)
Helper: "I verified, cvmfs, here's the result".
void StripAuthzSchema(const std::string &membership, std::string *authz_schema, std::string *pure_membership)
std::vector< std::string > GetEnvironmentSubset(const std::string &key_prefix, bool strip_prefix)
bool SafeWrite(int fd, const void *buf, size_t nbyte)
assert((mem||(size==0))&&"Out Of Memory")
bool Debase64(const string &data, string *decoded)
void MakePipe(int pipe_fd[2])
bool ParseMsgId(JSON *json_authz, AuthzExternalMsg *binary_msg)
static const uint32_t kProtocolVersion
Helper: "Yes, cvmfs, I'm here".
bool String2Uint64Parse(const std::string &value, uint64_t *result)
OptionsManager * options_manager_
bool ParsePermit(JSON *json_authz, AuthzExternalMsg *binary_msg)
bool FileExists(const std::string &path)
bool Recv(std::string *msg)
#define GetLogDebugFile()
ssize_t SafeRead(int fd, void *buf, size_t nbyte)
static JsonDocument * Create(const std::string &text)
vector< string > SplitString(const string &str, char delim)
static int g_suppressed_signals[13]
std::string FindHelper(const std::string &membership)
Cvmfs: "Please verify, helper".
string StringifyInt(const int64_t value)
struct AuthzExternalMsg::@0 permit
bool ParseRevision(JSON *json_authz, AuthzExternalMsg *binary_msg)
virtual ~AuthzExternalFetcher()
virtual AuthzStatus Fetch(const QueryInfo &query_info, AuthzToken *authz_token, unsigned *ttl)
bool ParseMsg(const std::string &json_msg, const AuthzExternalMsgIds expected_msgid, AuthzExternalMsg *binary_msg)
bool Send(const std::string &msg)
string Base64(const string &data)
BashOptionsManager options_manager_
Cvmfs: "Please shutdown, helper".
static const unsigned kDefaultTtl
First invalid message id.
const JSON * root() const
int GetLogSyslogFacility()
CVMFS_EXPORT void LogCvmfs(const LogSource source, const int mask, const char *format,...)