0

If the Tomcat server (on Linux) is running with client-authentication=on (org.jboss.web.connector.ssl.client-auth=true), then the client (OSX 1.7.3) can download the JNLP (in browser), but the java-webstart can't download anything not even the JNLP again, only showing an empty certificate choosing dialog.

The certificates are self-signed ones. The CA and the Client certificates are imported into the OSX's KeyChain (ca->system, client+key->login)

Debugging the problem it seems so that the Apple's JNLP Java interface trying to reach the OSX's KeyChain keystore in a wrong way, without password (*see example below)

I made a small program based on debugging the running code on JNLP downloading (on OSX).

import java.security.Key;
import java.security.KeyStore;
import java.security.cert.Certificate;
import java.security.cert.X509Certificate;
import java.util.Enumeration;

import javax.net.ssl.KeyManager;
import javax.net.ssl.KeyManagerFactory;
import javax.net.ssl.X509KeyManager;

public class OSXKeyChainTest {

/**
 * Demonstrating issue in OSX-JNLP-Java interface, the keys from the
 * KeyChain are not accessed during JNLP downloading phase. But if it would
 * use any password it would work (see the FIXME line). This small test
 * program is based on the debugging works on OSX 1.7.3.
 */
public static void main(String[] args) throws Exception {

    KeyStore ks = KeyStore.getInstance("KeyChainStore", "Apple");
    ks.load(null, new char[0]);
    KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance("SunX509", "SunJSSE");

    // FIXME !!!! try it with ANY password, and it will work, eg. = new char[] {'x'};
    char[] password = new char[] {};

    // as AppleX509DeployKeyManager.getBrowserKeyManager() does
    keyManagerFactory.init(ks, password);

    X509KeyManager localX509KeyManager = null;
    KeyManager[] arrayOfKeyManager = keyManagerFactory.getKeyManagers();

    int i = 0;
    while (i < arrayOfKeyManager.length) {
        if ((arrayOfKeyManager[i] instanceof X509KeyManager)) {
            localX509KeyManager = (X509KeyManager) arrayOfKeyManager[i];
            break;
        }

        i++;
    }

    for (Enumeration<String> t = ks.aliases(); t.hasMoreElements();) {
        String alias = t.nextElement();
        System.out.println("@Alias: " + alias);
        if (ks.isKeyEntry(alias)) {
            System.out.println("It's a key entry");
            for (Certificate c : ks.getCertificateChain(alias)) {
                X509Certificate x509 = (X509Certificate) c;
                System.out.println(x509.getSubjectDN().toString());
                System.out.println("SN: " + x509.getSerialNumber());
            }

            // as SunX509KeyManagerImpl does
            Key localKey = ks.getKey(alias, password);
            System.out.println("Localkey: " + localKey);
        }
    }

    System.out.println("--------------------------------");
    System.out.println("It should be not null!: " + localX509KeyManager.getPrivateKey("client"));
}

}
Ferte
  • 1

1 Answers1

0

Not sure if this will solve your problem, but here are a few points you should look at:

  • The KeychainStore is designed to work with any password.

    The actual authorisation should be handled by OSX's security daemon. When you're about to use the private key, a pop-up should appear and ask something along the lines of "Do you want to allow this application to sign using this private key?". If you don't get such a prompt, you probably have authorised the application to use the key without prompting, a setting that can be changed in Keychain.app.

    (To a degree, it would be similar to a hardware token with a keypad expecting you to type the PIN code in, without any interaction with Java.)

  • If you have multiple identities (cert + corresponding private key) in your keychain, there was a bug whereby the KeychainStore could only see one anyway. (Last time I checked, this hadn't been fixed.)

  • Safari had a number of issues regarding client-certificate selection (choice would not always be offered and you had to to the identity configuration manually beforehand, or it would only be done if the server rejected the connection without a client-certificate: Apache Httpd's SSLVerifyClient optional wouldn't work). I'm not sure if these issues have been fixed.

  • If you're using a self-signed client-certificate, either you should configure Tomcat to advertise it as an accepted issuer, or it should send an empty list. Although the latter is explicitly authorised by TLS 1.1, I'm not sure how OSX would behave on the client side.

Bruno
  • 119,590
  • 31
  • 270
  • 376