コード例 #1
0
 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();
   }
 }
コード例 #2
0
    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();
      }
    }
コード例 #3
0
    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();
      }
    }