XRootD
Macaroons::Authz Class Referencefinal

#include <XrdMacaroonsAuthz.hh>

+ Inheritance diagram for Macaroons::Authz:
+ Collaboration diagram for Macaroons::Authz:

Public Member Functions

 Authz (XrdSysLogger *lp, const char *parms, XrdAccAuthorize *chain)
 
virtual ~Authz ()
 
virtual XrdAccPrivs Access (const XrdSecEntity *Entity, const char *path, const Access_Operation oper, XrdOucEnv *env) override
 
virtual int Audit (const int accok, const XrdSecEntity *Entity, const char *path, const Access_Operation oper, XrdOucEnv *Env) override
 
virtual Issuers IssuerList () override
 
virtual int Test (const XrdAccPrivs priv, const Access_Operation oper) override
 
virtual bool Validate (const char *token, std::string &emsg, long long *expT, XrdSecEntity *entP) override
 
- Public Member Functions inherited from XrdAccAuthorize
 XrdAccAuthorize ()
 Constructor. More...
 
virtual ~XrdAccAuthorize ()
 Destructor. More...
 
virtual XrdAccPrivs Access (const XrdSecEntity *Entity, const char *path, const Access_Operation oper, std::string &eInfo, XrdOucEnv *Env=0)
 
- Public Member Functions inherited from XrdSciTokensHelper
 XrdSciTokensHelper ()
 Constructor and Destructor. More...
 
virtual ~XrdSciTokensHelper ()
 

Additional Inherited Members

- Public Types inherited from XrdSciTokensHelper
typedef std::vector< ValidIssuer > Issuers
 

Detailed Description

Definition at line 7 of file XrdMacaroonsAuthz.hh.

Constructor & Destructor Documentation

◆ Authz()

Authz::Authz ( XrdSysLogger *  lp,
const char *  parms,
XrdAccAuthorize *  chain 
)

Definition at line 133 of file XrdMacaroonsAuthz.cc.

134  : m_max_duration(86400),
135  m_chain(chain),
136  m_log(log, "macarons_"),
137  m_authz_behavior(static_cast<int>(Handler::AuthzBehavior::PASSTHROUGH))
138 {
139  Handler::AuthzBehavior behavior(Handler::AuthzBehavior::PASSTHROUGH);
140  XrdOucEnv env;
141  if (!Handler::Config(config, &env, &m_log, m_location, m_secret, m_max_duration, behavior))
142  {
143  throw std::runtime_error("Macaroon authorization config failed.");
144  }
145  m_authz_behavior = static_cast<int>(behavior);
146 }
static bool Config(const char *config, XrdOucEnv *env, XrdSysError *log, std::string &location, std::string &secret, ssize_t &max_duration, AuthzBehavior &behavior)

References Macaroons::Handler::Config().

+ Here is the call graph for this function:

◆ ~Authz()

virtual Macaroons::Authz::~Authz ( )
inlinevirtual

Definition at line 12 of file XrdMacaroonsAuthz.hh.

12 {}

Member Function Documentation

◆ Access()

XrdAccPrivs Authz::Access ( const XrdSecEntity *  Entity,
const char *  path,
const Access_Operation  oper,
XrdOucEnv *  Env 
)
overridevirtual

Check whether or not the client is permitted specified access to a path.

Parameters
Entity-> Authentication information
path-> The logical path which is the target of oper
oper-> The operation being attempted (see the enum above). If the oper is AOP_Any, then the actual privileges are returned and the caller may make subsequent tests using Test().
Env-> Environmental information at the time of the operation as supplied by the path CGI string. This is optional and the pointer may be zero.
Returns
Permit: a non-zero value (access is permitted) Deny: zero (access is denied)

Implements XrdAccAuthorize.

Definition at line 165 of file XrdMacaroonsAuthz.cc.

