public void handleEvent(final ConnectedMessageChannel channel) { final Pooled<ByteBuffer> pooledReceiveBuffer = connection.allocate(); try { final ByteBuffer receiveBuffer = pooledReceiveBuffer.getResource(); int res = 0; try { res = channel.receive(receiveBuffer); } catch (IOException e) { connection.handleException(e); return; } if (res == -1) { connection.handleException(client.abruptClose(connection)); return; } if (res == 0) { return; } client.tracef("Received %s", receiveBuffer); receiveBuffer.flip(); String serverName = channel.getPeerAddress(InetSocketAddress.class).getHostName(); final byte msgType = receiveBuffer.get(); switch (msgType) { case Protocol.CONNECTION_ALIVE: { client.trace("Client received connection alive"); return; } case Protocol.CONNECTION_CLOSE: { client.trace("Client received connection close request"); connection.handleIncomingCloseRequest(); return; } case Protocol.GREETING: { client.trace("Client received greeting"); while (receiveBuffer.hasRemaining()) { final byte type = receiveBuffer.get(); final int len = receiveBuffer.get() & 0xff; final ByteBuffer data = Buffers.slice(receiveBuffer, len); switch (type) { case Protocol.GRT_SERVER_NAME: { serverName = Buffers.getModifiedUtf8(data); client.tracef("Client received server name: %s", serverName); break; } default: { client.tracef( "Client received unknown greeting message %02x", Integer.valueOf(type & 0xff)); // unknown, skip it for forward compatibility. break; } } } sendCapRequest(serverName); return; } default: { client.unknownProtocolId(msgType); connection.handleException(client.invalidMessage(connection)); return; } } } catch (BufferUnderflowException e) { connection.handleException(client.invalidMessage(connection)); return; } catch (BufferOverflowException e) { connection.handleException(client.invalidMessage(connection)); return; } finally { pooledReceiveBuffer.free(); } }
public void handleEvent(final ConnectedMessageChannel channel) { final Pooled<ByteBuffer> pooledReceiveBuffer = connection.allocate(); try { final ByteBuffer receiveBuffer = pooledReceiveBuffer.getResource(); int res = 0; try { res = channel.receive(receiveBuffer); } catch (IOException e) { connection.handleException(e); return; } if (res == -1) { connection.handleException(client.abruptClose(connection)); return; } if (res == 0) { return; } receiveBuffer.flip(); boolean starttls = false; final Set<String> saslMechs = new LinkedHashSet<String>(); final byte msgType = receiveBuffer.get(); switch (msgType) { case Protocol.CONNECTION_ALIVE: { client.trace("Client received connection alive"); return; } case Protocol.CONNECTION_CLOSE: { client.trace("Client received connection close request"); connection.handleIncomingCloseRequest(); return; } case Protocol.CAPABILITIES: { client.trace("Client received capabilities response"); while (receiveBuffer.hasRemaining()) { final byte type = receiveBuffer.get(); final int len = receiveBuffer.get() & 0xff; final ByteBuffer data = Buffers.slice(receiveBuffer, len); switch (type) { case Protocol.CAP_VERSION: { final byte version = data.get(); client.tracef( "Client received capability: version %d", Integer.valueOf(version & 0xff)); // We only support version zero, so knowing the other side's version is not // useful presently break; } case Protocol.CAP_SASL_MECH: { final String mechName = Buffers.getModifiedUtf8(data); client.tracef("Client received capability: SASL mechanism %s", mechName); if (!failedMechs.contains(mechName) && !disallowedMechs.contains(mechName) && (allowedMechs == null || allowedMechs.contains(mechName))) { client.tracef("SASL mechanism %s added to allowed set", mechName); saslMechs.add(mechName); } break; } case Protocol.CAP_STARTTLS: { client.trace("Client received capability: STARTTLS"); starttls = true; break; } default: { client.tracef( "Client received unknown capability %02x", Integer.valueOf(type & 0xff)); // unknown, skip it for forward compatibility. break; } } } if (starttls) { // only initiate starttls if not forbidden by config if (optionMap.get(Options.SSL_STARTTLS, true)) { // Prepare the request message body final Pooled<ByteBuffer> pooledSendBuffer = connection.allocate(); final ByteBuffer sendBuffer = pooledSendBuffer.getResource(); sendBuffer.put(Protocol.STARTTLS); sendBuffer.flip(); connection.setReadListener(new StartTls(serverName)); connection.send(pooledSendBuffer); // all set return; } } if (saslMechs.isEmpty()) { connection.handleException( new SaslException("No more authentication mechanisms to try")); return; } // OK now send our authentication request final OptionMap optionMap = connection.getOptionMap(); final String userName = optionMap.get(RemotingOptions.AUTHORIZE_ID); final Map<String, ?> propertyMap = SaslUtils.createPropertyMap( optionMap, Channels.getOption(channel, Options.SECURE, false)); final SaslClient saslClient; try { saslClient = AccessController.doPrivileged( new PrivilegedExceptionAction<SaslClient>() { public SaslClient run() throws SaslException { return Sasl.createSaslClient( saslMechs.toArray(new String[saslMechs.size()]), userName, "remote", serverName, propertyMap, callbackHandler); } }, accessControlContext); } catch (PrivilegedActionException e) { final SaslException se = (SaslException) e.getCause(); connection.handleException(se); return; } final String mechanismName = saslClient.getMechanismName(); client.tracef("Client initiating authentication using mechanism %s", mechanismName); // Prepare the request message body final Pooled<ByteBuffer> pooledSendBuffer = connection.allocate(); final ByteBuffer sendBuffer = pooledSendBuffer.getResource(); sendBuffer.put(Protocol.AUTH_REQUEST); Buffers.putModifiedUtf8(sendBuffer, mechanismName); sendBuffer.flip(); connection.send(pooledSendBuffer); connection.setReadListener(new Authentication(saslClient, serverName)); return; } default: { client.unknownProtocolId(msgType); connection.handleException(client.invalidMessage(connection)); return; } } } catch (BufferUnderflowException e) { connection.handleException(client.invalidMessage(connection)); return; } catch (BufferOverflowException e) { connection.handleException(client.invalidMessage(connection)); return; } finally { pooledReceiveBuffer.free(); } }
public void handleEvent(final ConnectedMessageChannel channel) { final Pooled<ByteBuffer> pooledReceiveBuffer = connection.allocate(); try { final ByteBuffer receiveBuffer = pooledReceiveBuffer.getResource(); synchronized (connection.getLock()) { int res; try { res = channel.receive(receiveBuffer); } catch (IOException e) { connection.handleException(e); return; } if (res == -1) { connection.handleException(client.abruptClose(connection)); return; } if (res == 0) { return; } } receiveBuffer.flip(); boolean starttls = false; final Set<String> serverSaslMechs = new LinkedHashSet<String>(); final byte msgType = receiveBuffer.get(); switch (msgType) { case Protocol.CONNECTION_ALIVE: { client.trace("Client received connection alive"); connection.sendAliveResponse(); return; } case Protocol.CONNECTION_ALIVE_ACK: { client.trace("Client received connection alive ack"); return; } case Protocol.CONNECTION_CLOSE: { client.trace("Client received connection close request"); connection.handlePreAuthCloseRequest(); return; } case Protocol.CAPABILITIES: { client.trace("Client received capabilities response"); String remoteEndpointName = null; int version = Protocol.VERSION; int behavior = Protocol.BH_FAULTY_MSG_SIZE; boolean useDefaultChannels = true; int channelsIn = 40; int channelsOut = 40; while (receiveBuffer.hasRemaining()) { final byte type = receiveBuffer.get(); final int len = receiveBuffer.get() & 0xff; final ByteBuffer data = Buffers.slice(receiveBuffer, len); switch (type) { case Protocol.CAP_VERSION: { version = data.get() & 0xff; client.tracef( "Client received capability: version %d", Integer.valueOf(version & 0xff)); break; } case Protocol.CAP_SASL_MECH: { final String mechName = Buffers.getModifiedUtf8(data); client.tracef("Client received capability: SASL mechanism %s", mechName); if (!failedMechs.containsKey(mechName) && !disallowedMechs.contains(mechName) && (allowedMechs == null || allowedMechs.contains(mechName))) { client.tracef("SASL mechanism %s added to allowed set", mechName); serverSaslMechs.add(mechName); } break; } case Protocol.CAP_STARTTLS: { client.trace("Client received capability: STARTTLS"); starttls = true; break; } case Protocol.CAP_ENDPOINT_NAME: { remoteEndpointName = Buffers.getModifiedUtf8(data); client.tracef( "Client received capability: remote endpoint name \"%s\"", remoteEndpointName); break; } case Protocol.CAP_MESSAGE_CLOSE: { behavior |= Protocol.BH_MESSAGE_CLOSE; // remote side must be >= 3.2.11.GA // but, we'll assume it's >= 3.2.14.GA because no AS or EAP release included // 3.2.8.SP1 < x < 3.2.14.GA behavior &= ~Protocol.BH_FAULTY_MSG_SIZE; client.tracef("Client received capability: message close protocol supported"); break; } case Protocol.CAP_VERSION_STRING: { // remote side must be >= 3.2.16.GA behavior &= ~Protocol.BH_FAULTY_MSG_SIZE; final String remoteVersionString = Buffers.getModifiedUtf8(data); client.tracef( "Client received capability: remote version is \"%s\"", remoteVersionString); break; } case Protocol.CAP_CHANNELS_IN: { useDefaultChannels = false; // their channels in is our channels out channelsOut = ProtocolUtils.readIntData(data, len); client.tracef( "Client received capability: remote channels in is \"%d\"", channelsOut); break; } case Protocol.CAP_CHANNELS_OUT: { useDefaultChannels = false; // their channels out is our channels in channelsIn = ProtocolUtils.readIntData(data, len); client.tracef( "Client received capability: remote channels out is \"%d\"", channelsIn); break; } default: { client.tracef( "Client received unknown capability %02x", Integer.valueOf(type & 0xff)); // unknown, skip it for forward compatibility. break; } } } if (useDefaultChannels) { channelsIn = 40; channelsOut = 40; } if (starttls) { // only initiate starttls if not forbidden by config if (optionMap.get(Options.SSL_STARTTLS, true)) { // Prepare the request message body final Pooled<ByteBuffer> pooledSendBuffer = connection.allocate(); boolean ok = false; try { final ByteBuffer sendBuffer = pooledSendBuffer.getResource(); sendBuffer.put(Protocol.STARTTLS); sendBuffer.flip(); connection.setReadListener(new StartTls(remoteServerName), true); connection.send(pooledSendBuffer); ok = true; // all set return; } finally { if (!ok) pooledSendBuffer.free(); } } } if (serverSaslMechs.isEmpty()) { if (failedMechs.isEmpty()) { connection.handleException( new SaslException( "Authentication failed: the server presented no authentication mechanisms")); } else { // At this point we have been attempting to use mechanisms as they have been // presented to us but we have now exhausted the list. connection.handleException(allMechanismsFailed()); } return; } // OK now send our authentication request final AuthenticationContextConfigurationClient configurationClient = AUTH_CONFIGURATION_CLIENT; AuthenticationConfiguration configuration = configurationClient.getAuthenticationConfiguration(uri, authenticationContext); final SaslClient saslClient; try { saslClient = configurationClient.createSaslClient( uri, configuration, saslClientFactory, serverSaslMechs); } catch (SaslException e) { // apparently no more mechanisms can succeed connection.handleException(e); return; } if (saslClient == null) { connection.handleException(allMechanismsFailed()); return; } final String mechanismName = saslClient.getMechanismName(); client.tracef("Client initiating authentication using mechanism %s", mechanismName); connection.getChannel().suspendReads(); final int negotiatedVersion = version; final SaslClient usedSaslClient = saslClient; final Authentication authentication = new Authentication( usedSaslClient, remoteServerName, remoteEndpointName, behavior, channelsIn, channelsOut); connection .getExecutor() .execute( () -> { final byte[] response; try { response = usedSaslClient.hasInitialResponse() ? usedSaslClient.evaluateChallenge(EMPTY_BYTES) : null; } catch (SaslException e) { client.tracef("Client authentication failed: %s", e); saslDispose(usedSaslClient); failedMechs.put(mechanismName, e.toString()); sendCapRequest(remoteServerName); return; } // Prepare the request message body final Pooled<ByteBuffer> pooledSendBuffer = connection.allocate(); boolean ok = false; try { final ByteBuffer sendBuffer = pooledSendBuffer.getResource(); sendBuffer.put(Protocol.AUTH_REQUEST); if (negotiatedVersion < 1) { sendBuffer.put(mechanismName.getBytes(Protocol.UTF_8)); } else { ProtocolUtils.writeString(sendBuffer, mechanismName); if (response != null) { sendBuffer.put(response); } } sendBuffer.flip(); connection.send(pooledSendBuffer); ok = true; connection.setReadListener(authentication, true); return; } finally { if (!ok) pooledSendBuffer.free(); } }); return; } default: { client.unknownProtocolId(msgType); connection.handleException(client.invalidMessage(connection)); return; } } } catch (BufferUnderflowException | BufferOverflowException e) { connection.handleException(client.invalidMessage(connection)); return; } finally { pooledReceiveBuffer.free(); } }