From: Radoslaw Zarzynski Date: Wed, 18 Jan 2017 19:08:08 +0000 (+0100) Subject: rgw: implement descriptive authentication failure reasons. X-Git-Tag: v12.0.2~305^2~10 X-Git-Url: http://git-server-git.apps.pok.os.sepia.ceph.com/?a=commitdiff_plain;h=463fb1f9e4d49627cebb14196f309fd345838db3;p=ceph.git rgw: implement descriptive authentication failure reasons. Signed-off-by: Radoslaw Zarzynski --- diff --git a/src/rgw/rgw_auth.cc b/src/rgw/rgw_auth.cc index 8768a5343304..20087519bd20 100644 --- a/src/rgw/rgw_auth.cc +++ b/src/rgw/rgw_auth.cc @@ -104,47 +104,123 @@ static inline const std::string make_spec_item(const std::string& tenant, } +static inline std::pair +strategy_handle_rejected(rgw::auth::Engine::result_t&& engine_result, + const rgw::auth::Strategy::Control policy, + rgw::auth::Engine::result_t&& strategy_result) +{ + using Control = rgw::auth::Strategy::Control; + switch (policy) { + case Control::REQUISITE: + /* Don't try next. */ + return std::make_pair(false, std::move(engine_result)); + + case Control::SUFFICIENT: + /* Don't try next. */ + return std::make_pair(false, std::move(engine_result)); + + case Control::FALLBACK: + /* Don't try next. */ + return std::make_pair(false, std::move(strategy_result)); + + default: + /* Huh, memory corruption? */ + abort(); + } +} + +static inline std::pair +strategy_handle_denied(rgw::auth::Engine::result_t&& engine_result, + const rgw::auth::Strategy::Control policy, + rgw::auth::Engine::result_t&& strategy_result) +{ + using Control = rgw::auth::Strategy::Control; + switch (policy) { + case Control::REQUISITE: + /* Don't try next. */ + return std::make_pair(false, std::move(engine_result)); + + case Control::SUFFICIENT: + /* Just try next. */ + return std::make_pair(true, std::move(engine_result)); + + case Control::FALLBACK: + return std::make_pair(true, std::move(strategy_result)); + + default: + /* Huh, memory corruption? */ + abort(); + } +} + +static inline std::pair +strategy_handle_granted(rgw::auth::Engine::result_t&& engine_result, + const rgw::auth::Strategy::Control policy, + rgw::auth::Engine::result_t&& strategy_result) +{ + using Control = rgw::auth::Strategy::Control; + switch (policy) { + case Control::REQUISITE: + /* Try next. */ + return std::make_pair(true, std::move(engine_result)); + + case Control::SUFFICIENT: + /* Don't try next. */ + return std::make_pair(false, std::move(engine_result)); + + case Control::FALLBACK: + /* Don't try next. */ + return std::make_pair(false, std::move(engine_result)); + + default: + /* Huh, memory corruption? */ + abort(); + } +} + rgw::auth::Engine::result_t rgw::auth::Strategy::authenticate(const req_state* const s) const { - int previous_error = 0; + result_t strategy_result = result_t::deny(); + for (const stack_item_t& kv : auth_stack) { const rgw::auth::Engine& engine = kv.first; const auto& policy = kv.second; - rgw::auth::Engine::result_t res; + result_t engine_result = result_t::deny(); try { - res = engine.authenticate(s); + engine_result = engine.authenticate(s); } catch (const int err) { - previous_error = err; + engine_result = result_t::deny(err); } - const auto& applier = res.first; - if (! applier) { - /* The current auth engine denied authenticate the request returning - * a null rgw::auth::Applier. As it has been included into strategy - * as an obligatory one, we quite immediately. */ - switch (policy) { - case Control::REQUISITE: - goto auth_fail; - case Control::SUFFICIENT: - /* Just try next. */ - continue; - case Control::FALLBACK: - throw previous_error; - default: - /* Huh, memory corruption? */ - abort(); - } - } else { - /* Success. */ - return std::move(res); + bool try_next = true; + switch (engine_result.get_status()) { + case result_t::Status::REJECTED: + std::tie(try_next, strategy_result) = \ + strategy_handle_rejected(std::move(engine_result), policy, + std::move(strategy_result)); + break; + case result_t::Status::DENIED: + std::tie(try_next, strategy_result) = \ + strategy_handle_denied(std::move(engine_result), policy, + std::move(strategy_result)); + break; + case result_t::Status::GRANTED: + std::tie(try_next, strategy_result) = \ + strategy_handle_granted(std::move(engine_result), policy, + std::move(strategy_result)); + break; + default: + abort(); + } + + if (! try_next) { + break; } } -auth_fail: - /* Returning nullptr as the rgw::auth::Applier means access denied. */ - return Engine::result_t(nullptr, nullptr); + return strategy_result; } void @@ -332,7 +408,7 @@ rgw::auth::Engine::result_t rgw::auth::AnonymousEngine::authenticate(const req_state* const s) const { if (! is_applicable()) { - return std::make_pair(nullptr, nullptr); + return result_t::deny(); } else { RGWUserInfo user_info; rgw_get_anon_user(user_info); @@ -340,6 +416,6 @@ rgw::auth::AnonymousEngine::authenticate(const req_state* const s) const // FIXME: over 80 columns auto apl = apl_factory->create_apl_local(cct, s, user_info, rgw::auth::LocalApplier::NO_SUBUSER); - return std::make_pair(std::move(apl), nullptr); + return result_t::grant(std::move(apl)); } } diff --git a/src/rgw/rgw_auth.h b/src/rgw/rgw_auth.h index ca7ce6fafd4a..458f0ccae63a 100644 --- a/src/rgw/rgw_auth.h +++ b/src/rgw/rgw_auth.h @@ -104,10 +104,40 @@ public: }; +/* Interface class for completing the two-step authentication process. + * Completer provides the second step - the complete() method that should + * be called after Engine::authenticate() but before *committing* results + * of an RGWOp (or sending a response in the case of non-mutating ops). + * + * The motivation driving the interface is to address those authentication + * schemas that require message integrity verification *without* in-memory + * data buffering. Typical examples are AWS Auth v4 and the auth mechanism + * of browser uploads facilities both in S3 and Swift APIs (see RGWPostObj). + * The workflow of request from the authentication point-of-view does look + * like following one: + * A. authenticate (Engine::authenticate), + * B. authorize (see RGWOp::verify_permissions), + * C. execute-prepare (init potential data modifications), + * D. authenticate-complete - (Completer::complete), + * E. execute-commit - commit the modifications from point C. */ +class Completer { +public: + typedef std::unique_ptr cmplptr_t; + + virtual ~Completer() = default; + + /* Complete the authentication process. Return boolean indicating whether + * the completion succeeded. On error throws rgw::auth::Exception storing + * the reason. */ + virtual bool complete() = 0; +}; + + /* Interface class for authentication backends (auth engines) in RadosGW. * * An engine is supposed only to authenticate (not authorize!) requests - * basing on their req_state and provide an upper layer with: + * basing on their req_state and - if access has been granted - provide + * an upper layer with: * - rgw::auth::IdentityApplier to commit all changes to the request state as * well as to the RADOS store (creating an account, synchronizing * user-related information with external databases and so on). @@ -115,17 +145,19 @@ public: * of the request. Typical use case is verifying message integrity * in AWS Auth v4 and browser uploads (RGWPostObj). * - * The authentication process consists two steps: - * - Engine::authenticate() supposed to be called before *initiating* + * Both of them are supposed to be wrapped in Engine::AuthResult. + * + * The authentication process consists of two steps: + * - Engine::authenticate() which should be called before *initiating* * any modifications to RADOS store that are related to an operation * a client wants to perform (RGWOp::execute). * - Completer::complete() supposed to be called, if completer has been * returned, after the authenticate() step but before *committing* * those modifications or sending a response (RGWOp::complete). * - * An engine outlives both Applier and Completer. It's - * intended to live since RadosGW's initialization and handle multiple - * requests till a reconfiguration. + * An engine outlives both Applier and Completer. It's intended to live + * since RadosGW's initialization and handle multiple requests till + * a reconfiguration. * * Auth engine MUST NOT make any changes to req_state nor RADOS store. * This is solely an Applier's responsibility! @@ -138,8 +170,87 @@ class Engine { public: virtual ~Engine() = default; - using result_t = std::pair, - std::unique_ptr>; + class AuthResult { + struct rejection_mark_t {}; + bool is_rejected = false; + int reason = 0; + + std::pair result_pair; + + AuthResult(const int reason) + : reason(reason) { + } + + AuthResult(rejection_mark_t&&, const int reason) + : is_rejected(true), + reason(reason) { + } + + /* Allow only the reasonable combintations - returning just Completer + * without accompanying IdentityApplier is strictly prohibited! */ + AuthResult(IdentityApplier::aplptr_t&& applier) + : result_pair(std::move(applier), nullptr) { + } + + AuthResult(IdentityApplier::aplptr_t&& applier, + Completer::cmplptr_t&& completer) + : result_pair(std::move(applier), std::move(completer)) { + } + + public: + enum class Status { + /* Engine doesn't grant the access but also doesn't reject it. */ + DENIED, + + /* Engine successfully authenticated requester. */ + GRANTED, + + /* Engine strictly indicates that a request should be rejected + * without trying any further engine. */ + REJECTED + }; + + Status get_status() const { + if (is_rejected) { + return Status::REJECTED; + } else if (! result_pair.first) { + return Status::DENIED; + } else { + return Status::GRANTED; + } + } + + int get_reason() const { + return reason; + } + + IdentityApplier::aplptr_t get_applier() { + return std::move(result_pair.first); + } + + Completer::cmplptr_t get_completer() { + return std::move(result_pair.second); + } + + static AuthResult reject(const int reason = -EACCES) { + return AuthResult(rejection_mark_t(), reason); + } + + static AuthResult deny(const int reason = -EACCES) { + return AuthResult(reason); + } + + static AuthResult grant(IdentityApplier::aplptr_t&& applier) { + return AuthResult(std::move(applier)); + } + + static AuthResult grant(IdentityApplier::aplptr_t&& applier, + Completer::cmplptr_t&& completer) { + return AuthResult(std::move(applier), std::move(completer)); + } + }; + + using result_t = AuthResult; /* Get name of the auth engine. */ virtual const char* get_name() const noexcept = 0; @@ -156,35 +267,6 @@ public: }; -/* Interface class for completing the two-step authentication process. - * Completer provides the second step - the complete() method that should - * be called after Engine::authenticate() but before *committing* results - * of an RGWOp (or sending a response in the case of non-mutating ops). - * - * The motivation driving the interface is to address those authentication - * schemas that require message integrity verification *without* in-memory - * data buffering. Typical examples are AWS Auth v4 and the auth mechanism - * of browser uploads facilities both in S3 and Swift APIs (see RGWPostObj). - * The workflow of request from the authentication point-of-view does look - * like following one: - * A. authenticate (Engine::authenticate), - * B. authorize (see RGWOp::verify_permissions), - * C. execute-prepare (init potential data modifications), - * D. authenticate-complete - (Completer::complete), - * E. execute-commit - commit the modifications from point C. */ -class Completer { -public: - typedef std::unique_ptr cmplptr_t; - - virtual ~Completer() = default; - - /* Complete the authentication process. Return boolean indicating whether - * the completion succeeded. On error throws rgw::auth::Exception storing - * the reason. */ - virtual bool complete() = 0; -}; - - /* Interface for extracting a token basing from data carried by req_state. */ class TokenExtractor { public: @@ -204,14 +286,14 @@ public: * The names and semantic has been borrowed mostly from libpam. */ enum class Control { /* Failure of an engine injected with the REQUISITE specifier aborts - * the whole authentication process immediately. No other engine will - * be tried. */ + * the strategy's authentication process immediately. No other engine + * will be tried. */ REQUISITE, /* Success of an engine injected with the SUFFICIENT specifier ends - * the whole authentication process successfully. However, failure - * doesn't abort it - there will be fall-back to following engine - * it the one that failed wasn't the last. */ + * strategy's authentication process successfully. However, denying + * doesn't abort it -- there will be fall-back to following engine + * if the one that failed wasn't the last one. */ SUFFICIENT, /* Like SUFFICIENT with the exception that on failure the reason code diff --git a/src/rgw/rgw_auth_keystone.cc b/src/rgw/rgw_auth_keystone.cc index b333be9f7e2c..1c6a9cc41ae0 100644 --- a/src/rgw/rgw_auth_keystone.cc +++ b/src/rgw/rgw_auth_keystone.cc @@ -234,7 +234,7 @@ TokenEngine::authenticate(const std::string& token, << dendl; auto apl = apl_factory->create_apl_remote(cct, s, get_acl_strategy(t), get_creds_info(t, roles.admin)); - return std::make_pair(std::move(apl), nullptr); + return result_t::grant(std::move(apl)); } /* Retrieve token. */ @@ -255,7 +255,7 @@ TokenEngine::authenticate(const std::string& token, ldout(cct, 0) << "got expired token: " << t.get_project_name() << ":" << t.get_user_name() << " expired: " << t.get_expires() << dendl; - return std::make_pair(nullptr, nullptr); + return result_t::deny(); } /* Check for necessary roles. */ @@ -267,14 +267,14 @@ TokenEngine::authenticate(const std::string& token, token_cache.add(token_id, t); auto apl = apl_factory->create_apl_remote(cct, s, get_acl_strategy(t), get_creds_info(t, roles.admin)); - return std::make_pair(std::move(apl), nullptr); + return result_t::grant(std::move(apl)); } } ldout(cct, 0) << "user does not hold a matching role; required roles: " << g_conf->rgw_keystone_accepted_roles << dendl; - return std::make_pair(nullptr, nullptr); + return result_t::deny(); } @@ -344,7 +344,7 @@ EC2Engine::get_from_keystone(const std::string& access_key_id, if (ret < 0) { ldout(cct, 2) << "s3 keystone: token validation ERROR: " << token_body_bl.c_str() << dendl; - throw -EPERM; + throw ret; } /* if the supplied signature is wrong, we will get 401 from Keystone */ @@ -429,7 +429,7 @@ rgw::auth::Engine::result_t EC2Engine::authenticate(const std::string& access_ke ldout(cct, 0) << "got expired token: " << t.get_project_name() << ":" << t.get_user_name() << " expired: " << t.get_expires() << dendl; - return std::make_pair(nullptr, nullptr); + return result_t::deny(); } /* check if we have a valid role */ @@ -445,7 +445,7 @@ rgw::auth::Engine::result_t EC2Engine::authenticate(const std::string& access_ke ldout(cct, 5) << "s3 keystone: user does not hold a matching role;" " required roles: " << cct->_conf->rgw_keystone_accepted_roles << dendl; - return std::make_pair(nullptr, nullptr); + return result_t::deny(); } else { /* everything seems fine, continue with this user */ ldout(cct, 5) << "s3 keystone: validated token: " << t.get_project_name() @@ -454,7 +454,7 @@ rgw::auth::Engine::result_t EC2Engine::authenticate(const std::string& access_ke auto apl = apl_factory->create_apl_remote(cct, s, get_acl_strategy(t), get_creds_info(t, accepted_roles.admin)); - return std::make_pair(std::move(apl), nullptr); + return result_t::grant(std::move(apl)); } } diff --git a/src/rgw/rgw_rest_s3.cc b/src/rgw/rgw_rest_s3.cc index ea4d1f34b0c2..63bd0b99cdda 100644 --- a/src/rgw/rgw_rest_s3.cc +++ b/src/rgw/rgw_rest_s3.cc @@ -1833,12 +1833,13 @@ int RGWPostObj_ObjStore_S3::get_policy() const rgw::auth::s3::AWSv2AuthStrategy strategy(g_ceph_context, store, &extr); try { auto result = strategy.authenticate(s); - auto& applier = result.first; - if (! applier) { + if (result.get_status() != decltype(result)::Status::GRANTED) { return -EACCES; } try { + auto applier = result.get_applier(); + applier->load_acct_info(*s->user); s->perm_mask = applier->get_perm_mask(); applier->modify_request_state(s); @@ -3898,11 +3899,14 @@ int RGW_Auth_S3::authorize_v2(RGWRados *store, struct req_state *s) static const rgw::auth::s3::AWSv2AuthStrategy strategy(g_ceph_context, store); try { auto result = strategy.authenticate(s); - auto& applier = result.first; - if (! applier) { - return -EPERM; + if (result.get_status() != decltype(result)::Status::GRANTED) { + ldout(s->cct, 5) << "Failed the S3 auth strategy, reason=" + << result.get_reason() << dendl; + return result.get_reason(); } try { + auto applier = result.get_applier(); + applier->load_acct_info(*s->user); s->perm_mask = applier->get_perm_mask(); applier->modify_request_state(s); @@ -4348,7 +4352,7 @@ rgw::auth::s3::LDAPEngine::authenticate(const std::string& access_key_id, } if (! base64_token.valid()) { - return std::make_pair(nullptr, nullptr); + return result_t::deny(); } //TODO: Uncomment, when we have a migration plan in place. @@ -4364,12 +4368,12 @@ rgw::auth::s3::LDAPEngine::authenticate(const std::string& access_key_id, }*/ if (ldh->auth(base64_token.id, base64_token.key) != 0) { - return std::make_pair(nullptr, nullptr); + return result_t::deny(); } auto apl = apl_factory->create_apl_remote(cct, s, get_acl_strategy(), get_creds_info(base64_token)); - return std::make_pair(std::move(apl), nullptr); + return result_t::grant(std::move(apl)); } @@ -4380,17 +4384,12 @@ rgw::auth::s3::LocalVersion2ndEngine::authenticate(const std::string& access_key const std::string& string_to_sign, const req_state* const s) const { - if (access_key_id.empty() || signature.empty()) { - ldout(cct, 5) << "access_key_id or signature is empty" << dendl; - throw -EINVAL; - } - /* get the user info */ RGWUserInfo user_info; if (rgw_get_user_info_by_access_key(store, access_key_id, user_info) < 0) { ldout(cct, 5) << "error reading user info, uid=" << access_key_id << " can't authenticate" << dendl; - return std::make_pair(nullptr, nullptr); + return result_t::deny(-ERR_INVALID_ACCESS_KEY); } //TODO: Uncomment, when we have a migration plan in place. /*else { @@ -4404,14 +4403,14 @@ rgw::auth::s3::LocalVersion2ndEngine::authenticate(const std::string& access_key const auto iter = user_info.access_keys.find(access_key_id); if (iter == std::end(user_info.access_keys)) { ldout(cct, 0) << "ERROR: access key not encoded in user info" << dendl; - throw -EPERM; + return result_t::deny(-EPERM); } const RGWAccessKey& k = iter->second; std::string digest; int ret = rgw_get_s3_header_digest(string_to_sign, k.key, digest); if (ret < 0) { - throw -EPERM; + return result_t::deny(-EPERM); } ldout(cct, 15) << "string_to_sign=" << string_to_sign << dendl; @@ -4420,9 +4419,9 @@ rgw::auth::s3::LocalVersion2ndEngine::authenticate(const std::string& access_key ldout(cct, 15) << "compare=" << signature.compare(digest) << dendl; if (signature != digest) { - throw -ERR_SIGNATURE_NO_MATCH; + return result_t::deny(-ERR_SIGNATURE_NO_MATCH); } auto apl = apl_factory->create_apl_local(cct, s, user_info, k.subuser); - return std::make_pair(std::move(apl), nullptr); + return result_t::grant(std::move(apl)); } diff --git a/src/rgw/rgw_rest_s3.h b/src/rgw/rgw_rest_s3.h index 7450dfe3d34e..6ca8c899a6d3 100644 --- a/src/rgw/rgw_rest_s3.h +++ b/src/rgw/rgw_rest_s3.h @@ -659,7 +659,7 @@ public: extractor.get_auth_data(s); if (access_key_id.empty() || signature.empty()) { - return std::make_pair(nullptr, nullptr); + return result_t::deny(-EINVAL); } else { return authenticate(access_key_id, signature, string_to_sign, s); } diff --git a/src/rgw/rgw_rest_swift.cc b/src/rgw/rgw_rest_swift.cc index e1a116999fdb..9f06fa461877 100644 --- a/src/rgw/rgw_rest_swift.cc +++ b/src/rgw/rgw_rest_swift.cc @@ -2033,12 +2033,10 @@ RGWOp *RGWHandler_REST_Obj_SWIFT::op_options() int RGWHandler_REST_SWIFT::authorize() { - rgw::auth::IdentityApplier::aplptr_t applier; - rgw::auth::Completer::cmplptr_t completer; - std::tie(applier, completer) = auth_strategy.authenticate(s); - try { - if (! applier) { + auto result = auth_strategy.authenticate(s); + + if (result.get_status() != decltype(result)::Status::GRANTED) { /* Access denied is acknowledged by returning a std::unique_ptr with * nullptr inside. */ ldout(s->cct, 5) << "auth engine refused to authenicate" << dendl; @@ -2046,6 +2044,8 @@ int RGWHandler_REST_SWIFT::authorize() } try { + rgw::auth::IdentityApplier::aplptr_t applier = result.get_applier(); + /* Account used by a given RGWOp is decoupled from identity employed * in the authorization phase (RGWOp::verify_permissions). */ applier->load_acct_info(*s->user); @@ -2057,7 +2057,7 @@ int RGWHandler_REST_SWIFT::authorize() applier->modify_request_state(s); s->auth.identity = std::move(applier); - s->auth.completer = std::move(completer); + s->auth.completer = std::move(result.get_completer()); return 0; } catch (int err) { diff --git a/src/rgw/rgw_swift_auth.cc b/src/rgw/rgw_swift_auth.cc index 005d839045ab..cc26db4fcce5 100644 --- a/src/rgw/rgw_swift_auth.cc +++ b/src/rgw/rgw_swift_auth.cc @@ -194,14 +194,14 @@ TempURLEngine::result_t TempURLEngine::authenticate(const req_state* const s) const { if (! is_applicable(s)) { - return std::make_pair(nullptr, nullptr); + return result_t::deny(); } const string& temp_url_sig = s->info.args.get("temp_url_sig"); const string& temp_url_expires = s->info.args.get("temp_url_expires"); if (temp_url_sig.empty() || temp_url_expires.empty()) { - return std::make_pair(nullptr, nullptr); + return result_t::deny(); } RGWUserInfo owner_info; @@ -209,17 +209,17 @@ TempURLEngine::authenticate(const req_state* const s) const get_owner_info(s, owner_info); } catch (...) { ldout(cct, 5) << "cannot get user_info of account's owner" << dendl; - return std::make_pair(nullptr, nullptr); + return result_t::reject(); } if (owner_info.temp_url_keys.empty()) { ldout(cct, 5) << "user does not have temp url key set, aborting" << dendl; - return std::make_pair(nullptr, nullptr); + return result_t::reject(); } if (is_expired(temp_url_expires)) { ldout(cct, 5) << "temp url link expired" << dendl; - return std::make_pair(nullptr, nullptr); + return result_t::reject(); } /* We need to verify two paths because of compliance with Swift, Tempest @@ -270,7 +270,7 @@ TempURLEngine::authenticate(const req_state* const s) const if (sig_helper.is_equal_to(temp_url_sig)) { auto apl = apl_factory->create_apl_turl(cct, s, owner_info); - return std::make_pair(std::move(apl), nullptr); + return result_t::grant(std::move(apl)); } else { ldout(s->cct, 5) << "temp url signature mismatch: " << local_sig << " != " << temp_url_sig << dendl; @@ -279,7 +279,7 @@ TempURLEngine::authenticate(const req_state* const s) const } } - return std::make_pair(nullptr, nullptr); + return result_t::reject(); } @@ -300,7 +300,7 @@ ExternalTokenEngine::authenticate(const std::string& token, const req_state* const s) const { if (! is_applicable(token)) { - return std::make_pair(nullptr, nullptr); + return result_t::deny(); } std::string auth_url = g_conf->rgw_swift_auth_url; @@ -328,17 +328,17 @@ ExternalTokenEngine::authenticate(const std::string& token, ",", swift_groups); if (0 == swift_groups.size()) { - return std::make_pair(nullptr, nullptr); + return result_t::deny(); } else { swift_user = std::move(swift_groups[0]); } } catch (std::out_of_range) { /* The X-Auth-Groups header isn't present in the response. */ - return std::make_pair(nullptr, nullptr); + return result_t::deny(); } if (swift_user.empty()) { - return std::make_pair(nullptr, nullptr); + return result_t::deny(); } ldout(cct, 10) << "swift user=" << swift_user << dendl; @@ -352,7 +352,7 @@ ExternalTokenEngine::authenticate(const std::string& token, auto apl = apl_factory->create_apl_local(cct, s, tmp_uinfo, extract_swift_subuser(swift_user)); - return std::make_pair(std::move(apl), nullptr); + return result_t::grant(std::move(apl)); } static int build_token(const string& swift_user, @@ -416,7 +416,7 @@ SignedTokenEngine::authenticate(const std::string& token, const req_state* const s) const { if (! is_applicable(token)) { - return std::make_pair(nullptr, nullptr); + return result_t::deny(); } /* Effective token string is the part after the prefix. */ @@ -458,7 +458,7 @@ SignedTokenEngine::authenticate(const std::string& token, ldout(cct, 0) << "NOTICE: old timed out token was used now=" << now << " token.expiration=" << expiration << dendl; - return std::make_pair(nullptr, nullptr); + return result_t::deny(); } RGWUserInfo user_info; @@ -471,7 +471,7 @@ SignedTokenEngine::authenticate(const std::string& token, const auto siter = user_info.swift_keys.find(swift_user); if (siter == std::end(user_info.swift_keys)) { - return std::make_pair(nullptr, nullptr); + return result_t::deny(); } const auto swift_key = siter->second; @@ -487,7 +487,7 @@ SignedTokenEngine::authenticate(const std::string& token, << " tok_bl.length()=" << tok_bl.length() << " local_tok_bl.length()=" << local_tok_bl.length() << dendl; - return std::make_pair(nullptr, nullptr); + return result_t::deny(); } if (memcmp(local_tok_bl.c_str(), tok_bl.c_str(), @@ -498,12 +498,12 @@ SignedTokenEngine::authenticate(const std::string& token, local_tok_bl.length(), buf); ldout(cct, 0) << "NOTICE: tokens mismatch tok=" << buf << dendl; - return std::make_pair(nullptr, nullptr); + return result_t::deny(); } auto apl = apl_factory->create_apl_local(cct, s, user_info, extract_swift_subuser(swift_user)); - return std::make_pair(std::move(apl), nullptr); + return result_t::grant(std::move(apl)); } } /* namespace swift */