Check whether or not the client is permitted specified access to a path.
494 {
495 std::vector<std::string_view> authz_list;
496 authz_list.reserve(1);
497
498
499
500
501
502 ParseTokenString("authz", env, authz_list);
503 ParseTokenString("access_token", env, authz_list);
504
505 if (Entity && !strcmp(
"ztn", Entity->
prot) && Entity->
creds &&
507 {
508 authz_list.push_back(Entity->
creds);
509 }
510
511 if (authz_list.empty()) {
512 return OnMissing(Entity, path, oper, env);
513 }
514
515
516
517 if (authz_list.size() > 10) {
518 m_log.Log(LogMask::Warning, "Access", "Request had more than 10 tokens attached; ignoring");
519 return OnMissing(Entity, path, oper, env);
520 }
521
522 m_log.Log(LogMask::Debug, "Access", "Trying token-based access control");
523 std::vector<std::shared_ptr<XrdAccRules>> access_rules_list;
524 uint64_t now = monotonic_time();
525 Check(now);
526 for (const auto &authz : authz_list) {
527 std::shared_ptr<XrdAccRules> access_rules;
528 {
529 std::lock_guard<std::mutex> guard(m_map_mutex);
530 const auto iter = m_map.find(authz);
531 if (iter != m_map.end() && !iter->second->expired()) {
532 access_rules = iter->second;
533 }
534 }
535 if (!access_rules) {
536 m_log.Log(LogMask::Debug, "Access", "Token not found in recent cache; parsing.");
537 try {
538 uint64_t cache_expiry;
540 std::string username;
541 std::string token_subject;
542 std::string issuer;
543 std::vector<MapRule> map_rules;
544 std::vector<std::string> groups;
545 uint32_t authz_strategy;
547 if (GenerateAcls(authz, cache_expiry, rules, username, token_subject, issuer, map_rules, groups, authz_strategy, acceptable_authz)) {
548 access_rules.reset(new XrdAccRules(now + cache_expiry, username, token_subject, issuer, map_rules, groups, authz_strategy, acceptable_authz));
549 access_rules->parse(rules);
550 } else {
551 m_log.Log(LogMask::Warning, "Access", "Failed to generate ACLs for token");
552 continue;
553 }
554 if (m_log.getMsgMask() & LogMask::Debug) {
555 m_log.Log(LogMask::Debug, "Access", "New valid token", access_rules->str().c_str());
556 }
557 } catch (std::exception &exc) {
558 m_log.Log(LogMask::Warning, "Access", "Error generating ACLs for authorization", exc.what());
559 continue;
560 }
561 std::lock_guard<std::mutex> guard(m_map_mutex);
562 m_map[std::string(authz)] = access_rules;
563 } else if (m_log.getMsgMask() & LogMask::Debug) {
564 m_log.Log(LogMask::Debug, "Access", "Cached token", access_rules->str().c_str());
565 }
566 access_rules_list.push_back(access_rules);
567 }
568 if (access_rules_list.empty()) {
569 return OnMissing(Entity, path, oper, env);
570 }
571 std::string_view path_view(path, strlen(path));
572
573
575 return OnMissing(Entity, path, oper, env);
576 }
577
578
579
580
581
582
583
584
585
586
587
588
589 for (const auto &access_rules : access_rules_list) {
590
591 if (!access_rules->acceptable_authz(oper)) {
592 m_log.Log(LogMask::Debug, "Access", "Issuer is not acceptable for given operation:", access_rules->get_issuer().c_str());
593 continue;
594 }
595
596 XrdSecEntity new_secentity;
597 new_secentity.
vorg =
nullptr;
598 new_secentity.
grps =
nullptr;
599 new_secentity.
role =
nullptr;
602 const auto &issuer = access_rules->get_issuer();
603 if (!issuer.empty()) {
604 new_secentity.
vorg = strdup(issuer.c_str());
605 }
606 bool group_success = false;
607 if ((access_rules->get_authz_strategy() &
IssuerAuthz::Group) && access_rules->groups().size()) {
608 std::stringstream ss;
609 for (const auto &grp : access_rules->groups()) {
610 ss << grp << " ";
611 }
612 const auto &groups_str = ss.str();
613 new_secentity.
grps =
static_cast<char*
>(malloc(groups_str.size() + 1));
614 if (new_secentity.
grps) {
615 memcpy(new_secentity.
grps, groups_str.c_str(), groups_str.size());
616 new_secentity.
grps[groups_str.size()] =
'\0';
617 }
618 group_success = true;
619 }
620
621 std::string username;
622 bool mapping_success = false;
623 bool scope_success = false;
624 username = access_rules->get_username(path_view);
625
626 mapping_success = (access_rules->get_authz_strategy() &
IssuerAuthz::Mapping) && !username.empty();
627 scope_success = (access_rules->get_authz_strategy() &
IssuerAuthz::Capability) && access_rules->apply(oper, path_view);
628 if (scope_success && (m_log.getMsgMask() & LogMask::Debug)) {
629 std::stringstream ss;
630 ss << "Grant authorization based on scopes for operation=" << OpToName(oper) << ", path=" << path;
631 m_log.Log(LogMask::Debug, "Access", ss.str().c_str());
632 }
633
634 if (!scope_success && !mapping_success && !group_success) {
635 auto returned_accs = OnMissing(&new_secentity, path, oper, env);
636
637 if (new_secentity.
vorg !=
nullptr) free(new_secentity.
vorg);
638 if (new_secentity.
grps !=
nullptr) free(new_secentity.
grps);
639 if (new_secentity.
role !=
nullptr) free(new_secentity.
role);
640
641 return returned_accs;
642 }
643
644
645 if (scope_success && username.empty()) {
646 username = access_rules->get_default_username();
647 }
648
649
650
651 if (scope_success || mapping_success) {
652
653 Entity->
eaAPI->
Add(
"request.name", username,
true);
654 new_secentity.
eaAPI->
Add(
"request.name", username,
true);
655 m_log.Log(LogMask::Debug, "Access", "Request username", username.c_str());
656 }
657
658
659
660
661
662
663 const auto &token_subject = access_rules->get_token_subject();
664 if (!token_subject.empty()) {
665 Entity->
eaAPI->
Add(
"token.subject", token_subject,
true);
666 }
667
668
670
671
672
673
674 if (Entity->
secMon && scope_success && returned_op &&
Mon_isIO(oper))
675 Mon_Report(new_secentity, token_subject, username);
676
677
678 if (new_secentity.
vorg !=
nullptr) free(new_secentity.
vorg);
679 if (new_secentity.
grps !=
nullptr) free(new_secentity.
grps);
680 if (new_secentity.
role !=
nullptr) free(new_secentity.
role);
681 return returned_op;
682 }
683
684
685 return OnMissing(Entity, path, oper, env);
686 }
bool AuthorizesRequiredIssuers(Access_Operation client_oper, const std::string_view &path, const std::vector< std::pair< std::unique_ptr< SubpathMatch >, std::string > > &required_issuers, const std::vector< std::shared_ptr< XrdAccRules > > &access_rules_list)
std::vector< std::pair< Access_Operation, std::string > > AccessRulesRaw
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)