|
30 | 30 | /// asynchronously. |
31 | 31 |
|
32 | 32 | // MQB |
33 | | -#include <mqbblp_clustercatalog.h> |
34 | 33 | #include <mqbcfg_messages.h> |
35 | 34 | #include <mqbnet_authenticationcontext.h> |
36 | 35 | #include <mqbnet_initialconnectioncontext.h> |
37 | 36 | #include <mqbplug_authenticator.h> |
38 | 37 |
|
39 | 38 | // BMQ |
| 39 | +#include <bmqex_systemexecutor.h> |
40 | 40 | #include <bmqio_channel.h> |
41 | 41 | #include <bmqio_status.h> |
42 | 42 | #include <bmqp_ctrlmsg_messages.h> |
@@ -124,34 +124,52 @@ int Authenticator::onAuthenticationResponse( |
124 | 124 | return -1; |
125 | 125 | } |
126 | 126 |
|
127 | | -int Authenticator::sendAuthenticationMessage( |
128 | | - bsl::ostream& errorDescription, |
129 | | - const bmqp_ctrlmsg::AuthenticationMessage& message, |
130 | | - const bsl::shared_ptr<bmqio::Channel>& channel, |
131 | | - bmqp::EncodingType::Enum authenticationEncodingType) |
| 127 | +int Authenticator::sendAuthenticationResponse( |
| 128 | + bsl::ostream& errorDescription, |
| 129 | + int authnRc, |
| 130 | + bsl::string_view errorMsg, |
| 131 | + const bsl::optional<bsls::Types::Int64>& lifetimeMs, |
| 132 | + const bsl::shared_ptr<bmqio::Channel>& channel, |
| 133 | + bmqp::EncodingType::Enum authenticationEncodingType) |
132 | 134 | { |
133 | 135 | // executed by an *AUTHENTICATION* thread |
134 | | - |
135 | 136 | enum RcEnum { |
136 | 137 | // Value for the various RC error categories |
137 | 138 | rc_SUCCESS = 0, |
138 | 139 | rc_BUILD_FAILURE = -1, |
139 | 140 | rc_WRITE_FAILURE = -2 |
140 | 141 | }; |
141 | 142 |
|
| 143 | + // Build authentication response message |
| 144 | + bmqp_ctrlmsg::AuthenticationMessage message; |
| 145 | + bmqp_ctrlmsg::AuthenticationResponse& response = |
| 146 | + message.makeAuthenticationResponse(); |
| 147 | + |
| 148 | + response.status().code() = authnRc; |
| 149 | + response.status().message() = errorMsg; |
| 150 | + |
| 151 | + if (authnRc != 0) { |
| 152 | + response.status().category() = bmqp_ctrlmsg::StatusCategory::E_REFUSED; |
| 153 | + } |
| 154 | + else { |
| 155 | + response.status().category() = bmqp_ctrlmsg::StatusCategory::E_SUCCESS; |
| 156 | + response.lifetimeMs() = lifetimeMs; |
| 157 | + } |
| 158 | + |
| 159 | + // Send authentication response message |
142 | 160 | bdlma::LocalSequentialAllocator<2048> localAllocator(d_allocator_p); |
143 | 161 | bmqp::SchemaEventBuilder builder(d_blobSpPool_p, |
144 | 162 | authenticationEncodingType, |
145 | 163 | &localAllocator); |
146 | 164 |
|
147 | | - int rc = builder.setMessage(message, bmqp::EventType::e_AUTHENTICATION); |
| 165 | + int rc = builder.setMessage(response, bmqp::EventType::e_AUTHENTICATION); |
148 | 166 | if (rc != 0) { |
149 | 167 | errorDescription << "Failed building AuthenticationMessage " |
150 | 168 | << "[rc: " << rc << ", message: " << message << "]"; |
151 | 169 | return rc_BUILD_FAILURE; // RETURN |
152 | 170 | } |
153 | 171 |
|
154 | | - // Send response event |
| 172 | + // Send authnResponse event |
155 | 173 | bmqio::Status status; |
156 | 174 | channel->write(&status, *builder.blob()); |
157 | 175 | if (!status) { |
@@ -206,19 +224,11 @@ void Authenticator::authenticate( |
206 | 224 | enum RcEnum { |
207 | 225 | // Value for the various RC error categories |
208 | 226 | rc_SUCCESS = 0, |
209 | | - rc_BUILD_RESPONSE_FAILED = -1, |
210 | | - rc_AUTHENTICATION_FAILED = -2, |
| 227 | + rc_AUTHENTICATION_FAILED = -1, |
| 228 | + rc_SCHEDULE_REAUTHN_FAILED = -2, |
211 | 229 | rc_SEND_AUTHENTICATION_RESPONSE_FAILED = -3, |
212 | 230 | }; |
213 | 231 |
|
214 | | - const bmqp_ctrlmsg::AuthenticationRequest& authenticationRequest = |
215 | | - context->authenticationMessage().authenticationRequest(); |
216 | | - |
217 | | - bmqp_ctrlmsg::AuthenticationMessage authenticationResponse; |
218 | | - bmqp_ctrlmsg::AuthenticationResponse& response = |
219 | | - authenticationResponse.makeAuthenticationResponse(); |
220 | | - bmqp_ctrlmsg::Status& status = response.status(); |
221 | | - |
222 | 232 | int rc = rc_SUCCESS; |
223 | 233 | bsl::string error; |
224 | 234 |
|
@@ -248,127 +258,81 @@ void Authenticator::authenticate( |
248 | 258 | bsl::monostate())); |
249 | 259 | } |
250 | 260 |
|
| 261 | + const bmqp_ctrlmsg::AuthenticationRequest& authenticationRequest = |
| 262 | + context->authenticationMessage().authenticationRequest(); |
| 263 | + |
251 | 264 | BALL_LOG_INFO << (isReauthn ? "Reauthenticating" : "Authenticating") |
252 | 265 | << " connection '" << channel->peerUri() |
253 | 266 | << "' with mechanism '" << authenticationRequest.mechanism() |
254 | 267 | << "'"; |
255 | 268 |
|
256 | | - // Build the authentication response. |
257 | | - bmqu::MemOutStream buildResponseErrStream; |
258 | | - int buildResponseRc = authenticateAndBuildResponse(buildResponseErrStream, |
259 | | - &response, |
260 | | - authenticationRequest, |
261 | | - channel, |
262 | | - context); |
263 | | - if (buildResponseRc != rc_SUCCESS) { |
264 | | - rc = (buildResponseRc * 10) + rc_BUILD_RESPONSE_FAILED; |
265 | | - error = buildResponseErrStream.str(); |
266 | | - return; // RETURN |
267 | | - } |
| 269 | + // Authenticate |
| 270 | + bmqu::MemOutStream authnErrStream; |
| 271 | + bsl::shared_ptr<mqbplug::AuthenticationResult> result; |
| 272 | + const bsl::vector<char>& data = authenticationRequest.data().isNull() |
| 273 | + ? bsl::vector<char>() |
| 274 | + : authenticationRequest.data().value(); |
| 275 | + mqbplug::AuthenticationData authenticationData(data, channel->peerUri()); |
| 276 | + const int authnRc = d_authnController_p->authenticate( |
| 277 | + authnErrStream, |
| 278 | + &result, |
| 279 | + authenticationRequest.mechanism(), |
| 280 | + authenticationData); |
268 | 281 |
|
269 | 282 | // For anonymous authentication, skip sending the response and proceed |
270 | | - // directly to the next negotiation step. |
| 283 | + // directly to the next negotiation step |
271 | 284 | if (isDefaultAuthn) { |
272 | 285 | BSLS_ASSERT(!isReauthn); |
273 | 286 |
|
274 | | - if (status.category() != bmqp_ctrlmsg::StatusCategory::E_SUCCESS) { |
275 | | - rc = (status.code() * 10) + rc_AUTHENTICATION_FAILED; |
276 | | - error = status.message(); |
| 287 | + if (authnRc != 0) { |
| 288 | + rc = (authnRc * 10) + rc_AUTHENTICATION_FAILED; |
| 289 | + error = authnErrStream.str(); |
277 | 290 | } |
278 | 291 | else { |
279 | 292 | input.value() = InitialConnectionEvent::e_AUTHN_SUCCESS; |
280 | 293 | } |
281 | 294 | return; // RETURN |
282 | 295 | } |
283 | 296 |
|
284 | | - // Send authentication response back to the client |
| 297 | + // Set authentication result, state and schedule reauthentication timer |
| 298 | + if (authnRc == 0) { |
| 299 | + bmqu::MemOutStream scheduleErrStream; |
| 300 | + context->setAuthenticationResult(result); |
| 301 | + const int scheduleRc = context->setAuthenticatedAndScheduleReauthn( |
| 302 | + scheduleErrStream, |
| 303 | + d_scheduler_p, |
| 304 | + result->lifetimeMs(), |
| 305 | + channel); |
| 306 | + if (scheduleRc != 0) { |
| 307 | + rc = (scheduleRc * 10) + rc_SCHEDULE_REAUTHN_FAILED; |
| 308 | + error = scheduleErrStream.str(); |
| 309 | + return; // RETURN |
| 310 | + } |
| 311 | + } |
| 312 | + |
| 313 | + // Build authentication response and send it back to the client |
285 | 314 | bmqu::MemOutStream sendResponseErrStream; |
286 | | - const int sendRc = sendAuthenticationMessage(sendResponseErrStream, |
287 | | - authenticationResponse, |
288 | | - channel, |
289 | | - context->encodingType()); |
290 | | - |
291 | | - if (status.category() != bmqp_ctrlmsg::StatusCategory::E_SUCCESS) { |
292 | | - rc = (status.code() * 10) + rc_AUTHENTICATION_FAILED; |
293 | | - error = status.message(); |
| 315 | + const int sendRc = sendAuthenticationResponse(sendResponseErrStream, |
| 316 | + authnRc, |
| 317 | + authnErrStream.str(), |
| 318 | + result->lifetimeMs(), |
| 319 | + channel, |
| 320 | + context->encodingType()); |
| 321 | + |
| 322 | + if (authnRc != 0) { |
| 323 | + rc = (authnRc * 10) + rc_AUTHENTICATION_FAILED; |
| 324 | + error = authnErrStream.str(); |
294 | 325 | return; // RETURN |
295 | 326 | } |
296 | 327 |
|
297 | | - if (sendRc != rc_SUCCESS) { |
| 328 | + if (sendRc != 0) { |
298 | 329 | rc = (sendRc * 10) + rc_SEND_AUTHENTICATION_RESPONSE_FAILED; |
299 | 330 | error = sendResponseErrStream.str(); |
300 | 331 | return; // RETURN |
301 | 332 | } |
302 | 333 |
|
303 | | - // Authentication succeeded. |
304 | | - if (isReauthn) { |
305 | | - // Release the error guard to prevent error handling |
306 | | - scopeGuard.value().release(); |
307 | | - } |
308 | | - else { |
309 | | - // Transition to the next state |
310 | | - input.value() = InitialConnectionEvent::e_AUTHN_SUCCESS; |
311 | | - } |
312 | | -} |
313 | | - |
314 | | -int Authenticator::authenticateAndBuildResponse( |
315 | | - bsl::ostream& errorDescription, |
316 | | - bmqp_ctrlmsg::AuthenticationResponse* response, |
317 | | - const bmqp_ctrlmsg::AuthenticationRequest& request, |
318 | | - const bsl::shared_ptr<bmqio::Channel>& channel, |
319 | | - const AuthenticationContextSp& authenticationContext) |
320 | | -{ |
321 | | - // executed by an *AUTHENTICATION* thread |
322 | | - |
323 | | - enum RcEnum { |
324 | | - rc_SUCCESS = 0, |
325 | | - rc_SCHEDULE_REAUTHN_FAILED = -1, |
326 | | - }; |
327 | | - |
328 | | - bmqu::MemOutStream errorStream; |
329 | | - |
330 | | - bsl::shared_ptr<mqbplug::AuthenticationResult> result; |
331 | | - const bsl::vector<char>& data = request.data().isNull() |
332 | | - ? bsl::vector<char>() |
333 | | - : request.data().value(); |
334 | | - mqbplug::AuthenticationData authenticationData(data, channel->peerUri()); |
335 | | - |
336 | | - const int authnRc = d_authnController_p->authenticate(errorStream, |
337 | | - &result, |
338 | | - request.mechanism(), |
339 | | - authenticationData); |
340 | | - |
341 | | - if (authnRc != 0) { |
342 | | - response->status().code() = authnRc; |
343 | | - response->status().category() = |
344 | | - bmqp_ctrlmsg::StatusCategory::E_REFUSED; |
345 | | - response->status().message() = errorStream.str(); |
346 | | - } |
347 | | - else { |
348 | | - response->status().code() = 0; |
349 | | - response->status().category() = |
350 | | - bmqp_ctrlmsg::StatusCategory::E_SUCCESS; |
351 | | - response->lifetimeMs() = result->lifetimeMs(); |
352 | | - authenticationContext->setAuthenticationResult(result); |
353 | | - |
354 | | - const int rc = |
355 | | - authenticationContext->setAuthenticatedAndScheduleReauthn( |
356 | | - errorDescription, |
357 | | - d_scheduler_p, |
358 | | - result->lifetimeMs(), |
359 | | - channel); |
360 | | - |
361 | | - if (rc != 0) { |
362 | | - // `response` wouldn't be sent in this case as the connection will |
363 | | - // be closed by the caller. |
364 | | - response->status().code() = rc; |
365 | | - response->status().category() = |
366 | | - bmqp_ctrlmsg::StatusCategory::E_REFUSED; |
367 | | - return rc_SCHEDULE_REAUTHN_FAILED; |
368 | | - } |
369 | | - } |
370 | | - |
371 | | - return rc_SUCCESS; |
| 334 | + // Transition to the next state |
| 335 | + input.value() = InitialConnectionEvent::e_AUTHN_SUCCESS; |
372 | 336 | } |
373 | 337 |
|
374 | 338 | // CREATORS |
|
0 commit comments