]> granicus.if.org Git - postgresql/commitdiff
Extract common bits from OpenSSL implementation
authorPeter Eisentraut <peter_e@gmx.net>
Fri, 19 Jan 2018 15:17:56 +0000 (10:17 -0500)
committerPeter Eisentraut <peter_e@gmx.net>
Tue, 23 Jan 2018 12:11:39 +0000 (07:11 -0500)
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.

src/backend/libpq/be-secure-openssl.c
src/backend/libpq/be-secure.c
src/include/libpq/libpq.h
src/interfaces/libpq/fe-secure-openssl.c
src/interfaces/libpq/fe-secure.c

index f550ec82a99fab1c9ee2b4d4e7e9cc898f7909ae..02601da6c8211e3d48624e5ba6bb012ce58ac6a4 100644 (file)
@@ -75,7 +75,6 @@ be_tls_init(bool isServerStart)
 {
        STACK_OF(X509_NAME) *root_cert_list = NULL;
        SSL_CTX    *context;
-       struct stat buf;
 
        /* This stuff need be done only once. */
        if (!SSL_initialized)
@@ -133,63 +132,8 @@ be_tls_init(bool isServerStart)
                goto error;
        }
 
-       if (stat(ssl_key_file, &buf) != 0)
-       {
-               ereport(isServerStart ? FATAL : LOG,
-                               (errcode_for_file_access(),
-                                errmsg("could not access private key file \"%s\": %m",
-                                               ssl_key_file)));
+       if (!check_ssl_key_file_permissions(ssl_key_file, isServerStart))
                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;
-       }
-
-       /*
-        * 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.
@@ -516,10 +460,6 @@ aloop:
                port->peer_cert_valid = true;
        }
 
-       ereport(DEBUG2,
-                       (errmsg("SSL connection from \"%s\"",
-                                       port->peer_cn ? port->peer_cn : "(anonymous)")));
-
        /* set up debugging/info callback */
        SSL_CTX_set_info_callback(SSL_context, info_cb);
 
index eb42ea1a1ee71884ecad3f649e184ab1a231aa81..76c0a9e39b557ecfcf38f00eafb31c1dbb55a84f 100644 (file)
@@ -114,6 +114,10 @@ secure_open_server(Port *port)
 
 #ifdef USE_SSL
        r = be_tls_open_server(port);
+
+       ereport(DEBUG2,
+                       (errmsg("SSL connection from \"%s\"",
+                                       port->peer_cn ? port->peer_cn : "(anonymous)")));
 #endif
 
        return r;
@@ -314,3 +318,70 @@ secure_raw_write(Port *port, const void *ptr, size_t len)
 
        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;
+}
index 2e7725db212fffc14a1e28b464a92699325b87d4..255222acd7a26d490ed6f9cf778c783ae1721172 100644 (file)
@@ -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_raw_read(Port *port, 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;
 
index eb1312094128d41529eac4a346ff6e265124a998..9ab317320a2ee9f008f5fdf77bf23337fda5cf98 100644 (file)
@@ -1547,14 +1547,6 @@ SSLerrfree(char *buf)
 /*                                     SSL information functions                                       */
 /* ------------------------------------------------------------ */
 
-int
-PQsslInUse(PGconn *conn)
-{
-       if (!conn)
-               return 0;
-       return conn->ssl_in_use;
-}
-
 /*
  *     Return pointer to OpenSSL object.
  */
index ec6c65a4b49e108b1068a1a1ed10792c252d41a8..cfb77f6d85f65f9f50f93236468ffb605e9117e1 100644 (file)
@@ -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
  *     initialized OpenSSL.
@@ -384,12 +392,6 @@ retry_masked:
 /* Dummy versions of SSL info functions, when built without SSL support */
 #ifndef USE_SSL
 
-int
-PQsslInUse(PGconn *conn)
-{
-       return 0;
-}
-
 void *
 PQgetssl(PGconn *conn)
 {