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.Socket; 025 import java.net.UnknownHostException; 026 027 import javax.net.ssl.SSLSocket; 028 import javax.net.ssl.SSLSocketFactory; 029 030 import org.apache.logging.log4j.Level; 031 import org.apache.logging.log4j.core.Layout; 032 import org.apache.logging.log4j.core.appender.ManagerFactory; 033 import org.apache.logging.log4j.core.net.ssl.SslConfiguration; 034 import org.apache.logging.log4j.util.Strings; 035 036 /** 037 * 038 */ 039 public class SslSocketManager extends TcpSocketManager { 040 public static final int DEFAULT_PORT = 6514; 041 private static final SslSocketManagerFactory FACTORY = new SslSocketManagerFactory(); 042 private final SslConfiguration sslConfig; 043 044 /** 045 * 046 * 047 * @param name The unique name of this connection. 048 * @param os The OutputStream. 049 * @param sock The Socket. 050 * @param inetAddress The internet address of the host. 051 * @param host The name of the host. 052 * @param port The port number on the host. 053 * @param delay Reconnection interval. 054 * @param immediateFail 055 * @param layout The Layout. 056 */ 057 public SslSocketManager(final String name, final OutputStream os, final Socket sock, final SslConfiguration sslConfig, final InetAddress inetAddress, 058 final String host, final int port, final int delay, final boolean immediateFail, final Layout<? extends Serializable> layout) { 059 super(name, os, sock, inetAddress, host, port, delay, immediateFail, layout); 060 this.sslConfig = sslConfig; 061 } 062 063 private static class SslFactoryData { 064 protected SslConfiguration sslConfig; 065 private final String host; 066 private final int port; 067 private final int delayMillis; 068 private final boolean immediateFail; 069 private final Layout<? extends Serializable> layout; 070 071 public SslFactoryData(final SslConfiguration sslConfig, final String host, final int port, final int delayMillis, final boolean immediateFail, 072 final Layout<? extends Serializable> layout) { 073 this.host = host; 074 this.port = port; 075 this.delayMillis = delayMillis; 076 this.immediateFail = immediateFail; 077 this.layout = layout; 078 this.sslConfig = sslConfig; 079 } 080 } 081 082 public static SslSocketManager getSocketManager(final SslConfiguration sslConfig, final String host, int port, 083 int delayMillis, final boolean immediateFail, final Layout<? extends Serializable> layout ) { 084 if (Strings.isEmpty(host)) { 085 throw new IllegalArgumentException("A host name is required"); 086 } 087 if (port <= 0) { 088 port = DEFAULT_PORT; 089 } 090 if (delayMillis == 0) { 091 delayMillis = DEFAULT_RECONNECTION_DELAY_MILLIS; 092 } 093 return (SslSocketManager) getManager("TLS:" + host + ':' + port, 094 new SslFactoryData(sslConfig, host, port, delayMillis, immediateFail, layout), FACTORY); 095 } 096 097 @Override 098 protected Socket createSocket(final String host, final int port) throws IOException { 099 final SSLSocketFactory socketFactory = createSslSocketFactory(sslConfig); 100 return socketFactory.createSocket(host, port); 101 } 102 103 private static SSLSocketFactory createSslSocketFactory(final SslConfiguration sslConf) { 104 SSLSocketFactory socketFactory; 105 106 if (sslConf != null) { 107 socketFactory = sslConf.getSslSocketFactory(); 108 } else { 109 socketFactory = (SSLSocketFactory) SSLSocketFactory.getDefault(); 110 } 111 112 return socketFactory; 113 } 114 115 116 private static class SslSocketManagerFactory implements ManagerFactory<SslSocketManager, SslFactoryData> { 117 118 private class TlsSocketManagerFactoryException extends Exception { 119 120 private static final long serialVersionUID = 1L; 121 } 122 123 @Override 124 public SslSocketManager createManager(final String name, final SslFactoryData data) { 125 InetAddress inetAddress = null; 126 OutputStream os = null; 127 Socket socket = null; 128 129 try { 130 inetAddress = resolveAddress(data.host); 131 socket = createSocket(data); 132 os = socket.getOutputStream(); 133 checkDelay(data.delayMillis, os); 134 } 135 catch (final IOException e) { 136 LOGGER.error("SslSocketManager ({})", name, e); 137 os = new ByteArrayOutputStream(); 138 } 139 catch (final TlsSocketManagerFactoryException e) { 140 LOGGER.catching(Level.DEBUG, e); 141 return null; 142 } 143 return createManager(name, os, socket, data.sslConfig, inetAddress, data.host, data.port, data.delayMillis, data.immediateFail, data.layout); 144 } 145 146 private InetAddress resolveAddress(final String hostName) throws TlsSocketManagerFactoryException { 147 InetAddress address; 148 149 try { 150 address = InetAddress.getByName(hostName); 151 } catch (final UnknownHostException ex) { 152 LOGGER.error("Could not find address of {}", hostName, ex); 153 throw new TlsSocketManagerFactoryException(); 154 } 155 156 return address; 157 } 158 159 private void checkDelay(final int delay, final OutputStream os) throws TlsSocketManagerFactoryException { 160 if (delay == 0 && os == null) { 161 throw new TlsSocketManagerFactoryException(); 162 } 163 } 164 165 private Socket createSocket(final SslFactoryData data) throws IOException { 166 SSLSocketFactory socketFactory; 167 SSLSocket socket; 168 169 socketFactory = createSslSocketFactory(data.sslConfig); 170 socket = (SSLSocket) socketFactory.createSocket(data.host, data.port); 171 return socket; 172 } 173 174 private SslSocketManager createManager(final String name, final OutputStream os, final Socket socket, 175 final SslConfiguration sslConfig, final InetAddress inetAddress, final String host, final int port, 176 final int delay, final boolean immediateFail, final Layout<? extends Serializable> layout) { 177 return new SslSocketManager(name, os, socket, sslConfig, inetAddress, host, port, delay, immediateFail, 178 layout); 179 } 180 } 181 }