001 /*
002 * Licensed to the Apache Software Foundation (ASF) under one or more
003 * contributor license agreements. See the NOTICE file distributed with
004 * this work for additional information regarding copyright ownership.
005 * The ASF licenses this file to You under the Apache license, Version 2.0
006 * (the "License"); you may not use this file except in compliance with
007 * the License. You may obtain a copy of the License at
008 *
009 * http://www.apache.org/licenses/LICENSE-2.0
010 *
011 * Unless required by applicable law or agreed to in writing, software
012 * distributed under the License is distributed on an "AS IS" BASIS,
013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014 * See the license for the specific language governing permissions and
015 * limitations under the license.
016 */
017 package org.apache.logging.log4j.core.net;
018
019 import java.io.ByteArrayOutputStream;
020 import java.io.IOException;
021 import java.io.OutputStream;
022 import java.io.Serializable;
023 import java.net.InetAddress;
024 import java.net.InetSocketAddress;
025 import java.net.Socket;
026 import java.net.UnknownHostException;
027
028 import javax.net.ssl.SSLSocket;
029 import javax.net.ssl.SSLSocketFactory;
030
031 import org.apache.logging.log4j.Level;
032 import org.apache.logging.log4j.core.Layout;
033 import org.apache.logging.log4j.core.appender.ManagerFactory;
034 import org.apache.logging.log4j.core.net.ssl.SslConfiguration;
035 import org.apache.logging.log4j.util.Strings;
036
037 /**
038 *
039 */
040 public class SslSocketManager extends TcpSocketManager {
041 public static final int DEFAULT_PORT = 6514;
042 private static final SslSocketManagerFactory FACTORY = new SslSocketManagerFactory();
043 private final SslConfiguration sslConfig;
044
045 /**
046 *
047 *
048 * @param name The unique name of this connection.
049 * @param os The OutputStream.
050 * @param sock The Socket.
051 * @param inetAddress The Internet address of the host.
052 * @param host The name of the host.
053 * @param port The port number on the host.
054 * @param connectTimeoutMillis the connect timeout in milliseconds.
055 * @param delay Reconnection interval.
056 * @param immediateFail
057 * @param layout The Layout.
058 */
059 public SslSocketManager(final String name, final OutputStream os, final Socket sock,
060 final SslConfiguration sslConfig, final InetAddress inetAddress, final String host, final int port,
061 int connectTimeoutMillis, final int delay, final boolean immediateFail,
062 final Layout<? extends Serializable> layout) {
063 super(name, os, sock, inetAddress, host, port, connectTimeoutMillis, delay, immediateFail, layout);
064 this.sslConfig = sslConfig;
065 }
066
067 private static class SslFactoryData {
068 protected SslConfiguration sslConfig;
069 private final String host;
070 private final int port;
071 private final int connectTimeoutMillis;
072 private final int delayMillis;
073 private final boolean immediateFail;
074 private final Layout<? extends Serializable> layout;
075
076 public SslFactoryData(final SslConfiguration sslConfig, final String host, final int port,
077 int connectTimeoutMillis, final int delayMillis, final boolean immediateFail,
078 final Layout<? extends Serializable> layout) {
079 this.host = host;
080 this.port = port;
081 this.connectTimeoutMillis = connectTimeoutMillis;
082 this.delayMillis = delayMillis;
083 this.immediateFail = immediateFail;
084 this.layout = layout;
085 this.sslConfig = sslConfig;
086 }
087 }
088
089 public static SslSocketManager getSocketManager(final SslConfiguration sslConfig, final String host, int port,
090 int connectTimeoutMillis, int delayMillis, final boolean immediateFail,
091 final Layout<? extends Serializable> layout) {
092 if (Strings.isEmpty(host)) {
093 throw new IllegalArgumentException("A host name is required");
094 }
095 if (port <= 0) {
096 port = DEFAULT_PORT;
097 }
098 if (delayMillis == 0) {
099 delayMillis = DEFAULT_RECONNECTION_DELAY_MILLIS;
100 }
101 return (SslSocketManager) getManager("TLS:" + host + ':' + port, new SslFactoryData(sslConfig, host, port,
102 connectTimeoutMillis, delayMillis, immediateFail, layout), FACTORY);
103 }
104
105 @Override
106 protected Socket createSocket(final String host, final int port) throws IOException {
107 final SSLSocketFactory socketFactory = createSslSocketFactory(sslConfig);
108 final InetSocketAddress address = new InetSocketAddress(host, port);
109 final Socket newSocket = socketFactory.createSocket();
110 newSocket.connect(address, getConnectTimeoutMillis());
111 return newSocket;
112 }
113
114 private static SSLSocketFactory createSslSocketFactory(final SslConfiguration sslConf) {
115 SSLSocketFactory socketFactory;
116
117 if (sslConf != null) {
118 socketFactory = sslConf.getSslSocketFactory();
119 } else {
120 socketFactory = (SSLSocketFactory) SSLSocketFactory.getDefault();
121 }
122
123 return socketFactory;
124 }
125
126
127 private static class SslSocketManagerFactory implements ManagerFactory<SslSocketManager, SslFactoryData> {
128
129 private class TlsSocketManagerFactoryException extends Exception {
130
131 private static final long serialVersionUID = 1L;
132 }
133
134 @Override
135 public SslSocketManager createManager(final String name, final SslFactoryData data) {
136 InetAddress inetAddress = null;
137 OutputStream os = null;
138 Socket socket = null;
139
140 try {
141 inetAddress = resolveAddress(data.host);
142 socket = createSocket(data);
143 os = socket.getOutputStream();
144 checkDelay(data.delayMillis, os);
145 }
146 catch (final IOException e) {
147 LOGGER.error("SslSocketManager ({})", name, e);
148 os = new ByteArrayOutputStream();
149 }
150 catch (final TlsSocketManagerFactoryException e) {
151 LOGGER.catching(Level.DEBUG, e);
152 return null;
153 }
154 return new SslSocketManager(name, os, socket, data.sslConfig, inetAddress, data.host, data.port, 0,
155 data.delayMillis, data.immediateFail, data.layout);
156 }
157
158 private InetAddress resolveAddress(final String hostName) throws TlsSocketManagerFactoryException {
159 InetAddress address;
160
161 try {
162 address = InetAddress.getByName(hostName);
163 } catch (final UnknownHostException ex) {
164 LOGGER.error("Could not find address of {}", hostName, ex);
165 throw new TlsSocketManagerFactoryException();
166 }
167
168 return address;
169 }
170
171 private void checkDelay(final int delay, final OutputStream os) throws TlsSocketManagerFactoryException {
172 if (delay == 0 && os == null) {
173 throw new TlsSocketManagerFactoryException();
174 }
175 }
176
177 private Socket createSocket(final SslFactoryData data) throws IOException {
178 SSLSocketFactory socketFactory;
179 SSLSocket socket;
180
181 socketFactory = createSslSocketFactory(data.sslConfig);
182 socket = (SSLSocket) socketFactory.createSocket(data.host, data.port);
183 return socket;
184 }
185 }
186 }