Skip to content

Commit

Permalink
docs: improve documentation on SSL
Browse files Browse the repository at this point in the history
  • Loading branch information
davecramer authored and vlsi committed Aug 27, 2018
1 parent cdeeaca commit fa03273
Show file tree
Hide file tree
Showing 4 changed files with 99 additions and 41 deletions.
15 changes: 9 additions & 6 deletions docs/documentation/head/connect.md
Original file line number Diff line number Diff line change
Expand Up @@ -95,11 +95,14 @@ Connection conn = DriverManager.getConnection(url);

* **sslmode** = String

possible values include "disable", "require", "verify-ca" and "verify-full", "allow" and "prefer"
will throw an exception. "require" will default to a non validating SSL factory and not check the
validity of the certificates. "verify-ca" and "verify-full" use a validating SSL factory and will
check that the ca is correct and the host is correct. Setting these will necessitate storing the
server certificate on the client machine ["Configuring the client"](ssl-client.html).
possible values include `disable`, `allow`, `prefer`, `require`, `verify-ca` and `verify-full`
. `require`, `allow` and `prefer` all default to a non validating SSL factory and do not check the
validity of the certificate or the host name. `verify-ca` validates the certificate, but does not
verify the hostname. `verify-full` will validate that the certificate is correct and verify the
host connected to has the same hostname as the certificate.

Setting these will necessitate storing the server certificate on the client machine see
["Configuring the client"](ssl-client.html) for details.

* **sslcert** = String

Expand All @@ -117,7 +120,7 @@ Connection conn = DriverManager.getConnection(url);

* **sslhostnameverifier** = String

Class name of hostname verifier. Defaults to using `org.postgresql.ssl.jdbc4.LibPQFactory.verify()`
Class name of hostname verifier. Defaults to using `org.postgresql.ssl.PGjdbcHostnameVerifier`

* **sslpasswordcallback** = String

