]> granicus.if.org Git - postgresql/blobdiff - src/interfaces/libpq/fe-secure.c
Fix typo in comment.
[postgresql] / src / interfaces / libpq / fe-secure.c
index b4c24754aabe8090a7d56b01b6dc30ab1e453028..e058f4edcbfc6a65dff18b9212a881cb3d689e9a 100644 (file)
@@ -6,12 +6,12 @@
  *       message integrity and endpoint authentication.
  *
  *
- * Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1996-2006, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/interfaces/libpq/fe-secure.c,v 1.65 2005/01/06 21:41:44 tgl Exp $
+ *       $PostgreSQL: pgsql/src/interfaces/libpq/fe-secure.c,v 1.81 2006/05/11 23:27:35 momjian Exp $
  *
  * NOTES
  *       [ Most of these notes are wrong/obsolete, but perhaps not all ]
 
 #include "postgres_fe.h"
 
-#include <sys/types.h>
 #include <signal.h>
 #include <fcntl.h>
-#include <errno.h>
 #include <ctype.h>
-#include <string.h>
 
 #include "libpq-fe.h"
 #include "libpq-int.h"
 #include <sys/stat.h>
 
 #ifdef ENABLE_THREAD_SAFETY
+#ifdef WIN32
+#include "pthread-win32.h"
+#else
 #include <pthread.h>
 #endif
+#endif
 
 #ifndef HAVE_STRDUP
 #include "strdup.h"
 
 #ifdef USE_SSL
 #include <openssl/ssl.h>
-#include <openssl/dh.h>
 #endif   /* USE_SSL */
 
 
 #ifdef USE_SSL
 
 #ifndef WIN32
-#define USERCERTFILE   ".postgresql/postgresql.crt"
-#define USERKEYFILE            ".postgresql/postgresql.key"
-#define ROOTCERTFILE   ".postgresql/root.crt"
-#define DHFILEPATTERN  "%s/.postgresql/dh%d.pem"
+#define USER_CERT_FILE         ".postgresql/postgresql.crt"
+#define USER_KEY_FILE          ".postgresql/postgresql.key"
+#define ROOT_CERT_FILE         ".postgresql/root.crt"
+#define ROOT_CRL_FILE          ".postgresql/root.crl"
 #else
 /* On Windows, the "home" directory is already PostgreSQL-specific */
-#define USERCERTFILE   "postgresql.crt"
-#define USERKEYFILE            "postgresql.key"
-#define ROOTCERTFILE   "root.crt"
-#define DHFILEPATTERN  "%s/dh%d.pem"
+#define USER_CERT_FILE         "postgresql.crt"
+#define USER_KEY_FILE          "postgresql.key"
+#define ROOT_CERT_FILE         "root.crt"
+#define ROOT_CRL_FILE          "root.crl"
 #endif
 
 #ifdef NOT_USED
 static int     verify_peer(PGconn *);
 #endif
 static int     verify_cb(int ok, X509_STORE_CTX *ctx);
-static DH  *load_dh_file(int keylength);
-static DH  *load_dh_buffer(const char *, size_t);
-static DH  *tmp_dh_cb(SSL *s, int is_export, int keylength);
 static int     client_cert_cb(SSL *, X509 **, EVP_PKEY **);
 static int     init_ssl_system(PGconn *conn);
 static int     initialize_SSL(PGconn *);
@@ -157,70 +154,14 @@ static bool pq_initssllib = true;
 static SSL_CTX *SSL_context = NULL;
 #endif
 
