6165869eed50d6778befa6f59f6c387b9f1695b8
[netconf.git] / netconf / sal-netconf-connector / src / main / java / org / opendaylight / netconf / sal / connect / util / SslHandlerFactoryImpl.java
1 /*
2  * Copyright (c) 2019 Pantheon Technologies, s.r.o. 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 package org.opendaylight.netconf.sal.connect.util;
9
10 import static java.util.Objects.requireNonNull;
11
12 import com.google.common.collect.Sets;
13 import io.netty.handler.ssl.SslHandler;
14 import java.io.IOException;
15 import java.security.GeneralSecurityException;
16 import java.security.KeyStore;
17 import java.util.Set;
18 import javax.net.ssl.KeyManagerFactory;
19 import javax.net.ssl.SSLContext;
20 import javax.net.ssl.SSLEngine;
21 import javax.net.ssl.TrustManagerFactory;
22 import org.eclipse.jdt.annotation.Nullable;
23 import org.opendaylight.netconf.client.SslHandlerFactory;
24 import org.opendaylight.netconf.sal.connect.netconf.sal.NetconfKeystoreAdapter;
25 import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.netconf.node.connection.parameters.protocol.Specification;
26 import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.netconf.node.connection.parameters.protocol.specification.TlsCase;
27
28 public final class SslHandlerFactoryImpl implements SslHandlerFactory {
29     private final NetconfKeystoreAdapter keystoreAdapter;
30     private final @Nullable Specification specification;
31
32     public SslHandlerFactoryImpl(final NetconfKeystoreAdapter keystoreAdapter) {
33         this(keystoreAdapter, null);
34     }
35
36     public SslHandlerFactoryImpl(final NetconfKeystoreAdapter keystoreAdapter, final Specification specification) {
37         this.keystoreAdapter = requireNonNull(keystoreAdapter);
38         this.specification = specification;
39     }
40
41     @Override
42     public SslHandler createSslHandler() {
43         return createSslHandler(Set.of());
44     }
45
46     @Override
47     public SslHandler createSslHandler(final Set<String> allowedKeys) {
48         try {
49             final KeyStore keyStore = keystoreAdapter.getJavaKeyStore(allowedKeys);
50
51             final KeyManagerFactory kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
52             kmf.init(keyStore, "".toCharArray());
53
54             final TrustManagerFactory tmf =
55                     TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
56             tmf.init(keyStore);
57
58             final SSLContext sslCtx = SSLContext.getInstance("TLS");
59             sslCtx.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null);
60             final SSLEngine engine = sslCtx.createSSLEngine();
61             engine.setUseClientMode(true);
62
63             final String[] engineProtocols = engine.getSupportedProtocols();
64             final String[] enabledProtocols;
65             if (specification instanceof TlsCase tlsSpecification) {
66                 final Set<String> protocols = Sets.newHashSet(engineProtocols);
67                 protocols.removeAll(tlsSpecification.getTls().getExcludedVersions());
68                 enabledProtocols = protocols.toArray(new String[0]);
69             } else if (specification == null) {
70                 enabledProtocols = engineProtocols;
71             } else {
72                 throw new IllegalArgumentException("Cannot get TLS specification from: " + specification);
73             }
74
75             engine.setEnabledProtocols(enabledProtocols);
76             engine.setEnabledCipherSuites(engine.getSupportedCipherSuites());
77             engine.setEnableSessionCreation(true);
78             return new SslHandler(engine);
79         } catch (GeneralSecurityException | IOException exc) {
80             throw new IllegalStateException(exc);
81         }
82     }
83 }