|
11 | 11 | #include "security/scram_authenticator.h" |
12 | 12 |
|
13 | 13 | #include "base/vlog.h" |
| 14 | +#include "config/configuration.h" |
14 | 15 | #include "random/secure_generators.h" |
15 | 16 | #include "security/credential_store.h" |
16 | 17 | #include "security/errc.h" |
17 | 18 | #include "security/logger.h" |
| 19 | +#include "security/scram_credential_cache.h" |
18 | 20 |
|
19 | 21 | namespace security { |
20 | 22 |
|
@@ -148,22 +150,68 @@ scram_authenticator<T>::authenticate(bytes auth_bytes) { |
148 | 150 | template class scram_authenticator<scram_sha256>; |
149 | 151 | template class scram_authenticator<scram_sha512>; |
150 | 152 |
|
| 153 | +namespace { |
| 154 | + |
| 155 | +// Matches a password against a stored credential by rederiving its stored |
| 156 | +// key. When a cache is given, the derivation is memoized; a null cache |
| 157 | +// derives every time (the plain, un-memoized path). |
| 158 | +template<typename scram> |
| 159 | +bool match_password( |
| 160 | + scram_credential_cache* cache, |
| 161 | + const scram_credential& cred, |
| 162 | + const credential_password& password) { |
| 163 | + constexpr auto mech = scram_mechanism_traits<scram>::algorithm; |
| 164 | + if (cache != nullptr) { |
| 165 | + auto cached = cache->get( |
| 166 | + mech, password, cred.salt(), cred.iterations()); |
| 167 | + if (cached.has_value()) { |
| 168 | + return *cached == cred.stored_key(); |
| 169 | + } |
| 170 | + } |
| 171 | + auto stored_key = scram::derive_stored_key( |
| 172 | + password(), cred.salt(), cred.iterations()); |
| 173 | + auto valid = stored_key == cred.stored_key(); |
| 174 | + if (cache != nullptr) { |
| 175 | + cache->put( |
| 176 | + mech, |
| 177 | + password, |
| 178 | + cred.salt(), |
| 179 | + cred.iterations(), |
| 180 | + std::move(stored_key)); |
| 181 | + } |
| 182 | + return valid; |
| 183 | +} |
| 184 | +} // namespace |
| 185 | + |
| 186 | +namespace detail { |
| 187 | + |
151 | 188 | std::optional<std::string_view> validate_scram_credential( |
152 | | - const scram_credential& cred, const credential_password& password) { |
| 189 | + const scram_credential& cred, |
| 190 | + const credential_password& password, |
| 191 | + scram_credential_cache* cache) { |
153 | 192 | std::optional<std::string_view> sasl_mechanism; |
154 | 193 | if ( |
155 | | - cred.stored_key().size() == security::scram_sha256::key_size |
156 | | - && security::scram_sha256::validate_password( |
157 | | - password, cred.stored_key(), cred.salt(), cred.iterations())) { |
158 | | - sasl_mechanism = security::scram_sha256_authenticator::name; |
| 194 | + cred.stored_key().size() == scram_sha256::key_size |
| 195 | + && match_password<scram_sha256>(cache, cred, password)) { |
| 196 | + sasl_mechanism = scram_sha256_authenticator::name; |
159 | 197 | } else if ( |
160 | | - cred.stored_key().size() == security::scram_sha512::key_size |
161 | | - && security::scram_sha512::validate_password( |
162 | | - password, cred.stored_key(), cred.salt(), cred.iterations())) { |
163 | | - sasl_mechanism = security::scram_sha512_authenticator::name; |
| 198 | + cred.stored_key().size() == scram_sha512::key_size |
| 199 | + && match_password<scram_sha512>(cache, cred, password)) { |
| 200 | + sasl_mechanism = scram_sha512_authenticator::name; |
164 | 201 | } |
165 | 202 |
|
166 | 203 | return sasl_mechanism; |
167 | 204 | } |
| 205 | +} // namespace detail |
| 206 | + |
| 207 | +std::optional<std::string_view> validate_scram_credential( |
| 208 | + const scram_credential& cred, const credential_password& password) { |
| 209 | + if (config::shard_local_cfg().scram_credential_cache_enabled()) { |
| 210 | + static thread_local scram_credential_cache cache{ |
| 211 | + scram_credential_cache::default_capacity}; |
| 212 | + return detail::validate_scram_credential(cred, password, &cache); |
| 213 | + } |
| 214 | + return detail::validate_scram_credential(cred, password, nullptr); |
| 215 | +} |
168 | 216 |
|
169 | 217 | } // namespace security |
0 commit comments