167 {
168  // We don't allow any testing to occur in this authz module, preventing
169  // a macaroon to be used to receive further macaroons.
170  if (oper == AOP_Any)
171  {
172  return m_chain ? m_chain->Access(Entity, path, oper, env) : XrdAccPriv_None;
173  }
174 
175  const char *authz = env ? env->Get("authz") : nullptr;
176  if (authz && !strncmp(authz, "Bearer%20", 9))
177  {
178  authz += 9;
179  }
180  else if (!authz && (authz = env ? env->Get("access_token") : nullptr) && !strncmp(authz, "Bearer%20", 9))
181  {
182  authz += 9;
183  }
184 
185  // If there's no request-specific token, check for a ZTN session token
186  if (!authz && Entity && !strcmp("ztn", Entity->prot) && Entity->creds &&
187  Entity->credslen && Entity->creds[Entity->credslen] == '\0')
188  {
189  authz = Entity->creds;
190  }
191 
192  if (!authz) {
193  return OnMissing(Entity, path, oper, env);
194  }
195 
196  macaroon_returncode mac_err = MACAROON_SUCCESS;
197  struct macaroon* macaroon = macaroon_deserialize(
198  authz,
199  &mac_err);
200  if (!macaroon)
201  {
202  // Do not log - might be other token type!
203  //m_log.Emsg("Access", "Failed to parse the macaroon");
204  return OnMissing(Entity, path, oper, env);
205  }
206 
207  struct macaroon_verifier *verifier = macaroon_verifier_create();
208  if (!verifier)
209  {
210  m_log.Emsg("Access", "Failed to create a new macaroon verifier");
211  return XrdAccPriv_None;
212  }
213  if (!path)
214  {
215  m_log.Emsg("Access", "Request with no provided path.");
216  macaroon_verifier_destroy(verifier);
217  return XrdAccPriv_None;
218  }
219 
220  AuthzCheck check_helper(path, oper, m_max_duration, m_log);
221 
222  if (macaroon_verifier_satisfy_general(verifier, AuthzCheck::verify_before_s, &check_helper, &mac_err) ||
223  macaroon_verifier_satisfy_general(verifier, AuthzCheck::verify_activity_s, &check_helper, &mac_err) ||
224  macaroon_verifier_satisfy_general(verifier, AuthzCheck::verify_name_s, &check_helper, &mac_err) ||
225  macaroon_verifier_satisfy_general(verifier, AuthzCheck::verify_path_s, &check_helper, &mac_err))
226  {
227  m_log.Emsg("Access", "Failed to configure caveat verifier:");
228  macaroon_verifier_destroy(verifier);
229  return XrdAccPriv_None;
230  }
231 
232  const unsigned char *macaroon_loc;
233  size_t location_sz;
234  macaroon_location(macaroon, &macaroon_loc, &location_sz);
235  if (strncmp(reinterpret_cast<const char *>(macaroon_loc), m_location.c_str(), location_sz))
236  {
237  std::string location_str(reinterpret_cast<const char *>(macaroon_loc), location_sz);
238  m_log.Emsg("Access", "Macaroon is for incorrect location", location_str.c_str());
239  macaroon_verifier_destroy(verifier);
240  macaroon_destroy(macaroon);
241  return m_chain ? m_chain->Access(Entity, path, oper, env) : XrdAccPriv_None;
242  }
243 
244  if (macaroon_verify(verifier, macaroon,
245  reinterpret_cast<const unsigned char *>(m_secret.c_str()),
246  m_secret.size(),
247  nullptr, 0, // discharge macaroons
248  &mac_err))
249  {
250  m_log.Log(LogMask::Debug, "Access", "Macaroon verification failed");
251  macaroon_verifier_destroy(verifier);
252  macaroon_destroy(macaroon);
253  // This token is from our server (location matched) but caveats or HMAC
254  // failed. Falling through to the chain would let a path-restricted
255  // macaroon bypass its own restrictions. Deny unconditionally.
256  return XrdAccPriv_None;
257  }
258  macaroon_verifier_destroy(verifier);
259 
260  const unsigned char *macaroon_id;
261  size_t id_sz;
262  macaroon_identifier(macaroon, &macaroon_id, &id_sz);
263 
264  std::string macaroon_id_str(reinterpret_cast<const char *>(macaroon_id), id_sz);
265  m_log.Log(LogMask::Info, "Access", "Macaroon verification successful; ID", macaroon_id_str.c_str());
266  macaroon_destroy(macaroon);
267 
268  // Copy the name, if present into the macaroon, into the credential object.
269  if (Entity && check_helper.GetSecName().size()) {
270  const std::string &username = check_helper.GetSecName();
271  m_log.Log(LogMask::Debug, "Access", "Setting the request name to", username.c_str());
272  Entity->eaAPI->Add("request.name", username,true);
273  }
274 
275  // We passed verification - give the correct privilege.
276  return AddPriv(oper, XrdAccPriv_None);
277 }
@ AOP_Any
Special for getting privs.
@ XrdAccPriv_None
Definition: XrdAccPrivs.hh:55
bool Debug
virtual XrdAccPrivs Access(const XrdSecEntity *Entity, const char *path, const Access_Operation oper, XrdOucEnv *Env=0)=0
bool Add(XrdSecAttr &attr)
int credslen
Length of the 'creds' data.
Definition: XrdSecEntity.hh:78
XrdSecEntityAttr * eaAPI
non-const API to attributes
Definition: XrdSecEntity.hh:92
char prot[XrdSecPROTOIDSIZE]
Auth protocol used (e.g. krb5)
Definition: XrdSecEntity.hh:67
char * creds
Raw entity credentials or cert.
Definition: XrdSecEntity.hh:77
int Emsg(const char *esfx, int ecode, const char *text1, const char *text2=0)
Definition: XrdSysError.cc:116
void Log(int mask, const char *esfx, const char *text1, const char *text2=0, const char *text3=0)
Definition: XrdSysError.hh:167

