our Wildfly 8.1-Server needs to establish an outbound (!) LDAPS-connection to a server within the organization's network. This connection is only used to sync various application data.
Unfortunately, there's no documentation about Wildfly's outbound-only truststore. Every research I do just gives me results about enabling SSL for inbound connections.
How exactly can I add a certificate to Wildfly's truststore for outbound SSL connections? Is there any documentation about this? I'd be thankful for any help on this topic.
Found two possible solutions. First the one i would not use:
System.setProperty("javax.net.ssl.trustStore",path_to_your_cacerts_file);
The second one I'd prefer:
public class LDAPSSocketFactory extends SSLSocketFactory {
private SSLSocketFactory actualSocketFactory;
public LDAPSSocketFactory() {
InputStream certificateInputStream = this.getClass().getClassLoader().getResourceAsStream("yourcert.pfx");
try {
KeyStore pkcs12 = KeyStore.getInstance("pkcs12");
pkcs12.load(certificateInputStream, "".toCharArray());
TrustManagerFactory tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
tmf.init(pkcs12);
SSLContext ctx = SSLContext.getInstance("TLS");
ctx.init(null, tmf.getTrustManagers(), null);
actualSocketFactory = ctx.getSocketFactory();
} catch (KeyStoreException e) {
e.printStackTrace();
} catch (CertificateException e) {
e.printStackTrace();
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (KeyManagementException e) {
e.printStackTrace();
}
}
//Override methods by simply deligating them to the actualSocketFactory
}
And pass this as an JNDI param for ldap connections:
env.put("java.naming.ldap.factory.socket", "LDAPSSocketFactory");
Found all of this on StackOverflow, but I forgot where exactly, so I basically pasted their solution here.
Related
I have a rest org.apache.cxf.jaxrs.client.WebClient client for testing:
WebClient client = WebClient.create(URL);
and I want to make https request with cxf jax-rs
How can I do it? Examples?
ok, this is my solution:
public static void configureSSLOnTheClient(WebClient client,
String keyStoreFileName, String keyStorePassword,
String trustStoreFileName, String trustStorePassword) {
HTTPConduit httpConduit = (HTTPConduit) WebClient.getConfig(client).getConduit();
try {
TLSClientParameters tlsParams = new TLSClientParameters();
KeyStore keyStore;
KeyStore trustStore;
try {
keyStore = KeyStore.getInstance("JKS");
keyStore.load(ClassLoader.getSystemResourceAsStream(keyStoreFileName), keyStorePassword.toCharArray());
KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
keyManagerFactory.init(keyStore, keyStorePassword.toCharArray());
trustStore = KeyStore.getInstance("JKS");
trustStore.load(ClassLoader.getSystemResourceAsStream(trustStoreFileName), trustStorePassword.toCharArray());
TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
trustManagerFactory.init(trustStore);
SSLContext sslContext = SSLContext.getInstance("TLSv1.2");
sslContext.init(keyManagerFactory.getKeyManagers(), trustManagerFactory.getTrustManagers(), new SecureRandom());
tlsParams.setSSLSocketFactory(sslContext.getSocketFactory());
} catch (KeyStoreException e) {
e.printStackTrace();
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (CertificateException e) {
e.printStackTrace();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
// These filters ensure that a ciphersuite with export-suitable or null encryption is used,
// but exclude anonymous Diffie-Hellman key change as this is vulnerable to man-in-the-middle attacks
FiltersType filters = new FiltersType();
filters.getInclude().add(".*_EXPORT_.*");
filters.getInclude().add(".*_EXPORT1024_.*");
filters.getInclude().add(".*_WITH_DES_.*");
filters.getInclude().add(".*_WITH_AES_.*");
filters.getInclude().add(".*_WITH_NULL_.*");
filters.getExclude().add(".*_DH_anon_.*");
tlsParams.setCipherSuitesFilter(filters);
httpConduit.setTlsClientParameters(tlsParams);
} catch (Exception exception) {
LOGGER.error("Security configuration failed with the following: " + exception.getCause(), exception);
}
}
Scenario, I'm dealing with a Webserver that it is a mess (no I do not control this part, I have to play the game, this was coded by one of the biggest software vendors in the world)
By default, the webserver has 2 SSL services, each one of those might have a totally different SSL Certificate
Certificate A
Signature Algorithm: sha1WithRSAEncryption
RSA Key Strength: 1024
Subject: *.dummy.nodomain
Issuer: *.dummy.nodomain
Certificate B
Signature Algorithm: sha1WithRSAEncryption
RSA Key Strength: 2048
Subject: vhcalnplcs_NPL_01
Issuer: root_NPL
Following the examples of this page
public List<String> doPostWithSSL(String direction, String dataToSend, String contentType, boolean OverrideSecurityVerifications) {
try {
URL url = new URL(direction);
List<String> webcontent = new ArrayList();
HttpsURLConnection conn = (HttpsURLConnection) url.openConnection();
conn.setRequestMethod("POST");
conn.setRequestProperty("Host", getHostByUrl(direction));
conn = new UserAgentsLibrary().getRandomUserAgent(conn);
if (contentType != null) {
conn.setRequestProperty("Content-Type", contentType);
} else {
conn.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
}
conn.setDoOutput(true);
if (OverrideSecurityVerifications) {
try {
TrustManager[] trustAllCerts;
trustAllCerts = new TrustManager[]{new X509TrustManager() {
#Override
public X509Certificate[] getAcceptedIssuers() {
return new X509Certificate[0];
}
#Override
public void checkClientTrusted(X509Certificate[] certs, String authType) throws CertificateException {
}
#Override
public void checkServerTrusted(X509Certificate[] certs, String authType) throws CertificateException {
}
}};
// We want to override the SSL verifications
SSLContext ctx = SSLContext.getInstance("TLS");
ctx.init(null, trustAllCerts, null);
SSLSocketFactory factory = ctx.getSocketFactory();
conn.setDefaultSSLSocketFactory(ctx.getSocketFactory());
HostnameVerifier allHostsValid = (String hostname1, SSLSession session) -> true;
conn.setDefaultHostnameVerifier(allHostsValid);
conn.setSSLSocketFactory(factory);
} catch (KeyManagementException kex) {
System.out.println("[+] Error bypassing SSL Security " + kex.getMessage());
} catch (NoSuchAlgorithmException nsex) {
System.out.println("[+] Error forgeting TLS " + nsex.getMessage());
}
}
OutputStreamWriter wr = new OutputStreamWriter(conn.getOutputStream());
wr.write(dataToSend);
wr.flush();
BufferedReader rd = new BufferedReader(new InputStreamReader(conn.getInputStream()));
String line;
while ((line = rd.readLine()) != null) { //todo+=line+"\n";
webcontent.add(line);
}
wr.close();
rd.close();
return webcontent;
} catch (MalformedURLException mex) {
System.out.println("[+] Error: I received a malformed URL");
return null;
} catch (SSLHandshakeException sslex) {
System.out.println("[+] Error: SSL Handshake Error!" + sslex.getMessage());
return null;
} catch (IOException ioex) {
System.out.println("[+] Error: Input/Output Error!" + ioex.getMessage());
return null;
}
}
I was able to make my program work with certificate B (no issue here) but I cannot make it to work with certificate A (I suspect that the * is causing me trouble)
Things to consider
This is a sample code, do not look for irrelevant details ;)
Yes, I know that this code is vulnerable to MITM attacks and the user is being warned
No, I do not want to add the certificates to my keystore!
I'm using pure J2EE code, I do not wish to use anything that it is not standard
I would like to find a solution that will work for Windows, Mac and Linux
Someone had to have this issue in the past, could you lend me a hand?
I was too tired yesterday.
Replaced conn.setDefaultHostnameVerifier(allHostsValid);
by conn.setHostnameVerifier(allHostsValid);
And now even the cert with the wildcard works!
I have installed the SSL/TLS certificate on the server following the instructions provided by Digicert on the below link. https://www.digicert.com/ssl-certificate-installation-java.htm
Also defined the TrustManager but still i am not able to establish the secure connection.
I am getting the connection failed error with reason "Error in connection establishment: net::ERR_SSL_VERSION_OR_CIPHER_MISMATCH"
Below is my code to add SSL support.
private static void addSSLSupport(DefaultIoFilterChainBuilder chain)
throws Exception {
try {
KeyStore keyStore=KeyStore.getInstance("JKS");
char[] passphrase= {'t','e','s','t','s','s','l'};
keyStore.load(new FileInputStream("/home/ec2-user/digicert/mydomain.jks"),passphrase);
Util.logInfo("Key Store loaded");
SSLContext ctx=SSLContext.getInstance("TLS");
TrustManagerFactory trustFactory=TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
trustFactory.init(keyStore);
X509TrustManager defaultTrustManager = (X509TrustManager) trustFactory.getTrustManagers()[0];
ctx.init(null, trustFactory.getTrustManagers(), null);
SslFilter sslFilter = new SslFilter(ctx);
chain.addLast("sslFilter", sslFilter);
Util.logInfo("SSL ON");
}catch(Exception e){
Util.logError(e.toString());
throw e;
}
}
I have got it worked using KeyManager instead of TrustManager while initializing the SSLContext.
Below is the code for your reference.
private static void addSSLSupport(DefaultIoFilterChainBuilder chain)
throws Exception {
try {
KeyStore keyStore=KeyStore.getInstance("JKS");
char[] passphrase= {'t','e','s','t','s','s','l'};
keyStore.load(new FileInputStream("/root/mydomain.jks"),passphrase);
Util.logInfo("Key Store loaded");
KeyManagerFactory kmf = KeyManagerFactory
.getInstance(KEY_MANAGER_FACTORY_ALGORITHM);
kmf.init(keyStore, passphrase);
SSLContext ctx=SSLContext.getInstance("TLS");
ctx.init(kmf.getKeyManagers(), null, null);
SslFilter sslFilter = new SslFilter(ctx);
chain.addLast("sslFilter", sslFilter);
Util.logInfo("SSL ON");
}catch(Exception e){
Util.logError(e.toString());
throw e;
}
}
Can someone explain to me whether following code is correct to download a certificate ties to a specific person in java? I am getting an exception as "unknown protocol: ldaps".
public void downloadCert() {
String urlStr="ldaps://aServerSomeWhere:636/cn=doe%20john,ou=personnel,o=comany123,c=us?caCertificate;binary";
URL url = null;
try {
url = new URL(urlStr);
URLConnection con = url.openConnection();
InputStream is = con.getInputStream();
CertificateFactory certFactory = CertificateFactory.getInstance("X.509");
X509Certificate cert = (X509Certificate)certFactory.generateCertificate(is);
System.out.println("getVersion: " + cert.getVersion());
} catch (Exception e) {
System.out.println(e.getMessage());
}
}
No it isn't correct. There is no handler for the LDAPS: protocol in the URL/URLConnection system.
You can use JNDI to get the caCertificate attribute of that user, via DirContext.getAttributes().
Im trying to use send to paypal.
Im getting an error stating that my trustmanager has not been initialized. (I think).
This is my first steps into SSL so I may not have this set up correctly. Im getting SSlConfigurationException.
public static SSLContext setupClientSSL(String certPath, String certPassword)
throws SSLConfigurationException {
SSLContext sslContext = null;
try {
KeyManagerFactory kmf =
KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
KeyStore ks = p12ToKeyStore(certPath, certPassword);
kmf.init(ks, certPassword.toCharArray());
//sslContext = getSSLContext(kmf.getKeyManagers());
sslContext = SSLContext.getInstance("SSL", "IBMJSSE2");
} catch (NoSuchAlgorithmException e) {
throw new SSLConfigurationException(e.getMessage(), e);
} catch (KeyStoreException e) {
throw new SSLConfigurationException(e.getMessage(), e);
} catch (UnrecoverableKeyException e) {
throw new SSLConfigurationException(e.getMessage(), e);
} catch (CertificateException e) {
throw new SSLConfigurationException(e.getMessage(), e);
} catch (NoSuchProviderException e) {
throw new SSLConfigurationException(e.getMessage(), e);
} catch (IOException e) {
throw new SSLConfigurationException(e.getMessage(), e);
}
return sslContext;
}
The Information Center has documentation for using the Java Secure Socket Extension including setup and example code.