-/* ------------------------------------------------------------ */
-/*                                              Hardcoded values                                               */
-/* ------------------------------------------------------------ */
-
-/*
- *     Hardcoded DH parameters, used in empheral DH keying.
- *     As discussed above, EDH protects the confidentiality of
- *     sessions even if the static private key is compromised,
- *     so we are *highly* motivated to ensure that we can use
- *     EDH even if the user... or an attacker... deletes the
- *     ~/.postgresql/dh*.pem files.
- *
- *     It's not critical that users have EPH keys, but it doesn't
- *     hurt and if it's missing someone will demand it, so....
- */
-#ifdef USE_SSL
-
-static const char file_dh512[] =
-"-----BEGIN DH PARAMETERS-----\n\
-MEYCQQD1Kv884bEpQBgRjXyEpwpy1obEAxnIByl6ypUM2Zafq9AKUJsCRtMIPWak\n\
-XUGfnHy9iUsiGSa6q6Jew1XpKgVfAgEC\n\
------END DH PARAMETERS-----\n";
-
-static const char file_dh1024[] =
-"-----BEGIN DH PARAMETERS-----\n\
-MIGHAoGBAPSI/VhOSdvNILSd5JEHNmszbDgNRR0PfIizHHxbLY7288kjwEPwpVsY\n\
-jY67VYy4XTjTNP18F1dDox0YbN4zISy1Kv884bEpQBgRjXyEpwpy1obEAxnIByl6\n\
-ypUM2Zafq9AKUJsCRtMIPWakXUGfnHy9iUsiGSa6q6Jew1XpL3jHAgEC\n\
------END DH PARAMETERS-----\n";
-
-static const char file_dh2048[] =
-"-----BEGIN DH PARAMETERS-----\n\
-MIIBCAKCAQEA9kJXtwh/CBdyorrWqULzBej5UxE5T7bxbrlLOCDaAadWoxTpj0BV\n\
-89AHxstDqZSt90xkhkn4DIO9ZekX1KHTUPj1WV/cdlJPPT2N286Z4VeSWc39uK50\n\
-T8X8dryDxUcwYc58yWb/Ffm7/ZFexwGq01uejaClcjrUGvC/RgBYK+X0iP1YTknb\n\
-zSC0neSRBzZrM2w4DUUdD3yIsxx8Wy2O9vPJI8BD8KVbGI2Ou1WMuF040zT9fBdX\n\
-Q6MdGGzeMyEstSr/POGxKUAYEY18hKcKctaGxAMZyAcpesqVDNmWn6vQClCbAkbT\n\
-CD1mpF1Bn5x8vYlLIhkmuquiXsNV6TILOwIBAg==\n\
------END DH PARAMETERS-----\n";
-
-static const char file_dh4096[] =
-"-----BEGIN DH PARAMETERS-----\n\
-MIICCAKCAgEA+hRyUsFN4VpJ1O8JLcCo/VWr19k3BCgJ4uk+d+KhehjdRqNDNyOQ\n\
-l/MOyQNQfWXPeGKmOmIig6Ev/nm6Nf9Z2B1h3R4hExf+zTiHnvVPeRBhjdQi81rt\n\
-Xeoh6TNrSBIKIHfUJWBh3va0TxxjQIs6IZOLeVNRLMqzeylWqMf49HsIXqbcokUS\n\
-Vt1BkvLdW48j8PPv5DsKRN3tloTxqDJGo9tKvj1Fuk74A+Xda1kNhB7KFlqMyN98\n\
-VETEJ6c7KpfOo30mnK30wqw3S8OtaIR/maYX72tGOno2ehFDkq3pnPtEbD2CScxc\n\
-alJC+EL7RPk5c/tgeTvCngvc1KZn92Y//EI7G9tPZtylj2b56sHtMftIoYJ9+ODM\n\
-sccD5Piz/rejE3Ome8EOOceUSCYAhXn8b3qvxVI1ddd1pED6FHRhFvLrZxFvBEM9\n\
-ERRMp5QqOaHJkM+Dxv8Cj6MqrCbfC4u+ZErxodzuusgDgvZiLF22uxMZbobFWyte\n\
-OvOzKGtwcTqO/1wV5gKkzu1ZVswVUQd5Gg8lJicwqRWyyNRczDDoG9jVDxmogKTH\n\
-AaqLulO7R8Ifa1SwF2DteSGVtgWEN8gDpN3RBmmPTDngyF2DHb5qmpnznwtFKdTL\n\
-KWbuHn491xNO25CQWMtem80uKw+pTnisBRF/454n1Jnhub144YRBoN8CAQI=\n\
------END DH PARAMETERS-----\n";
-#endif
-
 /* ------------------------------------------------------------ */
 /*                      Procedures common to all secure sessions                       */
 /* ------------------------------------------------------------ */
 
 
 /*
- * Exported (but as yet undocumented) function to allow application to
- * tell us it's already initialized OpenSSL.
+ *     Exported function to allow application to tell us it's already
+ *     initialized OpenSSL.
  */
 void
 PQinitSSL(int do_init)
@@ -273,15 +214,16 @@ pqsecure_open_client(PGconn *conn)
                        char       *err = SSLerrmessage();
 
                        printfPQExpBuffer(&conn->errorMessage,
-                          libpq_gettext("could not establish SSL connection: %s\n"),
+                                  libpq_gettext("could not establish SSL connection: %s\n"),
                                                          err);
                        SSLerrfree(err);
                        close_SSL(conn);
                        return PGRES_POLLING_FAILED;
                }
+
                /*
-                * Initialize errorMessage to empty.  This allows open_client_SSL()
-                * to detect whether client_cert_cb() has stored a message.
+                * Initialize errorMessage to empty.  This allows open_client_SSL() to
+                * detect whether client_cert_cb() has stored a message.
                 */
                resetPQExpBuffer(&conn->errorMessage);
        }
