Fix XMPPTCPConnection.proceedTLSReceived()

The method was changed in c6594aec2f, but
this change causes issues if Smack is used on Android *without* a custom
SSLContext:

Caused by: java.security.KeyStoreException: java.security.NoSuchAlgorithmException: KeyStore jks implementation not found
 at java.security.KeyStore.getInstance(KeyStore.java:119)
 at org.jivesoftware.smack.tcp.XMPPTCPConnection.proceedTLSReceived(XMPPTCPConnection.java:697)

Caused by: java.security.NoSuchAlgorithmException: KeyManagerFactory SunX509 implementation not found
 at org.apache.harmony.security.fortress.Engine.notFound(Engine.java:177)
 at org.apache.harmony.security.fortress.Engine.getInstance(Engine.java:151)
 at javax.net.ssl.KeyManagerFactory.getInstance(KeyManagerFactory.java:77)
 at org.jivesoftware.smack.tcp.XMPPTCPConnection.proceedTLSReceived(XMPPTCPConnection.java:708)
This commit is contained in:
Florian Schmaus 2016-01-19 17:04:11 +01:00
parent 0761fe0dec
commit 085c3469e9
1 changed files with 26 additions and 19 deletions

View File

@ -674,7 +674,8 @@ public class XMPPTCPConnection extends AbstractXMPPConnection {
PasswordCallback pcb = null; PasswordCallback pcb = null;
if (context == null) { if (context == null) {
if(config.getKeystoreType().equals("PKCS11")) { final String keyStoreType = config.getKeystoreType();
if ("PKCS11".equals(keyStoreType)) {
try { try {
Constructor<?> c = Class.forName("sun.security.pkcs11.SunPKCS11").getConstructor(InputStream.class); Constructor<?> c = Class.forName("sun.security.pkcs11.SunPKCS11").getConstructor(InputStream.class);
String pkcs11Config = "name = SmartCard\nlibrary = "+config.getPKCS11Library(); String pkcs11Config = "name = SmartCard\nlibrary = "+config.getPKCS11Library();
@ -687,47 +688,53 @@ public class XMPPTCPConnection extends AbstractXMPPConnection {
ks.load(null,pcb.getPassword()); ks.load(null,pcb.getPassword());
} }
catch (Exception e) { catch (Exception e) {
LOGGER.log(Level.WARNING, "Exception", e);
ks = null; ks = null;
pcb = null; pcb = null;
} }
} }
else if(config.getKeystoreType().equals("Apple")) { else if ("Apple".equals(keyStoreType)) {
ks = KeyStore.getInstance("KeychainStore","Apple"); ks = KeyStore.getInstance("KeychainStore","Apple");
ks.load(null,null); ks.load(null,null);
//pcb = new PasswordCallback("Apple Keychain",false); //pcb = new PasswordCallback("Apple Keychain",false);
//pcb.setPassword(null); //pcb.setPassword(null);
} }
else { else if (keyStoreType != null){
ks = KeyStore.getInstance(config.getKeystoreType()); ks = KeyStore.getInstance(keyStoreType);
try { try {
pcb = new PasswordCallback("Keystore Password: ",false); pcb = new PasswordCallback("Keystore Password: ",false);
config.getCallbackHandler().handle(new Callback[]{pcb}); config.getCallbackHandler().handle(new Callback[]{pcb});
ks.load(new FileInputStream(config.getKeystorePath()), pcb.getPassword()); ks.load(new FileInputStream(config.getKeystorePath()), pcb.getPassword());
} }
catch(Exception e) { catch(Exception e) {
LOGGER.log(Level.WARNING, "Exception", e);
ks = null; ks = null;
pcb = null; pcb = null;
} }
} }
KeyManagerFactory kmf = KeyManagerFactory.getInstance("SunX509");
try {
if(pcb == null) {
kmf.init(ks,null);
} else {
kmf.init(ks,pcb.getPassword());
pcb.clearPassword();
}
kms = kmf.getKeyManagers();
} catch (NullPointerException npe) {
kms = null;
}
}
// If the user didn't specify a SSLContext, use the default one if (ks != null) {
if (context == null) { KeyManagerFactory kmf = KeyManagerFactory.getInstance("SunX509");
try {
if (pcb == null) {
kmf.init(ks, null);
}
else {
kmf.init(ks, pcb.getPassword());
pcb.clearPassword();
}
kms = kmf.getKeyManagers();
}
catch (NullPointerException npe) {
LOGGER.log(Level.WARNING, "NullPointerException", npe);
}
}
// If the user didn't specify a SSLContext, use the default one
context = SSLContext.getInstance("TLS"); context = SSLContext.getInstance("TLS");
context.init(kms, null, new java.security.SecureRandom()); context.init(kms, null, new java.security.SecureRandom());
} }
Socket plain = socket; Socket plain = socket;
// Secure the plain connection // Secure the plain connection
socket = context.getSocketFactory().createSocket(plain, socket = context.getSocketFactory().createSocket(plain,