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 */ 017package org.apache.logging.log4j.core.net; 018 019import java.io.ByteArrayOutputStream; 020import java.io.IOException; 021import java.io.OutputStream; 022import java.io.Serializable; 023import java.net.InetAddress; 024import java.net.InetSocketAddress; 025import java.net.Socket; 026import java.net.UnknownHostException; 027 028import javax.net.ssl.SSLSocket; 029import javax.net.ssl.SSLSocketFactory; 030 031import org.apache.logging.log4j.Level; 032import org.apache.logging.log4j.core.Layout; 033import org.apache.logging.log4j.core.appender.ManagerFactory; 034import org.apache.logging.log4j.core.net.ssl.SslConfiguration; 035import org.apache.logging.log4j.util.Strings; 036 037/** 038 * 039 */ 040public 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}