Expand Down
8 changes: 7 additions & 1 deletion docs/documentation/head/media/css/table.css
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ div.tblBasic table {

div.tblBasic table th {
padding-top: 20px;
border-bottom: 1px solid #EFEFEF;
border-bottom: 1px solid #F0F8FF;
vertical-align: bottom;
}

Expand Down Expand Up @@ -99,3 +99,9 @@ div.tblBasic table td.colLastRT {
text-align: right;
vertical-align: top;
}
div.tblBasic table.tblBasicWhite th {
background-color: aliceblue;
}
div.tblBasic table.tblBasicWhite td {
background-color: white;
}
100 changes: 76 additions & 24 deletions docs/documentation/head/ssl-client.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,24 +9,79 @@ nexttitle: Custom SSLSocketFactory
next: ssl-factory.html
---

Unlike psql and other libpq based programs the JDBC driver does server certificate
validation by default. This means that when establishing a SSL connection the
JDBC driver will validate the server's identity preventing "man in the middle"
attacks. It does this by checking that the server certificate is signed by a
trusted authority. If you have a certificate signed by a global certificate
authority (CA), there is nothing further to do because Java comes with copies of
the most common CA's certificates. If you are dealing with a self-signed certificate
though, you need to make this available to the Java client to enable it to validate
the server's certificate.

> ### Note
> Only the JDBC driver version 3 and greater supports SSL. The 1.4 JDK was the
first version to come bundled with SSL support. Previous JDK versions that wanted
to use SSL could make use of the additional JSSE library, but it does not support
the full range of features utilized by the PostgreSQL™ JDBC driver.

To make the server certificate available to Java, the first step is to convert
There are a number of connection parameters for configuring the client for SSL. See [SSL Connection parameters](connect.html#ssl)

The simplest being `ssl=true`, passing this into the driver will cause the driver to validate both
the SSL certificate and verify the hostname (same as `verify-full`). **Note** this is different than
libpq which defaults to a non-validating SSL connection.

In this mode, when establishing a SSL connection the JDBC driver will validate the server's
identity preventing "man in the middle" attacks. It does this by checking that the server
certificate is signed by a trusted authority, and that the host you are connecting to is the
same as the hostname in the certificate.

If you **require** encryption and want the connection to fail if it can't be encrypted then set
`sslmode=require` this ensures that the server is configured to accept SSL connections for this
Host/IP address and that the server recognizes the client certificate. In other words if the server
does not accept SSL connections or the client certificate is not recognized the connection will fail.
**Note** in this mode we will accept all server certificates.

If `sslmode=verify-ca`, the server is verified by checking the certificate chain up to the root
certificate stored on the client.

If `sslmode=verify-full`, the server host name will be verified to make sure it matches the name
stored in the server certificate.

The SSL connection will fail if the server certificate cannot be verified. `verify-full` is recommended
in most security-sensitive environments.


In the case where the certificate validation is failing you can try `sslcert=` and LibPQFactory will
not send the client certificate. If the server is not configured to authenticate using the certificate
it should connect.

The location of the client certificate, client key and root certificate can be overridden with the
`sslcert`, `sslkey`, and `sslrootcert` settings respectively. These default to /defaultdir/postgresql.crt,
/defaultdir/postgresql.pk8, and /defaultdir/root.crt respectively where defaultdir is
${user.home}/.postgresql/ in *nix systems and %appdata%/postgresql/ on windows

Finer control of the SSL connection can be achieved using the `sslmode` connection parameter.
This parameter is the same as the libpq `sslmode` parameter and the currently SSL implements the
following

<div class="tblBasic">
<table class="tblBasicWhite" border="1" summary="SSL Mode Descriptions" cellspacing="0" cellpadding="0">
<thead>
<tr>
<th>sslmode</th><th>Eavesdropping Protection</th><th> MITM Protection</th><th/>
</tr>
</thead>
<tr>
<td>disable</td><td>No</td><td>No</td><td>I don't care about security and don't want to pay the overhead for encryption</td>
</tr>
<tr>
<td>allow</td><td>Maybe</td><td>No</td><td>I don't care about security but will pay the overhead for encryption if the server insists on it</td>
</tr>
<tr>
<td>prefer</td><td>Maybe</td><td>No</td><td>I don't care about encryption but will pay the overhead of encryption if the server supports it</td>
</tr>
<tr>
<td>require</td><td>Yes</td><td>No</td><td>I want my data to be encrypted, and I accept the overhead. I trust that the network will make sure I always connect to the server I want.</td>
</tr>
<tr>
<td>verify-ca</td><td>Yes</td><td>Depends on CA policy</td><td>I want my data encrypted, and I accept the overhead. I want to be sure that I connect to a server that I trust.</td>
</tr>
<tr>
<td>verify-full</td><td>Yes</td><td>Yes</td><td>I want my data encrypted, and I accept the overhead. I want to be sure that I connect to a server I trust, and that it's the one I specify.</td>
</tr>
</table>
</div>


### Note

If you are using Java's default mechanism (not LibPQFactory) to create the SSL connection you will
need to make the server certificate available to Java, the first step is to convert
it to a form Java understands.

`openssl x509 -in server.crt -out server.crt.der -outform der`
Expand All @@ -52,9 +107,6 @@ to use.
In the event of problems extra debugging information is available by adding
`-Djavax.net.debug=ssl` to your command line.

To instruct the JDBC driver to try and establish a SSL connection you must add
the connection URL parameter `ssl=true`. See [SSL Connection parameters](connect.html#ssl)

<a name="nonvalidating"></a>
## Using SSL without Certificate Validation

Expand All @@ -65,6 +117,6 @@ certificate authority, but that is not always an option. The JDBC driver provid
an option to establish a SSL connection without doing any validation, but please
understand the risk involved before enabling this option.

A non-validating connection is established via a custom `SSLSocketFactory` class
that is provided with the driver. Setting the connection URL parameter `sslfactory=org.postgresql.ssl.NonValidatingFactory`
will turn off all SSL validation.
A non-validating connection is established via a custom `SSLSocketFactory` class that is provided
with the driver. Setting the connection URL parameter `sslfactory=org.postgresql.ssl.NonValidatingFactory`
will turn off all SSL validation.
17 changes: 7 additions & 10 deletions docs/documentation/head/ssl-factory.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,18 +12,15 @@ next: query.html
PostgreSQL™ provides a way for developers to customize how a SSL connection is
established. This may be used to provide a custom certificate source or other
extensions by allowing the developer to create their own `SSLContext` instance.
The connection URL parameters `sslfactory` and `sslfactoryarg` allow the user
to specify which custom class to use for creating the `SSLSocketFactory`. The
class name specified by `sslfactory` must extend `javax.net.ssl.SSLSocketFactory`
and be available to the driver's classloader. This class must have a zero argument
constructor or a single argument constructor taking a String argument. This
argument may optionally be supplied by `sslfactoryarg`.
The connection URL parameters `sslfactory` allow the user to specify which custom
class to use for creating the `SSLSocketFactory`. The class name specified by `sslfactory`
must extend ` javax.net.ssl.SSLSocketFactory` and be available to the driver's classloader.

This class must have a zero argument constructor or a single argument constructor preferentially taking
a `Properties` argument. There is a simple `org.postgresql.ssl.DefaultJavaSSLFactory` provided which uses the
default java SSLFactory.

Information on how to actually implement such a class is beyond the scope of this
documentation. Places to look for help are the [JSSE Reference Guide](https://docs.oracle.com/javase/8/docs/technotes/guides/security/jsse/JSSERefGuide.html)
and the source to the `NonValidatingFactory` provided by the JDBC driver.

The Java SSL API is not very well known to the JDBC driver developers and we
would be interested in any interesting and generally useful extensions that you
have implemented using this mechanism. Specifically it would be nice to be able
to provide client certificates to be validated by the server.

0 comments on commit fa03273

Please sign in to comment.