    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    }