Re: SSL connection and client verification

Поиск
Список
Период
Сортировка
От Vic Simkus
Тема Re: SSL connection and client verification
Дата
Msg-id 48A097C6.8080804@uic.edu
обсуждение исходный текст
Ответ на SSL connection and client verification  (Vic Simkus <vsimkus@uic.edu>)
Список pgsql-jdbc
Vic Simkus wrote:
> Hello
>
> Attached is a file that "implements" client authentication when using
> SSL (i.e. send the client cert to the server).  The difference between
> this and the code from
> http://archives.postgresql.org/pgsql-jdbc/2006-02/msg00166.php is that
> this implementation does not require any changes to existing code.
> Any comments?  Can we get this into the source tree?
Sorry about that - attached the wrong file.

package org.postgresql.ssl;

import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;

import java.security.KeyStore;

import java.util.Arrays;
import java.util.Properties;
import java.security.Security;

import javax.net.ssl.KeyManager;
import javax.net.ssl.KeyManagerFactory;
import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManager;
import javax.net.ssl.TrustManagerFactory;

import org.postgresql.ssl.WrappedFactory;

/**
Provides an implementation of socket factory that supports client authentication (sending client certificate to the
server)
 
for the PGSQL JDBC driver.  Most of this seems to happen automagicaly when a key manager is supplied to the SSLContext
init
 
method 

We try to use the JSSE system properties for configuration.

Properties used:
<ul>
    <li>javax.net.ssl.keyStorePassword - key store password.  If not set defaults to 'changeit' </li>
    <li>javax.net.ssl.keyStoreProvider - key store provider.  Should not need to be explicitly set.</li>
    <li>javax.net.ssl.keyStoreType - type of the key store.  Should not need to be explicitly set.</li>
    <li>javax.net.ssl.keyStore - Location of the key store.  If not set defaults to 'user.home/.keystore'.  If 
        specifyig explicitly  include the <b>complete</b> file system path</li>
    
    <li>javax.net.ssl.trustStore - location of the trust store (if the trust store is different from the key store).  
        If this is not set the keyStore location will be used.  Include the <b>complete</b> file system path</li>
    <li>javax.net.ssl.trustStorePassword - trust store password.  If not set defaults to 'changeit' </li>
    <li>javax.net.ssl.trustStoreProvider - trust store provider.  Should not need to be explicitly set.</li>
    <li>javax.net.ssl.trustStoreType - trust store type.  Should not need to be explicitly set.<li>
    
    <li>ssl.KeyManagerFactory.algorithm - Algoritm for the key manager factory.  Defaults to 'SunX509'</li>
    <li>ssl.TrustManagerFactory.algorithm - Algorithm for the trust manager factory.  Defaults to 'PKIX'</li>
</ul>

An attempt it made to make everything happen with as little configuration as possible.  If a trust store is not
specified
 
the key store is used instead.  If the key store is not specified an attempt is made to use the one created by default
by keytool - {user.home}/.keystore.  If the key store password is not specified 'changeit' is used.  Basically, if a
key
store is maintained using the default setting for keytool everything should work out of the box.

References:

http://java.sun.com/j2se/1.5.0/docs/guide/security/jsse/JSSERefGuide.html
http://archives.postgresql.org/pgsql-jdbc/2006-02/msg00166.php

@author Vic Simkus (vic.simkus@simkus.com)
*/
public class ValidatingFactory  extends WrappedFactory
{
    private String _key_store_password = null;
    private String _key_store_provider = null;
    private String _key_store_type = null;
    private String _key_store_location = null;
    
    private String _trust_store_location = null;
    private String _trust_store_password = null;
    private String _trust_store_provider = null;
    private String _trust_store_type = null;
    
    private String _key_manager_factory_algo = null;
    private String _trust_manager_factory_algo = null;
    
    /**
    XXX Does this need to be customizable?
    Defaults to SSLv3
    */
    private String _ssl_protocol = null;
    
    /**
    XXX Does this need to be customizable?
    Defaults to SunJSSE
    */
    private String _ssl_ctx_provider = null;
    
    private KeyStore _key_store_instance = null;
    private KeyStore _trust_store_instance = null;
    
    private KeyManager [] _key_managers = null;
    private TrustManager [] _trust_managers = null;
    
    private static final String _SYS_PROP_PREFIX = "javax.net.ssl.";
    private static final String _KEYSTORE_FILE_NAME=".keystore";
     
