WordPress and SSL

For a while my self-hosted WordPress has been a royal pain in the ass. Trying to compose through the WordPress.com interface through Jetpack would show occasional errors that “Saving of draft failed” or an inability to communicate. Sometimes it was usable, sometimes there were so many errors I gave up and used the site. The site admin interface sometimes made me login every hour or every couple minutes.

I reinstalled Jetpack a couple times. I poked around on the WordPress support forums which I apparently could not search.

So I searched via Google and ran across this How to Fix WordPress Keeps Logging Out Problem article. It dawned on me that I had let my hosting provider setup SSL for the site. The WordPress Address and Site Address fields were using http. So I changed them to https. That seems to have solved the login issues.

I am writing this through the WordPress.com interface and got a failure on saving the draft. So there is something else to make it all better.

DSID-0C090334

Working with our clients on LDAP configuration almost invariable starts with SSL certificates. Self-signed, intermediate, and take up a while. The two tools, openSSL and keytool have become my friends. Working with a network admin for the client, I finally saw the legitimate certificate correctly signed by the intermediate certificate not the self-signed. This means I finally saw this new I error I have never before seen.

javax.naming.AuthenticationException: [LDAP: error code 49 – 80090308: LdapErr: DSID-0C090334, comment: AcceptSecurityContext error, data 525, user@host.domain.tld:    at com.sun.jndi.ldap.LdapCtx.mapErrorCode(LdapCtx.java:3041)

Research on the error code DSID-0C090334 led to indications the LDAP search username was incorrect. The Blackboard CE/Vista LDAP client lacks capabilities many clients have to make it easier to use such as searching deeper into a tree or across branches. In this case our clients configured the user as “cn=account”. We looked at other clients who had something like “cn=account,ou=group,dc=domain,dc=edu”. When presented with this discrepancy as likely a problem, the client suggested a path for us to try like the latter. I entered it, tried our test user.

It worked. They also confirmed it worked. Something to add to the wiki, I guess.

OpenSSL Handshake

Chain

One of the questions we ask our clients initiating an engagement to help them setup external authentication from our LMS to their server is, “What is the certificate authority for your SSL certificate?” We have been burned by people purchasing certificates from authorities Java does not support. (And the support is indeed limited compared to say, Mozilla.)

We were given the name of an intermediate certificate which set off warning klaxons. There are none of these in the cacerts file, the list of root CAs Java uses.

So the clients setup to test. Failures. The error:

javax.naming.CommunicationException: hostname.domain.tld:port [Root exception is javax.net.ssl.SSLPeerUnverifiedException: peer not authenticated

From what I was able to find, the error meant the certificate was not understood. Framed into thinking the intermediate CA was the cause I started looking at how to make it work. The two potential routes were get the client to add the intermediate CA to their server or test ways to complete the chain by adding the intermediate to my client.

More failures.

Amy suggested looking at the certificate on the foreign server by connecting with openssl to get a better idea where it said there was a problem. The command looks like:

openssl s_client -connect hostname:port

The return was pretty clear that it could not understand or trust a self-signed certificate. The “i:” in the last line below is the Issuer. This made it clear the certificate was not signed by the intermediate CA we were told. It was a self-signed certificate. Doh!

depth=0 /CN=hostname.domain.tld
verify error:num=20:unable to get local issuer certificate
verify return:1
depth=0 /CN=hostname.domain.tld
verify error:num=27:certificate not trusted
verify return:1
depth=0 /CN=hostname.domain.tld
verify error:num=21:unable to verify the first certificate
verify return:1
---
Certificate chain
 0 s:/CN=hostname.domain.tld
   i:/DC=tld/DC=domain/CN=domain-NAME-CA

It is clear I need to make checking the certificate on the foreign host part of the standard practice. Did some spot checking of previous setups to test against LDAP and every one has a good certificate chain.

New Root CA

One of our clients introduced a new LDAP server for authentication. Like a good partner, they implemented it in the test environment, found it did not work and alerted us to the problem. They also informed us the problem would be the new Thawte Root CA was not implemented on many operating systems and applications. Indeed our research pointed out Sun/Oracle had not implemented the Root CA in their list of valid ones.

Normally we do not add root CAs. A specific case which comes to mind is another client “bought” a free SSL certificate for higher education from a place in Barcelona. In this case, we decided to go ahead and add it. However, we wanted to do so in a supported manner, so I opened a ticket with Blackboard.

The recommendation was to use the keytool to apply the new Root CA. (I would not do this without having an open ticket with Blackboard as if anything goes wrong, then at least you can get faster support.) After a couple modifications of what they gave me, the keytool command worked. Namely, the cacerts file is installed with read only permission, so it needs write to be edited. Plus the -keypass  The process to use if we need to do this again will be:

# Navigate to where the root cert is stored.
cd ${JAVA_HOME}
cd ../lib/security/
# Copy the existing cacerts file to a backup in case we need to revert.
cp cacerts cacerts.bak
# Copy the existing cacerts file to a working copy so not affect running processes while editing.
cp cacerts cacerts.new
# Java sets permissions on the file to 444. Change to 644 to edit.
chmod 644 cacerts.new && ls -l cacerts*
# Set the variable for the name of the file to import.
NEWCERT=newthawteroot1
# Run the import keytool. Will ask for password. Ask the system admin or try the Java default.
${JAVA_HOME}/keytool -import -trustcacerts -alias ${NEWCERT} -file ${NEWCERT}.pem -keystore cacerts.new
# Verify change took.
${JAVA_HOME}/keytool -list -v -keystore cacerts.new | grep -A 10 ${NEWCERT}
chmod 444 cacerts.new && ls -l cacerts*
chmod 644 cacerts && cp cacerts.new cacerts && chmod 444 cacerts && ls -l cacerts*
# Another verify but on  cacerts would not hurt to make sure it has the new root ca.

At this point I asked for the institution test on the node where I made the change. (It happens that test cluster has a single node in a special pool. I had made this change on that node. It also meant other institutions testing on that cluster were not affected.) We still want to verify introducing this does not affect others using LDAP. I don’t think that it will, but that never comes across to people as reliable when something completely unexpected causes a problem.

Now to write a script to push this change to the other 180 nodes. Should be easy enough as I copied the new cacerts to our mounted file system. I just need a script to navigate to the where the file is stored, make a backup, chmod, copy, chmod, and verify.