View Javadoc
1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one or more
3    * contributor license agreements. See the NOTICE file distributed with
4    * this work for additional information regarding copyright ownership.
5    * The ASF licenses this file to You under the Apache license, Version 2.0
6    * (the "License"); you may not use this file except in compliance with
7    * the License. You may obtain a copy of the License at
8    *
9    *      http://www.apache.org/licenses/LICENSE-2.0
10   *
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS,
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   * See the license for the specific language governing permissions and
15   * limitations under the license.
16   */
17  package org.apache.logging.log4j.core.net;
18  
19  import java.io.IOException;
20  import java.io.OutputStream;
21  import java.io.Serializable;
22  import java.net.InetAddress;
23  import java.net.InetSocketAddress;
24  import java.net.Socket;
25  import java.util.List;
26  
27  import javax.net.ssl.SSLSocket;
28  import javax.net.ssl.SSLSocketFactory;
29  
30  import org.apache.logging.log4j.core.Layout;
31  import org.apache.logging.log4j.core.net.ssl.SslConfiguration;
32  import org.apache.logging.log4j.util.Strings;
33  
34  /**
35   *
36   */
37  public class SslSocketManager extends TcpSocketManager {
38      public static final int DEFAULT_PORT = 6514;
39      private static final SslSocketManagerFactory FACTORY = new SslSocketManagerFactory();
40      private final SslConfiguration sslConfig;
41  
42      /**
43      *
44      *
45      * @param name          The unique name of this connection.
46      * @param os            The OutputStream.
47      * @param sock          The Socket.
48      * @param inetAddress          The Internet address of the host.
49      * @param host          The name of the host.
50      * @param port          The port number on the host.
51      * @param connectTimeoutMillis the connect timeout in milliseconds.
52      * @param reconnectionDelayMillis         Reconnection interval.
53      * @param immediateFail
54      * @param layout        The Layout.
55      * @param bufferSize The buffer size.
56      * @deprecated Use {@link #SslSocketManager(String, OutputStream, Socket, SslConfiguration, InetAddress, String, int, int, int, boolean, Layout, int, SocketOptions)}.
57      */
58     @Deprecated
59     public SslSocketManager(final String name, final OutputStream os, final Socket sock,
60             final SslConfiguration sslConfig, final InetAddress inetAddress, final String host, final int port,
61             final int connectTimeoutMillis, final int reconnectionDelayMillis, final boolean immediateFail,
62             final Layout<? extends Serializable> layout, final int bufferSize) {
63         super(name, os, sock, inetAddress, host, port, connectTimeoutMillis, reconnectionDelayMillis, immediateFail, layout, bufferSize, null);
64         this.sslConfig = sslConfig;
65     }
66  
67     /**
68     *
69     *
70     * @param name          The unique name of this connection.
71     * @param os            The OutputStream.
72     * @param sock          The Socket.
73     * @param inetAddress          The Internet address of the host.
74     * @param host          The name of the host.
75     * @param port          The port number on the host.
76     * @param connectTimeoutMillis the connect timeout in milliseconds.
77     * @param reconnectionDelayMillis         Reconnection interval.
78     * @param immediateFail
79     * @param layout        The Layout.
80     * @param bufferSize The buffer size.
81     */
82    public SslSocketManager(final String name, final OutputStream os, final Socket sock,
83            final SslConfiguration sslConfig, final InetAddress inetAddress, final String host, final int port,
84            final int connectTimeoutMillis, final int reconnectionDelayMillis, final boolean immediateFail,
85            final Layout<? extends Serializable> layout, final int bufferSize, final SocketOptions socketOptions) {
86        super(name, os, sock, inetAddress, host, port, connectTimeoutMillis, reconnectionDelayMillis, immediateFail, layout, bufferSize, socketOptions);
87        this.sslConfig = sslConfig;
88    }
89  
90      private static class SslFactoryData extends FactoryData {
91          protected SslConfiguration sslConfiguration;
92  
93          public SslFactoryData(final SslConfiguration sslConfiguration, final String host, final int port,
94                  final int connectTimeoutMillis, final int reconnectDelayMillis, final boolean immediateFail,
95                  final Layout<? extends Serializable> layout, final int bufferSize, final SocketOptions socketOptions) {
96              super(host, port, connectTimeoutMillis, reconnectDelayMillis, immediateFail, layout, bufferSize,
97                      socketOptions);
98              this.sslConfiguration = sslConfiguration;
99          }
100 
101         @Override
102         public String toString() {
103             return "SslFactoryData [sslConfiguration=" + sslConfiguration + ", host=" + host + ", port=" + port
104                     + ", connectTimeoutMillis=" + connectTimeoutMillis + ", reconnectDelayMillis="
105                     + reconnectDelayMillis + ", immediateFail=" + immediateFail + ", layout=" + layout + ", bufferSize="
106                     + bufferSize + ", socketOptions=" + socketOptions + "]";
107         }
108     }
109 
110     /**
111      * @deprecated Use {@link SslSocketManager#getSocketManager(SslConfiguration, String, int, int, int, boolean, Layout, int, SocketOptions)}.
112      */
113     @Deprecated
114     public static SslSocketManager getSocketManager(final SslConfiguration sslConfig, final String host, final int port,
115             final int connectTimeoutMillis, final int reconnectDelayMillis, final boolean immediateFail,
116             final Layout<? extends Serializable> layout, final int bufferSize) {
117         return getSocketManager(sslConfig, host, port, connectTimeoutMillis, reconnectDelayMillis, immediateFail, layout, bufferSize, null);
118     }
119 
120     public static SslSocketManager getSocketManager(final SslConfiguration sslConfig, final String host, int port,
121             final int connectTimeoutMillis, int reconnectDelayMillis, final boolean immediateFail,
122             final Layout<? extends Serializable> layout, final int bufferSize, final SocketOptions socketOptions) {
123         if (Strings.isEmpty(host)) {
124             throw new IllegalArgumentException("A host name is required");
125         }
126         if (port <= 0) {
127             port = DEFAULT_PORT;
128         }
129         if (reconnectDelayMillis == 0) {
130             reconnectDelayMillis = DEFAULT_RECONNECTION_DELAY_MILLIS;
131         }
132         final String name = "TLS:" + host + ':' + port;
133         return (SslSocketManager) getManager(name, new SslFactoryData(sslConfig, host, port, connectTimeoutMillis,
134                 reconnectDelayMillis, immediateFail, layout, bufferSize, socketOptions), FACTORY);
135     }
136 
137     @Override
138     protected Socket createSocket(final InetSocketAddress socketAddress) throws IOException {
139         final SSLSocketFactory socketFactory = createSslSocketFactory(sslConfig);
140         final Socket newSocket = socketFactory.createSocket();
141         newSocket.connect(socketAddress, getConnectTimeoutMillis());
142         return newSocket;
143     }
144 
145     private static SSLSocketFactory createSslSocketFactory(final SslConfiguration sslConf) {
146         SSLSocketFactory socketFactory;
147 
148         if (sslConf != null) {
149             socketFactory = sslConf.getSslSocketFactory();
150         } else {
151             socketFactory = (SSLSocketFactory) SSLSocketFactory.getDefault();
152         }
153 
154         return socketFactory;
155     }
156 
157 
158     private static class SslSocketManagerFactory extends TcpSocketManagerFactory<SslSocketManager, SslFactoryData> {
159 
160         @Override
161         SslSocketManager createManager(final String name, final OutputStream os, final Socket socket, final InetAddress inetAddress,
162                 final SslFactoryData data) {
163             return new SslSocketManager(name, os, socket, data.sslConfiguration, inetAddress, data.host, data.port,
164                     data.connectTimeoutMillis, data.reconnectDelayMillis, data.immediateFail, data.layout, data.bufferSize,
165                     data.socketOptions);
166         }
167 
168         @Override
169         Socket createSocket(final SslFactoryData data) throws IOException {
170             List<InetSocketAddress> socketAddresses = resolver.resolveHost(data.host, data.port);
171             IOException ioe = null;
172             for (InetSocketAddress socketAddress : socketAddresses) {
173                 try {
174                     return SslSocketManager.createSocket(socketAddress, data.connectTimeoutMillis,
175                             data.sslConfiguration, data.socketOptions);
176                 } catch (IOException ex) {
177                     ioe = ex;
178                 }
179             }
180             throw new IOException(errorMessage(data, socketAddresses) , ioe);
181         }
182     }
183 
184     static Socket createSocket(final InetSocketAddress socketAddress, final int connectTimeoutMillis,
185             final SslConfiguration sslConfiguration, final SocketOptions socketOptions) throws IOException {
186         final SSLSocketFactory socketFactory = createSslSocketFactory(sslConfiguration);
187         final SSLSocket socket = (SSLSocket) socketFactory.createSocket();
188         if (socketOptions != null) {
189             // Not sure which options must be applied before or after the connect() call.
190             socketOptions.apply(socket);
191         }
192         socket.connect(socketAddress, connectTimeoutMillis);
193         if (socketOptions != null) {
194             // Not sure which options must be applied before or after the connect() call.
195             socketOptions.apply(socket);
196         }
197         return socket;
198     }
199 }