     public ValidatingFactory() throws Exception
    {
        _key_store_password = System.getProperty(_SYS_PROP_PREFIX + "keyStorePassword");
    _key_store_provider = System.getProperty(_SYS_PROP_PREFIX + "keyStoreProvider");
    _key_store_type = System.getProperty(_SYS_PROP_PREFIX + "keyStoreType");
    _key_store_location = System.getProperty(_SYS_PROP_PREFIX + "keyStore");
    
    _trust_store_password = System.getProperty(_SYS_PROP_PREFIX + "trustStorePassword");
    _trust_store_provider = System.getProperty(_SYS_PROP_PREFIX + "trustStoreProvider");
    _trust_store_type = System.getProperty(_SYS_PROP_PREFIX + "trustStoreType");
    _trust_store_location = System.getProperty(_SYS_PROP_PREFIX + "trustStore");
    
    _key_manager_factory_algo = System.getProperty("ssl.KeyManagerFactory.algorithm");
    _trust_manager_factory_algo = System.getProperty("ssl.TrustManagerFactory.algorithm");
        
    if(_key_store_password == null)
    {
        _key_store_password = "changeit";
    }
    
    if(_trust_store_password == null)
    {
        _trust_store_password = "changeit";
    }
    
    if(_ssl_protocol == null) //this will always be null initial since we're not trying to configure it via the sytem
properties
    {
        _ssl_protocol = "SSLv3";
    }        
    
    if(_ssl_ctx_provider == null) //this will always be null initialy.  See above.
    {
        _ssl_ctx_provider = "SunJSSE";
    }
    
    if(_key_manager_factory_algo == null)
    {
        _key_manager_factory_algo = "SunX509";
    }
    
    if(_trust_manager_factory_algo == null)
    {
        _trust_manager_factory_algo = "PKIX";
    }
    
    if(_key_store_type == null)
    {
        _key_store_type = KeyStore.getDefaultType();
    }
    
    if(_trust_store_type == null)
    {
        _trust_store_type = _key_store_type;
    }
    
    if(_key_store_provider == null)
    {
        _key_store_provider = KeyStore.getInstance(_key_store_type).getProvider().getName();
    }
    
    if(_trust_store_provider == null)
    {
        _trust_store_provider = _key_store_provider;
    }
    
    /*
    Go on a hunt for the key store.
    */
    if(_key_store_location == null)
    {
        File keystore_file = new File(System.getProperty("user.home"),_KEYSTORE_FILE_NAME);
        
        if(keystore_file.isFile())
        {
            _key_store_location = keystore_file.getAbsolutePath();
        }
        else
        {
            throw new Error("Failed to find default key store (.keystore in user's home directory)");
        }
    }
    
    if(_trust_store_location == null)
    {
        _trust_store_password = _key_store_password;
        _trust_store_provider = _key_store_provider;
        _trust_store_type = _key_store_type;
        _trust_store_location = _key_store_location;        
    }
    
    _key_store_instance = getKeyStore(_key_store_type,_key_store_provider,new
File(_key_store_location),_key_store_password);   
 
    _trust_store_instance = getKeyStore(_trust_store_type,_trust_store_provider,new
File(_trust_store_location),_trust_store_password);
    
    /*
    Get a factory of a factory of a factory...
    */
    KeyManagerFactory key_manager_factory = KeyManagerFactory.getInstance(_key_manager_factory_algo);
    key_manager_factory.init(_key_store_instance,_key_store_password.toCharArray());    
    _key_managers = key_manager_factory.getKeyManagers();
    
    TrustManagerFactory trust_manager_factory = TrustManagerFactory.getInstance(_trust_manager_factory_algo);
    trust_manager_factory.init(_trust_store_instance);
    _trust_managers = trust_manager_factory.getTrustManagers();
    
        SSLContext sslContext = SSLContext.getInstance(_ssl_protocol,_ssl_ctx_provider);
        sslContext.init(_key_managers,_trust_managers, null);

        _factory = sslContext.getSocketFactory();
    }
    
    private static KeyStore getKeyStore(String type,String provider,File file,String password) throws Exception
    {
        KeyStore key_store = KeyStore.getInstance(type,provider);
        FileInputStream key_store_input = new FileInputStream(file); 
        key_store.load(key_store_input,password.toCharArray());
        key_store_input.close();
        
        return key_store;
    }
}

В списке pgsql-jdbc по дате отправления:

Предыдущее
От: Vic Simkus
Дата:
Сообщение: SSL connection and client verification
Следующее
От: "Paul Tomblin"
Дата:
Сообщение: OT: Question about transactions