@@ -331,11 +273,10 @@ rloop:
                        case SSL_ERROR_WANT_WRITE:
 
                                /*
-                                * Returning 0 here would cause caller to wait for
-                                * read-ready, which is not correct since what SSL wants
-                                * is wait for write-ready.  The former could get us stuck
-                                * in an infinite wait, so don't risk it; busy-loop
-                                * instead.
+                                * Returning 0 here would cause caller to wait for read-ready,
+                                * which is not correct since what SSL wants is wait for
+                                * write-ready.  The former could get us stuck in an infinite
+                                * wait, so don't risk it; busy-loop instead.
                                 */
                                goto rloop;
                        case SSL_ERROR_SYSCALL:
@@ -344,12 +285,12 @@ rloop:
 
                                        if (n == -1)
                                                printfPQExpBuffer(&conn->errorMessage,
-                                                               libpq_gettext("SSL SYSCALL error: %s\n"),
-                                               SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf)));
+                                                                       libpq_gettext("SSL SYSCALL error: %s\n"),
+                                                       SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf)));
                                        else
                                        {
                                                printfPQExpBuffer(&conn->errorMessage,
-                                                                                 libpq_gettext("SSL SYSCALL error: EOF detected\n"));
+                                                libpq_gettext("SSL SYSCALL error: EOF detected\n"));
 
                                                SOCK_ERRNO_SET(ECONNRESET);
                                                n = -1;
@@ -361,7 +302,7 @@ rloop:
                                        char       *err = SSLerrmessage();
 
                                        printfPQExpBuffer(&conn->errorMessage,
-                                                                 libpq_gettext("SSL error: %s\n"), err);
+                                                                         libpq_gettext("SSL error: %s\n"), err);
                                        SSLerrfree(err);
                                }
                                /* fall through */
@@ -371,7 +312,7 @@ rloop:
                                break;
                        default:
                                printfPQExpBuffer(&conn->errorMessage,
-                                                libpq_gettext("unrecognized SSL error code: %d\n"),
+                                                 libpq_gettext("unrecognized SSL error code: %d\n"),
                                                                  err);
                                n = -1;
                                break;
@@ -391,19 +332,20 @@ ssize_t
 pqsecure_write(PGconn *conn, const void *ptr, size_t len)
 {
        ssize_t         n;
-       
+
+#ifndef WIN32
 #ifdef ENABLE_THREAD_SAFETY
        sigset_t        osigmask;
        bool            sigpipe_pending;
        bool            got_epipe = false;
-       
+
+
        if (pq_block_sigpipe(&osigmask, &sigpipe_pending) < 0)
                return -1;
 #else
-#ifndef WIN32
        pqsigfunc       oldsighandler = pqsignal(SIGPIPE, SIG_IGN);
-#endif
-#endif
+#endif   /* ENABLE_THREAD_SAFETY */
+#endif   /* WIN32 */
 
 #ifdef USE_SSL
        if (conn->ssl)
@@ -420,8 +362,8 @@ pqsecure_write(PGconn *conn, const void *ptr, size_t len)
 
                                /*
                                 * Returning 0 here causes caller to wait for write-ready,
-                                * which is not really the right thing, but it's the best
-                                * we can do.
+                                * which is not really the right thing, but it's the best we
+                                * can do.
                                 */
                                n = 0;
                                break;
@@ -434,18 +376,18 @@ pqsecure_write(PGconn *conn, const void *ptr, size_t len)
 
                                        if (n == -1)
                                        {
-#ifdef ENABLE_THREAD_SAFETY
+#if defined(ENABLE_THREAD_SAFETY) && !defined(WIN32)
                                                if (SOCK_ERRNO == EPIPE)
                                                        got_epipe = true;
 #endif
                                                printfPQExpBuffer(&conn->errorMessage,
-                                                               libpq_gettext("SSL SYSCALL error: %s\n"),
-                                               SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf)));
+                                                                       libpq_gettext("SSL SYSCALL error: %s\n"),
+                                                       SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf)));
                                        }
                                        else
                                        {
                                                printfPQExpBuffer(&conn->errorMessage,
-                                                                                 libpq_gettext("SSL SYSCALL error: EOF detected\n"));
+                                                libpq_gettext("SSL SYSCALL error: EOF detected\n"));
                                                SOCK_ERRNO_SET(ECONNRESET);
                                                n = -1;
                                        }
@@ -456,7 +398,7 @@ pqsecure_write(PGconn *conn, const void *ptr, size_t len)
                                        char       *err = SSLerrmessage();
 
                                        printfPQExpBuffer(&conn->errorMessage,
-                                                                 libpq_gettext("SSL error: %s\n"), err);
+                                                                         libpq_gettext("SSL error: %s\n"), err);
                                        SSLerrfree(err);
                                }
                                /* fall through */
