2 * ============LICENSE_START====================================================
4 * ===========================================================================
5 * Copyright (c) 2018 AT&T Intellectual Property. All rights reserved.
6 * ===========================================================================
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
11 * http://www.apache.org/licenses/LICENSE-2.0
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
18 * ============LICENSE_END====================================================
22 package org.onap.aaf.cadi.config;
25 import java.io.FileInputStream;
26 import java.io.IOException;
27 import java.net.InetAddress;
28 import java.net.UnknownHostException;
29 import java.rmi.AccessException;
30 import java.security.KeyManagementException;
31 import java.security.KeyStore;
32 import java.security.KeyStoreException;
33 import java.security.NoSuchAlgorithmException;
34 import java.security.UnrecoverableKeyException;
35 import java.security.cert.CertificateException;
36 import java.security.cert.X509Certificate;
37 import java.util.ArrayList;
39 import javax.net.ssl.HostnameVerifier;
40 import javax.net.ssl.HttpsURLConnection;
41 import javax.net.ssl.KeyManager;
42 import javax.net.ssl.KeyManagerFactory;
43 import javax.net.ssl.SSLContext;
44 import javax.net.ssl.SSLSession;
45 import javax.net.ssl.SSLSocketFactory;
46 import javax.net.ssl.TrustManager;
47 import javax.net.ssl.TrustManagerFactory;
48 import javax.net.ssl.X509KeyManager;
49 import javax.net.ssl.X509TrustManager;
51 import org.onap.aaf.cadi.Access;
52 import org.onap.aaf.cadi.CadiException;
53 import org.onap.aaf.cadi.Access.Level;
54 import org.onap.aaf.cadi.util.MaskFormatException;
55 import org.onap.aaf.cadi.util.NetMask;
57 public class SecurityInfo {
58 private static final String SECURITY_ALGO = "RSA";
59 private static final String HTTPS_PROTOCOLS = "https.protocols";
60 private static final String JDK_TLS_CLIENT_PROTOCOLS = "jdk.tls.client.protocols";
62 public static final String HTTPS_PROTOCOLS_DEFAULT = "TLSv1.1,TLSv1.2";
63 public static final String REGEX_COMMA = "\\s*,\\s*";
64 public static final String SSL_KEY_MANAGER_FACTORY_ALGORITHM;
66 private SSLSocketFactory socketFactory;
67 private X509KeyManager[] x509KeyManager;
68 private X509TrustManager[] x509TrustManager;
69 public final String defaultAlias;
70 private NetMask[] trustMasks;
71 private SSLContext context;
72 private HostnameVerifier maskHV;
73 public final Access access;
75 // Change Key Algorithms for IBM's VM. Could put in others, if needed.
77 if ("IBM Corporation".equalsIgnoreCase(System.getProperty("java.vm.vendor"))) {
78 SSL_KEY_MANAGER_FACTORY_ALGORITHM = "IbmX509";
80 SSL_KEY_MANAGER_FACTORY_ALGORITHM = "SunX509";
85 public SecurityInfo(final Access access) throws CadiException {
88 // reuse DME2 Properties for convenience if specific Properties don't exist
90 initializeKeyManager();
92 initializeTrustManager();
94 defaultAlias = access.getProperty(Config.CADI_ALIAS, null);
96 initializeTrustMasks();
98 String httpsProtocols = Config.logProp(access, Config.CADI_PROTOCOLS,
99 access.getProperty(HTTPS_PROTOCOLS, HTTPS_PROTOCOLS_DEFAULT)
101 System.setProperty(HTTPS_PROTOCOLS, httpsProtocols);
102 System.setProperty(JDK_TLS_CLIENT_PROTOCOLS, httpsProtocols);
103 if ("1.7".equals(System.getProperty("java.specification.version")) && httpsProtocols.contains("TLSv1.2")) {
104 System.setProperty(Config.HTTPS_CIPHER_SUITES, Config.HTTPS_CIPHER_SUITES_DEFAULT);
107 context = SSLContext.getInstance("TLS");
108 context.init(x509KeyManager, x509TrustManager, null);
109 SSLContext.setDefault(context);
110 socketFactory = context.getSocketFactory();
111 } catch (NoSuchAlgorithmException | KeyManagementException | KeyStoreException | CertificateException | UnrecoverableKeyException | IOException e) {
112 throw new CadiException(e);
119 public SSLSocketFactory getSSLSocketFactory() {
120 return socketFactory;
123 public SSLContext getSSLContext() {
130 public X509KeyManager[] getKeyManagers() {
131 return x509KeyManager;
134 public void checkClientTrusted(X509Certificate[] certarr) throws CertificateException {
135 for (X509TrustManager xtm : x509TrustManager) {
136 xtm.checkClientTrusted(certarr, SECURITY_ALGO);
140 public void checkServerTrusted(X509Certificate[] certarr) throws CertificateException {
141 for (X509TrustManager xtm : x509TrustManager) {
142 xtm.checkServerTrusted(certarr, SECURITY_ALGO);
146 public void setSocketFactoryOn(HttpsURLConnection hsuc) {
147 hsuc.setSSLSocketFactory(socketFactory);
148 if (maskHV != null && !maskHV.equals(hsuc.getHostnameVerifier())) {
149 hsuc.setHostnameVerifier(maskHV);
153 protected void initializeKeyManager() throws CadiException, IOException, NoSuchAlgorithmException, KeyStoreException, CertificateException, UnrecoverableKeyException {
154 String keyStore = access.getProperty(Config.CADI_KEYSTORE, null);
157 } else if (!new File(keyStore).exists()) {
158 throw new CadiException(keyStore + " does not exist");
161 String keyStorePasswd = access.getProperty(Config.CADI_KEYSTORE_PASSWORD, null);
162 keyStorePasswd = (keyStorePasswd == null) ? null : access.decrypt(keyStorePasswd, false);
163 if (keyStore == null || keyStorePasswd == null) {
164 x509KeyManager = new X509KeyManager[0];
168 String keyPasswd = access.getProperty(Config.CADI_KEY_PASSWORD, null);
169 keyPasswd = (keyPasswd == null) ? keyStorePasswd : access.decrypt(keyPasswd, false);
171 KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance(SSL_KEY_MANAGER_FACTORY_ALGORITHM);
173 ArrayList<X509KeyManager> keyManagers = new ArrayList<>();
175 for (String ksname : keyStore.split(REGEX_COMMA)) {
176 String keystoreFormat;
177 if (ksname.endsWith(".p12") || ksname.endsWith(".pkcs12")) {
178 keystoreFormat = "PKCS12";
180 keystoreFormat = "JKS";
183 file = new File(ksname);
185 FileInputStream fis = new FileInputStream(file);
187 KeyStore ks = KeyStore.getInstance(keystoreFormat);
188 ks.load(fis, keyStorePasswd.toCharArray());
189 keyManagerFactory.init(ks, keyPasswd.toCharArray());
195 for (KeyManager keyManager : keyManagerFactory.getKeyManagers()) {
196 if (keyManager instanceof X509KeyManager) {
197 keyManagers.add((X509KeyManager)keyManager);
200 x509KeyManager = new X509KeyManager[keyManagers.size()];
201 keyManagers.toArray(x509KeyManager);
204 protected void initializeTrustManager() throws NoSuchAlgorithmException, CertificateException, IOException, KeyStoreException, CadiException {
205 String trustStore = access.getProperty(Config.CADI_TRUSTSTORE, null);
206 if(trustStore==null) {
208 } else if(!new File(trustStore).exists()) {
209 throw new CadiException(trustStore + " does not exist");
212 String trustStorePasswd = access.getProperty(Config.CADI_TRUSTSTORE_PASSWORD, null);
213 trustStorePasswd = (trustStorePasswd == null ) ? "changeit"/*defacto Java Trust Pass*/ : access.decrypt(trustStorePasswd, false);
215 TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(SSL_KEY_MANAGER_FACTORY_ALGORITHM);
217 for (String trustStoreName : trustStore.split(REGEX_COMMA)) {
218 file = new File(trustStoreName);
220 FileInputStream fis = new FileInputStream(file);
222 KeyStore ts = KeyStore.getInstance("JKS");
223 ts.load(fis, trustStorePasswd.toCharArray());
224 trustManagerFactory.init(ts);
231 TrustManager trustManagers[] = trustManagerFactory.getTrustManagers();
232 if (trustManagers == null || trustManagers.length == 0) {
236 x509TrustManager = new X509TrustManager[trustManagers.length];
237 for (int i = 0; i < trustManagers.length; ++i) {
239 x509TrustManager[i] = (X509TrustManager)trustManagers[i];
240 } catch (ClassCastException e) {
241 access.log(Level.WARN, "Non X509 TrustManager", x509TrustManager[i].getClass().getName(), "skipped in SecurityInfo");
246 protected void initializeTrustMasks() throws AccessException {
247 String tips = access.getProperty(Config.CADI_TRUST_MASKS, null);
252 access.log(Level.INIT, "Explicitly accepting valid X509s from", tips);
253 String[] ipsplit = tips.split(REGEX_COMMA);
254 trustMasks = new NetMask[ipsplit.length];
255 for (int i = 0; i < ipsplit.length; ++i) {
257 trustMasks[i] = new NetMask(ipsplit[i]);
258 } catch (MaskFormatException e) {
259 throw new AccessException("Invalid IP Mask in " + Config.CADI_TRUST_MASKS, e);
263 final HostnameVerifier origHV = HttpsURLConnection.getDefaultHostnameVerifier();
264 maskHV = new HostnameVerifier() {
266 public boolean verify(final String urlHostName, final SSLSession session) {
268 // This will pick up /etc/host entries as well as DNS
269 InetAddress ia = InetAddress.getByName(session.getPeerHost());
270 for (NetMask tmask : trustMasks) {
271 if (tmask.isInNet(ia.getHostAddress())) {
275 } catch (UnknownHostException e) {
276 // It's ok. do normal Verify
278 return origHV.verify(urlHostName, session);
281 HttpsURLConnection.setDefaultHostnameVerifier(maskHV);