Skip to content

Commit dae302b

Browse files
committed
added reauthentication
Signed-off-by: Emelia Lei <[email protected]>
1 parent 175e5e1 commit dae302b

25 files changed

+775
-314
lines changed

src/groups/mqb/mqba/mqba_application.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -359,14 +359,15 @@ int Application::start(bsl::ostream& errorDescription)
359359
bslma::ManagedPtr<mqbnet::InitialConnectionHandler>
360360
initialConnectionHandlerMp(
361361
new (*d_allocator_p) InitialConnectionHandler(
362-
authenticatorMp,
363362
negotiatorMp,
363+
authenticatorMp.get(),
364364
d_allocators.get("InitialConnectionHandler")),
365365
d_allocator_p);
366366

367367
d_transportManager_mp.load(new (*d_allocator_p) mqbnet::TransportManager(
368368
d_scheduler_p,
369369
&d_bufferFactory,
370+
authenticatorMp,
370371
initialConnectionHandlerMp,
371372
d_statController_mp.get(),
372373
d_allocators.get("TransportManager")),

src/groups/mqb/mqba/mqba_authenticator.cpp

Lines changed: 244 additions & 59 deletions
Large diffs are not rendered by default.

src/groups/mqb/mqba/mqba_authenticator.h

Lines changed: 41 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -144,14 +144,47 @@ class Authenticator : public mqbnet::Authenticator {
144144
int sendAuthenticationMessage(
145145
bsl::ostream& errorDescription,
146146
const bmqp_ctrlmsg::AuthenticationMessage& message,
147-
const InitialConnectionContextSp& context);
148-
149-
/// Authenticate using a plugin based on the mechanism specified in the
150-
/// `AuthenticateRequest` message. If the authentication fails, reset
151-
/// `AuthenticationContext` and close the channel. Send an
152-
/// `AuthenticationResponse` message back to the peer with the status of
153-
/// the authentication.
154-
void authenticate(const InitialConnectionContextSp& context);
147+
const bsl::shared_ptr<bmqio::Channel>& channel,
148+
bmqp::EncodingType::Enum authenticationEncodingType);
149+
150+
/// Schedule an authentication job in the thread pool using the
151+
/// specified `context` and `channel`. Return 0 on success, or a
152+
/// non-zero error code and populate the specified `errorDescription`
153+
/// with a description of the error otherwise.
154+
int authenticateAsync(bsl::ostream& errorDescription,
155+
const AuthenticationContextSp& context,
156+
const bsl::shared_ptr<bmqio::Channel>& channel);
157+
158+
/// Schedule a re-authentication job in the thread pool using the
159+
/// specified `context` and `channel`. Return 0 on success, or a
160+
/// non-zero error code and populate the specified `errorDescription`
161+
/// with a description of the error otherwise.
162+
int reAuthenticateAsync(bsl::ostream& errorDescription,
163+
const AuthenticationContextSp& context,
164+
const bsl::shared_ptr<bmqio::Channel>& channel);
165+
166+
/// Authenticate the connection using the `AuthenticationMessage` stored in
167+
/// `context`. If authentication fails, invoke
168+
/// `initialConnectionCompleteCb` to close the `channel`. Also, update the
169+
/// state of `context` as appropriate.
170+
void authenticate(const AuthenticationContextSp& context,
171+
const bsl::shared_ptr<bmqio::Channel>& channel);
172+
173+
/// Re-authenticate the connection using the `AuthenticationMessage`
174+
/// stored in `context`. If re-authentication fails, invoke
175+
/// `initialConnectionCompleteCb` to close the `channel`. Also, update the
176+
/// state of `context` as appropriate.
177+
void reAuthenticate(const AuthenticationContextSp& context,
178+
const bsl::shared_ptr<bmqio::Channel>& channel);
179+
180+
/// Handle re-authentication depending on the type of AuthenticationMessage
181+
/// stored in `context` for the specified `context` and `channel`. If the
182+
/// re-authentication is successful, return 0; otherwise, return a non-zero
183+
/// error code and populate the specified `errorDescription` with a
184+
/// description of the error.
185+
int handleReauthentication(bsl::ostream& errorDescription,
186+
const AuthenticationContextSp& context,
187+
const bsl::shared_ptr<bmqio::Channel>& channel);
155188

156189
public:
157190
// TRAITS

src/groups/mqb/mqba/mqba_clientsession.cpp

Lines changed: 62 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -153,6 +153,7 @@
153153
#include <mqbcfg_brokerconfig.h>
154154
#include <mqbi_cluster.h>
155155
#include <mqbi_queue.h>
156+
#include <mqbnet_authenticationcontext.h>
156157
#include <mqbnet_tcpsessionfactory.h>
157158
#include <mqbstat_brokerstats.h>
158159
#include <mqbu_messageguidutil.h>
@@ -2631,14 +2632,16 @@ ClientSession::ClientSession(
26312632
const bsl::shared_ptr<bmqio::Channel>& channel,
26322633
const bmqp_ctrlmsg::NegotiationMessage& negotiationMessage,
26332634
const bsl::string& sessionDescription,
2634-
mqbi::Dispatcher* dispatcher,
2635-
mqbblp::ClusterCatalog* clusterCatalog,
2636-
mqbi::DomainFactory* domainFactory,
2637-
bslma::ManagedPtr<bmqst::StatContext>& clientStatContext,
2638-
ClientSessionState::BlobSpPool* blobSpPool,
2639-
bdlbb::BlobBufferFactory* bufferFactory,
2640-
bdlmt::EventScheduler* scheduler,
2641-
bslma::Allocator* allocator)
2635+
const bsl::shared_ptr<mqbnet::AuthenticationContext>&
2636+
authenticationContext,
2637+
mqbi::Dispatcher* dispatcher,
2638+
mqbblp::ClusterCatalog* clusterCatalog,
2639+
mqbi::DomainFactory* domainFactory,
2640+
bslma::ManagedPtr<bmqst::StatContext>& clientStatContext,
2641+
ClientSessionState::BlobSpPool* blobSpPool,
2642+
bdlbb::BlobBufferFactory* bufferFactory,
2643+
bdlmt::EventScheduler* scheduler,
2644+
bslma::Allocator* allocator)
26422645
: d_self(this) // use default allocator
26432646
, d_operationState(e_RUNNING)
26442647
, d_isDisconnecting(false)
@@ -2650,6 +2653,7 @@ ClientSession::ClientSession(
26502653
bmqp::MessagePropertiesFeatures::k_MESSAGE_PROPERTIES_EX,
26512654
d_clientIdentity_p->features()))
26522655
, d_description(sessionDescription, allocator)
2656+
, d_authenticationContext(authenticationContext)
26532657
, d_channel_sp(channel)
26542658
, d_state(clientStatContext,
26552659
blobSpPool,
@@ -2716,7 +2720,56 @@ void ClientSession::processEvent(const bmqp::Event& event,
27162720
{
27172721
// executed by the *IO* thread
27182722

2719-
if (event.isControlEvent()) {
2723+
// TODO: uncomment when default credential support is implemented
2724+
// if (!event.isAuthenticationEvent() && !d_authenticationContext) {
2725+
// BALL_LOG_ERROR << "The authentication lifetime has expired. Need to
2726+
// "
2727+
// "re-authenticate.";
2728+
// return; // RETURN
2729+
// }
2730+
2731+
if (event.isAuthenticationEvent()) {
2732+
if (d_authenticationContext->state().testAndSwap(
2733+
AuthnState::e_AUTHENTICATED,
2734+
AuthnState::e_AUTHENTICATING) != AuthnState::e_AUTHENTICATED) {
2735+
BALL_LOG_ERROR << "#CLIENT_IMPROPER_BEHAVIOR " << description()
2736+
<< ": received Authentication event while "
2737+
"authentication is in progress";
2738+
return; // RETURN
2739+
}
2740+
2741+
bmqp_ctrlmsg::AuthenticationMessage authenticationMessage;
2742+
int rc = event.loadAuthenticationEvent(&authenticationMessage);
2743+
if (rc != 0) {
2744+
BALL_LOG_ERROR << "#CORRUPTED_EVENT " << description()
2745+
<< ": Received invalid authentication message "
2746+
"from client [reason: 'failed to decode', rc: "
2747+
<< rc << "]:\n"
2748+
<< bmqu::BlobStartHexDumper(event.blob());
2749+
return; // RETURN
2750+
}
2751+
2752+
BALL_LOG_INFO << description() << ": Received authentication message: "
2753+
<< authenticationMessage;
2754+
2755+
d_authenticationContext->setAuthenticationMessage(
2756+
authenticationMessage);
2757+
d_authenticationContext->setAuthenticationEncodingType(
2758+
event.authenticationEventEncodingType());
2759+
2760+
bmqu::MemOutStream errorStream;
2761+
rc = d_authenticationContext->reAuthenticateCb()(
2762+
errorStream,
2763+
d_authenticationContext,
2764+
d_channel_sp);
2765+
if (rc != 0) {
2766+
BALL_LOG_ERROR << "#AUTHENTICATION_FAILED " << description()
2767+
<< ": Authentication failed [reason: '"
2768+
<< errorStream.str() << "', rc: " << rc << "]";
2769+
return; // RETURN
2770+
}
2771+
}
2772+
else if (event.isControlEvent()) {
27202773
bdlma::LocalSequentialAllocator<2048> localAllocator(
27212774
d_state.d_allocator_p);
27222775
bmqp_ctrlmsg::ControlMessage controlMessage(&localAllocator);

src/groups/mqb/mqba/mqba_clientsession.h

Lines changed: 19 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,8 @@
3333
#include <mqbi_dispatcher.h>
3434
#include <mqbi_domain.h>
3535
#include <mqbi_queue.h>
36+
#include <mqbnet_authenticationcontext.h>
37+
#include <mqbnet_initialconnectioncontext.h>
3638
#include <mqbnet_session.h>
3739
#include <mqbstat_queuestats.h>
3840

@@ -255,6 +257,8 @@ class ClientSession : public mqbnet::Session,
255257

256258
typedef bsl::function<void(void)> VoidFunctor;
257259

260+
typedef mqbnet::AuthenticationContext::State AuthnState;
261+
258262
/// Enum to signify the session's operation state.
259263
enum OperationState {
260264
/// Running normally.
@@ -337,6 +341,11 @@ class ClientSession : public mqbnet::Session,
337341
/// Short identifier for this session.
338342
bsl::string d_description;
339343

344+
/// The authenticationContext first created during authentication in
345+
/// initial connection, and later on may get updated during
346+
/// re-authentication.
347+
bsl::shared_ptr<mqbnet::AuthenticationContext> d_authenticationContext;
348+
340349
/// Channel associated with this session.
341350
bsl::shared_ptr<bmqio::Channel> d_channel_sp;
342351

@@ -628,14 +637,16 @@ class ClientSession : public mqbnet::Session,
628637
ClientSession(const bsl::shared_ptr<bmqio::Channel>& channel,
629638
const bmqp_ctrlmsg::NegotiationMessage& negotiationMessage,
630639
const bsl::string& sessionDescription,
631-
mqbi::Dispatcher* dispatcher,
632-
mqbblp::ClusterCatalog* clusterCatalog,
633-
mqbi::DomainFactory* domainFactory,
634-
bslma::ManagedPtr<bmqst::StatContext>& clientStatContext,
635-
ClientSessionState::BlobSpPool* blobSpPool,
636-
bdlbb::BlobBufferFactory* bufferFactory,
637-
bdlmt::EventScheduler* scheduler,
638-
bslma::Allocator* allocator);
640+
const bsl::shared_ptr<mqbnet::AuthenticationContext>&
641+
authenticationContext,
642+
mqbi::Dispatcher* dispatcher,
643+
mqbblp::ClusterCatalog* clusterCatalog,
644+
mqbi::DomainFactory* domainFactory,
645+
bslma::ManagedPtr<bmqst::StatContext>& clientStatContext,
646+
ClientSessionState::BlobSpPool* blobSpPool,
647+
bdlbb::BlobBufferFactory* bufferFactory,
648+
bdlmt::EventScheduler* scheduler,
649+
bslma::Allocator* allocator);
639650

640651
/// Destructor
641652
~ClientSession() BSLS_KEYWORD_OVERRIDE;

src/groups/mqb/mqba/mqba_clientsession.t.cpp

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
#include <mqbmock_queue.h>
2727
#include <mqbmock_queueengine.h>
2828
#include <mqbmock_queuehandle.h>
29+
#include <mqbnet_initialconnectioncontext.h>
2930
#include <mqbstat_brokerstats.h>
3031
#include <mqbstat_queuestats.h>
3132
#include <mqbu_messageguidutil.h>
@@ -689,6 +690,7 @@ class TestBench {
689690
, d_cs(d_channel,
690691
negotiationMessage,
691692
"sessionDescription",
693+
bsl::shared_ptr<mqbnet::AuthenticationContext>(),
692694
setInDispatcherThread(&d_mockDispatcher),
693695
0, // ClusterCatalog
694696
&d_mockDomainFactory,
@@ -2125,7 +2127,7 @@ static void test11_initiateShutdown()
21252127
100000000); // 100 ms
21262128
bslmt::TimedSemaphore semaphore;
21272129
bmqp::Protocol::MsgGroupId msgGroupId(bmqtst::TestHelperUtil::allocator());
2128-
const unsigned int subscriptionId =
2130+
const unsigned int subscriptionId =
21292131
bmqp::Protocol::k_DEFAULT_SUBSCRIPTION_ID;
21302132
const unsigned int subQueueId = bmqp::QueueId::k_DEFAULT_SUBQUEUE_ID;
21312133

@@ -2376,11 +2378,11 @@ static void test11_initiateShutdown()
23762378

23772379
PV("Confirm multiple messsages while shutting down");
23782380
{
2379-
const int NUM_MESSAGES = 5;
2381+
const int NUM_MESSAGES = 5;
23802382
TestBench tb(client(e_FirstHop),
23812383
isAtMostOnce,
23822384
bmqtst::TestHelperUtil::allocator());
2383-
bsls::AtomicInt callbackCounter(0);
2385+
bsls::AtomicInt callbackCounter(0);
23842386
bsl::vector<bmqt::MessageGUID> guids(
23852387
bmqtst::TestHelperUtil::allocator());
23862388
guids.reserve(NUM_MESSAGES);

src/groups/mqb/mqba/mqba_initialconnectionhandler.cpp

Lines changed: 11 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -211,11 +211,10 @@ int InitialConnectionHandler::processBlob(
211211
context->negotiationContext()->d_negotiationMessage =
212212
bsl::get<bmqp_ctrlmsg::NegotiationMessage>(message.value());
213213

214-
rc = d_negotiator_mp->createSessionOnMsgType(
215-
errorDescription,
216-
session,
217-
isContinueRead,
218-
context->negotiationContext());
214+
rc = d_negotiator_mp->createSessionOnMsgType(errorDescription,
215+
session,
216+
isContinueRead,
217+
context);
219218
}
220219

221220
return rc;
@@ -334,9 +333,9 @@ void InitialConnectionHandler::complete(
334333
}
335334

336335
InitialConnectionHandler::InitialConnectionHandler(
337-
bslma::ManagedPtr<mqbnet::Authenticator>& authenticator,
338-
bslma::ManagedPtr<mqbnet::Negotiator>& negotiator,
339-
bslma::Allocator* allocator)
336+
bslma::ManagedPtr<mqbnet::Negotiator>& negotiator,
337+
mqbnet::Authenticator* authenticator,
338+
bslma::Allocator* allocator)
340339
: d_authenticator_mp(authenticator)
341340
, d_negotiator_mp(negotiator)
342341
, d_allocator_p(allocator)
@@ -397,8 +396,10 @@ void InitialConnectionHandler::handleConnectionFlow(
397396
rc = scheduleRead(errStream, context);
398397
}
399398
else {
400-
rc = d_negotiator_mp->negotiateOutbound(errStream,
401-
context->negotiationContext());
399+
// TODO: When we are ready to move on to the next step, we should
400+
// call `authenticationOutbound` here instead before calling
401+
// `negotiateOutbound`.
402+
rc = d_negotiator_mp->negotiateOutbound(errStream, context);
402403

403404
// Send outbound request success, continue to read
404405
if (rc == 0) {
@@ -414,17 +415,6 @@ void InitialConnectionHandler::handleConnectionFlow(
414415
guard.release();
415416
}
416417

417-
int InitialConnectionHandler::start(bsl::ostream& errorDescription)
418-
{
419-
int rc = d_authenticator_mp->start(errorDescription);
420-
return rc;
421-
}
422-
423-
void InitialConnectionHandler::stop()
424-
{
425-
d_authenticator_mp->stop();
426-
}
427-
428418
void InitialConnectionHandler::handleInitialConnection(
429419
const InitialConnectionContextSp& context)
430420
{

src/groups/mqb/mqba/mqba_initialconnectionhandler.h

Lines changed: 4 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,7 @@ class InitialConnectionHandler : public mqbnet::InitialConnectionHandler {
7171
// DATA
7272

7373
/// Authenticator to use for authenticating a connection.
74-
bslma::ManagedPtr<mqbnet::Authenticator> d_authenticator_mp;
74+
mqbnet::Authenticator* d_authenticator_mp;
7575

7676
/// Negotiator to use for converting a Channel to a Session.
7777
bslma::ManagedPtr<mqbnet::Negotiator> d_negotiator_mp;
@@ -148,24 +148,15 @@ class InitialConnectionHandler : public mqbnet::InitialConnectionHandler {
148148
public:
149149
// CREATORS
150150

151-
InitialConnectionHandler(
152-
bslma::ManagedPtr<mqbnet::Authenticator>& authenticator,
153-
bslma::ManagedPtr<mqbnet::Negotiator>& negotiator,
154-
bslma::Allocator* allocator);
151+
InitialConnectionHandler(bslma::ManagedPtr<mqbnet::Negotiator>& negotiator,
152+
mqbnet::Authenticator* authenticator,
153+
bslma::Allocator* allocator);
155154

156155
/// Destructor
157156
~InitialConnectionHandler() BSLS_KEYWORD_OVERRIDE;
158157

159158
// MANIPULATORS
160159

161-
/// Start the InitialConnectionHandler. Return 0 on success, or a
162-
/// non-zero error code and populate the specified `errorDescription`
163-
/// with a description of the error otherwise.
164-
int start(bsl::ostream& errorDescription) BSLS_KEYWORD_OVERRIDE;
165-
166-
/// Stop the InitialConnectionHandler.
167-
void stop() BSLS_KEYWORD_OVERRIDE;
168-
169160
/// Method invoked by the client of this object to negotiate a session.
170161
/// The specified `context` is an in-out member holding the initial
171162
/// connection context to use, including an

0 commit comments

Comments
 (0)