@@ -466,7 +408,7 @@ pqsecure_write(PGconn *conn, const void *ptr, size_t len)
                                break;
                        default:
                                printfPQExpBuffer(&conn->errorMessage,
-                                                libpq_gettext("unrecognized SSL error code: %d\n"),
+                                                 libpq_gettext("unrecognized SSL error code: %d\n"),
                                                                  err);
                                n = -1;
                                break;
@@ -476,19 +418,19 @@ pqsecure_write(PGconn *conn, const void *ptr, size_t len)
 #endif
        {
                n = send(conn->sock, ptr, len, 0);
-#ifdef ENABLE_THREAD_SAFETY
+#if defined(ENABLE_THREAD_SAFETY) && !defined(WIN32)
                if (n < 0 && SOCK_ERRNO == EPIPE)
                        got_epipe = true;
 #endif
        }
 
+#ifndef WIN32
 #ifdef ENABLE_THREAD_SAFETY
        pq_reset_sigpipe(&osigmask, sigpipe_pending, got_epipe);
 #else
-#ifndef WIN32
        pqsignal(SIGPIPE, oldsighandler);
-#endif
-#endif
+#endif   /* ENABLE_THREAD_SAFETY */
+#endif   /* WIN32 */
 
        return n;
 }
@@ -525,7 +467,7 @@ verify_peer(PGconn *conn)
        struct hostent *h = NULL;
        struct sockaddr addr;
        struct sockaddr_in *sin;
-       socklen_t       len;
+       ACCEPT_TYPE_ARG3 len;
        char      **s;
        unsigned long l;
 
@@ -537,7 +479,7 @@ verify_peer(PGconn *conn)
 
                printfPQExpBuffer(&conn->errorMessage,
                                                  libpq_gettext("error querying socket: %s\n"),
-                                               SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf)));
+                                                 SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf)));
                return -1;
        }
 
@@ -551,10 +493,9 @@ verify_peer(PGconn *conn)
                int                     herrno = 0;
 
                /*
-                * Currently, pqGethostbyname() is used only on platforms that
-                * don't have getaddrinfo().  If you enable this function, you
-                * should convert the pqGethostbyname() function call to use
-                * getaddrinfo().
+                * Currently, pqGethostbyname() is used only on platforms that don't
+                * have getaddrinfo().  If you enable this function, you should
+                * convert the pqGethostbyname() function call to use getaddrinfo().
                 */
                pqGethostbyname(conn->peer_cn, &hpstr, buf, sizeof(buf),
                                                &h, &herrno);
@@ -564,7 +505,7 @@ verify_peer(PGconn *conn)
        if (h == NULL)
        {
                printfPQExpBuffer(&conn->errorMessage,
-               libpq_gettext("could not get information about host \"%s\": %s\n"),
+                 libpq_gettext("could not get information about host \"%s\": %s\n"),
                                                  conn->peer_cn, hstrerror(h_errno));
                return -1;
        }
@@ -606,159 +547,19 @@ verify_peer(PGconn *conn)
                        printfPQExpBuffer(&conn->errorMessage,
                                                          libpq_gettext(
                                                                                        "server common name \"%s\" does not resolve to %ld.%ld.%ld.%ld\n"),
-                                        conn->peer_cn, (l >> 24) % 0x100, (l >> 16) % 0x100,
+                                                conn->peer_cn, (l >> 24) % 0x100, (l >> 16) % 0x100,
                                                          (l >> 8) % 0x100, l % 0x100);
                        break;
                default:
                        printfPQExpBuffer(&conn->errorMessage,
                                                          libpq_gettext(
-                                                                                       "server common name \"%s\" does not resolve to peer address\n"),
+                        "server common name \"%s\" does not resolve to peer address\n"),
                                                          conn->peer_cn);
        }
 
        return -1;
 }
