001 /*
002 * Copyright 2011-2014 UnboundID Corp.
003 * All Rights Reserved.
004 */
005 /*
006 * Copyright (C) 2011-2014 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 */
021 package com.unboundid.ldap.listener;
022
023
024
025 import java.net.InetAddress;
026 import javax.net.SocketFactory;
027 import javax.net.ServerSocketFactory;
028 import javax.net.ssl.SSLSocketFactory;
029 import javax.net.ssl.SSLServerSocketFactory;
030
031 import com.unboundid.ldap.sdk.LDAPException;
032 import com.unboundid.ldap.sdk.ResultCode;
033 import com.unboundid.util.Debug;
034 import com.unboundid.util.NotMutable;
035 import com.unboundid.util.StaticUtils;
036 import com.unboundid.util.ThreadSafety;
037 import com.unboundid.util.ThreadSafetyLevel;
038 import com.unboundid.util.ssl.SSLUtil;
039 import com.unboundid.util.ssl.TrustAllTrustManager;
040
041 import 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)
057 public 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 }