Lines 1-1352
Link Here
|
1 |
/* |
|
|
2 |
* Copyright (c) 2009, 2012 IBM Corp. |
3 |
* |
4 |
* All rights reserved. This program and the accompanying materials |
5 |
* are made available under the terms of the Eclipse Public License v1.0 |
6 |
* which accompanies this distribution, and is available at |
7 |
* http://www.eclipse.org/legal/epl-v10.html |
8 |
* |
9 |
* Contributors: |
10 |
* Dave Locke - initial API and implementation and/or initial documentation |
11 |
*/ |
12 |
package org.eclipse.paho.client.mqttv3.internal.security; |
13 |
|
14 |
import java.io.FileInputStream; |
15 |
import java.io.FileNotFoundException; |
16 |
import java.io.IOException; |
17 |
import java.security.KeyManagementException; |
18 |
import java.security.KeyStore; |
19 |
import java.security.KeyStoreException; |
20 |
import java.security.NoSuchAlgorithmException; |
21 |
import java.security.NoSuchProviderException; |
22 |
import java.security.UnrecoverableKeyException; |
23 |
import java.security.cert.CertificateException; |
24 |
import java.util.Hashtable; |
25 |
import java.util.Iterator; |
26 |
import java.util.Properties; |
27 |
import java.util.Set; |
28 |
import java.util.Vector; |
29 |
|
30 |
import javax.net.ssl.KeyManager; |
31 |
import javax.net.ssl.KeyManagerFactory; |
32 |
import javax.net.ssl.SSLContext; |
33 |
import javax.net.ssl.SSLSocketFactory; |
34 |
import javax.net.ssl.TrustManager; |
35 |
import javax.net.ssl.TrustManagerFactory; |
36 |
|
37 |
import org.eclipse.paho.client.mqttv3.MqttSecurityException; |
38 |
//import org.eclipse.paho.client.mqttv3.internal.comms.MqttDirectException; |
39 |
//import org.eclipse.paho.client.mqttv3.internal.comms.MqttSSLInitException; |
40 |
import org.eclipse.paho.client.mqttv3.logging.Logger; |
41 |
|
42 |
|
43 |
/** |
44 |
* An SSLSocketFactoryFactory provides a socket factory and a server socket |
45 |
* factory that then can be used to create SSL client sockets or SSL server |
46 |
* sockets. |
47 |
* <p> |
48 |
* The SSLSocketFactoryFactory is configured using IBM SSL properties, i.e. |
49 |
* properties of the format "com.ibm.ssl.propertyName", e.g. |
50 |
* "com.ibm.ssl.keyStore". The class supports multiple configurations, each |
51 |
* configuration is identified using a name or configuration ID. The |
52 |
* configuration ID with "null" is used as a default configuration. When a |
53 |
* socket factory is being created for a given configuration, properties of that |
54 |
* configuration are first picked. If a property is not defined there, then that |
55 |
* property is looked up in the default configuration. Finally, if a property |
56 |
* element is still not found, then the corresponding system property is |
57 |
* inspected, i.e. javax.net.ssl.keyStore. If the system property is not set |
58 |
* either, then the system's default value is used (if available) or an |
59 |
* exception is thrown. |
60 |
* <p> |
61 |
* The SSLSocketFacotryFactory can be reconfigured at any time. A |
62 |
* reconfiguration does not affect existing socket factories. |
63 |
* <p> |
64 |
* All properties share the same key space; i.e. the configuration ID is not |
65 |
* part of the property keys. |
66 |
* <p> |
67 |
* The methods should be called in the following order: |
68 |
* <ol> |
69 |
* <li><b>isSupportedOnJVM()</b>: to check whether this class is supported on |
70 |
* the runtime platform. Not all runtimes support SSL/TLS.</li> |
71 |
* <li><b>SSLSocketFactoryFactory()</b>: the constructor. Clients |
72 |
* (in the same JVM) may share an SSLSocketFactoryFactory, or have one each.</li> |
73 |
* <li><b>initialize(properties, configID)</b>: to initialize this object with |
74 |
* the required SSL properties for a configuration. This may be called multiple |
75 |
* times, once for each required configuration.It may be called again to change the required SSL |
76 |
* properties for a particular configuration</li> |
77 |
* <li><b>getEnabledCipherSuites(configID)</b>: to later set the enabled |
78 |
* cipher suites on the socket [see below].</li> |
79 |
* </ol> |
80 |
* <ul> |
81 |
* <li><i>For an MQTT server:</i></li> |
82 |
* <ol> |
83 |
* <li><b>getKeyStore(configID)</b>: Optionally, to check that if there is no |
84 |
* keystore, then that all the enabled cipher suits are anonymous.</li> |
85 |
* <li><b>createServerSocketFactory(configID)</b>: to create an |
86 |
* SSLServerSocketFactory.</li> |
87 |
* <li><b>getClientAuthentication(configID)</b>: to later set on the |
88 |
* SSLServerSocket (itself created from the SSLServerSocketFactory) whether |
89 |
* client authentication is needed.</li> |
90 |
* </ol> |
91 |
* <li><i>For an MQTT client:</i></li> |
92 |
* <ol> |
93 |
* <li><b>createSocketFactory(configID)</b>: to create an SSLSocketFactory.</li> |
94 |
* </ol> |
95 |
* </ul> |
96 |
*/ |
97 |
public class SSLSocketFactoryFactory { |
98 |
private final static String CLASS_NAME = "org.eclipse.paho.client.mqttv3.internal.security.SSLSocketFactoryFactory"; |
99 |
/** |
100 |
* Property keys specific to the client). |
101 |
*/ |
102 |
public final static String SSLPROTOCOL="com.ibm.ssl.protocol"; |
103 |
public final static String JSSEPROVIDER="com.ibm.ssl.contextProvider"; |
104 |
public final static String KEYSTORE="com.ibm.ssl.keyStore"; |
105 |
public final static String KEYSTOREPWD="com.ibm.ssl.keyStorePassword"; |
106 |
public final static String KEYSTORETYPE="com.ibm.ssl.keyStoreType"; |
107 |
public final static String KEYSTOREPROVIDER="com.ibm.ssl.keyStoreProvider"; |
108 |
public final static String KEYSTOREMGR="com.ibm.ssl.keyManager"; |
109 |
public final static String TRUSTSTORE="com.ibm.ssl.trustStore"; |
110 |
public final static String TRUSTSTOREPWD="com.ibm.ssl.trustStorePassword"; |
111 |
public final static String TRUSTSTORETYPE="com.ibm.ssl.trustStoreType"; |
112 |
public final static String TRUSTSTOREPROVIDER="com.ibm.ssl.trustStoreProvider"; |
113 |
public final static String TRUSTSTOREMGR="com.ibm.ssl.trustManager"; |
114 |
public final static String CIPHERSUITES="com.ibm.ssl.enabledCipherSuites"; |
115 |
public final static String CLIENTAUTH="com.ibm.ssl.clientAuthentication"; |
116 |
|
117 |
/** |
118 |
* Property keys used for java system properties |
119 |
*/ |
120 |
public final static String SYSKEYSTORE="javax.net.ssl.keyStore"; |
121 |
public final static String SYSKEYSTORETYPE="javax.net.ssl.keyStoreType"; |
122 |
public final static String SYSKEYSTOREPWD="javax.net.ssl.keyStorePassword"; |
123 |
public final static String SYSTRUSTSTORE="javax.net.ssl.trustStore"; |
124 |
public final static String SYSTRUSTSTORETYPE="javax.net.ssl.trustStoreType"; |
125 |
public final static String SYSTRUSTSTOREPWD="javax.net.ssl.trustStorePassword"; |
126 |
public final static String SYSKEYMGRALGO="ssl.KeyManagerFactory.algorithm"; |
127 |
public final static String SYSTRUSTMGRALGO="ssl.TrustManagerFactory.algorithm"; |
128 |
|
129 |
|
130 |
public final static String DEFAULT_PROTOCOL = "TLS"; // "SSL_TLS" is not supported by DesktopEE |
131 |
|
132 |
private final static String propertyKeys[] = { SSLPROTOCOL, JSSEPROVIDER, |
133 |
KEYSTORE, KEYSTOREPWD, KEYSTORETYPE, KEYSTOREPROVIDER, KEYSTOREMGR, |
134 |
TRUSTSTORE, TRUSTSTOREPWD, TRUSTSTORETYPE, TRUSTSTOREPROVIDER, |
135 |
TRUSTSTOREMGR, CIPHERSUITES, CLIENTAUTH}; |
136 |
|
137 |
private Hashtable configs; // a hashtable that maps configIDs to properties. |
138 |
|
139 |
private Properties defaultProperties; |
140 |
|
141 |
private static final byte[] key = { (byte) 0x9d, (byte) 0xa7, (byte) 0xd9, |
142 |
(byte) 0x80, (byte) 0x05, (byte) 0xb8, (byte) 0x89, (byte) 0x9c }; |
143 |
|
144 |
private static final String xorTag = "{xor}"; |
145 |
|
146 |
private Logger logger = null; |
147 |
|
148 |
|
149 |
/** |
150 |
* Not all of the JVM/Platforms support all of its |
151 |
* security features. This method determines if is supported. |
152 |
* |
153 |
* @return whether dependent classes can be instantiated on the current |
154 |
* JVM/platform. |
155 |
* |
156 |
* @throws Error |
157 |
* if any unexpected error encountered whilst checking. Note |
158 |
* this should not be a ClassNotFoundException, which should |
159 |
* cause the method to return false. |
160 |
*/ |
161 |
public static boolean isSupportedOnJVM() throws LinkageError, ExceptionInInitializerError { |
162 |
String requiredClassname = "javax.net.ssl.SSLServerSocketFactory"; |
163 |
try { |
164 |
Class.forName(requiredClassname); |
165 |
} catch (ClassNotFoundException e) { |
166 |
return false; |
167 |
} |
168 |
return true; |
169 |
} |
170 |
|
171 |
|
172 |
/** |
173 |
* Create new instance of class. |
174 |
* Constructor used by clients. |
175 |
*/ |
176 |
public SSLSocketFactoryFactory() { |
177 |
configs = new Hashtable(); |
178 |
} |
179 |
|
180 |
/** |
181 |
* Create new instance of class. |
182 |
* Constructor used by the broker. |
183 |
*/ |
184 |
public SSLSocketFactoryFactory(Logger logger) { |
185 |
this(); |
186 |
this.logger = logger; |
187 |
} |
188 |
|
189 |
/** |
190 |
* Checks whether a key belongs to the supported IBM SSL property keys. |
191 |
* |
192 |
* @param key |
193 |
* @return whether a key belongs to the supported IBM SSL property keys. |
194 |
*/ |
195 |
private boolean keyValid(String key) { |
196 |
int i = 0; |
197 |
while (i < propertyKeys.length) { |
198 |
if (propertyKeys[i].equals(key)) { |
199 |
break; |
200 |
} |
201 |
++i; |
202 |
} |
203 |
return i < propertyKeys.length; |
204 |
} |
205 |
|
206 |
/** |
207 |
* Checks whether the property keys belong to the supported IBM SSL property |
208 |
* key set. |
209 |
* |
210 |
* @param properties |
211 |
* @throws IllegalArgumentException |
212 |
* if any of the properties is not a valid IBM SSL property key. |
213 |
*/ |
214 |
private void checkPropertyKeys(Properties properties) |
215 |
throws IllegalArgumentException { |
216 |
Set keys = properties.keySet(); |
217 |
Iterator i = keys.iterator(); |
218 |
while (i.hasNext()) { |
219 |
String k = (String) i.next(); |
220 |
if (!keyValid(k)) { |
221 |
throw new IllegalArgumentException(k + " is not a valid IBM SSL property key."); |
222 |
} |
223 |
} |
224 |
} |
225 |
|
226 |
/** |
227 |
* Convert byte array to char array, where each char is constructed from two |
228 |
* bytes. |
229 |
* |
230 |
* @param b |
231 |
* byte array |
232 |
* @return char array |
233 |
*/ |
234 |
public static char[] toChar(byte[] b) { |
235 |
if(b==null) return null; |
236 |
char[] c= new char[b.length/2]; |
237 |
int i=0; int j=0; |
238 |
while(i<b.length) { |
239 |
c[j++] = (char) ((b[i++] & 0xFF) + ((b[i++] & 0xFF)<<8)); |
240 |
} |
241 |
return c; |
242 |
} |
243 |
|
244 |
/** |
245 |
* Convert char array to byte array, where each char is split into two |
246 |
* bytes. |
247 |
* |
248 |
* @param c |
249 |
* char array |
250 |
* @return byte array |
251 |
*/ |
252 |
public static byte[] toByte(char[] c) { |
253 |
if(c==null) return null; |
254 |
byte[] b=new byte[c.length*2]; |
255 |
int i=0; int j=0; |
256 |
while(j<c.length) { |
257 |
b[i++] = (byte) (c[j] & 0xFF); |
258 |
b[i++] = (byte) ((c[j++] >> 8)& 0xFF); |
259 |
} |
260 |
return b; |
261 |
} |
262 |
|
263 |
/** |
264 |
* Obfuscates the password using a simple and not very secure XOR mechanism. |
265 |
* This should not be used for cryptographical purpose, it's a simple |
266 |
* scrambler to obfuscate clear-text passwords. |
267 |
* |
268 |
* @see org.eclipse.paho.client.mqttv3.internal.security.SSLSocketFactoryFactory#deObfuscate |
269 |
* |
270 |
* @param password |
271 |
* The password to be encrypted, as a char[] array. |
272 |
* @return An obfuscated password as a String. |
273 |
*/ |
274 |
public static String obfuscate(char[] password) { |
275 |
if (password == null) |
276 |
return null; |
277 |
byte[] bytes = toByte(password); |
278 |
for (int i = 0; i < bytes.length; i++) { |
279 |
bytes[i] = (byte) ((bytes[i] ^ key[i % key.length]) & 0x00ff); |
280 |
} |
281 |
String encryptedValue = xorTag |
282 |
+ new String(SimpleBase64Encoder.encode(bytes)); |
283 |
return encryptedValue; |
284 |
} |
285 |
|
286 |
/** |
287 |
* The inverse operation of obfuscate: returns a cleartext password that was |
288 |
* previously obfuscated using the XOR scrambler. |
289 |
* |
290 |
* @see org.eclipse.paho.client.mqttv3.internal.security.SSLSocketFactoryFactory#obfuscate |
291 |
* |
292 |
* @param ePassword |
293 |
* An obfuscated password. |
294 |
* @return An array of char, containing the clear text password. |
295 |
*/ |
296 |
public static char[] deObfuscate(String ePassword) { |
297 |
if (ePassword == null) |
298 |
return null; |
299 |
byte[] bytes = null; |
300 |
try { |
301 |
bytes = SimpleBase64Encoder.decode(ePassword.substring(xorTag |
302 |
.length())); |
303 |
} catch (Exception e) { |
304 |
return null; |
305 |
} |
306 |
|
307 |
for (int i = 0; i < bytes.length; i++) { |
308 |
bytes[i] = (byte) ((bytes[i] ^ key[i % key.length]) & 0x00ff); |
309 |
} |
310 |
return toChar(bytes); |
311 |
} |
312 |
|
313 |
/** |
314 |
* Converts an array of ciphers into a single String. |
315 |
* |
316 |
* @param ciphers |
317 |
* The array of cipher names. |
318 |
* @return A string containing the name of the ciphers, separated by comma. |
319 |
*/ |
320 |
public static String packCipherSuites(String[] ciphers) { |
321 |
String cipherSet=null; |
322 |
if (ciphers != null) { |
323 |
StringBuffer buf = new StringBuffer(); |
324 |
for (int i = 0; i < ciphers.length; i++) { |
325 |
buf.append(ciphers[i]); |
326 |
if (i < ciphers.length - 1) { |
327 |
buf.append(','); |
328 |
} |
329 |
} |
330 |
cipherSet = buf.toString(); |
331 |
} |
332 |
return cipherSet; |
333 |
} |
334 |
|
335 |
/** |
336 |
* Inverse operation of packCipherSuites: converts a string of cipher names |
337 |
* into an array of cipher names |
338 |
* |
339 |
* @param ciphers |
340 |
* A list of ciphers, separated by comma. |
341 |
* @return An array of string, each string containing a single cipher name. |
342 |
*/ |
343 |
public static String[] unpackCipherSuites(String ciphers) { |
344 |
// can't use split as split is not available on all java platforms. |
345 |
if(ciphers==null) return null; |
346 |
Vector c=new Vector(); |
347 |
int i=ciphers.indexOf(','); |
348 |
int j=0; |
349 |
// handle all commas. |
350 |
while(i>-1) { |
351 |
// add stuff before and up to (but not including) the comma. |
352 |
c.add(ciphers.substring(j, i)); |
353 |
j=i+1; // skip the comma. |
354 |
i=ciphers.indexOf(',',j); |
355 |
} |
356 |
// add last element after the comma or only element if no comma is present. |
357 |
c.add(ciphers.substring(j)); |
358 |
String[] s = new String[c.size()]; |
359 |
c.toArray(s); |
360 |
return s; |
361 |
} |
362 |
|
363 |
/** |
364 |
* Obfuscate any key & trust store passwords within the given properties. |
365 |
* |
366 |
* @see org.eclipse.paho.client.mqttv3.internal.security.SSLSocketFactoryFactory#obfuscate |
367 |
* |
368 |
* @param p |
369 |
* properties |
370 |
*/ |
371 |
private void convertPassword(Properties p) { |
372 |
String pw = p.getProperty(KEYSTOREPWD); |
373 |
if (pw != null && !pw.startsWith(xorTag)) { |
374 |
String epw = obfuscate(pw.toCharArray()); |
375 |
p.put(KEYSTOREPWD, epw); |
376 |
} |
377 |
pw = p.getProperty(TRUSTSTOREPWD); |
378 |
if (pw != null && !pw.startsWith(xorTag)) { |
379 |
String epw = obfuscate(pw.toCharArray()); |
380 |
p.put(TRUSTSTOREPWD, epw); |
381 |
} |
382 |
} |
383 |
|
384 |
/** |
385 |
* Returns the properties object for configuration configID or creates a new |
386 |
* one if required. |
387 |
* |
388 |
* @param configID |
389 |
* The configuration identifier for selecting a configuration or |
390 |
* null for the default configuration. |
391 |
* @return the properties object for configuration configID |
392 |
*/ |
393 |
// private Properties getOrCreate(String configID) { |
394 |
// Properties res = null; |
395 |
// if (configID == null) { |
396 |
// if (this.defaultProperties == null) { |
397 |
// this.defaultProperties = new Properties(); |
398 |
// } |
399 |
// res = this.defaultProperties; |
400 |
// } else { |
401 |
// res = (Properties) this.configs.get(configID); |
402 |
// if (res == null) { |
403 |
// res = new Properties(); |
404 |
// this.configs.put(configID, res); |
405 |
// } |
406 |
// } |
407 |
// return res; |
408 |
// } |
409 |
|
410 |
/** |
411 |
* Initializes the SSLSocketFactoryFactory with the provided properties for |
412 |
* the provided configuration. |
413 |
* |
414 |
* @param props |
415 |
* A properties object containing IBM SSL properties that are |
416 |
* qualified by one or more configuration identifiers. |
417 |
* @param configID |
418 |
* The configuration identifier for selecting a configuration or |
419 |
* null for the default configuration. |
420 |
* @throws IllegalArgumentException |
421 |
* if any of the properties is not a valid IBM SSL property key. |
422 |
*/ |
423 |
public void initialize(Properties props, String configID) |
424 |
throws IllegalArgumentException { |
425 |
checkPropertyKeys(props); |
426 |
// copy the properties. |
427 |
Properties p = new Properties(); |
428 |
p.putAll(props); |
429 |
convertPassword(p); |
430 |
if (configID != null) { |
431 |
this.configs.put(configID, p); |
432 |
} else { |
433 |
this.defaultProperties = p; |
434 |
} |
435 |
} |
436 |
|
437 |
/** |
438 |
* Merges the given IBM SSL properties into the existing configuration, |
439 |
* overwriting existing properties. This method is used to selectively |
440 |
* change properties for a given configuration. The method throws an |
441 |
* IllegalArgumentException if any of the properties is not a valid IBM SSL |
442 |
* property key. |
443 |
* |
444 |
* @param props |
445 |
* A properties object containing IBM SSL properties |
446 |
* @param configID |
447 |
* The configuration identifier for selecting a configuration or |
448 |
* null for the default configuration. |
449 |
* @throws IllegalArgumentException |
450 |
* if any of the properties is not a valid IBM SSL property key. |
451 |
*/ |
452 |
public void merge(Properties props, String configID) |
453 |
throws IllegalArgumentException { |
454 |
checkPropertyKeys(props); |
455 |
Properties p = this.defaultProperties; |
456 |
if (configID == null) { |
457 |
p = (Properties) this.configs.get(configID); |
458 |
} |
459 |
if (p == null) { |
460 |
p = new Properties(); |
461 |
} |
462 |
convertPassword(props); |
463 |
p.putAll(props); |
464 |
if (configID != null) { |
465 |
this.configs.put(configID, p); |
466 |
} else { |
467 |
this.defaultProperties = p; |
468 |
} |
469 |
|
470 |
} |
471 |
|
472 |
/** |
473 |
* Remove the configuration of a given configuration identifier. |
474 |
* |
475 |
* @param configID |
476 |
* The configuration identifier for selecting a configuration or |
477 |
* null for the default configuration. |
478 |
* @return true, if the configuation could be removed. |
479 |
*/ |
480 |
public boolean remove(String configID) { |
481 |
boolean res = false; |
482 |
if (configID != null) { |
483 |
res = this.configs.remove(configID) != null; |
484 |
} else { |
485 |
if(null != this.defaultProperties) { |
486 |
res = true; |
487 |
this.defaultProperties = null; |
488 |
} |
489 |
} |
490 |
return res; |
491 |
} |
492 |
|
493 |
/** |
494 |
* Returns the configuration of the SSLSocketFactoryFactory for a given |
495 |
* configuration. Note that changes in the property are reflected in the |
496 |
* SSLSocketFactoryFactory. |
497 |
* |
498 |
* @param configID |
499 |
* The configuration identifier for selecting a configuration or |
500 |
* null for the default configuration. |
501 |
* @return A property object containing the current configuration of the |
502 |
* SSLSocketFactoryFactory. Note that it could be null. |
503 |
*/ |
504 |
public Properties getConfiguration(String configID) { |
505 |
return (Properties) (configID == null ? this.defaultProperties |
506 |
: this.configs.get(configID)); |
507 |
} |
508 |
|
509 |
/** |
510 |
* @return Returns the set of configuration IDs that exist in the SSLSocketFactoryFactory. |
511 |
*/ |
512 |
// public String[] getConfigurationIDs() { |
513 |
// Set s = this.configs.keySet(); |
514 |
// String[] configs = new String[s.size()]; |
515 |
// configs = (String[]) s.toArray(configs); |
516 |
// return configs; |
517 |
// } |
518 |
|
519 |
/** |
520 |
* If the value is not null, then put it in the properties object using the |
521 |
* key. If the value is null, then remove the entry in the properties object |
522 |
* with the key. |
523 |
* |
524 |
* @param p |
525 |
* @param key |
526 |
* @param value |
527 |
*/ |
528 |
// private final void putOrRemove(Properties p, String key, String value) { |
529 |
// if (value == null) { |
530 |
// p.remove(key); |
531 |
// } else { |
532 |
// p.put(key, value); |
533 |
// } |
534 |
// } |
535 |
|
536 |
/** |
537 |
* Sets the SSL protocol variant. If protocol is NULL then an existing value |
538 |
* will be removed. |
539 |
* |
540 |
* @param configID |
541 |
* The configuration identifier for selecting a configuration or |
542 |
* null for the default configuration. |
543 |
* @param protocol |
544 |
* One of SSL, SSLv3, TLS, TLSv1, SSL_TLS |
545 |
*/ |
546 |
// public void setSSLProtocol(String configID, String protocol) { |
547 |
// Properties p = getOrCreate(configID); |
548 |
// putOrRemove(p, SSLPROTOCOL, protocol); |
549 |
// } |
550 |
|
551 |
/** |
552 |
* Sets the JSSE context provider. If provider is null, then an existing |
553 |
* value will be removed. |
554 |
* |
555 |
* @param configID |
556 |
* The configuration identifier for selecting a configuration or |
557 |
* null for the default configuration. |
558 |
* @param provider |
559 |
* The JSSE provider. For example "IBMJSSE2" or "SunJSSE". |
560 |
*/ |
561 |
// public void setJSSEProvider(String configID, String provider) { |
562 |
// Properties p = getOrCreate(configID); |
563 |
// putOrRemove(p, JSSEPROVIDER, provider); |
564 |
// } |
565 |
|
566 |
/** |
567 |
* Sets the filename of the keyStore object. A null value is ignored. |
568 |
* |
569 |
* @param configID |
570 |
* The configuration identifier for selecting a configuration or |
571 |
* null for the default configuration. |
572 |
* @param keyStore |
573 |
* A filename that points to a valid keystore. |
574 |
*/ |
575 |
// public void setKeyStore(String configID, String keyStore) { |
576 |
// if (keyStore == null) |
577 |
// return; |
578 |
// Properties p = getOrCreate(configID); |
579 |
// putOrRemove(p, KEYSTORE, keyStore); |
580 |
// } |
581 |
|
582 |
/** |
583 |
* Sets the password that is used for the keystore. The password must be |
584 |
* provided in plain text, but it will be stored internally in a scrambled |
585 |
* XOR format. |
586 |
* |
587 |
* @see org.eclipse.paho.client.mqttv3.internal.security.SSLSocketFactoryFactory#obfuscate |
588 |
* |
589 |
* @param configID |
590 |
* The configuration identifier for selecting a configuration or |
591 |
* null for the default configuration. |
592 |
* @param password |
593 |
* The keystore password |
594 |
*/ |
595 |
// public void setKeyStorePassword(String configID, char[] password) { |
596 |
// if (password == null) |
597 |
// return; |
598 |
// Properties p = getOrCreate(configID); |
599 |
// // convert password, using XOR-based scrambling. |
600 |
// String ePasswd = obfuscate(password); |
601 |
// for(int i=0;i<password.length;i++) { |
602 |
// password[i]=' '; |
603 |
// } |
604 |
// putOrRemove(p, KEYSTOREPWD, ePasswd); |
605 |
// } |
606 |
|
607 |
/** |
608 |
* Sets the keystore provider. The corresponding provider must be installed |
609 |
* in the system. Example values: "IBMJCE" or "IBMJCEFIPS". |
610 |
* |
611 |
* @param configID |
612 |
* The configuration identifier for selecting a configuration or |
613 |
* null for the default configuration. |
614 |
* @param provider |
615 |
* The name of a java cryptography extension |
616 |
*/ |
617 |
// public void setKeyStoreProvider(String configID, String provider) { |
618 |
// Properties p = getOrCreate(configID); |
619 |
// putOrRemove(p, KEYSTOREPROVIDER, provider); |
620 |
// } |
621 |
|
622 |
/** |
623 |
* Sets the keystore type. For example, PKCS12, JKS or JCEKS. The types that |
624 |
* are supported depend on the keystore provider. |
625 |
* |
626 |
* @param configID |
627 |
* The configuration identifier for selecting a configuration or |
628 |
* null for the default configuration. |
629 |
* @param type |
630 |
* The keystore type |
631 |
*/ |
632 |
// public void setKeyStoreType(String configID, String type) { |
633 |
// Properties p = getOrCreate(configID); |
634 |
// putOrRemove(p, KEYSTORETYPE, type); |
635 |
// } |
636 |
|
637 |
/** |
638 |
* Sets a custom key manager and the algorithm that it uses. The keymanager |
639 |
* is specified in the format "algorithm|provider", for example |
640 |
* "IbmX509|IBMJSSE2". The provider might be empty, in which case the |
641 |
* default provider is configured with the specified algorithm. The key |
642 |
* manager must implement the javax.net.ssl.X509KeyManager interface. |
643 |
* |
644 |
* @param configID |
645 |
* The configuration identifier for selecting a configuration or |
646 |
* null for the default configuration. |
647 |
* @param keymanager |
648 |
* An algorithm, provider pair as secified above. |
649 |
*/ |
650 |
// public void setCustomKeyManager(String configID, String keymanager) { |
651 |
// Properties p = getOrCreate(configID); |
652 |
// putOrRemove(p, CUSTOMKEYMGR, keymanager); |
653 |
// } |
654 |
|
655 |
/** |
656 |
* Sets the filename of the truststore object. |
657 |
* |
658 |
* @param configID |
659 |
* The configuration identifier for selecting a configuration or |
660 |
* null for the default configuration. |
661 |
* @param trustStore |
662 |
* A filename that points to a valid truststore. |
663 |
*/ |
664 |
// public void setTrustStore(String configID, String trustStore) { |
665 |
// Properties p = getOrCreate(configID); |
666 |
// putOrRemove(p, TRUSTSTORE, trustStore); |
667 |
// } |
668 |
|
669 |
/** |
670 |
* Sets the password that is used for the truststore. The password must be |
671 |
* provided in plain text, but it will be stored internally in a scrambled |
672 |
* XOR format. |
673 |
* |
674 |
* @see org.eclipse.paho.client.mqttv3.internal.security.SSLSocketFactoryFactory#obfuscate |
675 |
* |
676 |
* @param configID |
677 |
* The configuration identifier for selecting a configuration or |
678 |
* null for the default configuration. |
679 |
* @param password |
680 |
* The truststore password. |
681 |
*/ |
682 |
// public void setTrustStorePassword(String configID, char[] password) { |
683 |
// Properties p = getOrCreate(configID); |
684 |
// // convert password, using XOR-based scrambling. |
685 |
// String ePasswd = obfuscate(password); |
686 |
// for(int i=0;i<password.length;i++) { |
687 |
// password[i]=' '; |
688 |
// } |
689 |
// putOrRemove(p, TRUSTSTOREPWD, ePasswd); |
690 |
// } |
691 |
|
692 |
/** |
693 |
* Sets the truststore provider. The corresponding provider must be |
694 |
* installed in the system. Example values: "IBMJCE" or "IBMJCEFIPS". |
695 |
* |
696 |
* @param configID |
697 |
* The configuration identifier for selecting a configuration or |
698 |
* null for the default configuration. |
699 |
* @param provider |
700 |
* The name of a java cryptography extension. |
701 |
*/ |
702 |
// public void setTrustStoreProvider(String configID, String provider) { |
703 |
// Properties p = getOrCreate(configID); |
704 |
// putOrRemove(p, TRUSTSTOREPROVIDER, provider); |
705 |
// } |
706 |
|
707 |
/** |
708 |
* Sets the truststore type. For example, PKCS12, JKS or JCEKS. The types |
709 |
* that are supported depend on the truststore provider. |
710 |
* |
711 |
* @param configID |
712 |
* The configuration identifier for selecting a configuration or |
713 |
* null for the default configuration. |
714 |
* @param type |
715 |
* The truststore type. |
716 |
*/ |
717 |
// public void setTrustStoreType(String configID, String type) { |
718 |
// Properties p = getOrCreate(configID); |
719 |
// putOrRemove(p, TRUSTSTORETYPE, type); |
720 |
// } |
721 |
|
722 |
/** |
723 |
* Sets a custom trust managers and the algorithm that it uses. The |
724 |
* trustmanager is specified in the format "algorithm|provider", for example |
725 |
* "IbmX509|IBMJSSE2". The provider might be empty, in which case the |
726 |
* default provider is configured with the specified algorithm. The trust |
727 |
* manager must implement the javax.net.ssl.X509TrustManager interface. |
728 |
* |
729 |
* @param configID |
730 |
* The configuration identifier for selecting a configuration or |
731 |
* null for the default configuration. |
732 |
* @param trustmanager |
733 |
* An algorithm, provider pair as secified above. |
734 |
*/ |
735 |
// public void setCustomTrustManager(String configID, String trustmanager) { |
736 |
// Properties p = getOrCreate(configID); |
737 |
// putOrRemove(p, CUSTOMTRUSTMGR, trustmanager); |
738 |
// } |
739 |
|
740 |
/** |
741 |
* Sets the list of enabled ciphers. For a list of acceptable values, see |
742 |
* the documentation of the underlying JSSE. |
743 |
* |
744 |
* @param configID |
745 |
* The configuration identifier for selecting a configuration or |
746 |
* null for the default configuration. |
747 |
* @param ciphers |
748 |
* An array of cipher suite names such as |
749 |
* SSL_RSA_WITH_AES_128_CBC_SHA. |
750 |
*/ |
751 |
// public void setEnabledCipherSuites(String configID, String[] ciphers) { |
752 |
// if (ciphers == null) |
753 |
// return; |
754 |
// Properties p = getOrCreate(configID); |
755 |
// String cipherSet = packCipherSuites(ciphers); |
756 |
// putOrRemove(p, CIPHERSUITES, cipherSet); |
757 |
// } |
758 |
|
759 |
/** |
760 |
* Specifies whether the client is required to provide a valid certificate |
761 |
* to the client during SSL negotiation. |
762 |
* |
763 |
* @param configID |
764 |
* The configuration identifier for selecting a configuration or |
765 |
* null for the default configuration. |
766 |
* @param clientAuth |
767 |
* true, if clients are required to authenticate, false |
768 |
* otherwise. |
769 |
*/ |
770 |
// public void setClientAuthentication(String configID, boolean clientAuth) { |
771 |
// Properties p = getOrCreate(configID); |
772 |
// p.put(CLIENTAUTH, Boolean.toString(clientAuth)); |
773 |
// } |
774 |
|
775 |
/** |
776 |
* Returns the property of a given key or null if it doesn't exist. It first |
777 |
* scans the indicated configuration, then the default configuration, then |
778 |
* the system properties. |
779 |
* |
780 |
* @param configID |
781 |
* The configuration identifier for selecting a configuration or |
782 |
* null for the default configuration. |
783 |
* @param ibmKey |
784 |
* @param sysProperty |
785 |
* The key for the System property. |
786 |
* @return the property of a given key or null if it doesn't exist. |
787 |
*/ |
788 |
private String getProperty(String configID, String ibmKey, String sysProperty) { |
789 |
String res = null; |
790 |
res = getPropertyFromConfig(configID, ibmKey); |
791 |
if ( res != null ) { |
792 |
return res; |
793 |
} |
794 |
// scan system property, if it exists. |
795 |
if (sysProperty != null) { |
796 |
res = System.getProperty(sysProperty); |
797 |
} |
798 |
return res; |
799 |
} |
800 |
|
801 |
/** |
802 |
* Returns the property of a given key or null if it doesn't exist. It first |
803 |
* scans the indicated configuration, then the default configuration |
804 |
* |
805 |
* @param configID |
806 |
* The configuration identifier for selecting a configuration or |
807 |
* null for the default configuration. |
808 |
* @param ibmKey |
809 |
* @return the property of a given key or null if it doesn't exist. It first |
810 |
* scans the indicated configuration, then the default configuration |
811 |
*/ |
812 |
private String getPropertyFromConfig(String configID, String ibmKey) { |
813 |
String res = null; |
814 |
Properties p =null; |
815 |
if(configID!=null) {; |
816 |
p = (Properties) configs.get(configID); |
817 |
} |
818 |
if (p != null) { |
819 |
res = p.getProperty(ibmKey); |
820 |
if (res != null) |
821 |
return res; |
822 |
} |
823 |
// not found in config. try default properties. |
824 |
p = (Properties) this.defaultProperties; |
825 |
if (p != null) { |
826 |
res = p.getProperty(ibmKey); |
827 |
if (res != null) |
828 |
return res; |
829 |
} |
830 |
return res; |
831 |
} |
832 |
|
833 |
/** |
834 |
* Gets the SSL protocol variant of the indicated configuration or the |
835 |
* default configuration. |
836 |
* |
837 |
* @param configID |
838 |
* The configuration identifier for selecting a configuration or |
839 |
* null for the default configuration. |
840 |
* @return The SSL protocol variant. |
841 |
*/ |
842 |
public String getSSLProtocol(String configID) { |
843 |
return getProperty(configID, SSLPROTOCOL, null); |
844 |
} |
845 |
|
846 |
/** |
847 |
* Gets the JSSE provider of the indicated configuration |
848 |
* |
849 |
* @param configID |
850 |
* The configuration identifier for selecting a configuration or |
851 |
* null for the default configuration. |
852 |
* @return The JSSE provider. |
853 |
*/ |
854 |
public String getJSSEProvider(String configID) { |
855 |
return getProperty(configID, JSSEPROVIDER, null); |
856 |
} |
857 |
|
858 |
// /** |
859 |
// * Get the XPD Keystore if running on the XPD platform (otherwise null). |
860 |
// * |
861 |
// * @return the XPD Keystore if running on the XPD platform (otherwise null). |
862 |
// * @throws MqttDirectException |
863 |
// */ |
864 |
// private KeyStore getXPDKeystore() throws MqttDirectException { |
865 |
// KeyStore keyStore = null; |
866 |
// try { |
867 |
// Class secPlatClass = Class.forName("com.ibm.rcp.security.auth.SecurePlatform"); |
868 |
// Method m = secPlatClass.getMethod("getKeyStore", null); |
869 |
// Object secPlat = m.invoke(null,null); // getKeyStore is static |
870 |
// m = secPlatClass.getMethod("isLoggedIn", null); |
871 |
// Boolean b = (Boolean) m.invoke(secPlat, null); |
872 |
// if (b.booleanValue()) { |
873 |
// // login to secure platform was done. |
874 |
// m = secPlatClass.getMethod("getKeyStore", null); |
875 |
// keyStore = (KeyStore) m.invoke(secPlat, null); |
876 |
// } |
877 |
// } catch (ClassNotFoundException e) { |
878 |
// /* |
879 |
// * DEVELOPER NOTE: This is not an error. This means that we are not |
880 |
// * running on XPD runtime and therefore we can not get XPD keystore. |
881 |
// * [Next step for the caller, is try to get the keystore from System |
882 |
// * properties (see getKeyStore() method).] |
883 |
// */ |
884 |
// } catch (IllegalAccessException e) { |
885 |
// Object[] inserts = { e.getLocalizedMessage() }; |
886 |
// throw new MqttSSLInitException(3026, inserts, e); |
887 |
// } catch (SecurityException e) { |
888 |
// Object[] inserts = { e.getLocalizedMessage() }; |
889 |
// throw new MqttSSLInitException(3026, inserts, e); |
890 |
// } catch (NoSuchMethodException e) { |
891 |
// Object[] inserts = { e.getLocalizedMessage() }; |
892 |
// throw new MqttSSLInitException(3026, inserts, e); |
893 |
// } catch (IllegalArgumentException e) { |
894 |
// Object[] inserts = { e.getLocalizedMessage() }; |
895 |
// throw new MqttSSLInitException(3026, inserts, e); |
896 |
// } catch (InvocationTargetException e) { |
897 |
// Object[] inserts = { e.getLocalizedMessage() }; |
898 |
// throw new MqttSSLInitException(3026, inserts, e); |
899 |
// } |
900 |
// return keyStore; |
901 |
// } |
902 |
|
903 |
/** |
904 |
* Gets the name of the keystore file that is used. |
905 |
* |
906 |
* @param configID |
907 |
* The configuration identifier for selecting a configuration or |
908 |
* null for the default configuration. |
909 |
* @return The name of the file that contains the keystore. |
910 |
*/ |
911 |
public String getKeyStore(String configID) { //throws MqttDirectException { |
912 |
String ibmKey = KEYSTORE; |
913 |
String sysProperty = SYSKEYSTORE; |
914 |
|
915 |
String res = null; |
916 |
res = getPropertyFromConfig(configID, ibmKey); |
917 |
if ( res != null ) { |
918 |
return res; |
919 |
} |
920 |
|
921 |
// // check for the XPD keystore here |
922 |
// if ( ibmKey != null && ibmKey.equals(KEYSTORE) ) { |
923 |
// KeyStore keyStore = getXPDKeystore(); |
924 |
// if (keyStore != null) |
925 |
// return res = "Lotus Expeditor"; |
926 |
// } |
927 |
|
928 |
// scan system property, if it exists. |
929 |
if (sysProperty != null) { |
930 |
res = System.getProperty(sysProperty); |
931 |
} |
932 |
|
933 |
return res; |
934 |
} |
935 |
|
936 |
/** |
937 |
* Gets the plain-text password that is used for the keystore. |
938 |
* |
939 |
* @param configID |
940 |
* The configuration identifier for selecting a configuration or |
941 |
* null for the default configuration. |
942 |
* @return The password in plain text. |
943 |
*/ |
944 |
public char[] getKeyStorePassword(String configID) { |
945 |
String pw = getProperty(configID, KEYSTOREPWD, SYSKEYSTOREPWD); |
946 |
char[] r=null; |
947 |
if (pw!=null) { |
948 |
if (pw.startsWith(xorTag)) { |
949 |
r = deObfuscate(pw); |
950 |
} else { |
951 |
r = pw.toCharArray(); |
952 |
} |
953 |
} |
954 |
return r; |
955 |
} |
956 |
|
957 |
/** |
958 |
* Gets the type of keystore. |
959 |
* |
960 |
* @param configID |
961 |
* The configuration identifier for selecting a configuration or |
962 |
* null for the default configuration. |
963 |
* @return The keystore type. |
964 |
*/ |
965 |
public String getKeyStoreType(String configID) { |
966 |
return getProperty(configID, KEYSTORETYPE, SYSKEYSTORETYPE); |
967 |
} |
968 |
|
969 |
/** |
970 |
* Gets the keystore provider. |
971 |
* |
972 |
* @param configID |
973 |
* The configuration identifier for selecting a configuration or |
974 |
* null for the default configuration. |
975 |
* @return The name of the keystore provider. |
976 |
*/ |
977 |
public String getKeyStoreProvider(String configID) { |
978 |
return getProperty(configID, KEYSTOREPROVIDER, null); |
979 |
} |
980 |
|
981 |
/** |
982 |
* Gets the key manager algorithm that is used. |
983 |
* |
984 |
* @param configID |
985 |
* The configuration identifier for selecting a configuration or |
986 |
* null for the default configuration. |
987 |
* @return The key manager algorithm. |
988 |
*/ |
989 |
public String getKeyManager(String configID) { |
990 |
return getProperty(configID, KEYSTOREMGR, SYSKEYMGRALGO); |
991 |
} |
992 |
|
993 |
/** |
994 |
* Gets the name of the truststore file that is used. |
995 |
* |
996 |
* @param configID |
997 |
* The configuration identifier for selecting a configuration or |
998 |
* null for the default configuration. |
999 |
* @return The name of the file that contains the truststore. |
1000 |
*/ |
1001 |
public String getTrustStore(String configID) { |
1002 |
return getProperty(configID, TRUSTSTORE, SYSTRUSTSTORE); |
1003 |
} |
1004 |
|
1005 |
/** |
1006 |
* Gets the plain-text password that is used for the truststore. |
1007 |
* |
1008 |
* @param configID |
1009 |
* The configuration identifier for selecting a configuration or |
1010 |
* null for the default configuration. |
1011 |
* @return The password in plain text. |
1012 |
*/ |
1013 |
public char[] getTrustStorePassword(String configID) { |
1014 |
String pw = getProperty(configID, TRUSTSTOREPWD, SYSTRUSTSTOREPWD); |
1015 |
char[] r=null; |
1016 |
if (pw!=null) { |
1017 |
if(pw.startsWith(xorTag)) { |
1018 |
r = deObfuscate(pw); |
1019 |
} else { |
1020 |
r = pw.toCharArray(); |
1021 |
} |
1022 |
} |
1023 |
return r; |
1024 |
} |
1025 |
|
1026 |
/** |
1027 |
* Gets the type of truststore. |
1028 |
* |
1029 |
* @param configID |
1030 |
* The configuration identifier for selecting a configuration or |
1031 |
* null for the default configuration. |
1032 |
* @return The truststore type. |
1033 |
*/ |
1034 |
public String getTrustStoreType(String configID) { |
1035 |
return getProperty(configID, TRUSTSTORETYPE, null); |
1036 |
} |
1037 |
|
1038 |
/** |
1039 |
* Gets the truststore provider. |
1040 |
* |
1041 |
* @param configID |
1042 |
* The configuration identifier for selecting a configuration or |
1043 |
* null for the default configuration. |
1044 |
* @return The name of the truststore provider. |
1045 |
*/ |
1046 |
public String getTrustStoreProvider(String configID) { |
1047 |
return getProperty(configID, TRUSTSTOREPROVIDER, null); |
1048 |
} |
1049 |
|
1050 |
/** |
1051 |
* Gets the trust manager algorithm that is used. |
1052 |
* |
1053 |
* @param configID |
1054 |
* The configuration identifier for selecting a configuration or |
1055 |
* null for the default configuration. |
1056 |
* @return The trust manager algorithm. |
1057 |
*/ |
1058 |
public String getTrustManager(String configID) { |
1059 |
return getProperty(configID, TRUSTSTOREMGR, SYSTRUSTMGRALGO); |
1060 |
} |
1061 |
|
1062 |
/** |
1063 |
* Returns an array with the enabled ciphers. |
1064 |
* |
1065 |
* @param configID |
1066 |
* The configuration identifier for selecting a configuration or |
1067 |
* null for the default configuration. |
1068 |
* @return an array with the enabled ciphers |
1069 |
*/ |
1070 |
public String[] getEnabledCipherSuites(String configID) { |
1071 |
String ciphers = getProperty(configID, CIPHERSUITES, null); |
1072 |
String[] res = unpackCipherSuites(ciphers); |
1073 |
return res; |
1074 |
} |
1075 |
|
1076 |
/** |
1077 |
* Returns whether client authentication is required. |
1078 |
* |
1079 |
* @param configID |
1080 |
* The configuration identifier for selecting a configuration or |
1081 |
* null for the default configuration. |
1082 |
* @return true, if clients are required to authenticate, false otherwise. |
1083 |
*/ |
1084 |
public boolean getClientAuthentication(String configID) { |
1085 |
String auth = getProperty(configID, CLIENTAUTH, null); |
1086 |
boolean res = false; |
1087 |
if (auth != null) { |
1088 |
res = Boolean.valueOf(auth).booleanValue(); |
1089 |
} |
1090 |
return res; |
1091 |
} |
1092 |
|
1093 |
/** |
1094 |
* Initializes key- and truststore. Returns an SSL context factory. If no |
1095 |
* SSLProtocol is already set, uses DEFAULT_PROTOCOL |
1096 |
* |
1097 |
* @see org.eclipse.paho.client.mqttv3.internal.security.SSLSocketFactoryFactory#DEFAULT_PROTOCOL |
1098 |
* |
1099 |
* @param configID |
1100 |
* The configuration ID |
1101 |
* @return An SSL context factory. |
1102 |
* @throws MqttDirectException |
1103 |
*/ |
1104 |
private SSLContext getSSLContext(String configID) |
1105 |
throws MqttSecurityException{ |
1106 |
final String METHOD_NAME = "getSSLContext"; |
1107 |
SSLContext ctx = null; |
1108 |
|
1109 |
String protocol = getSSLProtocol(configID); |
1110 |
if (protocol == null) { |
1111 |
protocol = DEFAULT_PROTOCOL; |
1112 |
} |
1113 |
if (logger != null) { |
1114 |
// 12000 "SSL initialization: configID = {0}, protocol = {1}" |
1115 |
logger.fine(CLASS_NAME, METHOD_NAME, "12000", new Object[] {configID!=null ? configID : "null (broker defaults)", |
1116 |
protocol}); |
1117 |
} |
1118 |
|
1119 |
String provider = getJSSEProvider(configID); |
1120 |
try { |
1121 |
if (provider == null) { |
1122 |
ctx = SSLContext.getInstance(protocol); |
1123 |
} else { |
1124 |
ctx = SSLContext.getInstance(protocol, provider); |
1125 |
} |
1126 |
if (logger != null) { |
1127 |
// 12001 "SSL initialization: configID = {0}, provider = {1}" |
1128 |
logger.fine(CLASS_NAME, METHOD_NAME, "12001", new Object[] {configID!=null ? configID : "null (broker defaults)", |
1129 |
ctx.getProvider().getName()}); |
1130 |
} |
1131 |
|
1132 |
String keyStoreName = getProperty(configID, KEYSTORE, null); |
1133 |
KeyStore keyStore=null; |
1134 |
KeyManagerFactory keyMgrFact=null; |
1135 |
KeyManager[] keyMgr=null; |
1136 |
// if(keyStoreName==null) { |
1137 |
// // try to instantiate XPD keyStore. |
1138 |
// keyStore=getXPDKeystore(); |
1139 |
// if (logger != null) { |
1140 |
// if (keyStore == null) { |
1141 |
// // 12002 "SSL initialization: configID = {0}, XPD keystore not available" |
1142 |
// logger.fine(CLASS_NAME, METHOD_NAME, "12002", new Object[]{configID!=null ? configID : "null (broker defaults)"}); |
1143 |
// } else { |
1144 |
// // 12003 "SSL initialization: configID = {0}, XPD keystore available" |
1145 |
// logger.fine(CLASS_NAME, METHOD_NAME, "12003", new Object[]{configID!=null ? configID : "null (broker defaults)"}); |
1146 |
// } |
1147 |
// } |
1148 |
// } |
1149 |
|
1150 |
if(keyStore==null) { |
1151 |
if(keyStoreName==null) { |
1152 |
/* |
1153 |
* No keystore in config, XPD keystore not available. Try to |
1154 |
* get config from system properties. |
1155 |
*/ |
1156 |
keyStoreName = getProperty(configID, KEYSTORE, SYSKEYSTORE); |
1157 |
} |
1158 |
if (logger != null) { |
1159 |
// 12004 "SSL initialization: configID = {0}, keystore = {1}" |
1160 |
logger.fine(CLASS_NAME, METHOD_NAME, "12004", new Object[]{configID!=null ? configID : "null (broker defaults)", |
1161 |
keyStoreName!=null ? keyStoreName : "null"}); |
1162 |
} |
1163 |
|
1164 |
char[] keyStorePwd=getKeyStorePassword(configID); |
1165 |
if (logger != null) { |
1166 |
// 12005 "SSL initialization: configID = {0}, keystore password = {1}" |
1167 |
logger.fine(CLASS_NAME, METHOD_NAME, "12005", new Object[]{configID!=null ? configID : "null (broker defaults)", |
1168 |
keyStorePwd!=null ? obfuscate(keyStorePwd) : "null"}); |
1169 |
} |
1170 |
|
1171 |
String keyStoreType=getKeyStoreType(configID); |
1172 |
if(keyStoreType==null) { |
1173 |
keyStoreType = KeyStore.getDefaultType(); |
1174 |
} |
1175 |
if (logger != null) { |
1176 |
// 12006 "SSL initialization: configID = {0}, keystore type = {1}" |
1177 |
logger.fine(CLASS_NAME, METHOD_NAME, "12006", new Object[]{configID!=null ? configID : "null (broker defaults)", |
1178 |
keyStoreType!=null ? keyStoreType : "null"}); |
1179 |
} |
1180 |
|
1181 |
String keyMgrAlgo = KeyManagerFactory.getDefaultAlgorithm(); |
1182 |
String keyMgrProvider = getKeyStoreProvider(configID); |
1183 |
String keyManager = getKeyManager(configID); |
1184 |
if (keyManager != null) { |
1185 |
keyMgrAlgo = keyManager; |
1186 |
} |
1187 |
|
1188 |
if(keyStoreName!=null && keyStoreType!=null && keyMgrAlgo!=null) { |
1189 |
try { |
1190 |
keyStore=KeyStore.getInstance(keyStoreType); |
1191 |
keyStore.load(new FileInputStream(keyStoreName), keyStorePwd); |
1192 |
if(keyMgrProvider!=null) { |
1193 |
keyMgrFact = KeyManagerFactory.getInstance(keyMgrAlgo, keyMgrProvider); |
1194 |
} else { |
1195 |
keyMgrFact = KeyManagerFactory.getInstance(keyMgrAlgo); |
1196 |
} |
1197 |
if (logger != null) { |
1198 |
// 12010 "SSL initialization: configID = {0}, keystore manager algorithm = {1}" |
1199 |
logger.fine(CLASS_NAME, METHOD_NAME, "12010", new Object[]{configID!=null ? configID : "null (broker defaults)", |
1200 |
keyMgrAlgo!=null ? keyMgrAlgo : "null"}); |
1201 |
// 12009 "SSL initialization: configID = {0}, keystore manager provider = {1}" |
1202 |
logger.fine(CLASS_NAME, METHOD_NAME, "12009", new Object[]{configID!=null ? configID : "null (broker defaults)", |
1203 |
keyMgrFact.getProvider().getName()}); |
1204 |
} |
1205 |
keyMgrFact.init(keyStore, keyStorePwd); |
1206 |
keyMgr=keyMgrFact.getKeyManagers(); |
1207 |
} catch (KeyStoreException e) { |
1208 |
throw new MqttSecurityException(e); |
1209 |
} catch (CertificateException e) { |
1210 |
throw new MqttSecurityException(e); |
1211 |
} catch (FileNotFoundException e) { |
1212 |
throw new MqttSecurityException(e); |
1213 |
} catch (IOException e) { |
1214 |
throw new MqttSecurityException(e); |
1215 |
} catch (UnrecoverableKeyException e) { |
1216 |
throw new MqttSecurityException(e); |
1217 |
} |
1218 |
} |
1219 |
} |
1220 |
// keystore loaded, keymanagers instantiated if possible |
1221 |
// now the same for the truststore. |
1222 |
String trustStoreName = getTrustStore(configID); |
1223 |
if (logger != null) { |
1224 |
// 12011 "SSL initialization: configID = {0}, truststore = {1}" |
1225 |
logger.fine(CLASS_NAME, METHOD_NAME, "12011", new Object[]{configID!=null ? configID : "null (broker defaults)", |
1226 |
trustStoreName!=null ? trustStoreName : "null"}); |
1227 |
} |
1228 |
KeyStore trustStore=null; |
1229 |
TrustManagerFactory trustMgrFact=null; |
1230 |
TrustManager[] trustMgr=null; |
1231 |
char[] trustStorePwd=getTrustStorePassword(configID); |
1232 |
if (logger != null) { |
1233 |
// 12012 "SSL initialization: configID = {0}, truststore password = {1}" |
1234 |
logger.fine(CLASS_NAME, METHOD_NAME, "12012", new Object[]{configID!=null ? configID : "null (broker defaults)", |
1235 |
trustStorePwd!=null ? obfuscate(trustStorePwd) : "null"}); |
1236 |
} |
1237 |
String trustStoreType=getTrustStoreType(configID); |
1238 |
if(trustStoreType==null) { |
1239 |
trustStoreType = KeyStore.getDefaultType(); |
1240 |
} |
1241 |
if (logger != null) { |
1242 |
// 12013 "SSL initialization: configID = {0}, truststore type = {1}" |
1243 |
logger.fine(CLASS_NAME, METHOD_NAME, "12013", new Object[]{configID!=null ? configID : "null (broker defaults)", |
1244 |
trustStoreType!=null ? trustStoreType : "null"}); |
1245 |
} |
1246 |
|
1247 |
String trustMgrAlgo = TrustManagerFactory.getDefaultAlgorithm(); |
1248 |
String trustMgrProvider = getTrustStoreProvider(configID); |
1249 |
String trustManager = getTrustManager(configID); |
1250 |
if (trustManager != null) { |
1251 |
trustMgrAlgo = trustManager; |
1252 |
} |
1253 |
|
1254 |
if(trustStoreName!=null && trustStoreType!=null && trustMgrAlgo!=null) { |
1255 |
try { |
1256 |
trustStore=KeyStore.getInstance(trustStoreType); |
1257 |
trustStore.load(new FileInputStream(trustStoreName), trustStorePwd); |
1258 |
if(trustMgrProvider!=null) { |
1259 |
trustMgrFact = TrustManagerFactory.getInstance(trustMgrAlgo, trustMgrProvider); |
1260 |
} else { |
1261 |
trustMgrFact = TrustManagerFactory.getInstance(trustMgrAlgo); |
1262 |
} |
1263 |
if (logger != null) { |
1264 |
|
1265 |
// 12017 "SSL initialization: configID = {0}, truststore manager algorithm = {1}" |
1266 |
logger.fine(CLASS_NAME, METHOD_NAME, "12017", new Object[]{configID!=null ? configID : "null (broker defaults)", |
1267 |
trustMgrAlgo!=null ? trustMgrAlgo : "null"}); |
1268 |
|
1269 |
// 12016 "SSL initialization: configID = {0}, truststore manager provider = {1}" |
1270 |
logger.fine(CLASS_NAME, METHOD_NAME, "12016", new Object[]{configID!=null ? configID : "null (broker defaults)", |
1271 |
trustMgrFact.getProvider().getName()}); |
1272 |
} |
1273 |
trustMgrFact.init(trustStore); |
1274 |
trustMgr=trustMgrFact.getTrustManagers(); |
1275 |
} catch (KeyStoreException e) { |
1276 |
throw new MqttSecurityException(e); |
1277 |
} catch (CertificateException e) { |
1278 |
throw new MqttSecurityException(e); |
1279 |
} catch (FileNotFoundException e) { |
1280 |
throw new MqttSecurityException(e); |
1281 |
} catch (IOException e) { |
1282 |
throw new MqttSecurityException(e); |
1283 |
} |
1284 |
} |
1285 |
// done. |
1286 |
ctx.init(keyMgr, trustMgr, null); |
1287 |
} catch (NoSuchAlgorithmException e) { |
1288 |
throw new MqttSecurityException(e); |
1289 |
} catch (NoSuchProviderException e) { |
1290 |
throw new MqttSecurityException(e); |
1291 |
} catch (KeyManagementException e) { |
1292 |
throw new MqttSecurityException(e); |
1293 |
} |
1294 |
return ctx; |
1295 |
} |
1296 |
|
1297 |
// /** |
1298 |
// * Returns an SSL server socket factory for the given configuration. If no |
1299 |
// * SSLProtocol is already set, uses DEFAULT_PROTOCOL. Throws |
1300 |
// * IllegalArgumentException if the server socket factory could not be |
1301 |
// * created due to underlying configuration problems. |
1302 |
// * |
1303 |
// * @see org.eclipse.paho.client.mqttv3.internal.security.SSLSocketFactoryFactory#DEFAULT_PROTOCOL |
1304 |
// * |
1305 |
// * @param configID |
1306 |
// * The configuration identifier for selecting a configuration. |
1307 |
// * @return An SSLServerSocketFactory |
1308 |
// * @throws MqttDirectException |
1309 |
// */ |
1310 |
// public SSLServerSocketFactory createServerSocketFactory(String configID) |
1311 |
// throws MqttDirectException { |
1312 |
// final String METHOD_NAME = "createServerSocketFactory"; |
1313 |
// SSLContext ctx = getSSLContext(configID); |
1314 |
// if (logger != null) { |
1315 |
// // 12018 "SSL initialization: configID = {0}, application-enabled cipher suites = {1}" |
1316 |
// logger.fine(CLASS_NAME, METHOD_NAME, "12018", new Object[]{configID!=null ? configID : "null (broker defaults)", |
1317 |
// getEnabledCipherSuites(configID)!=null ? getProperty(configID, CIPHERSUITES, null) : "null (using platform-enabled cipher suites)"}); |
1318 |
// |
1319 |
// // 12019 "SSL initialization: configID = {0}, client authentication = {1}" |
1320 |
// logger.fine(CLASS_NAME, METHOD_NAME, "12019", new Object[]{configID!=null ? configID : "null (broker defaults)", |
1321 |
// new Boolean (getClientAuthentication(configID)).toString()}); |
1322 |
// } |
1323 |
// |
1324 |
// return ctx.getServerSocketFactory(); |
1325 |
// } |
1326 |
|
1327 |
/** |
1328 |
* Returns an SSL socket factory for the given configuration. If no |
1329 |
* SSLProtocol is already set, uses DEFAULT_PROTOCOL. Throws |
1330 |
* IllegalArgumentException if the socket factory could not be created due |
1331 |
* to underlying configuration problems. |
1332 |
* |
1333 |
* @see org.eclipse.paho.client.mqttv3.internal.security.SSLSocketFactoryFactory#DEFAULT_PROTOCOL |
1334 |
* @param configID |
1335 |
* The configuration identifier for selecting a configuration. |
1336 |
* @return An SSLSocketFactory |
1337 |
* @throws MqttDirectException |
1338 |
*/ |
1339 |
public SSLSocketFactory createSocketFactory(String configID) |
1340 |
throws MqttSecurityException { |
1341 |
final String METHOD_NAME = "createSocketFactory"; |
1342 |
SSLContext ctx = getSSLContext(configID); |
1343 |
if (logger != null) { |
1344 |
// 12020 "SSL initialization: configID = {0}, application-enabled cipher suites = {1}" |
1345 |
logger.fine(CLASS_NAME, METHOD_NAME, "12020", new Object[]{configID!=null ? configID : "null (broker defaults)", |
1346 |
getEnabledCipherSuites(configID)!=null ? getProperty(configID, CIPHERSUITES, null) : "null (using platform-enabled cipher suites)"}); |
1347 |
} |
1348 |
|
1349 |
return ctx.getSocketFactory(); |
1350 |
} |
1351 |
|
1352 |
} |