-<!-- $PostgreSQL: pgsql/doc/src/sgml/libpq.sgml,v 1.273 2008/12/07 23:46:39 alvherre Exp $ -->
+<!-- $PostgreSQL: pgsql/doc/src/sgml/libpq.sgml,v 1.274 2008/12/15 10:28:21 mha Exp $ -->
<chapter id="libpq">
<title><application>libpq</application> - C Library</title>
</varlistentry>
<varlistentry>
+ <term><literal>sslcert</literal></term>
+ <listitem>
+ <para>
+ This parameter specifies the file name of the client SSL
+ certificate.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><literal>sslkey</literal></term>
+ <listitem>
+ <para>
+ This parameter specifies the location for the secret key
+ used for the client certificate. It can either specify a filename
+ that will be used instead of the default
+ <filename>~/.postgresql/postgresql.key</>, or can specify an external
+ engine (engines are <productname>OpenSSL</> loadable modules). The
+ external engine specification should consist of a colon-separated
+ engine name and an engine-specific key identifier.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><literal>sslrootcert</literal></term>
+ <listitem>
+ <para>
+ This parameter specifies the file name of the root SSL certificate.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><literal>sslcrl</literal></term>
+ <listitem>
+ <para>
+ This parameter specifies the file name of the SSL certificate
+ revocation list (CRL).
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
<term><literal>krbsrvname</literal></term>
<listitem>
<para>
<listitem>
<para>
<indexterm>
+ <primary><envar>PGSSLCERT</envar></primary>
+ </indexterm>
+ <envar>PGSSLCERT</envar> specifies the location for the client
+ certificate to use if the server requests one.
+ </para>
+ </listitem>
+
+ <listitem>
+ <para>
+ <indexterm>
<primary><envar>PGSSLKEY</envar></primary>
</indexterm>
- <envar>PGSSLKEY</envar> specifies the hardware token that stores the
- secret key for the client certificate. The value of this variable
- should consist of a colon-separated engine name (engines are
- <productname>OpenSSL</> loadable modules) and an engine-specific key
- identifier. If this is not set, the secret key must be kept in a
- file.
+ <envar>PGSSLKEY</envar> specifies the location for the secret key
+ used for the client certificate. It can either specify a filename
+ that will be used instead of the default
+ <filename>~/.postgresql/postgresql.key</>, or can specify an external
+ engine (engines are <productname>OpenSSL</> loadable modules). The
+ external engine specification should consist of a colon-separated
+ engine name and an engine-specific key identifier.
+ </para>
+ </listitem>
+
+ <listitem>
+ <para>
+ <indexterm>
+ <primary><envar>PGSSLROOTCERT</envar></primary>
+ </indexterm>
+ <envar>PGSSLROOTCERT</envar> specifies the file name where the SSL
+ root certificate is stored.
+ </para>
+ </listitem>
+
+ <listitem>
+ <para>
+ <indexterm>
+ <primary><envar>PGSSLCRL</envar></primary>
+ </indexterm>
+ <envar>PGSSLCRL</envar> specifies the file name where the SSL certificate
+ revocation list is stored.
</para>
</listitem>
if the file <filename>~/.postgresql/root.crl</filename> exists
(<filename>%APPDATA%\postgresql\root.crl</filename> on Microsoft
Windows).
+ The location of the root certificate store and the CRL can be overridden
+ by the connection parameters <literal>sslrootcert</> and <literal>sslcrl</>
+ or the environment variables <envar>PGSSLROOTCERT</> and <envar>PGSSLCRL</>.
</para>
<para>
directory. The certificate must be signed by one of the certificate
authorities (<acronym>CA</acronym>) trusted by the server. A matching
private key file <filename>~/.postgresql/postgresql.key</> must also
- be present, unless the secret key for the certificate is stored in a
- hardware token, as specified by <envar>PGSSLKEY</envar>. The private
+ be present. The private
key file must not allow any access to world or group; achieve this by the
command <command>chmod 0600 ~/.postgresql/postgresql.key</command>.
On Microsoft Windows these files are named
<filename>%APPDATA%\postgresql\postgresql.crt</filename> and
<filename>%APPDATA%\postgresql\postgresql.key</filename>, and there
is no special permissions check since the directory is presumed secure.
- </para>
-
- <para>
- If the environment variable <envar>PGSSLKEY</envar> is set, its value
- should consist of a colon-separated engine name and key identifier. In
- this case, <application>libpq</application> will load the specified
- engine, i.e. the <productname>OpenSSL</> module which supports special
- hardware, and reference the key with the specified identifier.
- Identifiers are engine-specific. Typically, cryptography hardware tokens
- do not reveal secret keys to the application. Instead, applications
- delegate all cryptography operations which require the secret key to
- the hardware token.
+ The location of the certificate and key files can be overridden by the
+ connection parameters <literal>sslcert</> and <literal>sslkey</> or the
+ environment variables <envar>PGSSLCERT</> and <envar>PGSSLKEY</>.
</para>
<para>
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/interfaces/libpq/fe-connect.c,v 1.370 2008/11/26 00:26:23 tgl Exp $
+ * $PostgreSQL: pgsql/src/interfaces/libpq/fe-connect.c,v 1.371 2008/12/15 10:28:21 mha Exp $
*
*-------------------------------------------------------------------------
*/
#endif
/*
- * "sslmode" option is allowed even without client SSL support because the
- * client can still handle SSL modes "disable" and "allow".
+ * ssl options are allowed even without client SSL support because the
+ * client can still handle SSL modes "disable" and "allow". Other parameters
+ * have no effect on non-SSL connections, so there is no reason to exclude them
+ * since none of them are mandatory.
*/
{"sslmode", "PGSSLMODE", DefaultSSLMode, NULL,
"SSL-Mode", "", 8}, /* sizeof("disable") == 8 */
{"sslverify", "PGSSLVERIFY", DefaultSSLVerify, NULL,
"SSL-Verify", "", 5}, /* sizeof("chain") == 5 */
+ {"sslcert", "PGSSLCERT", NULL, NULL,
+ "SSL-Client-Cert", "", 64},
+
+ {"sslkey", "PGSSLKEY", NULL, NULL,
+ "SSL-Client-Key", "", 64},
+
+ {"sslrootcert", "PGSSLROOTCERT", NULL, NULL,
+ "SSL-Root-Certificate", "", 64},
+
+ {"sslcrl", "PGSSLCRL", NULL, NULL,
+ "SSL-Revocation-List", "", 64},
+
#if defined(KRB5) || defined(ENABLE_GSS) || defined(ENABLE_SSPI)
/* Kerberos and GSSAPI authentication support specifying the service name */
{"krbsrvname", "PGKRBSRVNAME", PG_KRB_SRVNAM, NULL,
conn->sslmode = tmp ? strdup(tmp) : NULL;
tmp = conninfo_getval(connOptions, "sslverify");
conn->sslverify = tmp ? strdup(tmp) : NULL;
+ tmp = conninfo_getval(connOptions, "sslkey");
+ conn->sslkey = tmp ? strdup(tmp) : NULL;
+ tmp = conninfo_getval(connOptions, "sslcert");
+ conn->sslcert = tmp ? strdup(tmp) : NULL;
+ tmp = conninfo_getval(connOptions, "sslrootcert");
+ conn->sslrootcert = tmp ? strdup(tmp) : NULL;
+ tmp = conninfo_getval(connOptions, "sslcrl");
+ conn->sslcrl = tmp ? strdup(tmp) : NULL;
#ifdef USE_SSL
tmp = conninfo_getval(connOptions, "requiressl");
if (tmp && tmp[0] == '1')
free(conn->sslmode);
if (conn->sslverify)
free(conn->sslverify);
+ if (conn->sslcert)
+ free(conn->sslcert);
+ if (conn->sslkey)
+ free(conn->sslkey);
+ if (conn->sslrootcert)
+ free(conn->sslrootcert);
+ if (conn->sslcrl)
+ free(conn->sslcrl);
#if defined(KRB5) || defined(ENABLE_GSS) || defined(ENABLE_SSPI)
if (conn->krbsrvname)
free(conn->krbsrvname);
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/interfaces/libpq/fe-secure.c,v 1.113 2008/12/04 14:07:42 mha Exp $
+ * $PostgreSQL: pgsql/src/interfaces/libpq/fe-secure.c,v 1.114 2008/12/15 10:28:22 mha Exp $
*
* NOTES
*
}
/* read the user certificate */
- snprintf(fnbuf, sizeof(fnbuf), "%s/%s", homedir, USER_CERT_FILE);
+ if (conn->sslcert)
+ strncpy(fnbuf, conn->sslcert, sizeof(fnbuf));
+ else
+ snprintf(fnbuf, sizeof(fnbuf), "%s/%s", homedir, USER_CERT_FILE);
/*
* OpenSSL <= 0.9.8 lacks error stack handling, which means it's likely to
BIO_free(bio);
-#if (SSLEAY_VERSION_NUMBER >= 0x00907000L) && !defined(OPENSSL_NO_ENGINE)
- if (getenv("PGSSLKEY"))
+ /*
+ * Read the SSL key. If a key is specified, treat it as an engine:key combination
+ * if there is colon present - we don't support files with colon in the name. The
+ * exception is if the second character is a colon, in which case it can be a Windows
+ * filename with drive specification.
+ */
+ if (conn->sslkey && strlen(conn->sslkey) > 0)
{
- /* read the user key from engine */
- char *engine_env = getenv("PGSSLKEY");
- char *engine_colon = strchr(engine_env, ':');
- char *engine_str;
- ENGINE *engine_ptr;
-
- if (!engine_colon)
+#if (SSLEAY_VERSION_NUMBER >= 0x00907000L) && !defined(OPENSSL_NO_ENGINE)
+ if (strchr(conn->sslkey, ':')
+#ifdef WIN32
+ && conn->sslkey[1] != ':'
+#endif
+ )
{
- printfPQExpBuffer(&conn->errorMessage,
- libpq_gettext("invalid value of PGSSLKEY environment variable\n"));
- ERR_pop_to_mark();
- return 0;
- }
+ /* Colon, but not in second character, treat as engine:key */
+ ENGINE *engine_ptr;
+ char *engine_str = strdup(conn->sslkey);
+ char *engine_colon = strchr(engine_str, ':');
- engine_str = malloc(engine_colon - engine_env + 1);
- strlcpy(engine_str, engine_env, engine_colon - engine_env + 1);
- engine_ptr = ENGINE_by_id(engine_str);
- if (engine_ptr == NULL)
- {
- char *err = SSLerrmessage();
+ *engine_colon = '\0'; /* engine_str now has engine name */
+ engine_colon++; /* engine_colon now has key name */
- printfPQExpBuffer(&conn->errorMessage,
- libpq_gettext("could not load SSL engine \"%s\": %s\n"),
- engine_str, err);
- SSLerrfree(err);
- free(engine_str);
- ERR_pop_to_mark();
- return 0;
- }
+ engine_ptr = ENGINE_by_id(engine_str);
+ if (engine_ptr == NULL)
+ {
+ char *err = SSLerrmessage();
- *pkey = ENGINE_load_private_key(engine_ptr, engine_colon + 1,
- NULL, NULL);
- if (*pkey == NULL)
- {
- char *err = SSLerrmessage();
+ printfPQExpBuffer(&conn->errorMessage,
+ libpq_gettext("could not load SSL engine \"%s\": %s\n"),
+ engine_str, err);
+ SSLerrfree(err);
+ free(engine_str);
+ ERR_pop_to_mark();
+ return 0;
+ }
- printfPQExpBuffer(&conn->errorMessage,
- libpq_gettext("could not read private SSL key \"%s\" from engine \"%s\": %s\n"),
- engine_colon + 1, engine_str, err);
- SSLerrfree(err);
+ *pkey = ENGINE_load_private_key(engine_ptr, engine_colon,
+ NULL, NULL);
+ if (*pkey == NULL)
+ {
+ char *err = SSLerrmessage();
+
+ printfPQExpBuffer(&conn->errorMessage,
+ libpq_gettext("could not read private SSL key \"%s\" from engine \"%s\": %s\n"),
+ engine_colon, engine_str, err);
+ SSLerrfree(err);
+ free(engine_str);
+ ERR_pop_to_mark();
+ return 0;
+ }
free(engine_str);
- ERR_pop_to_mark();
- return 0;
+
+ fnbuf[0] = '\0'; /* indicate we're not going to load from a file */
+ }
+ else
+#endif /* support for SSL engines */
+ {
+ /* PGSSLKEY is not an engine, treat it as a filename */
+ strncpy(fnbuf, conn->sslkey, sizeof(fnbuf));
}
- free(engine_str);
}
else
-#endif /* use PGSSLKEY */
{
- /* read the user key from file */
+ /* No PGSSLKEY specified, load default file */
snprintf(fnbuf, sizeof(fnbuf), "%s/%s", homedir, USER_KEY_FILE);
+ }
+
+ if (fnbuf[0] != '\0')
+ {
+ /* read the user key from file */
+
if (stat(fnbuf, &buf) != 0)
{
printfPQExpBuffer(&conn->errorMessage,
/* Set up to verify server cert, if root.crt is present */
if (pqGetHomeDirectory(homedir, sizeof(homedir)))
{
- snprintf(fnbuf, sizeof(fnbuf), "%s/%s", homedir, ROOT_CERT_FILE);
+ if (conn->sslrootcert)
+ strncpy(fnbuf, conn->sslrootcert, sizeof(fnbuf));
+ else
+ snprintf(fnbuf, sizeof(fnbuf), "%s/%s", homedir, ROOT_CERT_FILE);
+
if (stat(fnbuf, &buf) == 0)
{
X509_STORE *cvstore;
if ((cvstore = SSL_CTX_get_cert_store(SSL_context)) != NULL)
{
+ if (conn->sslcrl)
+ strncpy(fnbuf, conn->sslcrl, sizeof(fnbuf));
+ else
+ snprintf(fnbuf, sizeof(fnbuf), "%s/%s", homedir, ROOT_CRL_FILE);
+
/* setting the flags to check against the complete CRL chain */
- if (X509_STORE_load_locations(cvstore, ROOT_CRL_FILE, NULL) != 0)
+ if (X509_STORE_load_locations(cvstore, fnbuf, NULL) != 0)
/* OpenSSL 0.96 does not support X509_V_FLAG_CRL_CHECK */
#ifdef X509_V_FLAG_CRL_CHECK
X509_STORE_set_flags(cvstore,
* Portions Copyright (c) 1996-2008, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
- * $PostgreSQL: pgsql/src/interfaces/libpq/libpq-int.h,v 1.137 2008/11/13 09:45:25 mha Exp $
+ * $PostgreSQL: pgsql/src/interfaces/libpq/libpq-int.h,v 1.138 2008/12/15 10:28:22 mha Exp $
*
*-------------------------------------------------------------------------
*/
char *pgpass;
char *sslmode; /* SSL mode (require,prefer,allow,disable) */
char *sslverify; /* Verify server SSL certificate (none,chain,cn) */
+ char *sslkey; /* client key filename */
+ char *sslcert; /* client certificate filename */
+ char *sslrootcert; /* root certificate filename */
+ char *sslcrl; /* certificate revocation list filename */
+
#if defined(KRB5) || defined(ENABLE_GSS) || defined(ENABLE_SSPI)
char *krbsrvname; /* Kerberos service name */
#endif