-#endif /* NOT_USED */
-
-/*
- *     Load precomputed DH parameters.
- *
- *     To prevent "downgrade" attacks, we perform a number of checks
- *     to verify that the DBA-generated DH parameters file contains
- *     what we expect it to contain.
- */
-static DH  *
-load_dh_file(int keylength)
-{
-       char            homedir[MAXPGPATH];
-       char            fnbuf[MAXPGPATH];
-       FILE       *fp;
-       DH                 *dh;
-       int                     codes;
-
-       if (!pqGetHomeDirectory(homedir, sizeof(homedir)))
-               return NULL;
-
-       /* attempt to open file.  It's not an error if it doesn't exist. */
-       snprintf(fnbuf, sizeof(fnbuf), DHFILEPATTERN, homedir, keylength);
-
-       if ((fp = fopen(fnbuf, "r")) == NULL)
-               return NULL;
-
-/*     flock(fileno(fp), LOCK_SH); */
-       dh = PEM_read_DHparams(fp, NULL, NULL, NULL);
-/*     flock(fileno(fp), LOCK_UN); */
-       fclose(fp);
-
-       /* is the prime the correct size? */
-       if (dh != NULL && 8 * DH_size(dh) < keylength)
-               dh = NULL;
-
-       /* make sure the DH parameters are usable */
-       if (dh != NULL)
-       {
-               if (DH_check(dh, &codes))
-                       return NULL;
-               if (codes & DH_CHECK_P_NOT_PRIME)
-                       return NULL;
-               if ((codes & DH_NOT_SUITABLE_GENERATOR) &&
-                       (codes & DH_CHECK_P_NOT_SAFE_PRIME))
-                       return NULL;
-       }
-
-       return dh;
-}
-
-/*
- *     Load hardcoded DH parameters.
- *
- *     To prevent problems if the DH parameters files don't even
- *     exist, we can load DH parameters hardcoded into this file.
- */
-static DH  *
-load_dh_buffer(const char *buffer, size_t len)
-{
-       BIO                *bio;
-       DH                 *dh = NULL;
-
-       bio = BIO_new_mem_buf((char *) buffer, len);
-       if (bio == NULL)
-               return NULL;
-       dh = PEM_read_bio_DHparams(bio, NULL, NULL, NULL);
-       BIO_free(bio);
-
-       return dh;
-}
-
-/*
- *     Generate an empheral DH key.  Because this can take a long
- *     time to compute, we can use precomputed parameters of the
- *     common key sizes.
- *
- *     Since few sites will bother to precompute these parameter
- *     files, we also provide a fallback to the parameters provided
- *     by the OpenSSL project.
- *
- *     These values can be static (once loaded or computed) since
- *     the OpenSSL library can efficiently generate random keys from
- *     the information provided.
- */
-static DH  *
-tmp_dh_cb(SSL *s, int is_export, int keylength)
-{
-       DH                 *r = NULL;
-       static DH  *dh = NULL;
-       static DH  *dh512 = NULL;
-       static DH  *dh1024 = NULL;
-       static DH  *dh2048 = NULL;
-       static DH  *dh4096 = NULL;
-
-       switch (keylength)
-       {
-               case 512:
-                       if (dh512 == NULL)
-                               dh512 = load_dh_file(keylength);
-                       if (dh512 == NULL)
-                               dh512 = load_dh_buffer(file_dh512, sizeof file_dh512);
-                       r = dh512;
-                       break;
-
-               case 1024:
-                       if (dh1024 == NULL)
-                               dh1024 = load_dh_file(keylength);
-                       if (dh1024 == NULL)
-                               dh1024 = load_dh_buffer(file_dh1024, sizeof file_dh1024);
-                       r = dh1024;
-                       break;
-
-               case 2048:
-                       if (dh2048 == NULL)
-                               dh2048 = load_dh_file(keylength);
-                       if (dh2048 == NULL)
-                               dh2048 = load_dh_buffer(file_dh2048, sizeof file_dh2048);
-                       r = dh2048;
-                       break;
-
-               case 4096:
-                       if (dh4096 == NULL)
-                               dh4096 = load_dh_file(keylength);
-                       if (dh4096 == NULL)
-                               dh4096 = load_dh_buffer(file_dh4096, sizeof file_dh4096);
-                       r = dh4096;
-                       break;
-
-               default:
-                       if (dh == NULL)
-                               dh = load_dh_file(keylength);
-                       r = dh;
-       }
-
-       /* this may take a long time, but it may be necessary... */
-       if (r == NULL || 8 * DH_size(r) < keylength)
-               r = DH_generate_parameters(keylength, DH_GENERATOR_2, NULL, NULL);
-
-       return r;
-}
+#endif   /* NOT_USED */
 
 /*
  *     Callback used by SSL to load client cert and key.
@@ -771,8 +572,11 @@ static int
 client_cert_cb(SSL *ssl, X509 **x509, EVP_PKEY **pkey)
 {
        char            homedir[MAXPGPATH];
-       struct stat buf,
-                               buf2;
+       struct stat buf;
+
+#ifndef WIN32
+       struct stat buf2;
+#endif
        char            fnbuf[MAXPGPATH];
        FILE       *fp;
        PGconn     *conn = (PGconn *) SSL_get_app_data(ssl);
@@ -782,16 +586,16 @@ client_cert_cb(SSL *ssl, X509 **x509, EVP_PKEY **pkey)
        if (!pqGetHomeDirectory(homedir, sizeof(homedir)))
        {
                printfPQExpBuffer(&conn->errorMessage,
-                                         libpq_gettext("could not get user information\n"));
+                                                 libpq_gettext("could not get user information\n"));
                return 0;
        }
 
        /* read the user certificate */