References XrdAccAuthorize::Access(), XrdSecEntityAttr::Add(), AOP_Any, XrdSecEntity::creds, XrdSecEntity::credslen, Debug, XrdSecEntity::eaAPI, XrdSysError::Emsg(), XrdOucEnv::Get(), TPC::Info, XrdSysError::Log(), XrdSecEntity::prot, and XrdAccPriv_None.

+ Here is the call graph for this function:

◆ Audit()

virtual int Macaroons::Authz::Audit ( const int  accok,
const XrdSecEntity *  Entity,
const char *  path,
const Access_Operation  oper,
XrdOucEnv *  Env 
)
inlineoverridevirtual

Route an audit message to the appropriate audit exit routine. See XrdAccAudit.h for more information on how the default implementation works. Currently, this method is not called by the ofs but should be used by the implementation to record denials or grants, as warranted.

Parameters
accok-> True is access was grated; false otherwise.
Entity-> Authentication information
path-> The logical path which is the target of oper
oper-> The operation being attempted (see above)
Env-> Environmental information at the time of the operation as supplied by the path CGI string. This is optional and the pointer may be zero.
Returns
Success: !0 information recorded. Failure: 0 information could not be recorded.

Implements XrdAccAuthorize.

Definition at line 26 of file XrdMacaroonsAuthz.hh.

29  {
30  return 0;
31  }

◆ IssuerList()

virtual Issuers Macaroons::Authz::IssuerList ( )
inlineoverridevirtual

Implements XrdSciTokensHelper.

Definition at line 41 of file XrdMacaroonsAuthz.hh.

41 {return Issuers();}
std::vector< ValidIssuer > Issuers

◆ Test()

virtual int Macaroons::Authz::Test ( const XrdAccPrivs  priv,
const Access_Operation  oper 
)
inlineoverridevirtual

Check whether the specified operation is permitted.

Parameters
priv-> the privileges as returned by Access().
oper-> The operation being attempted (see above)
Returns
Permit: a non-zero value (access is permitted) Deny: zero (access is denied)

Implements XrdAccAuthorize.

Definition at line 33 of file XrdMacaroonsAuthz.hh.

35  {
36  return 0;
37  }

◆ Validate()

