-
+
+
+
+PGSSLKEY
+specifies the hardware token which stores the secret key for the client
+certificate, instead of a file. The value of this variable should consist
+of a colon-separated engine name (engines are
OpenSSL>
+loadable modules) and an engine-specific key identifier.
+
+
+
for increased security. See for details
about the server-side
SSL> functionality.
-
+
libpq reads the system-wide
+
OpenSSL configuration file. By default, this
+ file is named openssl.cnf and is located in the
+ directory reported by
openssl>:
+ openssl version -d
+
+ The default can be overriden by setting environment variable
+ OPENSSL_CONF to the name of the desired configuration
+ file.
+
If the server demands a client certificate,
will send the certificate stored in file
~/.postgresql/postgresql.crt> within the user's home directory.
A matching private key file ~/.postgresql/postgresql.key>
- must also be present, and must not be world-readable.
+ must also be present, and must not be world-readable, unless the secret
+ key is stored in a hardware token, as specified by
+ PGSSLKEY.
(On Microsoft Windows these files are named
%APPDATA%\postgresql\postgresql.crt and
%APPDATA%\postgresql\postgresql.key.)
+ If the environment variable PGSSLKEY is set, its value
+ should consist of a colon-separated engine name and key identifier. In
+ this case,
libpq will load the specified
+ engine, i.e. the
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.
+
+
If the file ~/.postgresql/root.crt> is present in the user's
home directory,
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/libpq/be-secure.c,v 1.77 2007/02/07 00:52:35 petere Exp $
+ * $PostgreSQL: pgsql/src/backend/libpq/be-secure.c,v 1.78 2007/02/16 02:59:40 momjian Exp $
*
* Since the server static private key ($DataDir/server.key)
* will normally be stored unencrypted so that the database
#ifdef USE_SSL
#include
#include
+#if SSLEAY_VERSION_NUMBER >= 0x0907000L
+#include
+#endif
+
#endif
#include "libpq/libpq.h"
#define RENEGOTIATION_LIMIT (512 * 1024 * 1024)
static SSL_CTX *SSL_context = NULL;
+
+/* GUC variable controlling SSL cipher list*/
+extern char *SSLCipherSuites;
+
#endif
/* ------------------------------------------------------------ */
if (!SSL_context)
{
+#if SSLEAY_VERSION_NUMBER >= 0x0907000L
+ OPENSSL_config(NULL);
+#endif
SSL_library_init();
SSL_load_error_strings();
SSL_context = SSL_CTX_new(SSLv23_method());
SSL_CTX_set_options(SSL_context, SSL_OP_SINGLE_DH_USE | SSL_OP_NO_SSLv2);
/* setup the allowed cipher list */
- if (SSL_CTX_set_cipher_list(SSL_context, "ALL:!ADH:!LOW:!EXP:!MD5:@STRENGTH") != 1)
+ if (SSL_CTX_set_cipher_list(SSL_context, SSLCipherSuites) != 1)
elog(FATAL, "could not set the cipher list (no valid ciphers available)");
/*
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/interfaces/libpq/fe-secure.c,v 1.92 2007/02/08 11:10:27 petere Exp $
+ * $PostgreSQL: pgsql/src/interfaces/libpq/fe-secure.c,v 1.93 2007/02/16 02:59:41 momjian Exp $
*
* NOTES
* [ Most of these notes are wrong/obsolete, but perhaps not all ]
#ifdef USE_SSL
#include
+#if (SSLEAY_VERSION_NUMBER >= 0x00907000L)
+#include
+#endif
+#if (SSLEAY_VERSION_NUMBER >= 0x00907000L) && !defined(OPENSSL_NO_ENGINE)
+#include
+#endif
#endif /* USE_SSL */
}
fclose(fp);
- /* read the user key */
- snprintf(fnbuf, sizeof(fnbuf), "%s/%s", homedir, USER_KEY_FILE);
- if (stat(fnbuf, &buf) == -1)
- {
- printfPQExpBuffer(&conn->errorMessage,
- libpq_gettext("certificate present, but not private key file \"%s\"\n"),
- fnbuf);
- return 0;
- }
-#ifndef WIN32
- if (!S_ISREG(buf.st_mode) || (buf.st_mode & 0077) ||
- buf.st_uid != geteuid())
- {
- printfPQExpBuffer(&conn->errorMessage,
- libpq_gettext("private key file \"%s\" has wrong permissions\n"),
- fnbuf);
- return 0;
- }
-#endif
- if ((fp = fopen(fnbuf, "r")) == NULL)
- {
- printfPQExpBuffer(&conn->errorMessage,
- libpq_gettext("could not open private key file \"%s\": %s\n"),
- fnbuf, pqStrerror(errno, sebuf, sizeof(sebuf)));
- return 0;
- }
-#ifndef WIN32
- if (fstat(fileno(fp), &buf2) == -1 ||
- buf.st_dev != buf2.st_dev || buf.st_ino != buf2.st_ino)
+#if (SSLEAY_VERSION_NUMBER >= 0x00907000L) && !defined(OPENSSL_NO_ENGINE)
+ if (getenv("PGSSLKEY"))
{
- printfPQExpBuffer(&conn->errorMessage,
- libpq_gettext("private key file \"%s\" changed during execution\n"), fnbuf);
- return 0;
+ /* read the user key from engine */
+ char *engine_env = getenv("PGSSLKEY");
+ char *engine_colon = strchr(engine_env, ':');
+ char *engine_str;
+ ENGINE *engine_ptr = NULL;
+
+ if (!engine_colon)
+ {
+ printfPQExpBuffer(&conn->errorMessage,
+ libpq_gettext("invalid value of PGSSLKEY environment variable\n"));
+ return 0;
+ }
+
+ engine_str = malloc(engine_colon - engine_env + 1);
+ strlcpy(engine_str, engine_env, engine_colon - engine_env + 1);
+ if ((engine_ptr = ENGINE_by_id(engine_str)) == NULL)
+ {
+ char *err = SSLerrmessage();
+
+ printfPQExpBuffer(&conn->errorMessage,
+ libpq_gettext("could not load SSL engine \"%s\":%s\n"), engine_str, err);
+ free(engine_str);
+ SSLerrfree(err);
+ return 0;
+ }
+ if ((*pkey = ENGINE_load_private_key(engine_ptr,
+ engine_colon + 1, NULL, NULL)) == NULL)
+ {
+ char *err = SSLerrmessage();
+
+ 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);
+ free(engine_str);
+ return 0;
+ }
+ free(engine_str);
}
+ else
#endif
- if (PEM_read_PrivateKey(fp, pkey, NULL, NULL) == NULL)
{
- char *err = SSLerrmessage();
+ /* read the user key from file*/
+ snprintf(fnbuf, sizeof(fnbuf), "%s/%s", homedir, USER_KEY_FILE);
+ if (stat(fnbuf, &buf) == -1)
+ {
+ printfPQExpBuffer(&conn->errorMessage,
+ libpq_gettext("certificate present, but not private key file \"%s\"\n"),
+ fnbuf);
+ return 0;
+ }
+ #ifndef WIN32
+ if (!S_ISREG(buf.st_mode) || (buf.st_mode & 0077) ||
+ buf.st_uid != geteuid())
+ {
+ printfPQExpBuffer(&conn->errorMessage,
+ libpq_gettext("private key file \"%s\" has wrong permissions\n"),
+ fnbuf);
+ return 0;
+ }
+ #endif
+ if ((fp = fopen(fnbuf, "r")) == NULL)
+ {
+ printfPQExpBuffer(&conn->errorMessage,
+ libpq_gettext("could not open private key file \"%s\": %s\n"),
+ fnbuf, pqStrerror(errno, sebuf, sizeof(sebuf)));
+ return 0;
+ }
+ #ifndef WIN32
+ if (fstat(fileno(fp), &buf2) == -1 ||
+ buf.st_dev != buf2.st_dev || buf.st_ino != buf2.st_ino)
+ {
+ printfPQExpBuffer(&conn->errorMessage,
+ libpq_gettext("private key file \"%s\" changed during execution\n"), fnbuf);
+ return 0;
+ }
+ #endif
+ if (PEM_read_PrivateKey(fp, pkey, NULL, NULL) == NULL)
+ {
+ char *err = SSLerrmessage();
- printfPQExpBuffer(&conn->errorMessage,
- libpq_gettext("could not read private key file \"%s\": %s\n"),
- fnbuf, err);
- SSLerrfree(err);
+ printfPQExpBuffer(&conn->errorMessage,
+ libpq_gettext("could not read private key file \"%s\": %s\n"),
+ fnbuf, err);
+ SSLerrfree(err);
+ fclose(fp);
+ return 0;
+ }
fclose(fp);
- return 0;
}
- fclose(fp);
-
/* verify that the cert and key go together */
if (!X509_check_private_key(*x509, *pkey))
{
{
if (pq_initssllib)
{
+#if (SSLEAY_VERSION_NUMBER >= 0x00907000L)
+ OPENSSL_config(NULL);
+#endif
SSL_library_init();
SSL_load_error_strings();
}