Commit 1c218340 authored by Peter Eisentraut's avatar Peter Eisentraut

Extract common bits from OpenSSL implementation

Some things in be-secure-openssl.c and fe-secure-openssl.c were not
actually specific to OpenSSL but could also be used by other
implementations.  In order to avoid copy-and-pasting, move some of that
code to common files.
parent f966101d
...@@ -75,7 +75,6 @@ be_tls_init(bool isServerStart) ...@@ -75,7 +75,6 @@ be_tls_init(bool isServerStart)
{ {
STACK_OF(X509_NAME) *root_cert_list = NULL; STACK_OF(X509_NAME) *root_cert_list = NULL;
SSL_CTX *context; SSL_CTX *context;
struct stat buf;
/* This stuff need be done only once. */ /* This stuff need be done only once. */
if (!SSL_initialized) if (!SSL_initialized)
...@@ -133,63 +132,8 @@ be_tls_init(bool isServerStart) ...@@ -133,63 +132,8 @@ be_tls_init(bool isServerStart)
goto error; goto error;
} }
if (stat(ssl_key_file, &buf) != 0) if (!check_ssl_key_file_permissions(ssl_key_file, isServerStart))
{
ereport(isServerStart ? FATAL : LOG,
(errcode_for_file_access(),
errmsg("could not access private key file \"%s\": %m",
ssl_key_file)));
goto error;
}
if (!S_ISREG(buf.st_mode))
{
ereport(isServerStart ? FATAL : LOG,
(errcode(ERRCODE_CONFIG_FILE_ERROR),
errmsg("private key file \"%s\" is not a regular file",
ssl_key_file)));
goto error; goto error;
}
/*
* Refuse to load key files owned by users other than us or root.
*
* XXX surely we can check this on Windows somehow, too.
*/
#if !defined(WIN32) && !defined(__CYGWIN__)
if (buf.st_uid != geteuid() && buf.st_uid != 0)
{
ereport(isServerStart ? FATAL : LOG,
(errcode(ERRCODE_CONFIG_FILE_ERROR),
errmsg("private key file \"%s\" must be owned by the database user or root",
ssl_key_file)));
goto error;
}
#endif
/*
* Require no public access to key file. If the file is owned by us,
* require mode 0600 or less. If owned by root, require 0640 or less to
* allow read access through our gid, or a supplementary gid that allows
* to read system-wide certificates.
*
* XXX temporarily suppress check when on Windows, because there may not
* be proper support for Unix-y file permissions. Need to think of a
* reasonable check to apply on Windows. (See also the data directory
* permission check in postmaster.c)
*/
#if !defined(WIN32) && !defined(__CYGWIN__)
if ((buf.st_uid == geteuid() && buf.st_mode & (S_IRWXG | S_IRWXO)) ||
(buf.st_uid == 0 && buf.st_mode & (S_IWGRP | S_IXGRP | S_IRWXO)))
{
ereport(isServerStart ? FATAL : LOG,
(errcode(ERRCODE_CONFIG_FILE_ERROR),
errmsg("private key file \"%s\" has group or world access",
ssl_key_file),
errdetail("File must have permissions u=rw (0600) or less if owned by the database user, or permissions u=rw,g=r (0640) or less if owned by root.")));
goto error;
}
#endif
/* /*
* OK, try to load the private key file. * OK, try to load the private key file.
...@@ -516,10 +460,6 @@ aloop: ...@@ -516,10 +460,6 @@ aloop:
port->peer_cert_valid = true; port->peer_cert_valid = true;
} }
ereport(DEBUG2,
(errmsg("SSL connection from \"%s\"",
port->peer_cn ? port->peer_cn : "(anonymous)")));
/* set up debugging/info callback */ /* set up debugging/info callback */
SSL_CTX_set_info_callback(SSL_context, info_cb); SSL_CTX_set_info_callback(SSL_context, info_cb);
......
...@@ -114,6 +114,10 @@ secure_open_server(Port *port) ...@@ -114,6 +114,10 @@ secure_open_server(Port *port)
#ifdef USE_SSL #ifdef USE_SSL
r = be_tls_open_server(port); r = be_tls_open_server(port);
ereport(DEBUG2,
(errmsg("SSL connection from \"%s\"",
port->peer_cn ? port->peer_cn : "(anonymous)")));
#endif #endif
return r; return r;
...@@ -314,3 +318,70 @@ secure_raw_write(Port *port, const void *ptr, size_t len) ...@@ -314,3 +318,70 @@ secure_raw_write(Port *port, const void *ptr, size_t len)
return n; return n;
} }
bool
check_ssl_key_file_permissions(const char *ssl_key_file, bool isServerStart)
{
int loglevel = isServerStart ? FATAL : LOG;
struct stat buf;
if (stat(ssl_key_file, &buf) != 0)
{
ereport(loglevel,
(errcode_for_file_access(),
errmsg("could not access private key file \"%s\": %m",
ssl_key_file)));
return false;
}
if (!S_ISREG(buf.st_mode))
{
ereport(loglevel,
(errcode(ERRCODE_CONFIG_FILE_ERROR),
errmsg("private key file \"%s\" is not a regular file",
ssl_key_file)));
return false;
}
/*
* Refuse to load key files owned by users other than us or root.
*
* XXX surely we can check this on Windows somehow, too.
*/
#if !defined(WIN32) && !defined(__CYGWIN__)
if (buf.st_uid != geteuid() && buf.st_uid != 0)
{
ereport(loglevel,
(errcode(ERRCODE_CONFIG_FILE_ERROR),
errmsg("private key file \"%s\" must be owned by the database user or root",
ssl_key_file)));
return false;
}
#endif
/*
* Require no public access to key file. If the file is owned by us,
* require mode 0600 or less. If owned by root, require 0640 or less to
* allow read access through our gid, or a supplementary gid that allows
* to read system-wide certificates.
*
* XXX temporarily suppress check when on Windows, because there may not
* be proper support for Unix-y file permissions. Need to think of a
* reasonable check to apply on Windows. (See also the data directory
* permission check in postmaster.c)
*/
#if !defined(WIN32) && !defined(__CYGWIN__)
if ((buf.st_uid == geteuid() && buf.st_mode & (S_IRWXG | S_IRWXO)) ||
(buf.st_uid == 0 && buf.st_mode & (S_IWGRP | S_IXGRP | S_IRWXO)))
{
ereport(loglevel,
(errcode(ERRCODE_CONFIG_FILE_ERROR),
errmsg("private key file \"%s\" has group or world access",
ssl_key_file),
errdetail("File must have permissions u=rw (0600) or less if owned by the database user, or permissions u=rw,g=r (0640) or less if owned by root.")));
return false;
}
#endif
return true;
}
...@@ -90,6 +90,7 @@ extern ssize_t secure_read(Port *port, void *ptr, size_t len); ...@@ -90,6 +90,7 @@ extern ssize_t secure_read(Port *port, void *ptr, size_t len);
extern ssize_t secure_write(Port *port, void *ptr, size_t len); extern ssize_t secure_write(Port *port, void *ptr, size_t len);
extern ssize_t secure_raw_read(Port *port, void *ptr, size_t len); extern ssize_t secure_raw_read(Port *port, void *ptr, size_t len);
extern ssize_t secure_raw_write(Port *port, const void *ptr, size_t len); extern ssize_t secure_raw_write(Port *port, const void *ptr, size_t len);
extern bool check_ssl_key_file_permissions(const char *ssl_key_file, bool isServerStart);
extern bool ssl_loaded_verify_locations; extern bool ssl_loaded_verify_locations;
......
...@@ -1547,14 +1547,6 @@ SSLerrfree(char *buf) ...@@ -1547,14 +1547,6 @@ SSLerrfree(char *buf)
/* SSL information functions */ /* SSL information functions */
/* ------------------------------------------------------------ */ /* ------------------------------------------------------------ */
int
PQsslInUse(PGconn *conn)
{
if (!conn)
return 0;
return conn->ssl_in_use;
}
/* /*
* Return pointer to OpenSSL object. * Return pointer to OpenSSL object.
*/ */
......
...@@ -129,6 +129,14 @@ struct sigpipe_info ...@@ -129,6 +129,14 @@ struct sigpipe_info
/* ------------------------------------------------------------ */ /* ------------------------------------------------------------ */
int
PQsslInUse(PGconn *conn)
{
if (!conn)
return 0;
return conn->ssl_in_use;
}
/* /*
* Exported function to allow application to tell us it's already * Exported function to allow application to tell us it's already
* initialized OpenSSL. * initialized OpenSSL.
...@@ -384,12 +392,6 @@ retry_masked: ...@@ -384,12 +392,6 @@ retry_masked:
/* Dummy versions of SSL info functions, when built without SSL support */ /* Dummy versions of SSL info functions, when built without SSL support */
#ifndef USE_SSL #ifndef USE_SSL
int
PQsslInUse(PGconn *conn)
{
return 0;
}
void * void *
PQgetssl(PGconn *conn) PQgetssl(PGconn *conn)
{ {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment