All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.postgresql.ssl.SingleCertValidatingFactory Maven / Gradle / Ivy

There is a newer version: 42.7.3
Show newest version
/*-------------------------------------------------------------------------
*
* Copyright (c) 2004-2014, PostgreSQL Global Development Group
*
*
*-------------------------------------------------------------------------
*/
package org.postgresql.ssl;

import java.io.ByteArrayInputStream;
import java.io.BufferedInputStream;
import java.io.FileInputStream;
import java.io.InputStream;
import java.io.IOException;
import java.util.UUID;

import java.security.KeyStore;
import java.security.cert.CertificateException;
import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;
import java.security.GeneralSecurityException;

import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManager;
import javax.net.ssl.TrustManagerFactory;
import javax.net.ssl.X509TrustManager;

import org.postgresql.util.GT;
import org.postgresql.ssl.WrappedFactory;

/**
 * Provides a SSLSocketFactory that authenticates the remote server against
 * an explicit pre-shared SSL certificate. This is more secure than using the 
 * NonValidatingFactory as it prevents "man in the middle" attacks. It is also
 * more secure than relying on a central CA signing your server's certificate
 * as it pins the server's certificate.
 * 
 * 

* This class requires a single String parameter specified by setting * the connection property sslfactoryarg. The value of this property * is the PEM-encoded remote server's SSL certificate. *

*

* Where the certificate is loaded from is based upon the prefix of the *

sslfactoryarg
property. The following table lists the valid * set of prefixes. * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
PrefixExampleExplanation
classpath:
classpath:ssl/server.crt
Loaded from the classpath.
file:
file:/foo/bar/server.crt
Loaded from the filesystem.
env:
env:mydb_cert
Loaded from string value of the
mydb_cert
* environment variable.
sys:
sys:mydb_cert
Loaded from string value of the
mydb_cert
* system property.
-----BEGIN CERTIFICATE------
-----BEGIN CERTIFICATE-----
MIIDQzCCAqygAwIBAgIJAOd1tlfiGoEoMA0GCSqGSIb3DQEBBQUAMHUxCzAJBgNV
[... truncated ...]
UCmmYqgiVkAGWRETVo+byOSDZ4swb10=
-----END CERTIFICATE-----
 
Loaded from string value of the argument.
*/ public class SingleCertValidatingFactory extends WrappedFactory { private static final String FILE_PREFIX = "file:"; private static final String CLASSPATH_PREFIX = "classpath:"; private static final String ENV_PREFIX = "env:"; private static final String SYS_PROP_PREFIX = "sys:"; public SingleCertValidatingFactory(String sslFactoryArg) throws GeneralSecurityException { if( sslFactoryArg == null || sslFactoryArg.equals("")) { throw new GeneralSecurityException(GT.tr("The sslfactoryarg property may not be empty.")); } InputStream in = null; try { if( sslFactoryArg.startsWith(FILE_PREFIX) ) { String path = sslFactoryArg.substring(FILE_PREFIX.length()); in = new BufferedInputStream(new FileInputStream(path)); } else if( sslFactoryArg.startsWith(CLASSPATH_PREFIX) ) { String path = sslFactoryArg.substring(CLASSPATH_PREFIX.length()); in = new BufferedInputStream(Thread.currentThread().getContextClassLoader().getResourceAsStream(path)); } else if( sslFactoryArg.startsWith(ENV_PREFIX) ) { String name = sslFactoryArg.substring(ENV_PREFIX.length()); String cert = System.getenv(name); if( cert == null || "".equals(cert) ) { throw new GeneralSecurityException( GT.tr("The environment variable containing the server's SSL certificate must not be empty.")); } in = new ByteArrayInputStream(cert.getBytes("UTF-8")); } else if( sslFactoryArg.startsWith(SYS_PROP_PREFIX) ) { String name = sslFactoryArg.substring(SYS_PROP_PREFIX.length()); String cert = System.getProperty(name); if( cert == null || "".equals(cert) ) { throw new GeneralSecurityException( GT.tr("The system property containing the server's SSL certificate must not be empty.")); } in = new ByteArrayInputStream(cert.getBytes("UTF-8")); } else if( sslFactoryArg.startsWith("-----BEGIN CERTIFICATE-----") ) { in = new ByteArrayInputStream(sslFactoryArg.getBytes("UTF-8")); } else { throw new GeneralSecurityException( GT.tr("The sslfactoryarg property must start with the prefix file:, classpath:, env:, sys:, or -----BEGIN CERTIFICATE-----.")); } SSLContext ctx = SSLContext.getInstance("TLS"); ctx.init(null, new TrustManager[] { new SingleCertTrustManager(in) }, null); _factory = ctx.getSocketFactory(); } catch( RuntimeException e ) { throw (RuntimeException)e; } catch( Exception e ) { if( e instanceof GeneralSecurityException ) { throw (GeneralSecurityException) e; } throw new GeneralSecurityException(GT.tr("An error occurred reading the certificate"), e); } finally { if( in != null ) { try { in.close(); } catch( Exception e2) { // ignore } } } } public class SingleCertTrustManager implements X509TrustManager { X509Certificate cert; X509TrustManager trustManager; public SingleCertTrustManager(InputStream in) throws IOException, GeneralSecurityException { KeyStore ks = KeyStore.getInstance(KeyStore.getDefaultType()); try { // Note: KeyStore requires it be loaded even if you don't load anything into it: ks.load(null); } catch (Exception e) { } CertificateFactory cf = CertificateFactory.getInstance("X509"); cert = (X509Certificate) cf.generateCertificate(in); ks.setCertificateEntry(UUID.randomUUID().toString(), cert); TrustManagerFactory tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm()); tmf.init(ks); for (TrustManager tm : tmf.getTrustManagers()) { if (tm instanceof X509TrustManager) { trustManager = (X509TrustManager) tm; break; } } if (trustManager == null) { throw new GeneralSecurityException(GT.tr("No X509TrustManager found")); } } public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException { } public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException { trustManager.checkServerTrusted(chain, authType); } public X509Certificate[] getAcceptedIssuers() { return new X509Certificate[] { cert }; } } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy