Update project structure for aaf/cadi
[aaf/cadi.git] / core / src / main / java / org / onap / aaf / cadi / config / SecurityInfo.java
1 /*******************************************************************************\r
2  * ============LICENSE_START====================================================\r
3  * * org.onap.aaf\r
4  * * ===========================================================================\r
5  * * Copyright © 2017 AT&T Intellectual Property. All rights reserved.\r
6  * * ===========================================================================\r
7  * * Licensed under the Apache License, Version 2.0 (the "License");\r
8  * * you may not use this file except in compliance with the License.\r
9  * * You may obtain a copy of the License at\r
10  * * \r
11  *  *      http://www.apache.org/licenses/LICENSE-2.0\r
12  * * \r
13  *  * Unless required by applicable law or agreed to in writing, software\r
14  * * distributed under the License is distributed on an "AS IS" BASIS,\r
15  * * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
16  * * See the License for the specific language governing permissions and\r
17  * * limitations under the License.\r
18  * * ============LICENSE_END====================================================\r
19  * *\r
20  * * ECOMP is a trademark and service mark of AT&T Intellectual Property.\r
21  * *\r
22  ******************************************************************************/\r
23 package org.onap.aaf.cadi.config;\r
24 \r
25 import java.io.File;\r
26 import java.io.FileInputStream;\r
27 import java.io.IOException;\r
28 import java.net.InetAddress;\r
29 import java.net.UnknownHostException;\r
30 import java.rmi.AccessException;\r
31 import java.security.GeneralSecurityException;\r
32 import java.security.KeyStore;\r
33 import java.security.cert.CertificateException;\r
34 import java.security.cert.X509Certificate;\r
35 import java.util.ArrayList;\r
36 \r
37 import javax.net.ssl.HostnameVerifier;\r
38 import javax.net.ssl.HttpsURLConnection;\r
39 import javax.net.ssl.KeyManager;\r
40 import javax.net.ssl.KeyManagerFactory;\r
41 import javax.net.ssl.SSLContext;\r
42 import javax.net.ssl.SSLSession;\r
43 import javax.net.ssl.SSLSocketFactory;\r
44 import javax.net.ssl.TrustManager;\r
45 import javax.net.ssl.TrustManagerFactory;\r
46 import javax.net.ssl.X509KeyManager;\r
47 import javax.net.ssl.X509TrustManager;\r
48 \r
49 import org.onap.aaf.cadi.Access;\r
50 import org.onap.aaf.cadi.Access.Level;\r
51 import org.onap.aaf.cadi.util.MaskFormatException;\r
52 import org.onap.aaf.cadi.util.NetMask;\r
53 \r
54 public class SecurityInfo {\r
55         private static final String SECURITY_ALGO = "RSA";\r
56         private static final String HTTPS_PROTOCOLS = "https.protocols";\r
57         private static final String JDK_TLS_CLIENT_PROTOCOLS = "jdk.tls.client.protocols";\r
58 \r
59         public static final String HTTPS_PROTOCOLS_DEFAULT = "TLSv1.1,TLSv1.2";\r
60         public static final String REGEX_COMMA = "\\s*,\\s*";\r
61         public static final String SslKeyManagerFactoryAlgorithm;\r
62         \r
63         private SSLSocketFactory scf;\r
64         private X509KeyManager[] km;\r
65         private X509TrustManager[] tm;\r
66         public final String default_alias;\r
67         private NetMask[] trustMasks;\r
68         private SSLContext ctx;\r
69         private HostnameVerifier maskHV;\r
70 \r
71         // Change Key Algorithms for IBM's VM.  Could put in others, if needed.\r
72         static {\r
73                 if(System.getProperty("java.vm.vendor").equalsIgnoreCase("IBM Corporation")) {\r
74                         SslKeyManagerFactoryAlgorithm = "IbmX509";\r
75                 } else {\r
76                         SslKeyManagerFactoryAlgorithm = "SunX509";\r
77                 }\r
78         }\r
79         \r
80 \r
81         public SecurityInfo(final Access access) throws GeneralSecurityException, IOException {\r
82                 // reuse DME2 Properties for convenience if specific Properties don't exist\r
83                 String keyStore = access.getProperty(Config.CADI_KEYSTORE,\r
84                                 access.getProperty(Config.AFT_DME2_KEYSTORE,null));\r
85                 String keyStorePasswd = access.getProperty(Config.CADI_KEYSTORE_PASSWORD,\r
86                                 access.getProperty(Config.AFT_DME2_KEYSTORE_PASSWORD, null));\r
87                 keyStorePasswd = keyStorePasswd==null?null:access.decrypt(keyStorePasswd,false);\r
88                 String trustStore = access.getProperty(Config.CADI_TRUSTSTORE,\r
89                                 access.getProperty(Config.AFT_DME2_TRUSTSTORE, null));\r
90                 String trustStorePasswd = access.getProperty(Config.CADI_TRUSTSTORE_PASSWORD,\r
91                                 access.getProperty(Config.AFT_DME2_TRUSTSTORE_PASSWORD,null));\r
92                 trustStorePasswd = trustStorePasswd==null?null:access.decrypt(trustStorePasswd,false);\r
93                 default_alias = access.getProperty(Config.CADI_ALIAS, \r
94                                 access.getProperty(Config.AFT_DME2_CLIENT_SSL_CERT_ALIAS,null));\r
95                 \r
96                 String keyPasswd = access.getProperty(Config.CADI_KEY_PASSWORD,null);\r
97                 keyPasswd = keyPasswd==null?keyStorePasswd:access.decrypt(keyPasswd,false);\r
98                 String tips=access.getProperty(Config.CADI_TRUST_MASKS, null);\r
99                 if(tips!=null) {\r
100                         access.log(Level.INIT,"Explicitly accepting valid X509s from",tips);\r
101                         String[] ipsplit = tips.split(REGEX_COMMA);\r
102                         trustMasks = new NetMask[ipsplit.length];\r
103                         for(int i=0;i<ipsplit.length;++i) {\r
104                                 try {\r
105                                         trustMasks[i]=new NetMask(ipsplit[i]);\r
106                                 } catch (MaskFormatException e) {\r
107                                         throw new AccessException("Invalid IP Mask in " + Config.CADI_TRUST_MASKS,e);\r
108                                 }\r
109                         }\r
110                 }\r
111                 String https_protocols = Config.logProp(access,Config.CADI_PROTOCOLS, \r
112                                 access.getProperty(Config.AFT_DME2_SSL_INCLUDE_PROTOCOLS, \r
113                                         access.getProperty(HTTPS_PROTOCOLS,HTTPS_PROTOCOLS_DEFAULT)\r
114                                         ));\r
115                 System.setProperty(HTTPS_PROTOCOLS,https_protocols);\r
116                 System.setProperty(JDK_TLS_CLIENT_PROTOCOLS, https_protocols);\r
117                 \r
118                 KeyManagerFactory kmf = KeyManagerFactory.getInstance(SslKeyManagerFactoryAlgorithm);\r
119                 File file;\r
120 \r
121 \r
122                 if(keyStore==null || keyStorePasswd == null) { \r
123                         km = new X509KeyManager[0];\r
124                 } else {\r
125                         ArrayList<X509KeyManager> kmal = new ArrayList<X509KeyManager>();\r
126                         for(String ksname : keyStore.split(REGEX_COMMA)) {\r
127                                 file = new File(ksname);\r
128                                 String keystoreFormat;\r
129                                 if(ksname.endsWith("pkcs12")) {\r
130                                         keystoreFormat = "PKCS12";\r
131                                 } else {\r
132                                         keystoreFormat = "JKS";\r
133                                 }\r
134                                 if(file.exists()) {\r
135                                         FileInputStream fis = new FileInputStream(file);\r
136                                         try {\r
137                                                 KeyStore ks = KeyStore.getInstance(keystoreFormat);\r
138                                                 ks.load(fis, keyStorePasswd.toCharArray());\r
139                                                 kmf.init(ks, keyPasswd.toCharArray());\r
140                                         } finally {\r
141                                                 fis.close();\r
142                                         }\r
143                                 }\r
144                         }\r
145                         for(KeyManager km : kmf.getKeyManagers()) {\r
146                                 if(km instanceof X509KeyManager) {\r
147                                         kmal.add((X509KeyManager)km);\r
148                                 }\r
149                         }\r
150                         km = new X509KeyManager[kmal.size()];\r
151                         kmal.toArray(km);\r
152                 }\r
153 \r
154                 TrustManagerFactory tmf = TrustManagerFactory.getInstance(SslKeyManagerFactoryAlgorithm);\r
155                 if(trustStore!=null) {\r
156                         for(String tsname : trustStore.split(REGEX_COMMA)) {\r
157                                 file = new File(tsname);\r
158                                 if(file.exists()) {\r
159                                         FileInputStream fis = new FileInputStream(file);\r
160                                         try {\r
161                                                 KeyStore ts = KeyStore.getInstance("JKS");\r
162                                                 ts.load(fis, trustStorePasswd.toCharArray());\r
163                                                 tmf.init(ts); \r
164                                         } finally {\r
165                                                 fis.close();\r
166                                         }\r
167                                 }\r
168                         }\r
169                         TrustManager tms[] = tmf.getTrustManagers();\r
170                         tm = new X509TrustManager[tms==null?0:tms.length];\r
171                         for(int i=0;i<tms.length;++i) {\r
172                                 try {\r
173                                         tm[i]=(X509TrustManager)tms[i];\r
174                                 } catch (ClassCastException e) {\r
175                                         access.log(Level.WARN, "Non X509 TrustManager", tm[i].getClass().getName(),"skipped in SecurityInfo");\r
176                                 }\r
177                         }\r
178                 }\r
179                 \r
180                 if(trustMasks!=null) {\r
181                         final HostnameVerifier origHV = HttpsURLConnection.getDefaultHostnameVerifier();\r
182                         HttpsURLConnection.setDefaultHostnameVerifier(maskHV = new HostnameVerifier() {\r
183                                 @Override\r
184                                 public boolean verify(final String urlHostName, final SSLSession session) {\r
185                                         try {\r
186                                                 // This will pick up /etc/host entries as well as DNS\r
187                                                 InetAddress ia = InetAddress.getByName(session.getPeerHost());\r
188                                                 for(NetMask tmask : trustMasks) {\r
189                                                         if(tmask.isInNet(ia.getHostAddress())) {\r
190                                                                 return true;\r
191                                                         }\r
192                                                 }\r
193                                         } catch (UnknownHostException e) {\r
194                                                 // It's ok. do normal Verify\r
195                                         }\r
196                                         return origHV.verify(urlHostName,session);\r
197                                 };\r
198                         });\r
199                 }\r
200                 ctx = SSLContext.getInstance("TLS");\r
201                 ctx.init(km, tm, null);\r
202                 SSLContext.setDefault(ctx);\r
203                 scf = ctx.getSocketFactory();\r
204         }\r
205 \r
206         /**\r
207          * @return the scf\r
208          */\r
209         public SSLSocketFactory getSSLSocketFactory() {\r
210                 return scf;\r
211         }\r
212 \r
213         public SSLContext getSSLContext() {\r
214                 return ctx;\r
215         }\r
216 \r
217         /**\r
218          * @return the km\r
219          */\r
220         public X509KeyManager[] getKeyManagers() {\r
221                 return km;\r
222         }\r
223 \r
224         public void checkClientTrusted(X509Certificate[] certarr) throws CertificateException {\r
225                 for(X509TrustManager xtm : tm) {\r
226                         xtm.checkClientTrusted(certarr, SECURITY_ALGO);\r
227                 }\r
228         }\r
229 \r
230         public void checkServerTrusted(X509Certificate[] certarr) throws CertificateException {\r
231                 for(X509TrustManager xtm : tm) {\r
232                         xtm.checkServerTrusted(certarr, SECURITY_ALGO);\r
233                 }\r
234         }\r
235 \r
236         public void setSocketFactoryOn(HttpsURLConnection hsuc) {\r
237                 hsuc.setSSLSocketFactory(scf);\r
238                 if(maskHV!=null && !maskHV.equals(hsuc.getHostnameVerifier())) {\r
239                         hsuc.setHostnameVerifier(maskHV);\r
240                 }\r
241         }\r
242 \r
243 }\r