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 org.apache.logging.log4j.core.Layout;
20  import org.apache.logging.log4j.core.appender.ManagerFactory;
21  import org.apache.logging.log4j.core.helpers.Strings;
22  import org.apache.logging.log4j.core.net.ssl.SSLConfiguration;
23  
24  import javax.net.ssl.SSLSocket;
25  import javax.net.ssl.SSLSocketFactory;
26  import java.io.ByteArrayOutputStream;
27  import java.io.IOException;
28  import java.io.OutputStream;
29  import java.net.InetAddress;
30  import java.net.Socket;
31  import java.net.UnknownHostException;
32  
33  /**
34   *
35   */
36  public class TLSSocketManager extends TCPSocketManager {
37      public static final int DEFAULT_PORT = 6514;
38      private static final TLSSocketManagerFactory FACTORY = new TLSSocketManagerFactory();
39      private SSLConfiguration sslConfig;
40  
41      /**
42       *
43       *
44       * @param name          The unique name of this connection.
45       * @param os            The OutputStream.
46       * @param sock          The Socket.
47       * @param addr          The internet address of the host.
48       * @param host          The name of the host.
49       * @param port          The port number on the host.
50       * @param delay         Reconnection interval.
51       * @param immediateFail
52       * @param layout        The Layout.
53       */
54      public TLSSocketManager(String name, OutputStream os, Socket sock, SSLConfiguration sslConfig, InetAddress addr,
55                              String host, int port, int delay, boolean immediateFail, Layout layout) {
56          super(name, os, sock, addr, host, port, delay, immediateFail, layout);
57          this.sslConfig = sslConfig;
58      }
59  
60      private static class TLSFactoryData {
61          protected SSLConfiguration sslConfig;
62          private final String host;
63          private final int port;
64          private final int delay;
65          private final boolean immediateFail;
66          private final Layout layout;
67  
68          public TLSFactoryData(SSLConfiguration sslConfig, String host, int port, int delay, boolean immediateFail,
69                                Layout layout) {
70              this.host = host;
71              this.port = port;
72              this.delay = delay;
73              this.immediateFail = immediateFail;
74              this.layout = layout;
75              this.sslConfig = sslConfig;
76          }
77      }
78  
79      public static TLSSocketManager getSocketManager(final SSLConfiguration sslConfig, final String host, int port,
80                                                      int delay, final boolean immediateFail, final Layout layout ) {
81          if (Strings.isEmpty(host)) {
82              throw new IllegalArgumentException("A host name is required");
83          }
84          if (port <= 0) {
85              port = DEFAULT_PORT;
86          }
87          if (delay == 0) {
88              delay = DEFAULT_RECONNECTION_DELAY;
89          }
90          return (TLSSocketManager) getManager("TLS:" + host + ":" + port,
91                  new TLSFactoryData(sslConfig, host, port, delay, immediateFail, layout), FACTORY);
92      }
93  
94      @Override
95      protected Socket createSocket(String host, int port) throws IOException {
96          SSLSocketFactory socketFactory = createSSLSocketFactory(sslConfig);
97          return socketFactory.createSocket(host, port);
98      }
99  
100     private static SSLSocketFactory createSSLSocketFactory(SSLConfiguration sslConf) {
101         SSLSocketFactory socketFactory;
102 
103         if (sslConf != null) {
104             socketFactory = sslConf.getSSLSocketFactory();
105         } else {
106             socketFactory = (SSLSocketFactory) SSLSocketFactory.getDefault();
107         }
108 
109         return socketFactory;
110     }
111 
112 
113     private static class TLSSocketManagerFactory implements ManagerFactory<TLSSocketManager, TLSFactoryData> {
114 
115         private class TLSSocketManagerFactoryException extends Exception {
116 
117             private static final long serialVersionUID = 1L;
118         }
119 
120         @Override
121         public TLSSocketManager createManager(final String name, final TLSFactoryData data) {
122             InetAddress address = null;
123             OutputStream os = null;
124             Socket socket = null;
125 
126             try {
127                 address = resolveAddress(data.host);
128                 socket = createSocket(data);
129                 os = socket.getOutputStream();
130                 checkDelay(data.delay, os);
131             }
132             catch (IOException e) {
133                 LOGGER.error("TLSSocketManager (" + name + ") " + e);
134                 os = new ByteArrayOutputStream();
135             }
136             catch (TLSSocketManagerFactoryException e) {
137                 return null;
138             }
139             return createManager(name, os, socket, data.sslConfig, address, data.host, data.port, data.delay, data.immediateFail, data.layout);
140         }
141 
142         private InetAddress resolveAddress(String hostName) throws TLSSocketManagerFactoryException {
143             InetAddress address;
144 
145             try {
146                 address = InetAddress.getByName(hostName);
147             } catch (final UnknownHostException ex) {
148                 LOGGER.error("Could not find address of " + hostName, ex);
149                 throw new TLSSocketManagerFactoryException();
150             }
151 
152             return address;
153         }
154 
155         private void checkDelay(int delay, OutputStream os) throws TLSSocketManagerFactoryException {
156             if (delay == 0 && os == null) {
157                 throw new TLSSocketManagerFactoryException();
158             }
159         }
160 
161         private Socket createSocket(TLSFactoryData data) throws IOException {
162             SSLSocketFactory socketFactory;
163             SSLSocket socket;
164 
165             socketFactory = createSSLSocketFactory(data.sslConfig);
166             socket = (SSLSocket) socketFactory.createSocket(data.host, data.port);
167             return socket;
168         }
169 
170         private TLSSocketManager createManager(String name, OutputStream os, Socket socket, SSLConfiguration sslConfig, InetAddress address, String host, int port, int delay, boolean immediateFail, Layout layout) {
171             return new TLSSocketManager(name, os, socket, sslConfig, address, host, port, delay, immediateFail, layout);
172         }
173     }
174 }