Fix findbugs violations in netconf
[netconf.git] / netconf / netconf-ssh / src / main / java / org / opendaylight / netconf / ssh / SshProxyServer.java
1 /*
2  * Copyright (c) 2014 Cisco Systems, Inc. and others.  All rights reserved.
3  *
4  * This program and the accompanying materials are made available under the
5  * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6  * and is available at http://www.eclipse.org/legal/epl-v10.html
7  */
8
9 package org.opendaylight.netconf.ssh;
10
11 import com.google.common.collect.ImmutableList;
12 import io.netty.channel.EventLoopGroup;
13 import java.io.IOException;
14 import java.nio.channels.AsynchronousChannelGroup;
15 import java.util.List;
16 import java.util.concurrent.ExecutorService;
17 import java.util.concurrent.ScheduledExecutorService;
18 import java.util.concurrent.TimeUnit;
19 import org.apache.sshd.common.FactoryManager;
20 import org.apache.sshd.common.NamedFactory;
21 import org.apache.sshd.common.RuntimeSshException;
22 import org.apache.sshd.common.cipher.BuiltinCiphers;
23 import org.apache.sshd.common.cipher.Cipher;
24 import org.apache.sshd.common.io.IoAcceptor;
25 import org.apache.sshd.common.io.IoConnector;
26 import org.apache.sshd.common.io.IoHandler;
27 import org.apache.sshd.common.io.IoServiceFactory;
28 import org.apache.sshd.common.io.IoServiceFactoryFactory;
29 import org.apache.sshd.common.io.nio2.Nio2Acceptor;
30 import org.apache.sshd.common.io.nio2.Nio2Connector;
31 import org.apache.sshd.common.io.nio2.Nio2ServiceFactoryFactory;
32 import org.apache.sshd.common.util.closeable.AbstractCloseable;
33 import org.apache.sshd.server.ServerFactoryManager;
34 import org.apache.sshd.server.SshServer;
35
36 /**
37  * Proxy SSH server that just delegates decrypted content to a delegate server within same VM.
38  * Implemented using Apache Mina SSH lib.
39  */
40 public class SshProxyServer implements AutoCloseable {
41     private final SshServer sshServer;
42     private final ScheduledExecutorService minaTimerExecutor;
43     private final EventLoopGroup clientGroup;
44     private final IoServiceFactoryFactory nioServiceWithPoolFactoryFactory;
45
46     public SshProxyServer(final ScheduledExecutorService minaTimerExecutor,
47                           final EventLoopGroup clientGroup, final ExecutorService nioExecutor) {
48         this.minaTimerExecutor = minaTimerExecutor;
49         this.clientGroup = clientGroup;
50         this.nioServiceWithPoolFactoryFactory =
51                 new NioServiceWithPoolFactory.NioServiceWithPoolFactoryFactory(nioExecutor);
52         this.sshServer = SshServer.setUpDefaultServer();
53     }
54
55     public void bind(final SshProxyServerConfiguration sshProxyServerConfiguration) throws IOException {
56         sshServer.setHost(sshProxyServerConfiguration.getBindingAddress().getHostString());
57         sshServer.setPort(sshProxyServerConfiguration.getBindingAddress().getPort());
58
59         //remove rc4 ciphers
60         final List<NamedFactory<Cipher>> cipherFactories = sshServer.getCipherFactories();
61         cipherFactories.removeIf(factory -> factory.getName().contains(BuiltinCiphers.arcfour128.getName())
62                 || factory.getName().contains(BuiltinCiphers.arcfour256.getName()));
63         sshServer.setPasswordAuthenticator(
64             (username, password, session)
65                 -> sshProxyServerConfiguration.getAuthenticator().authenticated(username, password));
66
67         sshProxyServerConfiguration.getPublickeyAuthenticator().ifPresent(sshServer::setPublickeyAuthenticator);
68
69         sshServer.setKeyPairProvider(sshProxyServerConfiguration.getKeyPairProvider());
70
71         sshServer.setIoServiceFactoryFactory(nioServiceWithPoolFactoryFactory);
72         sshServer.setScheduledExecutorService(minaTimerExecutor);
73         sshServer.getProperties().put(ServerFactoryManager.IDLE_TIMEOUT,
74             String.valueOf(sshProxyServerConfiguration.getIdleTimeout()));
75         sshServer.getProperties().put(ServerFactoryManager.AUTH_TIMEOUT,
76             String.valueOf(sshProxyServerConfiguration.getIdleTimeout()));
77
78         final RemoteNetconfCommand.NetconfCommandFactory netconfCommandFactory =
79                 new RemoteNetconfCommand.NetconfCommandFactory(clientGroup,
80                         sshProxyServerConfiguration.getLocalAddress());
81         sshServer.setSubsystemFactories(ImmutableList.of(netconfCommandFactory));
82         sshServer.start();
83     }
84
85     @Override
86     public void close() throws IOException {
87         try {
88             sshServer.stop(true);
89         } finally {
90             sshServer.close(true);
91         }
92     }
93
94     /**
95      * Based on Nio2ServiceFactory with one addition: injectable executor.
96      */
97     private static final class NioServiceWithPoolFactory extends AbstractCloseable implements IoServiceFactory {
98
99         private final FactoryManager manager;
100         private final AsynchronousChannelGroup group;
101
102         NioServiceWithPoolFactory(final FactoryManager manager, final ExecutorService executor) {
103             this.manager = manager;
104             try {
105                 group = AsynchronousChannelGroup.withThreadPool(executor);
106             } catch (final IOException e) {
107                 throw new RuntimeSshException(e);
108             }
109         }
110
111         @Override
112         public IoConnector createConnector(final IoHandler handler) {
113             return new Nio2Connector(manager, handler, group);
114         }
115
116         @Override
117         public IoAcceptor createAcceptor(final IoHandler handler) {
118             return new Nio2Acceptor(manager, handler, group);
119         }
120
121         @SuppressWarnings("checkstyle:IllegalCatch")
122         @Override
123         protected void doCloseImmediately() {
124             try {
125                 group.shutdownNow();
126                 group.awaitTermination(5, TimeUnit.SECONDS);
127             } catch (final Exception e) {
128                 log.debug("Exception caught while closing channel group", e);
129             } finally {
130                 super.doCloseImmediately();
131             }
132         }
133
134         private static final class NioServiceWithPoolFactoryFactory extends Nio2ServiceFactoryFactory {
135
136             private final ExecutorService nioExecutor;
137
138             private NioServiceWithPoolFactoryFactory(final ExecutorService nioExecutor) {
139                 this.nioExecutor = nioExecutor;
140             }
141
142             @Override
143             public IoServiceFactory create(final FactoryManager manager) {
144                 return new NioServiceWithPoolFactory(manager, nioExecutor);
145             }
146         }
147     }
148
149 }