-       snprintf(fnbuf, sizeof(fnbuf), "%s/%s", homedir, USERCERTFILE);
+       snprintf(fnbuf, sizeof(fnbuf), "%s/%s", homedir, USER_CERT_FILE);
        if ((fp = fopen(fnbuf, "r")) == NULL)
        {
                printfPQExpBuffer(&conn->errorMessage,
-                                 libpq_gettext("could not open certificate file \"%s\": %s\n"),
+                          libpq_gettext("could not open certificate file \"%s\": %s\n"),
                                                  fnbuf, pqStrerror(errno, sebuf, sizeof(sebuf)));
                return 0;
        }
@@ -800,7 +604,7 @@ client_cert_cb(SSL *ssl, X509 **x509, EVP_PKEY **pkey)
                char       *err = SSLerrmessage();
 
                printfPQExpBuffer(&conn->errorMessage,
-                                 libpq_gettext("could not read certificate file \"%s\": %s\n"),
+                          libpq_gettext("could not read certificate file \"%s\": %s\n"),
                                                  fnbuf, err);
                SSLerrfree(err);
                fclose(fp);
@@ -809,20 +613,20 @@ client_cert_cb(SSL *ssl, X509 **x509, EVP_PKEY **pkey)
        fclose(fp);
 
        /* read the user key */
-       snprintf(fnbuf, sizeof(fnbuf), "%s/%s", homedir, USERKEYFILE);
+       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"),
+                                                 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 != getuid())
+               buf.st_uid != geteuid())
        {
                printfPQExpBuffer(&conn->errorMessage,
-               libpq_gettext("private key file \"%s\" has wrong permissions\n"),
+                       libpq_gettext("private key file \"%s\" has wrong permissions\n"),
                                                  fnbuf);
                return 0;
        }
@@ -830,10 +634,11 @@ client_cert_cb(SSL *ssl, X509 **x509, EVP_PKEY **pkey)
        if ((fp = fopen(fnbuf, "r")) == NULL)
        {
                printfPQExpBuffer(&conn->errorMessage,
-                        libpq_gettext("could not open private key file \"%s\": %s\n"),
+                          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)
        {
@@ -841,12 +646,13 @@ client_cert_cb(SSL *ssl, X509 **x509, EVP_PKEY **pkey)
                                                  libpq_gettext("private key file \"%s\" changed during execution\n"), fnbuf);
                return 0;
        }
+#endif
        if (PEM_read_PrivateKey(fp, pkey, cb, NULL) == NULL)
        {
                char       *err = SSLerrmessage();
 
                printfPQExpBuffer(&conn->errorMessage,
-                                 libpq_gettext("could not read private key file \"%s\": %s\n"),
+                          libpq_gettext("could not read private key file \"%s\": %s\n"),
                                                  fnbuf, err);
                SSLerrfree(err);
                fclose(fp);
@@ -860,7 +666,7 @@ client_cert_cb(SSL *ssl, X509 **x509, EVP_PKEY **pkey)
                char       *err = SSLerrmessage();
 
                printfPQExpBuffer(&conn->errorMessage,
-                       libpq_gettext("certificate does not match private key file \"%s\": %s\n"),
+                                                 libpq_gettext("certificate does not match private key file \"%s\": %s\n"),
                                                  fnbuf, err);
                SSLerrfree(err);
                return 0;
@@ -874,6 +680,11 @@ client_cert_cb(SSL *ssl, X509 **x509, EVP_PKEY **pkey)
 static unsigned long
 pq_threadidcallback(void)
 {
+       /*
+        * This is not standards-compliant.  pthread_self() returns pthread_t, and
+        * shouldn't be cast to unsigned long, but CRYPTO_set_id_callback requires
+        * it, so we have to do it.
+        */
        return (unsigned long) pthread_self();
 }
 
@@ -887,7 +698,6 @@ pq_lockingcallback(int mode, int n, const char *file, int line)
        else
                pthread_mutex_unlock(&pq_lockarray[n]);
 }
-
 #endif   /* ENABLE_THREAD_SAFETY */
 
 static int
@@ -896,7 +706,6 @@ init_ssl_system(PGconn *conn)
 #ifdef ENABLE_THREAD_SAFETY
 #ifndef WIN32
        static pthread_mutex_t init_mutex = PTHREAD_MUTEX_INITIALIZER;
-
 #else
        static pthread_mutex_t init_mutex = NULL;
        static long mutex_initlock = 0;
@@ -943,7 +752,7 @@ init_ssl_system(PGconn *conn)
                        char       *err = SSLerrmessage();
 
                        printfPQExpBuffer(&conn->errorMessage,
-                                        libpq_gettext("could not create SSL context: %s\n"),
+                                                libpq_gettext("could not create SSL context: %s\n"),
                                                          err);
                        SSLerrfree(err);
 #ifdef ENABLE_THREAD_SAFETY
