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