Using TLS encryption with the TDI LDAP connector
Many TDI connectors have the ability to use SSL encryption on network connections,
but this has been deprecated by the IETF standards for some years.
The preferred security mechanism is TLS (Transport Layer Security) as defined in
RFC2246,
RFC4346 and
RFC5246.
Unfortunately, TDI 7.0 does not yet have a simple tick-box to support TLS in connectors
so we need to add some code (not very much though).
Negotiating TLS
The whole point of using TLS rather than SSL is that TLS can be negotiated after the
application protocol has started. Thus an LDAP server for example only needs to listen on
one TCP port to handle both encrypted and unprotected sessions.
From a TDI point of view, this means that we can intervene in a connector hook to
add TLS protection and the rest of the system does not need to know what we have done.
Here is some code to start TLS:
var ctx;
try{
ctx = thisConnector.connector.getLdapContext();
tls = ctx.extendedOperation(new Packages.javax.naming.ldap.StartTlsRequest());
task.logmsg("Negotiating TLS");
tls.negotiate();
task.logmsg("TLS OK");
} catch (E) {
task.logmsg("TLS negotiation FAILED");
task.logmsg(E);
tls.close();
tls=null;
throw(E);
}
// Now it is safe to authenticate...
try {
ctx.addToEnvironment(
Packages.javax.naming.Context.SECURITY_PRINCIPAL,
"uid=tdi,dc=example,dc=org");
ctx.addToEnvironment(
Packages.javax.naming.Context.SECURITY_CREDENTIALS,
"myPassword");
ctx.reconnect(null);
} catch (E) {
task.logmsg("Bind failed after TLS negotiation");
throw(E);
}
Note that the bind DN and password should
not be specified in the connector configuration, as they will be sent before TLS is established.
It would seem reasonable to put this code in the
After Initialise hook,
but if the connector is in Iterator mode
that does not work as the LDAP search is issued first!
Thus in an LDAP iterator the code must go in the
Before Selection hook.
Drop the code snippet into a suitable connector and try it.
You are likely get a failure message even with a TLS-enabled LDAP server, as the cryptographic trust relationship must be set up before TLS negotiation will succeed.
Key and Certificate management
To set up the cryptographic trust relationship you need to import the CA certificate that signed the LDAP server's certificate. (If you are using a self-signed certificate then just import that, but such relationships are harder to manage in the long run).
TDI 7 comes with the IBM Key Manager that can be started by clicking the 'key manager' button at the top of the CE window. This will allow you to import standard PEM certificates into the JKS keystores that TDI uses.
The complication here is that TDI already uses SSL/TLS when talking to the runtime server, so you must preserve or replace the keys used for that purpose. By default, the same file is used as both keystore and truststore. It is
/opt/IBM/TDI/V7.0/serverapi/testadmin.jks
and the password for it is
administrator
Note also that the keys in the default version expire on 7th September 2010, so if your CE stops talking to the development server on that day you will know why!
I suggest copying the supplied file and editing your
solution.properties
file to point to your local copy.
Look for these items:
javax.net.ssl.trustStore {protect}-javax.net.ssl.trustStorePassword
javax.net.ssl.keyStore {protect}-javax.net.ssl.keyStorePassword
Use the key manager to import your own CA certificate as a Signer Certificate.
TDI should now be able to use TLS when making connections to any server whose certificate was signed by that CA.
A Simple CA
The IBM Key Manager will make self-signed certificates, but will not run a CA for you. Here is a quick way to build a certificate hierarchy using
OpenSSL:
First make the Certificate Authority (only need to do this ONCE):
openssl genrsa -aes128 -out ca.key 2048
openssl req -new -x509 -days 8000 -key ca.key -out ca.cert
Fill in the fields as appropriate - not much is critical here
Remember the passphrase for the CA key!
Useful info comes from these:
openssl x509 -in ca.cert -noout -hash
openssl x509 -in ca.cert -noout -text
Now make a key and certificate for servers accessed through localhost:
openssl genrsa -out localhost.key 1024
openssl req -new -key localhost.key -out localhost.csr
The critical thing here is that the CN field must be 'localhost'
Sign the certificate with your CA:
openssl x509 -req -in localhost.csr -out localhost.cert -CA ca.cert -CAkey ca.key -CAcreateserial -days 7999
Check the certificate:
openssl x509 -in localhost.cert -noout -text
Thanks
The TLS code snippet is based on a
newsgroup posting by Ezra Epstein.
--
AndrewFindlay - 03 Jun 2010