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...
 
- Public Member Functions inherited from XrdSciTokensHelper
 XrdSciTokensHelper ()
 Constructor and Destructor. More...
 
virtual ~XrdSciTokensHelper ()
 

Additional Inherited Members

- Public Types inherited from XrdSciTokensHelper
typedef std::vector< ValidIssuerIssuers
 

Detailed Description

Definition at line 12 of file XrdMacaroonsAuthz.hh.

Constructor & Destructor Documentation

◆ Authz()

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

Definition at line 132 of file XrdMacaroonsAuthz.cc.

133  : m_max_duration(86400),
134  m_chain(chain),
135  m_log(log, "macarons_"),
136  m_authz_behavior(static_cast<int>(Handler::AuthzBehavior::PASSTHROUGH))
137 {
138  Handler::AuthzBehavior behavior(Handler::AuthzBehavior::PASSTHROUGH);
139  XrdOucEnv env;
140  if (!Handler::Config(config, &env, &m_log, m_location, m_secret, m_max_duration, behavior))
141  {
142  throw std::runtime_error("Macaroon authorization config failed.");
143  }
144  m_authz_behavior = static_cast<int>(behavior);
145 }
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 17 of file XrdMacaroonsAuthz.hh.

17 {}

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 
181  // If there's no request-specific token, check for a ZTN session token
182  if (!authz && Entity && !strcmp("ztn", Entity->prot) && Entity->creds &&
183  Entity->credslen && Entity->creds[Entity->credslen] == '\0')
184  {
185  authz = Entity->creds;
186  }
187 
188  if (!authz) {
189  return OnMissing(Entity, path, oper, env);
190  }
191 
192  macaroon_returncode mac_err = MACAROON_SUCCESS;
193  struct macaroon* macaroon = macaroon_deserialize(
194  authz,
195  &mac_err);
196  if (!macaroon)
197  {
198  // Do not log - might be other token type!
199  //m_log.Emsg("Access", "Failed to parse the macaroon");
200  return OnMissing(Entity, path, oper, env);
201  }
202 
203  struct macaroon_verifier *verifier = macaroon_verifier_create();
204  if (!verifier)
205  {
206  m_log.Emsg("Access", "Failed to create a new macaroon verifier");
207  return XrdAccPriv_None;
208  }
209  if (!path)
210  {
211  m_log.Emsg("Access", "Request with no provided path.");
212  macaroon_verifier_destroy(verifier);
213  return XrdAccPriv_None;
214  }
215 
216  AuthzCheck check_helper(path, oper, m_max_duration, m_log);
217 
218  if (macaroon_verifier_satisfy_general(verifier, AuthzCheck::verify_before_s, &check_helper, &mac_err) ||
219  macaroon_verifier_satisfy_general(verifier, AuthzCheck::verify_activity_s, &check_helper, &mac_err) ||
220  macaroon_verifier_satisfy_general(verifier, AuthzCheck::verify_name_s, &check_helper, &mac_err) ||
221  macaroon_verifier_satisfy_general(verifier, AuthzCheck::verify_path_s, &check_helper, &mac_err))
222  {
223  m_log.Emsg("Access", "Failed to configure caveat verifier:");
224  macaroon_verifier_destroy(verifier);
225  return XrdAccPriv_None;
226  }
227 
228  const unsigned char *macaroon_loc;
229  size_t location_sz;
230  macaroon_location(macaroon, &macaroon_loc, &location_sz);
231  if (strncmp(reinterpret_cast<const char *>(macaroon_loc), m_location.c_str(), location_sz))
232  {
233  std::string location_str(reinterpret_cast<const char *>(macaroon_loc), location_sz);
234  m_log.Emsg("Access", "Macaroon is for incorrect location", location_str.c_str());
235  macaroon_verifier_destroy(verifier);
236  macaroon_destroy(macaroon);
237  return m_chain ? m_chain->Access(Entity, path, oper, env) : XrdAccPriv_None;
238  }
239 
240  if (macaroon_verify(verifier, macaroon,
241  reinterpret_cast<const unsigned char *>(m_secret.c_str()),
242  m_secret.size(),
243  NULL, 0, // discharge macaroons
244  &mac_err))
245  {
246  m_log.Log(LogMask::Debug, "Access", "Macaroon verification failed");
247  macaroon_verifier_destroy(verifier);
248  macaroon_destroy(macaroon);
249  return m_chain ? m_chain->Access(Entity, path, oper, env) : XrdAccPriv_None;
250  }
251  macaroon_verifier_destroy(verifier);
252 
253  const unsigned char *macaroon_id;
254  size_t id_sz;
255  macaroon_identifier(macaroon, &macaroon_id, &id_sz);
256 
257  std::string macaroon_id_str(reinterpret_cast<const char *>(macaroon_id), id_sz);
258  m_log.Log(LogMask::Info, "Access", "Macaroon verification successful; ID", macaroon_id_str.c_str());
259  macaroon_destroy(macaroon);
260 
261  // Copy the name, if present into the macaroon, into the credential object.
262  if (Entity && check_helper.GetSecName().size()) {
263  const std::string &username = check_helper.GetSecName();
264  m_log.Log(LogMask::Debug, "Access", "Setting the request name to", username.c_str());
265  Entity->eaAPI->Add("request.name", username,true);
266  }
267 
268  // We passed verification - give the correct privilege.
269  return AddPriv(oper, XrdAccPriv_None);
270 }
@ AOP_Any
Special for getting privs.
@ XrdAccPriv_None
Definition: XrdAccPrivs.hh:53
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:95
void Log(int mask, const char *esfx, const char *text1, const char *text2=0, const char *text3=0)
Definition: XrdSysError.hh:133

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 31 of file XrdMacaroonsAuthz.hh.

34  {
35  return 0;
36  }

◆ IssuerList()

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

Implements XrdSciTokensHelper.

Definition at line 46 of file XrdMacaroonsAuthz.hh.

46 {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 38 of file XrdMacaroonsAuthz.hh.

40  {
41  return 0;
42  }

◆ 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 272 of file XrdMacaroonsAuthz.cc.

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