]> git.basschouten.com Git - openhab-addons.git/blob
99ed5882e331ea0d3297c831dc5b4ea78ddefffe
[openhab-addons.git] /
1 /**
2  * Copyright (c) 2010-2023 Contributors to the openHAB project
3  *
4  * See the NOTICE file(s) distributed with this work for additional
5  * information.
6  *
7  * This program and the accompanying materials are made available under the
8  * terms of the Eclipse Public License 2.0 which is available at
9  * http://www.eclipse.org/legal/epl-2.0
10  *
11  * SPDX-License-Identifier: EPL-2.0
12  */
13 package org.openhab.binding.hue.internal.connection;
14
15 import java.io.IOException;
16 import java.io.InputStream;
17 import java.net.MalformedURLException;
18 import java.net.URL;
19 import java.nio.charset.StandardCharsets;
20 import java.security.cert.CertificateException;
21
22 import javax.net.ssl.X509ExtendedTrustManager;
23
24 import org.eclipse.jdt.annotation.NonNullByDefault;
25 import org.eclipse.jdt.annotation.Nullable;
26 import org.openhab.core.io.net.http.PEMTrustManager;
27 import org.openhab.core.io.net.http.PEMTrustManager.CertificateInstantiationException;
28 import org.openhab.core.io.net.http.TlsTrustManagerProvider;
29 import org.openhab.core.io.net.http.TrustAllTrustManager;
30 import org.slf4j.Logger;
31 import org.slf4j.LoggerFactory;
32
33 /**
34  * Provides a {@link PEMTrustManager} to allow secure connections to any Hue Bridge.
35  *
36  * @author Christoph Weitkamp - Initial Contribution
37  */
38 @NonNullByDefault
39 public class HueTlsTrustManagerProvider implements TlsTrustManagerProvider {
40
41     private static final String PEM_FILENAME = "huebridge_cacert.pem";
42     private final String hostname;
43     private final boolean useSelfSignedCertificate;
44
45     private final Logger logger = LoggerFactory.getLogger(HueTlsTrustManagerProvider.class);
46
47     private @Nullable PEMTrustManager trustManager;
48
49     public HueTlsTrustManagerProvider(String hostname, boolean useSelfSignedCertificate) {
50         this.hostname = hostname;
51         this.useSelfSignedCertificate = useSelfSignedCertificate;
52     }
53
54     @Override
55     public String getHostName() {
56         return hostname;
57     }
58
59     @Override
60     public X509ExtendedTrustManager getTrustManager() {
61         PEMTrustManager localTrustManager = getPEMTrustManager();
62         if (localTrustManager == null) {
63             logger.error("Cannot get the PEM certificate - returning a TrustAllTrustManager");
64         }
65         return localTrustManager != null ? localTrustManager : TrustAllTrustManager.getInstance();
66     }
67
68     public @Nullable PEMTrustManager getPEMTrustManager() {
69         PEMTrustManager localTrustManager = trustManager;
70         if (localTrustManager != null) {
71             return localTrustManager;
72         }
73         try {
74             if (useSelfSignedCertificate) {
75                 logger.trace("Use self-signed certificate downloaded from Hue Bridge.");
76                 // use self-signed certificate downloaded from Hue Bridge
77                 localTrustManager = PEMTrustManager.getInstanceFromServer("https://" + getHostName());
78             } else {
79                 logger.trace("Use Signify private CA Certificate for Hue Bridges from resources.");
80                 // use Signify private CA Certificate for Hue Bridges from resources
81                 localTrustManager = getInstanceFromResource(PEM_FILENAME);
82             }
83             this.trustManager = localTrustManager;
84         } catch (CertificateException | MalformedURLException e) {
85             logger.debug("An unexpected exception occurred: {}", e.getMessage(), e);
86         }
87         return localTrustManager;
88     }
89
90     /**
91      * Creates a {@link PEMTrustManager} instance by reading the PEM certificate from the given file.
92      * This is useful if you have a private CA Certificate stored in a file.
93      *
94      * @param fileName name to the PEM file located in the resources folder
95      * @return a {@link PEMTrustManager} instance
96      * @throws CertificateInstantiationException
97      */
98     private PEMTrustManager getInstanceFromResource(String fileName) throws CertificateException {
99         String pemCert = readPEMCertificateStringFromResource(fileName);
100         if (pemCert != null) {
101             return new PEMTrustManager(pemCert);
102         }
103         throw new CertificateInstantiationException(
104                 String.format("Certificate resource '%s' not found or not accessible.", fileName));
105     }
106
107     private @Nullable String readPEMCertificateStringFromResource(String fileName) {
108         URL resource = Thread.currentThread().getContextClassLoader().getResource(fileName);
109         if (resource != null) {
110             try (InputStream certInputStream = resource.openStream()) {
111                 return new String(certInputStream.readAllBytes(), StandardCharsets.UTF_8);
112             } catch (IOException e) {
113                 logger.error("An unexpected exception occurred: ", e);
114             }
115         }
116         return null;
117     }
118 }