@@ -974,9 +783,11 @@ initialize_SSL(PGconn *conn)
        /* Set up to verify server cert, if root.crt is present */
        if (pqGetHomeDirectory(homedir, sizeof(homedir)))
        {
-               snprintf(fnbuf, sizeof(fnbuf), "%s/%s", homedir, ROOTCERTFILE);
+               snprintf(fnbuf, sizeof(fnbuf), "%s/%s", homedir, ROOT_CERT_FILE);
                if (stat(fnbuf, &buf) == 0)
                {
+                       X509_STORE *cvstore;
+                       
                        if (!SSL_CTX_load_verify_locations(SSL_context, fnbuf, NULL))
                        {
                                char       *err = SSLerrmessage();
@@ -988,14 +799,32 @@ initialize_SSL(PGconn *conn)
                                return -1;
                        }
 
+                       if ((cvstore = SSL_CTX_get_cert_store(SSL_context)) != NULL)
+                       {
+                               /* setting the flags to check against the complete CRL chain */
+                               if (X509_STORE_load_locations(cvstore, ROOT_CRL_FILE, NULL) != 0)
+/* OpenSSL 0.96 does not support X509_V_FLAG_CRL_CHECK */
+#ifdef X509_V_FLAG_CRL_CHECK
+                                  X509_STORE_set_flags(cvstore,
+                                                               X509_V_FLAG_CRL_CHECK|X509_V_FLAG_CRL_CHECK_ALL);
+                               /* if not found, silently ignore;  we do not require CRL */
+#else
+                               {
+                                       char       *err = SSLerrmessage();
+       
+                                       printfPQExpBuffer(&conn->errorMessage,
+                                                                         libpq_gettext("Installed SSL library does not support CRL certificates, file \"%s\"\n"),
+                                                                         fnbuf);
+                                       SSLerrfree(err);
+                                       return -1;
+                               }
+#endif
+                       }
+       
                        SSL_CTX_set_verify(SSL_context, SSL_VERIFY_PEER, verify_cb);
                }
        }
 
-       /* set up empheral DH keys */
-       SSL_CTX_set_tmp_dh_callback(SSL_context, tmp_dh_cb);
-       SSL_CTX_set_options(SSL_context, SSL_OP_SINGLE_DH_USE);
-
        /* set up mechanism to provide client certificate, if available */
        SSL_CTX_set_client_cert_cb(SSL_context, client_cert_cb);
 
@@ -1026,7 +855,7 @@ open_client_SSL(PGconn *conn)
        r = SSL_connect(conn->ssl);
        if (r <= 0)
        {
-               int err = SSL_get_error(conn->ssl, r);
+               int                     err = SSL_get_error(conn->ssl, r);
 
                switch (err)
                {
@@ -1042,11 +871,11 @@ open_client_SSL(PGconn *conn)
 
                                        if (r == -1)
                                                printfPQExpBuffer(&conn->errorMessage,
-                                                               libpq_gettext("SSL SYSCALL error: %s\n"),
-                                               SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf)));
+                                                                       libpq_gettext("SSL SYSCALL error: %s\n"),
+                                                       SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf)));
                                        else
                                                printfPQExpBuffer(&conn->errorMessage,
-                                                                                 libpq_gettext("SSL SYSCALL error: EOF detected\n"));
+                                                libpq_gettext("SSL SYSCALL error: EOF detected\n"));
                                        close_SSL(conn);
                                        return PGRES_POLLING_FAILED;
                                }
@@ -1057,7 +886,7 @@ open_client_SSL(PGconn *conn)
                                         * these will be detected by client_cert_cb() which is
                                         * called from SSL_connect().  We want to return that
                                         * error message and not the rather unhelpful error that
-                                        * OpenSSL itself returns.  So check to see if an error
+                                        * OpenSSL itself returns.      So check to see if an error
                                         * message was already stored.
                                         */
                                        if (conn->errorMessage.len == 0)
@@ -1075,7 +904,7 @@ open_client_SSL(PGconn *conn)
 
                        default:
                                printfPQExpBuffer(&conn->errorMessage,
-                                                libpq_gettext("unrecognized SSL error code: %d\n"),
+                                                 libpq_gettext("unrecognized SSL error code: %d\n"),
                                                                  err);
                                close_SSL(conn);
                                return PGRES_POLLING_FAILED;
