| | |
| | | * CDDL HEADER END |
| | | * |
| | | * |
| | | * Portions Copyright 2013-2015 ForgeRock AS |
| | | * Portions Copyright 2014 ForgeRock AS |
| | | * Copyright 2013-2015 ForgeRock AS |
| | | */ |
| | | package org.opends.server.protocols.http; |
| | | |
| | |
| | | import org.forgerock.opendj.rest2ldap.servlet.Rest2LDAPContextFactory; |
| | | import org.glassfish.grizzly.http.HttpProbe; |
| | | import org.glassfish.grizzly.http.server.HttpServer; |
| | | import org.glassfish.grizzly.http.server.HttpServerMonitoringConfig; |
| | | import org.glassfish.grizzly.http.server.NetworkListener; |
| | | import org.glassfish.grizzly.http.server.ServerConfiguration; |
| | | import org.glassfish.grizzly.monitoring.MonitoringConfig; |
| | |
| | | * with clients over HTTP. The connection handler is responsible for |
| | | * starting/stopping the embedded web server. |
| | | */ |
| | | public class HTTPConnectionHandler extends |
| | | ConnectionHandler<HTTPConnectionHandlerCfg> implements |
| | | ConfigurationChangeListener<HTTPConnectionHandlerCfg>, |
| | | ServerShutdownListener, AlertGenerator |
| | | public class HTTPConnectionHandler extends ConnectionHandler<HTTPConnectionHandlerCfg> |
| | | implements ConfigurationChangeListener<HTTPConnectionHandlerCfg>, |
| | | ServerShutdownListener, |
| | | AlertGenerator |
| | | { |
| | | |
| | | /** The tracer object for the debug logger. */ |
| | | private static final LocalizedLogger logger = LocalizedLogger.getLoggerForThisClass(); |
| | | |
| | |
| | | /** SSL instance name used in context creation. */ |
| | | private static final String SSL_CONTEXT_INSTANCE_NAME = "TLS"; |
| | | |
| | | private static final ObjectMapper JSON_MAPPER = new ObjectMapper().configure( |
| | | JsonParser.Feature.ALLOW_COMMENTS, true); |
| | | private static final ObjectMapper JSON_MAPPER = new ObjectMapper().configure(JsonParser.Feature.ALLOW_COMMENTS, true); |
| | | |
| | | /** The initialization configuration. */ |
| | | private HTTPConnectionHandlerCfg initConfig; |
| | |
| | | /** The current configuration. */ |
| | | private HTTPConnectionHandlerCfg currentConfig; |
| | | |
| | | /** |
| | | * Indicates whether the Directory Server is in the process of shutting down. |
| | | */ |
| | | /** Indicates whether the Directory Server is in the process of shutting down. */ |
| | | private volatile boolean shutdownRequested; |
| | | |
| | | /** Indicates whether this connection handler is enabled. */ |
| | |
| | | /** The friendly name of this connection handler. */ |
| | | private String friendlyName; |
| | | |
| | | /** |
| | | * The SSL engine configurator is used for obtaining default SSL parameters. |
| | | */ |
| | | /** The SSL engine configurator is used for obtaining default SSL parameters. */ |
| | | private SSLEngineConfigurator sslEngineConfigurator; |
| | | |
| | | /** |
| | | * Default constructor. It is invoked by reflection to create this |
| | | * {@link ConnectionHandler}. |
| | | */ |
| | | /** Default constructor. It is invoked by reflection to create this {@link ConnectionHandler}. */ |
| | | public HTTPConnectionHandler() |
| | | { |
| | | super(DEFAULT_FRIENDLY_NAME); |
| | |
| | | */ |
| | | public boolean acceptUnauthenticatedRequests() |
| | | { |
| | | // the global setting overrides the more specific setting here. |
| | | return !DirectoryServer.rejectUnauthenticatedRequests() |
| | | && !this.currentConfig.isAuthenticationRequired(); |
| | | // The global setting overrides the more specific setting here. |
| | | return !DirectoryServer.rejectUnauthenticatedRequests() && !this.currentConfig.isAuthenticationRequired(); |
| | | } |
| | | |
| | | /** |
| | |
| | | clientConnections.put(clientConnection, clientConnection); |
| | | } |
| | | |
| | | /** {@inheritDoc} */ |
| | | @Override |
| | | public ConfigChangeResult applyConfigurationChange( |
| | | HTTPConnectionHandlerCfg config) |
| | | public ConfigChangeResult applyConfigurationChange(HTTPConnectionHandlerCfg config) |
| | | { |
| | | final ConfigChangeResult ccr = new ConfigChangeResult(); |
| | | |
| | |
| | | } |
| | | |
| | | if (config.isEnabled() && this.currentConfig.isEnabled() && isListening()) |
| | | { // server was running and will still be running |
| | | // if the "enabled" was flipped, leave it to the stop / start server to |
| | | // handle it |
| | | { |
| | | // Server was running and will still be running if the "enabled" was flipped, |
| | | // leave it to the stop / start server to handle it. |
| | | if (!this.currentConfig.isKeepStats() && config.isKeepStats()) |
| | | { // it must now keep stats while it was not previously |
| | | { |
| | | // It must now keep stats while it was not previously. |
| | | setHttpStatsProbe(this.httpServer); |
| | | } |
| | | else if (this.currentConfig.isKeepStats() && !config.isKeepStats() |
| | | && this.httpProbe != null) |
| | | { // it must NOT keep stats anymore |
| | | else if (this.currentConfig.isKeepStats() && !config.isKeepStats() && this.httpProbe != null) |
| | | { |
| | | // It must NOT keep stats anymore. |
| | | getHttpConfig(this.httpServer).removeProbes(this.httpProbe); |
| | | this.httpProbe = null; |
| | | } |
| | |
| | | } |
| | | } |
| | | |
| | | /** {@inheritDoc} */ |
| | | @Override |
| | | public void finalizeConnectionHandler(LocalizableMessage finalizeReason) |
| | | { |
| | |
| | | } |
| | | } |
| | | |
| | | /** {@inheritDoc} */ |
| | | @Override |
| | | public Map<String, String> getAlerts() |
| | | { |
| | |
| | | return alerts; |
| | | } |
| | | |
| | | /** {@inheritDoc} */ |
| | | @Override |
| | | public String getClassName() |
| | | { |
| | | return HTTPConnectionHandler.class.getName(); |
| | | } |
| | | |
| | | /** {@inheritDoc} */ |
| | | @Override |
| | | public Collection<ClientConnection> getClientConnections() |
| | | { |
| | | return clientConnections.keySet(); |
| | | } |
| | | |
| | | /** {@inheritDoc} */ |
| | | @Override |
| | | public DN getComponentEntryDN() |
| | | { |
| | | return currentConfig.dn(); |
| | | } |
| | | |
| | | /** {@inheritDoc} */ |
| | | @Override |
| | | public String getConnectionHandlerName() |
| | | { |
| | |
| | | return this.currentConfig; |
| | | } |
| | | |
| | | /** {@inheritDoc} */ |
| | | @Override |
| | | public Collection<String> getEnabledSSLCipherSuites() |
| | | { |
| | |
| | | return super.getEnabledSSLCipherSuites(); |
| | | } |
| | | |
| | | /** {@inheritDoc} */ |
| | | @Override |
| | | public Collection<String> getEnabledSSLProtocols() |
| | | { |
| | |
| | | return super.getEnabledSSLProtocols(); |
| | | } |
| | | |
| | | /** {@inheritDoc} */ |
| | | @Override |
| | | public Collection<HostPort> getListeners() |
| | | { |
| | |
| | | return this.initConfig.getListenPort(); |
| | | } |
| | | |
| | | /** {@inheritDoc} */ |
| | | @Override |
| | | public String getProtocol() |
| | | { |
| | |
| | | return sslEngineConfigurator.createSSLEngine(); |
| | | } |
| | | |
| | | /** {@inheritDoc} */ |
| | | @Override |
| | | public String getShutdownListenerName() |
| | | { |
| | |
| | | return statTracker; |
| | | } |
| | | |
| | | /** {@inheritDoc} */ |
| | | @Override |
| | | public void initializeConnectionHandler(HTTPConnectionHandlerCfg config) |
| | | throws ConfigException, InitializationException |
| | |
| | | return nameBuffer.toString(); |
| | | } |
| | | |
| | | /** {@inheritDoc} */ |
| | | @Override |
| | | public boolean isConfigurationAcceptable(ConnectionHandlerCfg configuration, |
| | | List<LocalizableMessage> unacceptableReasons) |
| | | public boolean isConfigurationAcceptable( |
| | | ConnectionHandlerCfg configuration, List<LocalizableMessage> unacceptableReasons) |
| | | { |
| | | HTTPConnectionHandlerCfg config = (HTTPConnectionHandlerCfg) configuration; |
| | | |
| | |
| | | { |
| | | // Attempt to bind to the listen port on all configured addresses to |
| | | // verify whether the connection handler will be able to start. |
| | | LocalizableMessage errorMessage = |
| | | checkAnyListenAddressInUse(config.getListenAddress(), config |
| | | .getListenPort(), config.isAllowTCPReuseAddress(), config.dn()); |
| | | LocalizableMessage errorMessage = checkAnyListenAddressInUse( |
| | | config.getListenAddress(), config.getListenPort(), config.isAllowTCPReuseAddress(), config.dn()); |
| | | if (errorMessage != null) |
| | | { |
| | | unacceptableReasons.add(errorMessage); |
| | |
| | | catch (DirectoryException e) |
| | | { |
| | | logger.traceException(e); |
| | | |
| | | unacceptableReasons.add(e.getMessageObject()); |
| | | return false; |
| | | } |
| | |
| | | * null otherwise. |
| | | */ |
| | | private LocalizableMessage checkAnyListenAddressInUse( |
| | | Collection<InetAddress> listenAddresses, int listenPort, |
| | | boolean allowReuseAddress, DN configEntryDN) |
| | | Collection<InetAddress> listenAddresses, int listenPort, boolean allowReuseAddress, DN configEntryDN) |
| | | { |
| | | for (InetAddress a : listenAddresses) |
| | | { |
| | |
| | | catch (IOException e) |
| | | { |
| | | logger.traceException(e); |
| | | return ERR_CONNHANDLER_CANNOT_BIND.get("HTTP", configEntryDN, a.getHostAddress(), listenPort, |
| | | getExceptionMessage(e)); |
| | | return ERR_CONNHANDLER_CANNOT_BIND.get( |
| | | "HTTP", configEntryDN, a.getHostAddress(), listenPort, getExceptionMessage(e)); |
| | | } |
| | | } |
| | | return null; |
| | | } |
| | | |
| | | /** {@inheritDoc} */ |
| | | @Override |
| | | public boolean isConfigurationChangeAcceptable( |
| | | HTTPConnectionHandlerCfg configuration, List<LocalizableMessage> unacceptableReasons) |
| | |
| | | return currentConfig.isKeepStats(); |
| | | } |
| | | |
| | | /** {@inheritDoc} */ |
| | | @Override |
| | | public void processServerShutdown(LocalizableMessage reason) |
| | | { |
| | |
| | | return httpServer != null; |
| | | } |
| | | |
| | | /** {@inheritDoc} */ |
| | | @Override |
| | | public void start() |
| | | { |
| | | // The Directory Server start process should only return |
| | | // when the connection handlers port are fully opened |
| | | // and working. The start method therefore needs to wait for |
| | | // the created thread to |
| | | // The Directory Server start process should only return when the connection handlers port |
| | | // are fully opened and working. |
| | | // The start method therefore needs to wait for the created thread too. |
| | | synchronized (waitListen) |
| | | { |
| | | super.start(); |
| | |
| | | } |
| | | catch (InterruptedException e) |
| | | { |
| | | // If something interrupted the start its probably better |
| | | // to return ASAP. |
| | | // If something interrupted the start its probably better to return ASAP |
| | | } |
| | | } |
| | | } |
| | |
| | | clientConnections.remove(clientConnection); |
| | | } |
| | | |
| | | /** {@inheritDoc} */ |
| | | @Override |
| | | public void run() |
| | | { |
| | |
| | | |
| | | while (!shutdownRequested) |
| | | { |
| | | // If this connection handler is not enabled, then just sleep |
| | | // for a bit and check again. |
| | | // If this connection handler is not enabled, then just sleep for a bit and check again. |
| | | if (!this.enabled) |
| | | { |
| | | if (isListening()) |
| | |
| | | |
| | | if (starting) |
| | | { |
| | | // This may happen if there was an initialisation error |
| | | // which led to disable the connector. |
| | | // The main thread is waiting for the connector to listen |
| | | // on its port, which will not occur yet, |
| | | // This may happen if there was an initialisation error which led to disable the connector. |
| | | // The main thread is waiting for the connector to listen on its port, which will not occur yet, |
| | | // so notify here to allow the server startup to complete. |
| | | synchronized (waitListen) |
| | | { |
| | |
| | | |
| | | try |
| | | { |
| | | // At this point, the connection Handler either started |
| | | // correctly or failed to start but the start process |
| | | // should be notified and resume its work in any cases. |
| | | // At this point, the connection Handler either started correctly or failed |
| | | // to start but the start process should be notified and resume its work in any cases. |
| | | synchronized (waitListen) |
| | | { |
| | | waitListen.notify(); |
| | | } |
| | | |
| | | // If we have gotten here, then we are about to start listening |
| | | // for the first time since startup or since we were previously |
| | | // disabled. Start the embedded HTTP server |
| | | // for the first time since startup or since we were previously disabled. |
| | | // Start the embedded HTTP server |
| | | startHttpServer(); |
| | | lastIterationFailed = false; |
| | | } |
| | | catch (Exception e) |
| | | { |
| | | // clean up the messed up HTTP server |
| | | // Clean up the messed up HTTP server |
| | | cleanUpHttpServer(); |
| | | |
| | | // error + alert about the horked config |
| | | // Error + alert about the horked config |
| | | logger.traceException(e); |
| | | |
| | | logger.error(ERR_CONNHANDLER_CANNOT_ACCEPT_CONNECTION, |
| | | friendlyName, currentConfig.dn(), getExceptionMessage(e)); |
| | | logger.error( |
| | | ERR_CONNHANDLER_CANNOT_ACCEPT_CONNECTION, friendlyName, currentConfig.dn(), getExceptionMessage(e)); |
| | | |
| | | if (lastIterationFailed) |
| | | { |
| | | // The last time through the accept loop we also |
| | | // encountered a failure. Rather than enter a potential |
| | | // infinite loop of failures, disable this acceptor and |
| | | // log an error. |
| | | LocalizableMessage message = |
| | | ERR_CONNHANDLER_CONSECUTIVE_ACCEPT_FAILURES.get(friendlyName, |
| | | currentConfig.dn(), stackTraceToSingleLineString(e)); |
| | | // The last time through the accept loop we also encountered a failure. |
| | | // Rather than enter a potential infinite loop of failures, |
| | | // disable this acceptor and log an error. |
| | | LocalizableMessage message = ERR_CONNHANDLER_CONSECUTIVE_ACCEPT_FAILURES.get( |
| | | friendlyName, currentConfig.dn(), stackTraceToSingleLineString(e)); |
| | | logger.error(message); |
| | | |
| | | DirectoryServer.sendAlertNotification(this, |
| | | ALERT_TYPE_HTTP_CONNECTION_HANDLER_CONSECUTIVE_FAILURES, message); |
| | | |
| | | DirectoryServer.sendAlertNotification(this, ALERT_TYPE_HTTP_CONNECTION_HANDLER_CONSECUTIVE_FAILURES, message); |
| | | this.enabled = false; |
| | | } |
| | | else |
| | |
| | | |
| | | private void startHttpServer() throws Exception |
| | | { |
| | | // silence Grizzly's own logging |
| | | // Silence Grizzly's own logging |
| | | Logger.getLogger("org.glassfish.grizzly").setLevel(Level.OFF); |
| | | |
| | | if (HTTPAccessLogger.getHTTPAccessLogPublishers().isEmpty()) |
| | |
| | | |
| | | this.httpServer = createHttpServer(); |
| | | |
| | | // register servlet as default servlet and also able to serve REST requests |
| | | // Register servlet as default servlet and also able to serve REST requests |
| | | createAndRegisterServlet("OpenDJ Rest2LDAP servlet", "", "/*"); |
| | | |
| | | logger.trace("Starting HTTP server..."); |
| | |
| | | setHttpStatsProbe(server); |
| | | } |
| | | |
| | | // configure the network listener |
| | | final NetworkListener listener = |
| | | new NetworkListener("Rest2LDAP", NetworkListener.DEFAULT_NETWORK_HOST, |
| | | initConfig.getListenPort()); |
| | | // Configure the network listener |
| | | final NetworkListener listener = new NetworkListener( |
| | | "Rest2LDAP", NetworkListener.DEFAULT_NETWORK_HOST, initConfig.getListenPort()); |
| | | server.addListener(listener); |
| | | |
| | | // configure the network transport |
| | | // Configure the network transport |
| | | final TCPNIOTransport transport = listener.getTransport(); |
| | | transport.setReuseAddress(currentConfig.isAllowTCPReuseAddress()); |
| | | transport.setKeepAlive(currentConfig.isUseTCPKeepAlive()); |
| | | transport.setTcpNoDelay(currentConfig.isUseTCPNoDelay()); |
| | | transport.setWriteTimeout(currentConfig.getMaxBlockedWriteTimeLimit(), |
| | | TimeUnit.MILLISECONDS); |
| | | transport.setWriteTimeout(currentConfig.getMaxBlockedWriteTimeLimit(), TimeUnit.MILLISECONDS); |
| | | |
| | | final int bufferSize = (int) currentConfig.getBufferSize(); |
| | | transport.setReadBufferSize(bufferSize); |
| | | transport.setWriteBufferSize(bufferSize); |
| | | transport.setIOStrategy(SameThreadIOStrategy.getInstance()); |
| | | final int numRequestHandlers = |
| | | getNumRequestHandlers(currentConfig.getNumRequestHandlers(), |
| | | friendlyName); |
| | | |
| | | final int numRequestHandlers = getNumRequestHandlers(currentConfig.getNumRequestHandlers(), friendlyName); |
| | | transport.setSelectorRunnersCount(numRequestHandlers); |
| | | transport.setServerConnectionBackLog(currentConfig.getAcceptBacklog()); |
| | | |
| | | // configure SSL |
| | | // Configure SSL |
| | | if (sslEngineConfigurator != null) |
| | | { |
| | | listener.setSecure(true); |
| | |
| | | |
| | | private MonitoringConfig<HttpProbe> getHttpConfig(HttpServer server) |
| | | { |
| | | final HttpServerMonitoringConfig monitoringCfg = |
| | | server.getServerConfiguration().getMonitoringConfig(); |
| | | return monitoringCfg.getHttpConfig(); |
| | | return server.getServerConfiguration().getMonitoringConfig().getHttpConfig(); |
| | | } |
| | | |
| | | private void createAndRegisterServlet(final String servletName, |
| | | final String... urlPatterns) throws Exception |
| | | private void createAndRegisterServlet(final String servletName, final String... urlPatterns) throws Exception |
| | | { |
| | | // parse and use JSON config |
| | | // Parse and use JSON config |
| | | File jsonConfigFile = getFileForPath(this.currentConfig.getConfigFile()); |
| | | final JsonValue configuration = |
| | | parseJsonConfiguration(jsonConfigFile).recordKeyAccesses(); |
| | | final HTTPAuthenticationConfig authenticationConfig = |
| | | getAuthenticationConfig(configuration); |
| | | final JsonValue configuration = parseJsonConfiguration(jsonConfigFile).recordKeyAccesses(); |
| | | final HTTPAuthenticationConfig authenticationConfig = getAuthenticationConfig(configuration); |
| | | final ConnectionFactory connFactory = getConnectionFactory(configuration); |
| | | configuration.verifyAllKeysAccessed(); |
| | | |
| | | Filter filter = |
| | | new CollectClientConnectionsFilter(this, authenticationConfig); |
| | | final HttpServlet servlet = new HttpServlet(connFactory, |
| | | Filter filter = new CollectClientConnectionsFilter(this, authenticationConfig); |
| | | // Used for hooking our HTTPClientConnection in Rest2LDAP |
| | | Rest2LDAPContextFactory.getHttpServletContextFactory()); |
| | | final HttpServlet servlet = new HttpServlet(connFactory, Rest2LDAPContextFactory.getHttpServletContextFactory()); |
| | | |
| | | // Create and deploy the Web app context |
| | | final WebappContext ctx = new WebappContext(servletName); |
| | | ctx.addFilter("collectClientConnections", filter).addMappingForUrlPatterns( |
| | | EnumSet.of(DispatcherType.REQUEST), true, urlPatterns); |
| | | ctx.addFilter("collectClientConnections", filter) |
| | | .addMappingForUrlPatterns(EnumSet.of(DispatcherType.REQUEST), true, urlPatterns); |
| | | ctx.addServlet(servletName, servlet).addMapping(urlPatterns); |
| | | ctx.deploy(this.httpServer); |
| | | } |
| | | |
| | | private HTTPAuthenticationConfig getAuthenticationConfig( |
| | | final JsonValue configuration) |
| | | private HTTPAuthenticationConfig getAuthenticationConfig(final JsonValue configuration) |
| | | { |
| | | final HTTPAuthenticationConfig result = new HTTPAuthenticationConfig(); |
| | | |
| | | final JsonValue val = configuration.get("authenticationFilter"); |
| | | result.setBasicAuthenticationSupported(asBool(val, |
| | | "supportHTTPBasicAuthentication")); |
| | | result.setCustomHeadersAuthenticationSupported(asBool(val, |
| | | "supportAltAuthentication")); |
| | | result.setCustomHeaderUsername(val.get("altAuthenticationUsernameHeader") |
| | | .asString()); |
| | | result.setCustomHeaderPassword(val.get("altAuthenticationPasswordHeader") |
| | | .asString()); |
| | | result.setBasicAuthenticationSupported(asBool(val, "supportHTTPBasicAuthentication")); |
| | | result.setCustomHeadersAuthenticationSupported(asBool(val, "supportAltAuthentication")); |
| | | result.setCustomHeaderUsername(val.get("altAuthenticationUsernameHeader").asString()); |
| | | result.setCustomHeaderPassword(val.get("altAuthenticationPasswordHeader").asString()); |
| | | |
| | | final String searchBaseDN = asString(val, "searchBaseDN"); |
| | | result.setSearchBaseDN(org.forgerock.opendj.ldap.DN.valueOf(searchBaseDN)); |
| | | result.setSearchScope(SearchScope.valueOf(asString(val, "searchScope"))); |
| | | result.setSearchFilterTemplate(asString(val, "searchFilterTemplate")); |
| | | |
| | | return result; |
| | | } |
| | | |
| | |
| | | private ConnectionFactory getConnectionFactory(final JsonValue configuration) |
| | | { |
| | | final Router router = new Router(); |
| | | final JsonValue mappings = |
| | | configuration.get("servlet").get("mappings").required(); |
| | | final JsonValue mappings = configuration.get("servlet").get("mappings").required(); |
| | | for (final String mappingUrl : mappings.keys()) |
| | | { |
| | | final JsonValue mapping = mappings.get(mappingUrl); |
| | | final CollectionResourceProvider provider = |
| | | Rest2LDAP.builder().authorizationPolicy(AuthorizationPolicy.REUSE) |
| | | final CollectionResourceProvider provider = Rest2LDAP.builder() |
| | | .authorizationPolicy(AuthorizationPolicy.REUSE) |
| | | .configureMapping(mapping).build(); |
| | | router.addRoute(mappingUrl, provider); |
| | | } |
| | | return Resources.newInternalConnectionFactory(router); |
| | | } |
| | | |
| | | private JsonValue parseJsonConfiguration(File configFile) throws IOException, |
| | | JsonParseException, JsonMappingException, ServletException |
| | | private JsonValue parseJsonConfiguration(File configFile) |
| | | throws IOException, JsonParseException, JsonMappingException, ServletException |
| | | { |
| | | // Parse the config file. |
| | | final Object content = JSON_MAPPER.readValue(configFile, Object.class); |
| | | if (!(content instanceof Map)) |
| | | { |
| | | throw new ServletException("Servlet configuration file '" + configFile |
| | | + "' does not contain a valid JSON configuration"); |
| | | throw new ServletException( |
| | | "Servlet configuration file '" + configFile + "' does not contain a valid JSON configuration"); |
| | | } |
| | | return new JsonValue(content); |
| | | } |
| | |
| | | this.httpProbe = null; |
| | | } |
| | | |
| | | /** {@inheritDoc} */ |
| | | @Override |
| | | public void toString(StringBuilder buffer) |
| | | { |
| | | buffer.append(handlerName); |
| | | } |
| | | |
| | | private SSLEngineConfigurator createSSLEngineConfigurator( |
| | | HTTPConnectionHandlerCfg config) throws DirectoryException |
| | | private SSLEngineConfigurator createSSLEngineConfigurator(HTTPConnectionHandlerCfg config) throws DirectoryException |
| | | { |
| | | if (!config.isUseSSL()) |
| | | { |
| | |
| | | try |
| | | { |
| | | SSLContext sslContext = createSSLContext(config); |
| | | SSLEngineConfigurator configurator = |
| | | new SSLEngineConfigurator(sslContext); |
| | | SSLEngineConfigurator configurator = new SSLEngineConfigurator(sslContext); |
| | | configurator.setClientMode(false); |
| | | |
| | | // configure with defaults from the JVM |
| | |
| | | final Set<String> protocols = config.getSSLProtocol(); |
| | | if (!protocols.isEmpty()) |
| | | { |
| | | String[] array = protocols.toArray(new String[protocols.size()]); |
| | | configurator.setEnabledProtocols(array); |
| | | configurator.setEnabledProtocols(protocols.toArray(new String[protocols.size()])); |
| | | } |
| | | |
| | | final Set<String> ciphers = config.getSSLCipherSuite(); |
| | | if (!ciphers.isEmpty()) |
| | | { |
| | | String[] array = ciphers.toArray(new String[ciphers.size()]); |
| | | configurator.setEnabledCipherSuites(array); |
| | | configurator.setEnabledCipherSuites(ciphers.toArray(new String[ciphers.size()])); |
| | | } |
| | | |
| | | switch (config.getSSLClientAuthPolicy()) |
| | |
| | | { |
| | | logger.traceException(e); |
| | | ResultCode resCode = DirectoryServer.getServerErrorResultCode(); |
| | | LocalizableMessage message = |
| | | ERR_CONNHANDLER_SSL_CANNOT_INITIALIZE.get(getExceptionMessage(e)); |
| | | throw new DirectoryException(resCode, message, e); |
| | | throw new DirectoryException(resCode, ERR_CONNHANDLER_SSL_CANNOT_INITIALIZE.get(getExceptionMessage(e)), e); |
| | | } |
| | | } |
| | | |
| | | private SSLContext createSSLContext(HTTPConnectionHandlerCfg config) |
| | | throws Exception |
| | | private SSLContext createSSLContext(HTTPConnectionHandlerCfg config) throws Exception |
| | | { |
| | | if (!config.isUseSSL()) |
| | | { |
| | |
| | | } |
| | | |
| | | DN keyMgrDN = config.getKeyManagerProviderDN(); |
| | | KeyManagerProvider<?> keyManagerProvider = |
| | | DirectoryServer.getKeyManagerProvider(keyMgrDN); |
| | | KeyManagerProvider<?> keyManagerProvider = DirectoryServer.getKeyManagerProvider(keyMgrDN); |
| | | if (keyManagerProvider == null) { |
| | | logger.error(ERR_NULL_KEY_PROVIDER_MANAGER, keyMgrDN, friendlyName); |
| | | logger.warn(INFO_DISABLE_CONNECTION, friendlyName); |
| | |
| | | logger.warn(INFO_DISABLE_CONNECTION, friendlyName); |
| | | enabled = false; |
| | | } |
| | | keyManagers = |
| | | SelectableCertificateKeyManager.wrap(keyManagerProvider |
| | | .getKeyManagers(), alias); |
| | | keyManagers = SelectableCertificateKeyManager.wrap(keyManagerProvider.getKeyManagers(), alias); |
| | | } |
| | | |
| | | DN trustMgrDN = config.getTrustManagerProviderDN(); |
| | | TrustManagerProvider<?> trustManagerProvider = |
| | | DirectoryServer.getTrustManagerProvider(trustMgrDN); |
| | | TrustManagerProvider<?> trustManagerProvider = DirectoryServer.getTrustManagerProvider(trustMgrDN); |
| | | if (trustManagerProvider == null) |
| | | { |
| | | trustManagerProvider = new NullTrustManagerProvider(); |
| | |
| | | sslContext.init(keyManagers, trustManagerProvider.getTrustManagers(), null); |
| | | return sslContext; |
| | | } |
| | | |
| | | } |