001/* 002 * Copyright 2011-2017 UnboundID Corp. 003 * All Rights Reserved. 004 */ 005/* 006 * Copyright (C) 2011-2017 UnboundID Corp. 007 * 008 * This program is free software; you can redistribute it and/or modify 009 * it under the terms of the GNU General Public License (GPLv2 only) 010 * or the terms of the GNU Lesser General Public License (LGPLv2.1 only) 011 * as published by the Free Software Foundation. 012 * 013 * This program is distributed in the hope that it will be useful, 014 * but WITHOUT ANY WARRANTY; without even the implied warranty of 015 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 016 * GNU General Public License for more details. 017 * 018 * You should have received a copy of the GNU General Public License 019 * along with this program; if not, see <http://www.gnu.org/licenses>. 020 */ 021package com.unboundid.ldap.listener; 022 023 024 025import java.net.InetAddress; 026import javax.net.SocketFactory; 027import javax.net.ServerSocketFactory; 028import javax.net.ssl.SSLSocketFactory; 029import javax.net.ssl.SSLServerSocketFactory; 030 031import com.unboundid.ldap.sdk.LDAPException; 032import com.unboundid.ldap.sdk.ResultCode; 033import com.unboundid.util.Debug; 034import com.unboundid.util.NotMutable; 035import com.unboundid.util.StaticUtils; 036import com.unboundid.util.ThreadSafety; 037import com.unboundid.util.ThreadSafetyLevel; 038import com.unboundid.util.ssl.SSLUtil; 039import com.unboundid.util.ssl.TrustAllTrustManager; 040 041import static com.unboundid.ldap.listener.ListenerMessages.*; 042 043 044 045/** 046 * This class provides a data structure that can be used to configure a 047 * listener for use in the in-memory directory server. Each in-memory directory 048 * server instance has the ability to have multiple listeners, and those 049 * listeners may have different settings (e.g., listen on one port for 050 * unencrypted LDAP communication with optional support for StartTLS, and listen 051 * on a separate port for SSL-encrypted communication). If the server is to 052 * provide support for SSL and/or StartTLS, then the {@link SSLUtil} class can 053 * make it easy to create the necessary socket factories. 054 */ 055@NotMutable() 056@ThreadSafety(level=ThreadSafetyLevel.COMPLETELY_THREADSAFE) 057public final class InMemoryListenerConfig 058{ 059 // The address on which this listener should accept client connections. 060 private final InetAddress listenAddress; 061 062 // The port on which this listener should accept client connections. 063 private final int listenPort; 064 065 // The socket factory that should be used for accepting new connections. 066 private final ServerSocketFactory serverSocketFactory; 067 068 // The socket factory that should be used for creating client connections. 069 private final SocketFactory clientSocketFactory; 070 071 // The socket factory that will be used to add StartTLS encryption to an 072 // existing connection. 073 private final SSLSocketFactory startTLSSocketFactory; 074 075 // The used to refer to this listener. 076 private final String listenerName; 077 078 079 080 /** 081 * Creates a new in-memory directory server listener configuration with the 082 * provided settings. 083 * 084 * @param listenerName The name to assign to this listener. It 085 * must not be {@code null} and must not be the 086 * same as the name for any other listener 087 * configured in the server. 088 * @param listenAddress The address on which the listener should 089 * accept connections from clients. It may be 090 * {@code null} to indicate that it should 091 * accept connections on all addresses on all 092 * interfaces. 093 * @param listenPort The port on which the listener should accept 094 * connections from clients. It may be 0 to 095 * indicate that the server should 096 * automatically choose an available port. 097 * @param serverSocketFactory The socket factory that should be used to 098 * create sockets when accepting client 099 * connections. It may be {@code null} if the 100 * JVM-default server socket factory should be 101 * used. 102 * @param clientSocketFactory The socket factory that should be used to 103 * create client connections to the server. It 104 * may be {@code null} if the JVM-default 105 * socket factory should be used. 106 * @param startTLSSocketFactory The socket factory that should be used to 107 * add StartTLS encryption to existing 108 * connections. It may be {@code null} if 109 * StartTLS is not to be supported on this 110 * listener, and should be {@code null} if the 111 * server socket factory already provides some 112 * other form of communication security. 113 * 114 * @throws LDAPException If the provided listener name is {@code null} or 115 * the configured listen port is out of range. 116 */ 117 public InMemoryListenerConfig(final String listenerName, 118 final InetAddress listenAddress, 119 final int listenPort, 120 final ServerSocketFactory serverSocketFactory, 121 final SocketFactory clientSocketFactory, 122 final SSLSocketFactory startTLSSocketFactory) 123 throws LDAPException 124 { 125 if ((listenerName == null) || (listenerName.length() == 0)) 126 { 127 throw new LDAPException(ResultCode.PARAM_ERROR, 128 ERR_LISTENER_CFG_NO_NAME.get()); 129 } 130 131 if ((listenPort < 0) || (listenPort > 65535)) 132 { 133 throw new LDAPException(ResultCode.PARAM_ERROR, 134 ERR_LISTENER_CFG_INVALID_PORT.get(listenPort)); 135 } 136 137 this.listenerName = listenerName; 138 this.listenAddress = listenAddress; 139 this.listenPort = listenPort; 140 this.serverSocketFactory = serverSocketFactory; 141 this.clientSocketFactory = clientSocketFactory; 142 this.startTLSSocketFactory = startTLSSocketFactory; 143 } 144 145 146 147 /** 148 * Creates a new listener configuration that will listen for unencrypted LDAP 149 * communication on an automatically-selected port on all available addresses. 150 * It will not support StartTLS. 151 * 152 * @param listenerName The name to use for the listener. It must not be 153 * {@code null}. 154 * 155 * @return The newly-created listener configuration. 156 * 157 * @throws LDAPException If the provided name is {@code null}. 158 */ 159 public static InMemoryListenerConfig createLDAPConfig( 160 final String listenerName) 161 throws LDAPException 162 { 163 return new InMemoryListenerConfig(listenerName, null, 0, null, null, null); 164 } 165 166 167 168 /** 169 * Creates a new listener configuration that will listen for unencrypted LDAP 170 * communication on the specified port on all available addresses. It will 171 * not support StartTLS. 172 * 173 * @param listenerName The name to use for the listener. It must not be 174 * {@code null}. 175 * @param listenPort The port on which the listener should accept 176 * connections from clients. It may be 0 to indicate 177 * that the server should automatically choose an 178 * available port. 179 * 180 * @return The newly-created listener configuration. 181 * 182 * @throws LDAPException If the provided listener name is {@code null} or 183 * the configured listen port is out of range. 184 */ 185 public static InMemoryListenerConfig createLDAPConfig( 186 final String listenerName, 187 final int listenPort) 188 throws LDAPException 189 { 190 return new InMemoryListenerConfig(listenerName, null, listenPort, null, 191 null, null); 192 } 193 194 195 196 /** 197 * Creates a new listener configuration that will listen for unencrypted LDAP 198 * communication, and may optionally support StartTLS. 199 * 200 * @param listenerName The name to assign to this listener. It 201 * must not be {@code null} and must not be the 202 * same as the name for any other listener 203 * configured in the server. 204 * @param listenAddress The address on which the listener should 205 * accept connections from clients. It may be 206 * {@code null} to indicate that it should 207 * accept connections on all addresses on all 208 * interfaces. 209 * @param listenPort The port on which the listener should accept 210 * connections from clients. It may be 0 to 211 * indicate that the server should 212 * automatically choose an available port. 213 * @param startTLSSocketFactory The socket factory that should be used to 214 * add StartTLS encryption to an existing 215 * connection. It may be {@code null} if 216 * StartTLS is not to be supported on this 217 * listener, and should be {@code null} if the 218 * server socket factory already provides some 219 * other form of communication security. 220 * 221 * @return The newly-created listener configuration. 222 * 223 * @throws LDAPException If the provided listener name is {@code null} or 224 * the configured listen port is out of range. 225 */ 226 public static InMemoryListenerConfig createLDAPConfig( 227 final String listenerName, final InetAddress listenAddress, 228 final int listenPort, 229 final SSLSocketFactory startTLSSocketFactory) 230 throws LDAPException 231 { 232 return new InMemoryListenerConfig(listenerName, listenAddress, listenPort, 233 null, null, startTLSSocketFactory); 234 } 235 236 237 238 /** 239 * Creates a new listener configuration that will listen for SSL-encrypted 240 * LDAP communication on an automatically-selected port on all available 241 * addresses. 242 * 243 * @param listenerName The name to use for the listener. It must not 244 * be {@code null}. 245 * @param serverSocketFactory The SSL server socket factory that will be 246 * used for accepting SSL-based connections from 247 * clients. It must not be {@code null}. 248 * 249 * @return The newly-created listener configuration. 250 * 251 * @throws LDAPException If the provided name is {@code null}. 252 */ 253 public static InMemoryListenerConfig createLDAPSConfig( 254 final String listenerName, 255 final SSLServerSocketFactory serverSocketFactory) 256 throws LDAPException 257 { 258 return createLDAPSConfig(listenerName, null, 0, serverSocketFactory, null); 259 } 260 261 262 263 /** 264 * Creates a new listener configuration that will listen for SSL-encrypted 265 * LDAP communication on the specified port on all available addresses. 266 * 267 * @param listenerName The name to use for the listener. It must not 268 * be {@code null}. 269 * @param listenPort The port on which the listener should accept 270 * connections from clients. It may be 0 to 271 * indicate that the server should 272 * automatically choose an available port. 273 * @param serverSocketFactory The SSL server socket factory that will be 274 * used for accepting SSL-based connections from 275 * clients. It must not be {@code null}. 276 * 277 * @return The newly-created listener configuration. 278 * 279 * @throws LDAPException If the provided name is {@code null}. 280 */ 281 public static InMemoryListenerConfig createLDAPSConfig( 282 final String listenerName, final int listenPort, 283 final SSLServerSocketFactory serverSocketFactory) 284 throws LDAPException 285 { 286 return createLDAPSConfig(listenerName, null, listenPort, 287 serverSocketFactory, null); 288 } 289 290 291 292 /** 293 * Creates a new listener configuration that will listen for SSL-encrypted 294 * LDAP communication on an automatically-selected port on all available 295 * addresses. 296 * 297 * @param listenerName The name to use for the listener. It must not 298 * be {@code null}. 299 * @param listenAddress The address on which the listener should 300 * accept connections from clients. It may be 301 * {@code null} to indicate that it should 302 * accept connections on all addresses on all 303 * interfaces. 304 * @param listenPort The port on which the listener should accept 305 * connections from clients. It may be 0 to 306 * indicate that the server should 307 * automatically choose an available port. 308 * @param serverSocketFactory The SSL server socket factory that will be 309 * used for accepting SSL-based connections from 310 * clients. It must not be {@code null}. 311 * @param clientSocketFactory The SSL socket factory that will be used to 312 * create secure connections to the server. It 313 * may be {@code null} if a default "trust all" 314 * socket factory should be used. 315 * 316 * @return The newly-created listener configuration. 317 * 318 * @throws LDAPException If the provided name or server socket factory is 319 * {@code null}, or an error occurs while attempting to create a 320 * client socket factory. 321 */ 322 public static InMemoryListenerConfig createLDAPSConfig( 323 final String listenerName, final InetAddress listenAddress, 324 final int listenPort, 325 final SSLServerSocketFactory serverSocketFactory, 326 final SSLSocketFactory clientSocketFactory) 327 throws LDAPException 328 { 329 if (serverSocketFactory == null) 330 { 331 throw new LDAPException(ResultCode.PARAM_ERROR, 332 ERR_LISTENER_CFG_NO_SSL_SERVER_SOCKET_FACTORY.get()); 333 } 334 335 final SSLSocketFactory clientFactory; 336 if (clientSocketFactory == null) 337 { 338 try 339 { 340 final SSLUtil sslUtil = new SSLUtil(new TrustAllTrustManager()); 341 clientFactory = sslUtil.createSSLSocketFactory(); 342 } 343 catch (final Exception e) 344 { 345 Debug.debugException(e); 346 throw new LDAPException(ResultCode.LOCAL_ERROR, 347 ERR_LISTENER_CFG_COULD_NOT_CREATE_SSL_SOCKET_FACTORY.get( 348 StaticUtils.getExceptionMessage(e)), 349 e); 350 } 351 } 352 else 353 { 354 clientFactory = clientSocketFactory; 355 } 356 357 return new InMemoryListenerConfig(listenerName, listenAddress, listenPort, 358 serverSocketFactory, clientFactory, null); 359 } 360 361 362 363 /** 364 * Retrieves the name for this listener configuration. 365 * 366 * @return The name for this listener configuration. 367 */ 368 public String getListenerName() 369 { 370 return listenerName; 371 } 372 373 374 375 /** 376 * Retrieves the address on which the listener should accept connections from 377 * clients, if defined. 378 * 379 * @return The address on which the listener should accept connections from 380 * clients, or {@code null} if it should accept connections on all 381 * addresses on all interfaces. 382 */ 383 public InetAddress getListenAddress() 384 { 385 return listenAddress; 386 } 387 388 389 390 /** 391 * Retrieves the port on which the listener should accept connections from 392 * clients, if defined. 393 * 394 * @return The port on which the listener should accept connections from 395 * clients, or 0 if the listener should automatically select an 396 * available port. 397 */ 398 public int getListenPort() 399 { 400 return listenPort; 401 } 402 403 404 405 /** 406 * Retrieves the socket factory that should be used to create sockets when 407 * accepting client connections, if defined. 408 * 409 * @return The socket factory that should be used to create sockets when 410 * accepting client connections, or {@code null} if the JVM-default 411 * server socket factory should be used. 412 */ 413 public ServerSocketFactory getServerSocketFactory() 414 { 415 return serverSocketFactory; 416 } 417 418 419 420 /** 421 * Retrieves the socket factory that should be used to create client 422 * connections to the server, if defined. 423 * 424 * @return The socket factory that should be used to create client 425 * connections to the server, or {@code null} if the JVM-default 426 * socket factory should be used. 427 */ 428 public SocketFactory getClientSocketFactory() 429 { 430 return clientSocketFactory; 431 } 432 433 434 435 /** 436 * Retrieves the socket factory that should be used to add StartTLS encryption 437 * to existing connections, if defined. 438 * 439 * @return The socket factory that should be used to add StartTLS encryption 440 * to existing connections, or {@code null} if StartTLS should not be 441 * supported. 442 */ 443 public SSLSocketFactory getStartTLSSocketFactory() 444 { 445 return startTLSSocketFactory; 446 } 447 448 449 450 /** 451 * Retrieves a string representation of this listener configuration. 452 * 453 * @return A string representation of this listener configuration. 454 */ 455 @Override() 456 public String toString() 457 { 458 final StringBuilder buffer = new StringBuilder(); 459 toString(buffer); 460 return buffer.toString(); 461 } 462 463 464 465 /** 466 * Appends a string representation of this listener configuration to the 467 * provided buffer. 468 * 469 * @param buffer The buffer to which the information should be appended. 470 */ 471 public void toString(final StringBuilder buffer) 472 { 473 buffer.append("InMemoryListenerConfig(name='"); 474 buffer.append(listenerName); 475 buffer.append('\''); 476 477 if (listenAddress != null) 478 { 479 buffer.append(", listenAddress='"); 480 buffer.append(listenAddress.getHostAddress()); 481 buffer.append('\''); 482 } 483 484 buffer.append(", listenPort="); 485 buffer.append(listenPort); 486 487 if (serverSocketFactory != null) 488 { 489 buffer.append(", serverSocketFactoryClass='"); 490 buffer.append(serverSocketFactory.getClass().getName()); 491 buffer.append('\''); 492 } 493 494 if (clientSocketFactory != null) 495 { 496 buffer.append(", clientSocketFactoryClass='"); 497 buffer.append(clientSocketFactory.getClass().getName()); 498 buffer.append('\''); 499 } 500 501 if (startTLSSocketFactory != null) 502 { 503 buffer.append(", startTLSSocketFactoryClass='"); 504 buffer.append(startTLSSocketFactory.getClass().getName()); 505 buffer.append('\''); 506 } 507 508 buffer.append(')'); 509 } 510}