@@ -1095,7 +924,7 @@ open_client_SSL(PGconn *conn)
        if (r != X509_V_OK)
        {
                printfPQExpBuffer(&conn->errorMessage,
-                          libpq_gettext("certificate could not be validated: %s\n"),
+                                  libpq_gettext("certificate could not be validated: %s\n"),
                                                  X509_verify_cert_error_string(r));
                close_SSL(conn);
                return PGRES_POLLING_FAILED;
@@ -1109,7 +938,7 @@ open_client_SSL(PGconn *conn)
                char       *err = SSLerrmessage();
 
                printfPQExpBuffer(&conn->errorMessage,
-                               libpq_gettext("certificate could not be obtained: %s\n"),
+                                       libpq_gettext("certificate could not be obtained: %s\n"),
                                                  err);
                SSLerrfree(err);
                close_SSL(conn);
@@ -1131,8 +960,8 @@ open_client_SSL(PGconn *conn)
 
        /*
         * this is necessary to eliminate man-in-the-middle attacks and
-        * impersonations where the attacker somehow learned the server's
-        * private key
+        * impersonations where the attacker somehow learned the server's private
+        * key
         */
        if (verify_peer(conn) == -1)
        {
@@ -1211,38 +1040,36 @@ SSLerrfree(char *buf)
 }
 
 /*
- *     Return pointer to SSL object.
+ *     Return pointer to OpenSSL object.
  */
-SSL *
+void *
 PQgetssl(PGconn *conn)
 {
        if (!conn)
                return NULL;
        return conn->ssl;
 }
-
-#else   /* !USE_SSL */
+#else                                                  /* !USE_SSL */
 
 void *
 PQgetssl(PGconn *conn)
 {
        return NULL;
 }
-
 #endif   /* USE_SSL */
 
-#ifdef ENABLE_THREAD_SAFETY
+#if defined(ENABLE_THREAD_SAFETY) && !defined(WIN32)
 
 /*
- *     Block SIGPIPE for this thread.  This prevents send()/write() from exiting
+ *     Block SIGPIPE for this thread.  This prevents send()/write() from exiting
  *     the application.
  */
 int
 pq_block_sigpipe(sigset_t *osigset, bool *sigpipe_pending)
 {
-       sigset_t sigpipe_sigset;
-       sigset_t sigset;
-       
+       sigset_t        sigpipe_sigset;
+       sigset_t        sigset;
+
        sigemptyset(&sigpipe_sigset);
        sigaddset(&sigpipe_sigset, SIGPIPE);
 
@@ -1257,7 +1084,7 @@ pq_block_sigpipe(sigset_t *osigset, bool *sigpipe_pending)
                /* Is there a pending SIGPIPE? */
                if (sigpending(&sigset) != 0)
                        return -1;
-       
+
                if (sigismember(&sigset, SIGPIPE))
                        *sigpipe_pending = true;
                else
@@ -1265,15 +1092,15 @@ pq_block_sigpipe(sigset_t *osigset, bool *sigpipe_pending)
        }
        else
                *sigpipe_pending = false;
-       
+
        return 0;
 }
-       
+
 /*
  *     Discard any pending SIGPIPE and reset the signal mask.
  *
  * Note: we are effectively assuming here that the C library doesn't queue
- * up multiple SIGPIPE events.  If it did, then we'd accidentally leave
+ * up multiple SIGPIPE events. If it did, then we'd accidentally leave
  * ours in the queue when an event was already pending and we got another.
  * As long as it doesn't queue multiple events, we're OK because the caller
  * can't tell the difference.
@@ -1284,15 +1111,15 @@ pq_block_sigpipe(sigset_t *osigset, bool *sigpipe_pending)
  * gotten one, pass got_epipe = TRUE.
  *
  * We do not want this to change errno, since if it did that could lose
- * the error code from a preceding send().  We essentially assume that if
+ * the error code from a preceding send().     We essentially assume that if
  * we were able to do pq_block_sigpipe(), this can't fail.
  */
 void
 pq_reset_sigpipe(sigset_t *osigset, bool sigpipe_pending, bool got_epipe)
 {
-       int     save_errno = SOCK_ERRNO;
-       int     signo;
-       sigset_t sigset;
+       int                     save_errno = SOCK_ERRNO;
+       int                     signo;
+       sigset_t        sigset;
 
        /* Clear SIGPIPE only if none was pending */
        if (got_epipe && !sigpipe_pending)
@@ -1300,19 +1127,19 @@ pq_reset_sigpipe(sigset_t *osigset, bool sigpipe_pending, bool got_epipe)
                if (sigpending(&sigset) == 0 &&
                        sigismember(&sigset, SIGPIPE))
                {
-                       sigset_t sigpipe_sigset;
-                       
+                       sigset_t        sigpipe_sigset;
+
                        sigemptyset(&sigpipe_sigset);
                        sigaddset(&sigpipe_sigset, SIGPIPE);
 
                        sigwait(&sigpipe_sigset, &signo);
                }
        }
-       
+
        /* Restore saved block mask */
        pthread_sigmask(SIG_SETMASK, osigset, NULL);
 
        SOCK_ERRNO_SET(save_errno);
 }
 
-#endif /* ENABLE_THREAD_SAFETY */
+#endif   /* ENABLE_THREAD_SAFETY */