1
0
mirror of https://github.com/postgres/postgres.git synced 2025-07-27 12:41:57 +03:00

SSL improvements:

o read global SSL configuration file
	o add GUC "ssl_ciphers" to control allowed ciphers
	o add libpq environment variable PGSSLKEY to control SSL hardware keys

Victor B. Wagner
This commit is contained in:
Bruce Momjian
2007-02-16 02:59:41 +00:00
parent 68046a20c7
commit c7b08050d9
9 changed files with 205 additions and 57 deletions

View File

@ -11,7 +11,7 @@
*
*
* 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
@ -92,6 +92,10 @@
#ifdef USE_SSL
#include <openssl/ssl.h>
#include <openssl/dh.h>
#if SSLEAY_VERSION_NUMBER >= 0x0907000L
#include <openssl/conf.h>
#endif
#endif
#include "libpq/libpq.h"
@ -125,6 +129,10 @@ static const char *SSLerrmessage(void);
#define RENEGOTIATION_LIMIT (512 * 1024 * 1024)
static SSL_CTX *SSL_context = NULL;
/* GUC variable controlling SSL cipher list*/
extern char *SSLCipherSuites;
#endif
/* ------------------------------------------------------------ */
@ -719,6 +727,9 @@ initialize_SSL(void)
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());
@ -780,7 +791,7 @@ initialize_SSL(void)
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)");
/*

View File

@ -37,7 +37,7 @@
*
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/postmaster/postmaster.c,v 1.523 2007/02/16 02:10:07 alvherre Exp $
* $PostgreSQL: pgsql/src/backend/postmaster/postmaster.c,v 1.524 2007/02/16 02:59:41 momjian Exp $
*
* NOTES
*
@ -187,6 +187,7 @@ static int SendStop = false;
/* still more option variables */
bool EnableSSL = false;
char *SSLCipherSuites;
bool SilentMode = false; /* silent mode (-S) */
int PreAuthDelay = 0;

View File

@ -10,7 +10,7 @@
* Written by Peter Eisentraut <peter_e@gmx.net>.
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/utils/misc/guc.c,v 1.374 2007/02/14 03:08:44 neilc Exp $
* $PostgreSQL: pgsql/src/backend/utils/misc/guc.c,v 1.375 2007/02/16 02:59:41 momjian Exp $
*
*--------------------------------------------------------------------
*/
@ -2314,6 +2314,16 @@ static struct config_string ConfigureNamesString[] =
NULL, assign_temp_tablespaces, NULL
},
{
{"ssl_ciphers", PGC_POSTMASTER, CONN_AUTH_SECURITY,
gettext_noop("Sets the list of allowed SSL ciphers."),
NULL,
GUC_SUPERUSER_ONLY
},
&SSLCipherSuites,
"ALL:!ADH:!LOW:!EXP:!MD5:@STRENGTH", NULL, NULL
},
/* End-of-list marker */
{
{NULL, 0, 0, NULL, NULL}, NULL, NULL, NULL, NULL

View File

@ -74,6 +74,7 @@
#authentication_timeout = 1min # 1s-600s
#ssl = off # (change requires restart)
#ssl_ciphers = 'ALL:!ADH:!LOW:!EXP:!MD5:@STRENGTH' # List of ciphers to use
#password_encryption = on
#db_user_namespace = off

View File

@ -6,7 +6,7 @@
* Portions Copyright (c) 1996-2007, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* $PostgreSQL: pgsql/src/include/postmaster/postmaster.h,v 1.15 2007/01/05 22:19:57 momjian Exp $
* $PostgreSQL: pgsql/src/include/postmaster/postmaster.h,v 1.16 2007/02/16 02:59:41 momjian Exp $
*
*-------------------------------------------------------------------------
*/
@ -15,6 +15,7 @@
/* GUC options */
extern bool EnableSSL;
extern char *SSLCipherSuites;
extern bool SilentMode;
extern int ReservedBackends;
extern int PostPortNumber;

View File

@ -11,7 +11,7 @@
*
*
* 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 ]
@ -111,6 +111,12 @@
#ifdef USE_SSL
#include <openssl/ssl.h>
#if (SSLEAY_VERSION_NUMBER >= 0x00907000L)
#include <openssl/conf.h>
#endif
#if (SSLEAY_VERSION_NUMBER >= 0x00907000L) && !defined(OPENSSL_NO_ENGINE)
#include <openssl/engine.h>
#endif
#endif /* USE_SSL */
@ -606,54 +612,99 @@ client_cert_cb(SSL *ssl, X509 **x509, EVP_PKEY **pkey)
}
fclose(fp);
/* read the user key */
snprintf(fnbuf, sizeof(fnbuf), "%s/%s", homedir, USER_KEY_FILE);
if (stat(fnbuf, &buf) == -1)
#if (SSLEAY_VERSION_NUMBER >= 0x00907000L) && !defined(OPENSSL_NO_ENGINE)
if (getenv("PGSSLKEY"))
{
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();
/* read the user key from engine */
char *engine_env = getenv("PGSSLKEY");
char *engine_colon = strchr(engine_env, ':');
char *engine_str;
ENGINE *engine_ptr = NULL;
printfPQExpBuffer(&conn->errorMessage,
libpq_gettext("could not read private key file \"%s\": %s\n"),
fnbuf, err);
SSLerrfree(err);
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
{
/* 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);
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))
{
@ -737,6 +788,9 @@ init_ssl_system(PGconn *conn)
{
if (pq_initssllib)
{
#if (SSLEAY_VERSION_NUMBER >= 0x00907000L)
OPENSSL_config(NULL);
#endif
SSL_library_init();
SSL_load_error_strings();
}