bool Authz::Validate ( const char *  token,
std::string &  emsg,
long long *  expT,
XrdSecEntity *  entP 
)
overridevirtual

Validate a scitoken.

Parameters
token- Pointer to the token to validate.
emsg- Reference to a string to hold the reason for rejection
expT- Pointer to where the expiry value is to be placed. If nill, the value is not returned.
entP- Pointer to the SecEntity object and when not nil requests that it be filled with any identifying information in the token. The caller assumes that all supplied fields may be released by calling free().
Returns
Return true if the token is valid; false otherwise with emsg set.

Implements XrdSciTokensHelper.

Definition at line 279 of file XrdMacaroonsAuthz.cc.

283 {
284  macaroon_returncode mac_err = MACAROON_SUCCESS;
285  std::unique_ptr<struct macaroon, decltype(&macaroon_destroy)> macaroon(
286  macaroon_deserialize(token, &mac_err),
287  &macaroon_destroy);
288 
289  if (!macaroon)
290  {
291  emsg = "Failed to deserialize the token as a macaroon";
292  // Purposely log at debug level in case if this validation is ever
293  // chained so we don't have overly-chatty logs.
294  m_log.Log(LogMask::Debug, "Validate", emsg.c_str());
295  return false;
296  }
297 
298  std::unique_ptr<struct macaroon_verifier, decltype(&macaroon_verifier_destroy)> verifier(
299  macaroon_verifier_create(), &macaroon_verifier_destroy);
300  if (!verifier)
301  {
302  emsg = "Internal error: failed to create a verifier.";
303  m_log.Log(LogMask::Error, "Validate", emsg.c_str());
304  return false;
305  }
306 
307  // Note the path and operation here are ignored as we won't use those validators
308  AuthzCheck check_helper("/", AOP_Read, m_max_duration, m_log);
309 
310  if (macaroon_verifier_satisfy_general(verifier.get(), AuthzCheck::verify_before_s, &check_helper, &mac_err) ||
311  macaroon_verifier_satisfy_general(verifier.get(), validate_verify_empty, nullptr, &mac_err))
312  {
313  emsg = "Failed to configure the verifier";
314  m_log.Log(LogMask::Error, "Validate", emsg.c_str());
315  return false;
316  }
317 
318  const unsigned char *macaroon_loc;
319  size_t location_sz;
320  macaroon_location(macaroon.get(), &macaroon_loc, &location_sz);
321  if (strncmp(reinterpret_cast<const char *>(macaroon_loc), m_location.c_str(), location_sz))
322  {
323  emsg = "Macaroon contains incorrect location: " +
324  std::string(reinterpret_cast<const char *>(macaroon_loc), location_sz);
325  m_log.Log(LogMask::Warning, "Validate", emsg.c_str(), ("all.sitename is " + m_location).c_str());
326  return false;
327  }
328 
329  if (macaroon_verify(verifier.get(), macaroon.get(),
330  reinterpret_cast<const unsigned char *>(m_secret.c_str()),
331  m_secret.size(),
332  nullptr, 0,
333  &mac_err))
334  {
335  emsg = "Macaroon verification error" + (check_helper.GetErrorMessage().size() ?
336  (", " + check_helper.GetErrorMessage()) : "");
337  m_log.Log(LogMask::Warning, "Validate", emsg.c_str());
338  return false;
339  }
340 
341  const unsigned char *macaroon_id;
342  size_t id_sz;
343  macaroon_identifier(macaroon.get(), &macaroon_id, &id_sz);
344  m_log.Log(LogMask::Info, "Validate", ("Macaroon verification successful; ID " +
345  std::string(reinterpret_cast<const char *>(macaroon_id), id_sz)).c_str());
346 
347  return true;
348 }
@ AOP_Read
open() r/o, prepare()
int emsg(int rc, char *msg)
@ Error
@ Warning

References AOP_Read, Debug, emsg(), Error, TPC::Info, XrdSysError::Log(), and TPC::Warning.

+ Here is the call graph for this function:

The documentation for this class was generated from the following files: