| 1 |  |  | /** | 
    
    | 2 |  |  |  * This file is part of the CernVM File System. | 
    
    | 3 |  |  |  */ | 
    
    | 4 |  |  |  | 
    
    | 5 |  |  | #include "helper_util.h" | 
    
    | 6 |  |  |  | 
    
    | 7 |  |  | #include <alloca.h> | 
    
    | 8 |  |  | #include <errno.h> | 
    
    | 9 |  |  | #include <stdint.h> | 
    
    | 10 |  |  | #include <unistd.h> | 
    
    | 11 |  |  |  | 
    
    | 12 |  |  | #include <cassert> | 
    
    | 13 |  |  | #include <cstdio> | 
    
    | 14 |  |  | #include <cstdlib> | 
    
    | 15 |  |  | #include <cstring> | 
    
    | 16 |  |  |  | 
    
    | 17 |  |  | #include "authz/helper_log.h" | 
    
    | 18 |  |  | #include "json.h" | 
    
    | 19 |  |  | typedef struct json_value JSON; | 
    
    | 20 |  |  |  | 
    
    | 21 |  |  | #ifdef __APPLE__ | 
    
    | 22 |  |  | #define strdupa(s) strcpy(/* NOLINT(runtime/printf) */\ | 
    
    | 23 |  |  |   reinterpret_cast<char *>(alloca(strlen((s)) + 1)), (s)) | 
    
    | 24 |  |  | #endif | 
    
    | 25 |  |  |  | 
    
    | 26 |  |  | using namespace std;  // NOLINT | 
    
    | 27 |  |  |  | 
    
    | 28 |  |  | /** | 
    
    | 29 |  |  |  * Helper binaries are supposed to be called from the cvmfs client, not | 
    
    | 30 |  |  |  * stand-alone. | 
    
    | 31 |  |  |  */ | 
    
    | 32 |  |  | void CheckCallContext() { | 
    
    | 33 |  |  |   if (getenv("CVMFS_AUTHZ_HELPER") == NULL) { | 
    
    | 34 |  |  |     printf("This program is supposed to be called from the CernVM-FS client."); | 
    
    | 35 |  |  |     printf("\n"); | 
    
    | 36 |  |  |     abort(); | 
    
    | 37 |  |  |   } | 
    
    | 38 |  |  | } | 
    
    | 39 |  |  |  | 
    
    | 40 |  |  |  | 
    
    | 41 |  |  | void ParseHandshakeInit(const string &msg) { | 
    
    | 42 |  |  |   block_allocator allocator(2048); | 
    
    | 43 |  |  |   char *err_pos; char *err_desc; int err_line; | 
    
    | 44 |  |  |   JSON *json = json_parse(strdupa(msg.c_str()), | 
    
    | 45 |  |  |                           &err_pos, &err_desc, &err_line, | 
    
    | 46 |  |  |                           &allocator); | 
    
    | 47 |  |  |   assert((json != NULL) && (json->first_child != NULL)); | 
    
    | 48 |  |  |   json = json->first_child; | 
    
    | 49 |  |  |   assert((string(json->name) == "cvmfs_authz_v1")); | 
    
    | 50 |  |  |   json = json->first_child; | 
    
    | 51 |  |  |   while (json) { | 
    
    | 52 |  |  |     string name(json->name); | 
    
    | 53 |  |  |     if (name == "debug_log") { | 
    
    | 54 |  |  |       SetLogAuthzDebug(string(json->string_value) + ".authz"); | 
    
    | 55 |  |  |     } else if (name == "fqrn") { | 
    
    | 56 |  |  |       LogAuthz(kLogAuthzDebug, "fqrn is %s", json->string_value); | 
    
    | 57 |  |  |       SetLogAuthzSyslogPrefix(string(json->string_value)); | 
    
    | 58 |  |  |     } else if (name == "syslog_level") { | 
    
    | 59 |  |  |       SetLogAuthzSyslogLevel(json->int_value); | 
    
    | 60 |  |  |     } else if (name == "syslog_facility") { | 
    
    | 61 |  |  |       SetLogAuthzSyslogFacility(json->int_value); | 
    
    | 62 |  |  |     } | 
    
    | 63 |  |  |     json = json->next_sibling; | 
    
    | 64 |  |  |   } | 
    
    | 65 |  |  | } | 
    
    | 66 |  |  |  | 
    
    | 67 |  |  |  | 
    
    | 68 |  |  | void ParseRequest(const string &msg) { | 
    
    | 69 |  |  |   block_allocator allocator(2048); | 
    
    | 70 |  |  |   char *err_pos; char *err_desc; int err_line; | 
    
    | 71 |  |  |   JSON *json = json_parse(strdupa(msg.c_str()), | 
    
    | 72 |  |  |                           &err_pos, &err_desc, &err_line, | 
    
    | 73 |  |  |                           &allocator); | 
    
    | 74 |  |  |   assert((json != NULL) && (json->first_child != NULL)); | 
    
    | 75 |  |  |   json = json->first_child; | 
    
    | 76 |  |  |   assert((string(json->name) == "cvmfs_authz_v1")); | 
    
    | 77 |  |  |   json = json->first_child; | 
    
    | 78 |  |  |   while (json) { | 
    
    | 79 |  |  |     string name(json->name); | 
    
    | 80 |  |  |     if (name == "msgid") { | 
    
    | 81 |  |  |       if (json->int_value == 4) {  /* kAuthzMsgQuit */ | 
    
    | 82 |  |  |         LogAuthz(kLogAuthzDebug, "shut down"); | 
    
    | 83 |  |  |         exit(0); | 
    
    | 84 |  |  |       } | 
    
    | 85 |  |  |     } | 
    
    | 86 |  |  |     json = json->next_sibling; | 
    
    | 87 |  |  |   } | 
    
    | 88 |  |  | } | 
    
    | 89 |  |  |  | 
    
    | 90 |  |  |  | 
    
    | 91 |  |  | /** | 
    
    | 92 |  |  |  * Get bytes from stdin. | 
    
    | 93 |  |  |  */ | 
    
    | 94 |  |  | static void Read(void *buf, size_t nbyte) { | 
    
    | 95 |  |  |   int num_bytes; | 
    
    | 96 |  |  |   do { | 
    
    | 97 |  |  |     num_bytes = read(fileno(stdin), buf, nbyte); | 
    
    | 98 |  |  |   } while ((num_bytes < 0) && (errno == EINTR)); | 
    
    | 99 |  |  |   assert((num_bytes >= 0) && (static_cast<size_t>(num_bytes) == nbyte)); | 
    
    | 100 |  |  | } | 
    
    | 101 |  |  |  | 
    
    | 102 |  |  |  | 
    
    | 103 |  |  | /** | 
    
    | 104 |  |  |  * Reads a complete message from the cvmfs client. | 
    
    | 105 |  |  |  */ | 
    
    | 106 |  |  | string ReadMsg() { | 
    
    | 107 |  |  |   uint32_t version; | 
    
    | 108 |  |  |   uint32_t length; | 
    
    | 109 |  |  |   Read(&version, sizeof(version)); | 
    
    | 110 |  |  |   assert(version == kProtocolVersion); | 
    
    | 111 |  |  |   Read(&length, sizeof(length)); | 
    
    | 112 |  |  |   if (length == 0) | 
    
    | 113 |  |  |     return ""; | 
    
    | 114 |  |  |   char *buf = reinterpret_cast<char *>(alloca(length)); | 
    
    | 115 |  |  |   Read(buf, length); | 
    
    | 116 |  |  |   return string(buf, length); | 
    
    | 117 |  |  | } | 
    
    | 118 |  |  |  | 
    
    | 119 |  |  |  | 
    
    | 120 |  |  | /** | 
    
    | 121 |  |  |  * Send bytes to stdout. | 
    
    | 122 |  |  |  */ | 
    
    | 123 |  |  | static void Write(const void *buf, size_t nbyte) { | 
    
    | 124 |  |  |   int num_bytes; | 
    
    | 125 |  |  |   do { | 
    
    | 126 |  |  |     num_bytes = write(fileno(stdout), buf, nbyte); | 
    
    | 127 |  |  |   } while ((num_bytes < 0) && (errno == EINTR)); | 
    
    | 128 |  |  |   assert((num_bytes >= 0) && (static_cast<size_t>(num_bytes) == nbyte)); | 
    
    | 129 |  |  | } | 
    
    | 130 |  |  |  | 
    
    | 131 |  |  |  | 
    
    | 132 |  |  | /** | 
    
    | 133 |  |  |  * Sends a (JSON formatted) message back to the cvmfs client. | 
    
    | 134 |  |  |  */ | 
    
    | 135 |  |  | void WriteMsg(const string &msg) { | 
    
    | 136 |  |  |   struct { | 
    
    | 137 |  |  |     uint32_t version; | 
    
    | 138 |  |  |     uint32_t length; | 
    
    | 139 |  |  |   } header; | 
    
    | 140 |  |  |   header.version = kProtocolVersion; | 
    
    | 141 |  |  |   header.length = msg.length(); | 
    
    | 142 |  |  |   Write(&header, sizeof(header)); | 
    
    | 143 |  |  |   Write(msg.data(), header.length); | 
    
    | 144 |  |  | } |