private void handleListMechsResponse ( ChannelHandlerContext ctx , FullBinaryMemcacheResponse msg ) throws Exception { String remote = ctx . channel ( ) . remoteAddress ( ) . toString ( ) ; String [ ] supportedMechanisms = msg . content ( ) . toString ( CharsetUtil . UTF_8 ) . split ( " " ) ; if ( supportedMechanisms . length == 0 ) { throw new AuthenticationException ( "Received empty SASL mechanisms list from server: " + remote ) ; } if ( forceSaslPlain ) { LOGGER . trace ( "Got SASL Mechs {} but forcing PLAIN due to config setting." , Arrays . asList ( supportedMechanisms ) ) ; supportedMechanisms = new String [ ] { "PLAIN" } ; } saslClient = Sasl . createSaslClient ( supportedMechanisms , null , "couchbase" , remote , null , this ) ; selectedMechanism = saslClient . getMechanismName ( ) ; int mechanismLength = selectedMechanism . length ( ) ; byte [ ] bytePayload = saslClient . hasInitialResponse ( ) ? saslClient . evaluateChallenge ( new byte [ ] { } ) : null ; ByteBuf payload = bytePayload != null ? ctx . alloc ( ) . buffer ( ) . writeBytes ( bytePayload ) : Unpooled . EMPTY_BUFFER ; FullBinaryMemcacheRequest initialRequest = new DefaultFullBinaryMemcacheRequest ( selectedMechanism . getBytes ( CharsetUtil . UTF_8 ) , Unpooled . EMPTY_BUFFER , payload ) ; initialRequest . setOpcode ( SASL_AUTH_OPCODE ) . setKeyLength ( ( short ) mechanismLength ) . setTotalBodyLength ( mechanismLength + payload . readableBytes ( ) ) ; ChannelFuture future = ctx . writeAndFlush ( initialRequest ) ; future . addListener ( new GenericFutureListener < Future < Void > > ( ) { @ Override public void operationComplete ( Future < Void > future ) throws Exception { if ( ! future . isSuccess ( ) ) { LOGGER . warn ( "Error during SASL Auth negotiation phase." , future ) ; } } } ) ; }
Handles an incoming SASL list mechanisms response and dispatches the next SASL AUTH step .