XRootD
Loading...
Searching...
No Matches
XrdMacaroonsConfigure.cc
Go to the documentation of this file.
1
2#include <fcntl.h>
3#include <cerrno>
4
5#include <openssl/bio.h>
6#include <openssl/evp.h>
7
9#include <XrdSys/XrdSysE2T.hh>
10
12
13
14using namespace Macaroons;
15
16
17static bool xonmissing(XrdOucStream &config_obj, XrdSysError *log, Handler::AuthzBehavior &behavior)
18{
19 char *val = config_obj.GetWord();
20 if (!val || !val[0])
21 {
22 log->Emsg("Config", "macaroons.onmissing requires a value (valid values: passthrough [default], allow, deny)");
23 return false;
24 }
25 if (!strcasecmp(val, "passthrough")) {
26 behavior = Handler::AuthzBehavior::PASSTHROUGH;
27 } else if (!strcasecmp(val, "allow")) {
28 behavior = Handler::AuthzBehavior::ALLOW;
29 } else if (!strcasecmp(val, "deny")) {
30 behavior = Handler::AuthzBehavior::DENY;
31 } else
32 {
33 log->Emsg("Config", "macaroons.onmissing is invalid (valid values: passthrough [default], allow, deny)! Provided value:", val);
34 return false;
35 }
36 return true;
37}
38
39bool Handler::Config(const char *config, XrdOucEnv *env, XrdSysError *log,
40 std::string &location, std::string &secret, ssize_t &max_duration,
41 AuthzBehavior &behavior)
42{
43 XrdOucStream config_obj(log, getenv("XRDINSTANCE"), env, "=====> ");
44
45 // Open and attach the config file
46 //
47 int cfg_fd;
48 if ((cfg_fd = open(config, O_RDONLY, 0)) < 0) {
49 return log->Emsg("Config", errno, "open config file", config);
50 }
51 config_obj.Attach(cfg_fd);
52 static const char *cvec[] = { "*** macaroons plugin config:", 0 };
53 config_obj.Capture(cvec);
54
55 // Set default mask for logging.
57
58 // Set default maximum duration (24 hours).
59 max_duration = 24*3600;
60
61 // Process items
62 //
63 char *orig_var, *var;
64 bool success = true, ismine;
65 while ((orig_var = config_obj.GetMyFirstWord())) {
66 var = orig_var;
67 if ((ismine = !strncmp("all.sitename", var, 12))) var += 4;
68 else if ((ismine = !strncmp("macaroons.", var, 10)) && var[10]) var += 10;
69
70
71
72 if (!ismine) {continue;}
73
74 if (!strcmp("secretkey", var)) {success = xsecretkey(config_obj, log, secret);}
75 else if (!strcmp("sitename", var)) {success = xsitename(config_obj, log, location);}
76 else if (!strcmp("trace", var)) {success = xtrace(config_obj, log);}
77 else if (!strcmp("maxduration", var)) {success = xmaxduration(config_obj, log, max_duration);}
78 else if (!strcmp("onmissing", var)) {success = xonmissing(config_obj, log, behavior);}
79 else {
80 log->Say("Config warning: ignoring unknown directive '", orig_var, "'.");
81 config_obj.Echo();
82 continue;
83 }
84 if (!success) {
85 config_obj.Echo();
86 break;
87 }
88 }
89
90 if (success && !location.size())
91 {
92 log->Emsg("Config", "all.sitename must be specified to use macaroons.");
93 return false;
94 }
95
96 return success;
97}
98
99
100bool Handler::xtrace(XrdOucStream &Config, XrdSysError *log)
101{
102 static struct traceopts { const char *opname; enum LogMask opval; } tropts[] = {
103 { "all", LogMask::All },
104 { "error", LogMask::Error },
105 { "warning", LogMask::Warning },
106 { "info", LogMask::Info },
107 { "debug", LogMask::Debug }
108 };
109
110 int i, neg, trval = 0, numopts = sizeof(tropts)/sizeof(struct traceopts);
111
112 char *val = Config.GetWord();
113
114 if (!val || !*val) {
115 log->Emsg("Config", "macaroons.trace requires at least one directive"
116 " [ all | error | warning | info | debug | none | off ]");
117 return false;
118 }
119
120 while (val && *val) {
121 if (strcmp(val, "off") == 0 || strcmp(val, "none") == 0) {
122 trval = 0;
123 } else {
124 if ((neg = (val[0] == '-' && val[1])))
125 val++;
126 for (i = 0; i < numopts; i++) {
127 if (!strcmp(val, tropts[i].opname)) {
128 if (neg)
129 trval &= ~tropts[i].opval;
130 else
131 trval |= tropts[i].opval;
132 break;
133 }
134 }
135 if (neg) --val;
136 if (i >= numopts)
137 log->Emsg("Config", "macaroons.trace: ignoring invalid trace option:", val);
138 }
139 val = Config.GetWord();
140 }
141
142 log->setMsgMask(trval);
143
144 return true;
145}
146
147bool Handler::xmaxduration(XrdOucStream &config_obj, XrdSysError *log, ssize_t &max_duration)
148{
149 char *val = config_obj.GetWord();
150 if (!val || !val[0])
151 {
152 log->Emsg("Config", "macaroons.maxduration requires a value");
153 return false;
154 }
155 char *endptr = NULL;
156 long int max_duration_parsed = strtoll(val, &endptr, 10);
157 if (endptr == val)
158 {
159 log->Emsg("Config", "Unable to parse macaroons.maxduration as an integer", val);
160 return false;
161 }
162 if (errno != 0)
163 {
164 log->Emsg("Config", errno, "parse macaroons.maxduration as an integer.");
165 }
166 max_duration = max_duration_parsed;
167
168 return true;
169}
170
171bool Handler::xsitename(XrdOucStream &config_obj, XrdSysError *log, std::string &location)
172{
173 char *val = config_obj.GetWord();
174 if (!val || !val[0])
175 {
176 log->Emsg("Config", "all.sitename requires a name");
177 return false;
178 }
179
180 location = val;
181 return true;
182}
183
184bool Handler::xsecretkey(XrdOucStream &config_obj, XrdSysError *log, std::string &secret)
185{
186 char *val = config_obj.GetWord();
187 if (!val || !val[0])
188 {
189 log->Emsg("Config", "Shared secret key not specified");
190 return false;
191 }
192
193 FILE *fp = fopen(val, "rb");
194
195 if (fp == NULL) {
196 log->Emsg("Config", errno, "open shared secret key file", val);
197 return false;
198 }
199
200 BIO *bio, *b64, *bio_out;
201 char inbuf[512];
202 int inlen;
203
204 b64 = BIO_new(BIO_f_base64());
205 if (!b64)
206 {
207 log->Emsg("Config", "Failed to allocate base64 filter");
208 return false;
209 }
210 bio = BIO_new_fp(fp, 0); // fp will be closed when BIO is freed.
211 if (!bio)
212 {
213 BIO_free_all(b64);
214 log->Emsg("Config", "Failed to allocate BIO filter");
215 return false;
216 }
217 bio_out = BIO_new(BIO_s_mem());
218 if (!bio_out)
219 {
220 BIO_free_all(b64);
221 BIO_free_all(bio);
222 log->Emsg("Config", "Failed to allocate BIO output");
223 return false;
224 }
225
226 BIO_push(b64, bio);
227 while ((inlen = BIO_read(b64, inbuf, 512)) > 0)
228 {
229 if (inlen < 0) {
230 if (errno == EINTR) continue;
231 break;
232 } else {
233 BIO_write(bio_out, inbuf, inlen);
234 }
235 }
236 if (inlen < 0) {
237 BIO_free_all(b64);
238 BIO_free_all(bio_out);
239 log->Emsg("Config", errno, "read secret key.");
240 return false;
241 }
242 if (!BIO_flush(bio_out)) {
243 BIO_free_all(b64);
244 BIO_free_all(bio_out);
245 log->Emsg("Config", errno, "flush secret key.");
246 return false;
247 }
248
249 char *decoded;
250 long data_len = BIO_get_mem_data(bio_out, &decoded);
251 BIO_free_all(b64);
252
253 secret = std::string(decoded, data_len);
254
255 BIO_free_all(bio_out);
256
257 if (secret.size() < 32) {
258 log->Emsg("Config", "Secret key is too short; must be 32 bytes long. Try running 'openssl rand -base64 -out", val, "64' to generate a new key");
259 return false;
260 }
261
262 return true;
263}
static bool xonmissing(XrdOucStream &config_obj, XrdSysError *log, Handler::AuthzBehavior &behavior)
#define fopen(a, b)
Definition XrdPosix.hh:54
#define open
Definition XrdPosix.hh:76
static bool Config(const char *config, XrdOucEnv *env, XrdSysError *log, std::string &location, std::string &secret, ssize_t &max_duration, AuthzBehavior &behavior)
char * GetMyFirstWord(int lowcase=0)
char * GetWord(int lowcase=0)
int Attach(int FileDescriptor, int bsz=2047)
static void Capture(const char **cVec=0, bool linefeed=true)
int Emsg(const char *esfx, int ecode, const char *text1, const char *text2=0)
void Say(const char *text1, const char *text2=0, const char *txt3=0, const char *text4=0, const char *text5=0, const char *txt6=0)
void setMsgMask(int mask)