Check whether or not the client is permitted specified access to a path.
512 {
513 const char *authz = env ? env->Get("authz") : nullptr;
514
515
516
517
518 if (authz && !strncmp(authz, "Bearer%20", 9)) {
519 authz += 9;
520 }
521
522
523 if (!authz && Entity && !strcmp(
"ztn", Entity->
prot) && Entity->
creds &&
525 {
526 authz = Entity->
creds;
527 }
528 if (authz == nullptr) {
529 return OnMissing(Entity, path, oper, env);
530 }
531 m_log.Log(LogMask::Debug, "Access", "Trying token-based access control");
532 std::shared_ptr<XrdAccRules> access_rules;
533 uint64_t now = monotonic_time();
534 Check(now);
535 {
536 std::lock_guard<std::mutex> guard(m_map_mutex);
537 const auto iter = m_map.find(authz);
538 if (iter != m_map.end() && !iter->second->expired()) {
539 access_rules = iter->second;
540 }
541 }
542 if (!access_rules) {
543 m_log.Log(LogMask::Debug, "Access", "Token not found in recent cache; parsing.");
544 try {
545 uint64_t cache_expiry;
546 AccessRulesRaw rules;
547 std::string username;
548 std::string token_subject;
549 std::string issuer;
550 std::vector<MapRule> map_rules;
551 std::vector<std::string> groups;
552 uint32_t authz_strategy;
553 if (GenerateAcls(authz, cache_expiry, rules, username, token_subject, issuer, map_rules, groups, authz_strategy)) {
554 access_rules.reset(new XrdAccRules(now + cache_expiry, username, token_subject, issuer, map_rules, groups, authz_strategy));
555 access_rules->parse(rules);
556 } else {
557 m_log.Log(LogMask::Warning, "Access", "Failed to generate ACLs for token");
558 return OnMissing(Entity, path, oper, env);
559 }
560 if (m_log.getMsgMask() & LogMask::Debug) {
561 m_log.Log(LogMask::Debug, "Access", "New valid token", access_rules->str().c_str());
562 }
563 } catch (std::exception &exc) {
564 m_log.Log(LogMask::Warning, "Access", "Error generating ACLs for authorization", exc.what());
565 return OnMissing(Entity, path, oper, env);
566 }
567 std::lock_guard<std::mutex> guard(m_map_mutex);
568 m_map[authz] = access_rules;
569 } else if (m_log.getMsgMask() & LogMask::Debug) {
570 m_log.Log(LogMask::Debug, "Access", "Cached token", access_rules->str().c_str());
571 }
572
573
574
575
576
577
578
579
580
581
582
583
584 XrdSecEntity new_secentity;
585 new_secentity.
vorg =
nullptr;
586 new_secentity.
grps =
nullptr;
587 new_secentity.
role =
nullptr;
590 const auto &issuer = access_rules->get_issuer();
591 if (!issuer.empty()) {
592 new_secentity.
vorg = strdup(issuer.c_str());
593 }
594 bool group_success = false;
595 if ((access_rules->get_authz_strategy() & IssuerAuthz::Group) && access_rules->groups().size()) {
596 std::stringstream ss;
597 for (const auto &grp : access_rules->groups()) {
598 ss << grp << " ";
599 }
600 const auto &groups_str = ss.str();
601 new_secentity.
grps =
static_cast<char*
>(malloc(groups_str.size() + 1));
602 if (new_secentity.
grps) {
603 memcpy(new_secentity.
grps, groups_str.c_str(), groups_str.size());
604 new_secentity.
grps[groups_str.size()] =
'\0';
605 group_success = true;
606 }
607 }
608
609 std::string username;
610 bool mapping_success = false;
611 bool scope_success = false;
612 username = access_rules->get_username(path);
613
614 mapping_success = (access_rules->get_authz_strategy() & IssuerAuthz::Mapping) && !username.empty();
615 scope_success = (access_rules->get_authz_strategy() & IssuerAuthz::Capability) && access_rules->apply(oper, path);
616 if (scope_success && (m_log.getMsgMask() & LogMask::Debug)) {
617 std::stringstream ss;
618 ss << "Grant authorization based on scopes for operation=" << OpToName(oper) << ", path=" << path;
619 m_log.Log(LogMask::Debug, "Access", ss.str().c_str());
620 }
621
622 if (!scope_success && !mapping_success && !group_success) {
623 auto returned_accs = OnMissing(&new_secentity, path, oper, env);
624
625 if (new_secentity.
vorg !=
nullptr) free(new_secentity.
vorg);
626 if (new_secentity.
grps !=
nullptr) free(new_secentity.
grps);
627 if (new_secentity.
role !=
nullptr) free(new_secentity.
role);
628
629 return returned_accs;
630 }
631
632
633 if (scope_success && username.empty()) {
634 username = access_rules->get_default_username();
635 }
636
637
638
639 if (scope_success || mapping_success) {
640
641 Entity->
eaAPI->
Add(
"request.name", username,
true);
642 new_secentity.
eaAPI->
Add(
"request.name", username,
true);
643 m_log.Log(LogMask::Debug, "Access", "Request username", username.c_str());
644 }
645
646
647
648
649
650
651 const auto &token_subject = access_rules->get_token_subject();
652 if (!token_subject.empty()) {
653 Entity->
eaAPI->
Add(
"token.subject", token_subject,
true);
654 }
655
656
658
659
660
661
662 if (Entity->
secMon && scope_success && returned_op &&
Mon_isIO(oper))
663 Mon_Report(new_secentity, token_subject, username);
664
665
666 if (new_secentity.
vorg !=
nullptr) free(new_secentity.
vorg);
667 if (new_secentity.
grps !=
nullptr) free(new_secentity.
grps);
668 if (new_secentity.
role !=
nullptr) free(new_secentity.
role);
669
670 return returned_op;
671 }
bool Mon_isIO(const Access_Operation oper)
void Mon_Report(const XrdSecEntity &Entity, const std::string &subject, const std::string &username)
bool Add(XrdSecAttr &attr)
char * vorg
Entity's virtual organization(s).
int credslen
Length of the 'creds' data.
XrdNetAddrInfo * addrInfo
Entity's connection details.
XrdSecEntityAttr * eaAPI
non-const API to attributes
char prot[XrdSecPROTOIDSIZE]
Auth protocol used (e.g. krb5).
char * creds
Raw entity credentials or cert.
XrdSecMonitor * secMon
If !0 security monitoring enabled.
char * grps
Entity's group name(s).
char * role
Entity's role(s).