Header And Logo

PostgreSQL
| The world's most advanced open source database.

be-secure.c

Go to the documentation of this file.
00001 /*-------------------------------------------------------------------------
00002  *
00003  * be-secure.c
00004  *    functions related to setting up a secure connection to the frontend.
00005  *    Secure connections are expected to provide confidentiality,
00006  *    message integrity and endpoint authentication.
00007  *
00008  *
00009  * Portions Copyright (c) 1996-2013, PostgreSQL Global Development Group
00010  * Portions Copyright (c) 1994, Regents of the University of California
00011  *
00012  *
00013  * IDENTIFICATION
00014  *    src/backend/libpq/be-secure.c
00015  *
00016  *    Since the server static private key ($DataDir/server.key)
00017  *    will normally be stored unencrypted so that the database
00018  *    backend can restart automatically, it is important that
00019  *    we select an algorithm that continues to provide confidentiality
00020  *    even if the attacker has the server's private key.  Ephemeral
00021  *    DH (EDH) keys provide this, and in fact provide Perfect Forward
00022  *    Secrecy (PFS) except for situations where the session can
00023  *    be hijacked during a periodic handshake/renegotiation.
00024  *    Even that backdoor can be closed if client certificates
00025  *    are used (since the imposter will be unable to successfully
00026  *    complete renegotiation).
00027  *
00028  *    N.B., the static private key should still be protected to
00029  *    the largest extent possible, to minimize the risk of
00030  *    impersonations.
00031  *
00032  *    Another benefit of EDH is that it allows the backend and
00033  *    clients to use DSA keys.  DSA keys can only provide digital
00034  *    signatures, not encryption, and are often acceptable in
00035  *    jurisdictions where RSA keys are unacceptable.
00036  *
00037  *    The downside to EDH is that it makes it impossible to
00038  *    use ssldump(1) if there's a problem establishing an SSL
00039  *    session.  In this case you'll need to temporarily disable
00040  *    EDH by commenting out the callback.
00041  *
00042  *    ...
00043  *
00044  *    Because the risk of cryptanalysis increases as large
00045  *    amounts of data are sent with the same session key, the
00046  *    session keys are periodically renegotiated.
00047  *
00048  *-------------------------------------------------------------------------
00049  */
00050 
00051 #include "postgres.h"
00052 
00053 #include <sys/stat.h>
00054 #include <signal.h>
00055 #include <fcntl.h>
00056 #include <ctype.h>
00057 #include <sys/socket.h>
00058 #include <unistd.h>
00059 #include <netdb.h>
00060 #include <netinet/in.h>
00061 #ifdef HAVE_NETINET_TCP_H
00062 #include <netinet/tcp.h>
00063 #include <arpa/inet.h>
00064 #endif
00065 
00066 #ifdef USE_SSL
00067 #include <openssl/ssl.h>
00068 #include <openssl/dh.h>
00069 #if SSLEAY_VERSION_NUMBER >= 0x0907000L
00070 #include <openssl/conf.h>
00071 #endif
00072 #endif   /* USE_SSL */
00073 
00074 #include "libpq/libpq.h"
00075 #include "tcop/tcopprot.h"
00076 #include "utils/memutils.h"
00077 
00078 
00079 #ifdef USE_SSL
00080 
00081 static DH  *load_dh_file(int keylength);
00082 static DH  *load_dh_buffer(const char *, size_t);
00083 static DH  *tmp_dh_cb(SSL *s, int is_export, int keylength);
00084 static int  verify_cb(int, X509_STORE_CTX *);
00085 static void info_cb(const SSL *ssl, int type, int args);
00086 static void initialize_SSL(void);
00087 static int  open_server_SSL(Port *);
00088 static void close_SSL(Port *);
00089 static const char *SSLerrmessage(void);
00090 #endif
00091 
00092 char       *ssl_cert_file;
00093 char       *ssl_key_file;
00094 char       *ssl_ca_file;
00095 char       *ssl_crl_file;
00096 
00097 /*
00098  *  How much data can be sent across a secure connection
00099  *  (total in both directions) before we require renegotiation.
00100  *  Set to 0 to disable renegotiation completely.
00101  */
00102 int         ssl_renegotiation_limit;
00103 
00104 #ifdef USE_SSL
00105 static SSL_CTX *SSL_context = NULL;
00106 static bool ssl_loaded_verify_locations = false;
00107 #endif
00108 
00109 /* GUC variable controlling SSL cipher list */
00110 char       *SSLCipherSuites = NULL;
00111 
00112 /* ------------------------------------------------------------ */
00113 /*                       Hardcoded values                       */
00114 /* ------------------------------------------------------------ */
00115 
00116 /*
00117  *  Hardcoded DH parameters, used in ephemeral DH keying.
00118  *  As discussed above, EDH protects the confidentiality of
00119  *  sessions even if the static private key is compromised,
00120  *  so we are *highly* motivated to ensure that we can use
00121  *  EDH even if the DBA... or an attacker... deletes the
00122  *  $DataDir/dh*.pem files.
00123  *
00124  *  We could refuse SSL connections unless a good DH parameter
00125  *  file exists, but some clients may quietly renegotiate an
00126  *  unsecured connection without fully informing the user.
00127  *  Very uncool.
00128  *
00129  *  Alternatively, the backend could attempt to load these files
00130  *  on startup if SSL is enabled - and refuse to start if any
00131  *  do not exist - but this would tend to piss off DBAs.
00132  *
00133  *  If you want to create your own hardcoded DH parameters
00134  *  for fun and profit, review "Assigned Number for SKIP
00135  *  Protocols" (http://www.skip-vpn.org/spec/numbers.html)
00136  *  for suggestions.
00137  */
00138 #ifdef USE_SSL
00139 
00140 static const char file_dh512[] =
00141 "-----BEGIN DH PARAMETERS-----\n\
00142 MEYCQQD1Kv884bEpQBgRjXyEpwpy1obEAxnIByl6ypUM2Zafq9AKUJsCRtMIPWak\n\
00143 XUGfnHy9iUsiGSa6q6Jew1XpKgVfAgEC\n\
00144 -----END DH PARAMETERS-----\n";
00145 
00146 static const char file_dh1024[] =
00147 "-----BEGIN DH PARAMETERS-----\n\
00148 MIGHAoGBAPSI/VhOSdvNILSd5JEHNmszbDgNRR0PfIizHHxbLY7288kjwEPwpVsY\n\
00149 jY67VYy4XTjTNP18F1dDox0YbN4zISy1Kv884bEpQBgRjXyEpwpy1obEAxnIByl6\n\
00150 ypUM2Zafq9AKUJsCRtMIPWakXUGfnHy9iUsiGSa6q6Jew1XpL3jHAgEC\n\
00151 -----END DH PARAMETERS-----\n";
00152 
00153 static const char file_dh2048[] =
00154 "-----BEGIN DH PARAMETERS-----\n\
00155 MIIBCAKCAQEA9kJXtwh/CBdyorrWqULzBej5UxE5T7bxbrlLOCDaAadWoxTpj0BV\n\
00156 89AHxstDqZSt90xkhkn4DIO9ZekX1KHTUPj1WV/cdlJPPT2N286Z4VeSWc39uK50\n\
00157 T8X8dryDxUcwYc58yWb/Ffm7/ZFexwGq01uejaClcjrUGvC/RgBYK+X0iP1YTknb\n\
00158 zSC0neSRBzZrM2w4DUUdD3yIsxx8Wy2O9vPJI8BD8KVbGI2Ou1WMuF040zT9fBdX\n\
00159 Q6MdGGzeMyEstSr/POGxKUAYEY18hKcKctaGxAMZyAcpesqVDNmWn6vQClCbAkbT\n\
00160 CD1mpF1Bn5x8vYlLIhkmuquiXsNV6TILOwIBAg==\n\
00161 -----END DH PARAMETERS-----\n";
00162 
00163 static const char file_dh4096[] =
00164 "-----BEGIN DH PARAMETERS-----\n\
00165 MIICCAKCAgEA+hRyUsFN4VpJ1O8JLcCo/VWr19k3BCgJ4uk+d+KhehjdRqNDNyOQ\n\
00166 l/MOyQNQfWXPeGKmOmIig6Ev/nm6Nf9Z2B1h3R4hExf+zTiHnvVPeRBhjdQi81rt\n\
00167 Xeoh6TNrSBIKIHfUJWBh3va0TxxjQIs6IZOLeVNRLMqzeylWqMf49HsIXqbcokUS\n\
00168 Vt1BkvLdW48j8PPv5DsKRN3tloTxqDJGo9tKvj1Fuk74A+Xda1kNhB7KFlqMyN98\n\
00169 VETEJ6c7KpfOo30mnK30wqw3S8OtaIR/maYX72tGOno2ehFDkq3pnPtEbD2CScxc\n\
00170 alJC+EL7RPk5c/tgeTvCngvc1KZn92Y//EI7G9tPZtylj2b56sHtMftIoYJ9+ODM\n\
00171 sccD5Piz/rejE3Ome8EOOceUSCYAhXn8b3qvxVI1ddd1pED6FHRhFvLrZxFvBEM9\n\
00172 ERRMp5QqOaHJkM+Dxv8Cj6MqrCbfC4u+ZErxodzuusgDgvZiLF22uxMZbobFWyte\n\
00173 OvOzKGtwcTqO/1wV5gKkzu1ZVswVUQd5Gg8lJicwqRWyyNRczDDoG9jVDxmogKTH\n\
00174 AaqLulO7R8Ifa1SwF2DteSGVtgWEN8gDpN3RBmmPTDngyF2DHb5qmpnznwtFKdTL\n\
00175 KWbuHn491xNO25CQWMtem80uKw+pTnisBRF/454n1Jnhub144YRBoN8CAQI=\n\
00176 -----END DH PARAMETERS-----\n";
00177 #endif
00178 
00179 /* ------------------------------------------------------------ */
00180 /*           Procedures common to all secure sessions           */
00181 /* ------------------------------------------------------------ */
00182 
00183 /*
00184  *  Initialize global context
00185  */
00186 int
00187 secure_initialize(void)
00188 {
00189 #ifdef USE_SSL
00190     initialize_SSL();
00191 #endif
00192 
00193     return 0;
00194 }
00195 
00196 /*
00197  * Indicate if we have loaded the root CA store to verify certificates
00198  */
00199 bool
00200 secure_loaded_verify_locations(void)
00201 {
00202 #ifdef USE_SSL
00203     return ssl_loaded_verify_locations;
00204 #else
00205     return false;
00206 #endif
00207 }
00208 
00209 /*
00210  *  Attempt to negotiate secure session.
00211  */
00212 int
00213 secure_open_server(Port *port)
00214 {
00215     int         r = 0;
00216 
00217 #ifdef USE_SSL
00218     r = open_server_SSL(port);
00219 #endif
00220 
00221     return r;
00222 }
00223 
00224 /*
00225  *  Close secure session.
00226  */
00227 void
00228 secure_close(Port *port)
00229 {
00230 #ifdef USE_SSL
00231     if (port->ssl)
00232         close_SSL(port);
00233 #endif
00234 }
00235 
00236 /*
00237  *  Read data from a secure connection.
00238  */
00239 ssize_t
00240 secure_read(Port *port, void *ptr, size_t len)
00241 {
00242     ssize_t     n;
00243 
00244 #ifdef USE_SSL
00245     if (port->ssl)
00246     {
00247         int         err;
00248 
00249 rloop:
00250         errno = 0;
00251         n = SSL_read(port->ssl, ptr, len);
00252         err = SSL_get_error(port->ssl, n);
00253         switch (err)
00254         {
00255             case SSL_ERROR_NONE:
00256                 port->count += n;
00257                 break;
00258             case SSL_ERROR_WANT_READ:
00259             case SSL_ERROR_WANT_WRITE:
00260                 if (port->noblock)
00261                 {
00262                     errno = EWOULDBLOCK;
00263                     n = -1;
00264                     break;
00265                 }
00266 #ifdef WIN32
00267                 pgwin32_waitforsinglesocket(SSL_get_fd(port->ssl),
00268                                             (err == SSL_ERROR_WANT_READ) ?
00269                                     FD_READ | FD_CLOSE : FD_WRITE | FD_CLOSE,
00270                                             INFINITE);
00271 #endif
00272                 goto rloop;
00273             case SSL_ERROR_SYSCALL:
00274                 /* leave it to caller to ereport the value of errno */
00275                 if (n != -1)
00276                 {
00277                     errno = ECONNRESET;
00278                     n = -1;
00279                 }
00280                 break;
00281             case SSL_ERROR_SSL:
00282                 ereport(COMMERROR,
00283                         (errcode(ERRCODE_PROTOCOL_VIOLATION),
00284                          errmsg("SSL error: %s", SSLerrmessage())));
00285                 /* fall through */
00286             case SSL_ERROR_ZERO_RETURN:
00287                 errno = ECONNRESET;
00288                 n = -1;
00289                 break;
00290             default:
00291                 ereport(COMMERROR,
00292                         (errcode(ERRCODE_PROTOCOL_VIOLATION),
00293                          errmsg("unrecognized SSL error code: %d",
00294                                 err)));
00295                 n = -1;
00296                 break;
00297         }
00298     }
00299     else
00300 #endif
00301     {
00302         prepare_for_client_read();
00303 
00304         n = recv(port->sock, ptr, len, 0);
00305 
00306         client_read_ended();
00307     }
00308 
00309     return n;
00310 }
00311 
00312 /*
00313  *  Write data to a secure connection.
00314  */
00315 ssize_t
00316 secure_write(Port *port, void *ptr, size_t len)
00317 {
00318     ssize_t     n;
00319 
00320 #ifdef USE_SSL
00321     if (port->ssl)
00322     {
00323         int         err;
00324 
00325         if (ssl_renegotiation_limit && port->count > ssl_renegotiation_limit * 1024L)
00326         {
00327             SSL_set_session_id_context(port->ssl, (void *) &SSL_context,
00328                                        sizeof(SSL_context));
00329             if (SSL_renegotiate(port->ssl) <= 0)
00330                 ereport(COMMERROR,
00331                         (errcode(ERRCODE_PROTOCOL_VIOLATION),
00332                          errmsg("SSL renegotiation failure")));
00333             if (SSL_do_handshake(port->ssl) <= 0)
00334                 ereport(COMMERROR,
00335                         (errcode(ERRCODE_PROTOCOL_VIOLATION),
00336                          errmsg("SSL renegotiation failure")));
00337             if (port->ssl->state != SSL_ST_OK)
00338                 ereport(COMMERROR,
00339                         (errcode(ERRCODE_PROTOCOL_VIOLATION),
00340                          errmsg("SSL failed to send renegotiation request")));
00341             port->ssl->state |= SSL_ST_ACCEPT;
00342             SSL_do_handshake(port->ssl);
00343             if (port->ssl->state != SSL_ST_OK)
00344                 ereport(COMMERROR,
00345                         (errcode(ERRCODE_PROTOCOL_VIOLATION),
00346                          errmsg("SSL renegotiation failure")));
00347             port->count = 0;
00348         }
00349 
00350 wloop:
00351         errno = 0;
00352         n = SSL_write(port->ssl, ptr, len);
00353         err = SSL_get_error(port->ssl, n);
00354         switch (err)
00355         {
00356             case SSL_ERROR_NONE:
00357                 port->count += n;
00358                 break;
00359             case SSL_ERROR_WANT_READ:
00360             case SSL_ERROR_WANT_WRITE:
00361 #ifdef WIN32
00362                 pgwin32_waitforsinglesocket(SSL_get_fd(port->ssl),
00363                                             (err == SSL_ERROR_WANT_READ) ?
00364                                     FD_READ | FD_CLOSE : FD_WRITE | FD_CLOSE,
00365                                             INFINITE);
00366 #endif
00367                 goto wloop;
00368             case SSL_ERROR_SYSCALL:
00369                 /* leave it to caller to ereport the value of errno */
00370                 if (n != -1)
00371                 {
00372                     errno = ECONNRESET;
00373                     n = -1;
00374                 }
00375                 break;
00376             case SSL_ERROR_SSL:
00377                 ereport(COMMERROR,
00378                         (errcode(ERRCODE_PROTOCOL_VIOLATION),
00379                          errmsg("SSL error: %s", SSLerrmessage())));
00380                 /* fall through */
00381             case SSL_ERROR_ZERO_RETURN:
00382                 errno = ECONNRESET;
00383                 n = -1;
00384                 break;
00385             default:
00386                 ereport(COMMERROR,
00387                         (errcode(ERRCODE_PROTOCOL_VIOLATION),
00388                          errmsg("unrecognized SSL error code: %d",
00389                                 err)));
00390                 n = -1;
00391                 break;
00392         }
00393     }
00394     else
00395 #endif
00396         n = send(port->sock, ptr, len, 0);
00397 
00398     return n;
00399 }
00400 
00401 /* ------------------------------------------------------------ */
00402 /*                        SSL specific code                     */
00403 /* ------------------------------------------------------------ */
00404 #ifdef USE_SSL
00405 
00406 /*
00407  * Private substitute BIO: this does the sending and receiving using send() and
00408  * recv() instead. This is so that we can enable and disable interrupts
00409  * just while calling recv(). We cannot have interrupts occurring while
00410  * the bulk of openssl runs, because it uses malloc() and possibly other
00411  * non-reentrant libc facilities. We also need to call send() and recv()
00412  * directly so it gets passed through the socket/signals layer on Win32.
00413  *
00414  * They are closely modelled on the original socket implementations in OpenSSL.
00415  */
00416 
00417 static bool my_bio_initialized = false;
00418 static BIO_METHOD my_bio_methods;
00419 
00420 static int
00421 my_sock_read(BIO *h, char *buf, int size)
00422 {
00423     int         res = 0;
00424 
00425     prepare_for_client_read();
00426 
00427     if (buf != NULL)
00428     {
00429         res = recv(h->num, buf, size, 0);
00430         BIO_clear_retry_flags(h);
00431         if (res <= 0)
00432         {
00433             /* If we were interrupted, tell caller to retry */
00434             if (errno == EINTR)
00435             {
00436                 BIO_set_retry_read(h);
00437             }
00438         }
00439     }
00440 
00441     client_read_ended();
00442 
00443     return res;
00444 }
00445 
00446 static int
00447 my_sock_write(BIO *h, const char *buf, int size)
00448 {
00449     int         res = 0;
00450 
00451     res = send(h->num, buf, size, 0);
00452     if (res <= 0)
00453     {
00454         if (errno == EINTR)
00455         {
00456             BIO_set_retry_write(h);
00457         }
00458     }
00459 
00460     return res;
00461 }
00462 
00463 static BIO_METHOD *
00464 my_BIO_s_socket(void)
00465 {
00466     if (!my_bio_initialized)
00467     {
00468         memcpy(&my_bio_methods, BIO_s_socket(), sizeof(BIO_METHOD));
00469         my_bio_methods.bread = my_sock_read;
00470         my_bio_methods.bwrite = my_sock_write;
00471         my_bio_initialized = true;
00472     }
00473     return &my_bio_methods;
00474 }
00475 
00476 /* This should exactly match openssl's SSL_set_fd except for using my BIO */
00477 static int
00478 my_SSL_set_fd(SSL *s, int fd)
00479 {
00480     int         ret = 0;
00481     BIO        *bio = NULL;
00482 
00483     bio = BIO_new(my_BIO_s_socket());
00484 
00485     if (bio == NULL)
00486     {
00487         SSLerr(SSL_F_SSL_SET_FD, ERR_R_BUF_LIB);
00488         goto err;
00489     }
00490     BIO_set_fd(bio, fd, BIO_NOCLOSE);
00491     SSL_set_bio(s, bio, bio);
00492     ret = 1;
00493 err:
00494     return ret;
00495 }
00496 
00497 /*
00498  *  Load precomputed DH parameters.
00499  *
00500  *  To prevent "downgrade" attacks, we perform a number of checks
00501  *  to verify that the DBA-generated DH parameters file contains
00502  *  what we expect it to contain.
00503  */
00504 static DH  *
00505 load_dh_file(int keylength)
00506 {
00507     FILE       *fp;
00508     char        fnbuf[MAXPGPATH];
00509     DH         *dh = NULL;
00510     int         codes;
00511 
00512     /* attempt to open file.  It's not an error if it doesn't exist. */
00513     snprintf(fnbuf, sizeof(fnbuf), "dh%d.pem", keylength);
00514     if ((fp = fopen(fnbuf, "r")) == NULL)
00515         return NULL;
00516 
00517 /*  flock(fileno(fp), LOCK_SH); */
00518     dh = PEM_read_DHparams(fp, NULL, NULL, NULL);
00519 /*  flock(fileno(fp), LOCK_UN); */
00520     fclose(fp);
00521 
00522     /* is the prime the correct size? */
00523     if (dh != NULL && 8 * DH_size(dh) < keylength)
00524     {
00525         elog(LOG, "DH errors (%s): %d bits expected, %d bits found",
00526              fnbuf, keylength, 8 * DH_size(dh));
00527         dh = NULL;
00528     }
00529 
00530     /* make sure the DH parameters are usable */
00531     if (dh != NULL)
00532     {
00533         if (DH_check(dh, &codes) == 0)
00534         {
00535             elog(LOG, "DH_check error (%s): %s", fnbuf, SSLerrmessage());
00536             return NULL;
00537         }
00538         if (codes & DH_CHECK_P_NOT_PRIME)
00539         {
00540             elog(LOG, "DH error (%s): p is not prime", fnbuf);
00541             return NULL;
00542         }
00543         if ((codes & DH_NOT_SUITABLE_GENERATOR) &&
00544             (codes & DH_CHECK_P_NOT_SAFE_PRIME))
00545         {
00546             elog(LOG,
00547                  "DH error (%s): neither suitable generator or safe prime",
00548                  fnbuf);
00549             return NULL;
00550         }
00551     }
00552 
00553     return dh;
00554 }
00555 
00556 /*
00557  *  Load hardcoded DH parameters.
00558  *
00559  *  To prevent problems if the DH parameters files don't even
00560  *  exist, we can load DH parameters hardcoded into this file.
00561  */
00562 static DH  *
00563 load_dh_buffer(const char *buffer, size_t len)
00564 {
00565     BIO        *bio;
00566     DH         *dh = NULL;
00567 
00568     bio = BIO_new_mem_buf((char *) buffer, len);
00569     if (bio == NULL)
00570         return NULL;
00571     dh = PEM_read_bio_DHparams(bio, NULL, NULL, NULL);
00572     if (dh == NULL)
00573         ereport(DEBUG2,
00574                 (errmsg_internal("DH load buffer: %s",
00575                                  SSLerrmessage())));
00576     BIO_free(bio);
00577 
00578     return dh;
00579 }
00580 
00581 /*
00582  *  Generate an ephemeral DH key.  Because this can take a long
00583  *  time to compute, we can use precomputed parameters of the
00584  *  common key sizes.
00585  *
00586  *  Since few sites will bother to precompute these parameter
00587  *  files, we also provide a fallback to the parameters provided
00588  *  by the OpenSSL project.
00589  *
00590  *  These values can be static (once loaded or computed) since
00591  *  the OpenSSL library can efficiently generate random keys from
00592  *  the information provided.
00593  */
00594 static DH  *
00595 tmp_dh_cb(SSL *s, int is_export, int keylength)
00596 {
00597     DH         *r = NULL;
00598     static DH  *dh = NULL;
00599     static DH  *dh512 = NULL;
00600     static DH  *dh1024 = NULL;
00601     static DH  *dh2048 = NULL;
00602     static DH  *dh4096 = NULL;
00603 
00604     switch (keylength)
00605     {
00606         case 512:
00607             if (dh512 == NULL)
00608                 dh512 = load_dh_file(keylength);
00609             if (dh512 == NULL)
00610                 dh512 = load_dh_buffer(file_dh512, sizeof file_dh512);
00611             r = dh512;
00612             break;
00613 
00614         case 1024:
00615             if (dh1024 == NULL)
00616                 dh1024 = load_dh_file(keylength);
00617             if (dh1024 == NULL)
00618                 dh1024 = load_dh_buffer(file_dh1024, sizeof file_dh1024);
00619             r = dh1024;
00620             break;
00621 
00622         case 2048:
00623             if (dh2048 == NULL)
00624                 dh2048 = load_dh_file(keylength);
00625             if (dh2048 == NULL)
00626                 dh2048 = load_dh_buffer(file_dh2048, sizeof file_dh2048);
00627             r = dh2048;
00628             break;
00629 
00630         case 4096:
00631             if (dh4096 == NULL)
00632                 dh4096 = load_dh_file(keylength);
00633             if (dh4096 == NULL)
00634                 dh4096 = load_dh_buffer(file_dh4096, sizeof file_dh4096);
00635             r = dh4096;
00636             break;
00637 
00638         default:
00639             if (dh == NULL)
00640                 dh = load_dh_file(keylength);
00641             r = dh;
00642     }
00643 
00644     /* this may take a long time, but it may be necessary... */
00645     if (r == NULL || 8 * DH_size(r) < keylength)
00646     {
00647         ereport(DEBUG2,
00648                 (errmsg_internal("DH: generating parameters (%d bits)",
00649                                  keylength)));
00650         r = DH_generate_parameters(keylength, DH_GENERATOR_2, NULL, NULL);
00651     }
00652 
00653     return r;
00654 }
00655 
00656 /*
00657  *  Certificate verification callback
00658  *
00659  *  This callback allows us to log intermediate problems during
00660  *  verification, but for now we'll see if the final error message
00661  *  contains enough information.
00662  *
00663  *  This callback also allows us to override the default acceptance
00664  *  criteria (e.g., accepting self-signed or expired certs), but
00665  *  for now we accept the default checks.
00666  */
00667 static int
00668 verify_cb(int ok, X509_STORE_CTX *ctx)
00669 {
00670     return ok;
00671 }
00672 
00673 /*
00674  *  This callback is used to copy SSL information messages
00675  *  into the PostgreSQL log.
00676  */
00677 static void
00678 info_cb(const SSL *ssl, int type, int args)
00679 {
00680     switch (type)
00681     {
00682         case SSL_CB_HANDSHAKE_START:
00683             ereport(DEBUG4,
00684                     (errmsg_internal("SSL: handshake start")));
00685             break;
00686         case SSL_CB_HANDSHAKE_DONE:
00687             ereport(DEBUG4,
00688                     (errmsg_internal("SSL: handshake done")));
00689             break;
00690         case SSL_CB_ACCEPT_LOOP:
00691             ereport(DEBUG4,
00692                     (errmsg_internal("SSL: accept loop")));
00693             break;
00694         case SSL_CB_ACCEPT_EXIT:
00695             ereport(DEBUG4,
00696                     (errmsg_internal("SSL: accept exit (%d)", args)));
00697             break;
00698         case SSL_CB_CONNECT_LOOP:
00699             ereport(DEBUG4,
00700                     (errmsg_internal("SSL: connect loop")));
00701             break;
00702         case SSL_CB_CONNECT_EXIT:
00703             ereport(DEBUG4,
00704                     (errmsg_internal("SSL: connect exit (%d)", args)));
00705             break;
00706         case SSL_CB_READ_ALERT:
00707             ereport(DEBUG4,
00708                     (errmsg_internal("SSL: read alert (0x%04x)", args)));
00709             break;
00710         case SSL_CB_WRITE_ALERT:
00711             ereport(DEBUG4,
00712                     (errmsg_internal("SSL: write alert (0x%04x)", args)));
00713             break;
00714     }
00715 }
00716 
00717 /*
00718  *  Initialize global SSL context.
00719  */
00720 static void
00721 initialize_SSL(void)
00722 {
00723     struct stat buf;
00724 
00725     STACK_OF(X509_NAME) *root_cert_list = NULL;
00726 
00727     if (!SSL_context)
00728     {
00729 #if SSLEAY_VERSION_NUMBER >= 0x0907000L
00730         OPENSSL_config(NULL);
00731 #endif
00732         SSL_library_init();
00733         SSL_load_error_strings();
00734         SSL_context = SSL_CTX_new(SSLv23_method());
00735         if (!SSL_context)
00736             ereport(FATAL,
00737                     (errmsg("could not create SSL context: %s",
00738                             SSLerrmessage())));
00739 
00740         /*
00741          * Disable OpenSSL's moving-write-buffer sanity check, because it
00742          * causes unnecessary failures in nonblocking send cases.
00743          */
00744         SSL_CTX_set_mode(SSL_context, SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER);
00745 
00746         /*
00747          * Load and verify server's certificate and private key
00748          */
00749         if (SSL_CTX_use_certificate_chain_file(SSL_context,
00750                                                ssl_cert_file) != 1)
00751             ereport(FATAL,
00752                     (errcode(ERRCODE_CONFIG_FILE_ERROR),
00753                   errmsg("could not load server certificate file \"%s\": %s",
00754                          ssl_cert_file, SSLerrmessage())));
00755 
00756         if (stat(ssl_key_file, &buf) != 0)
00757             ereport(FATAL,
00758                     (errcode_for_file_access(),
00759                      errmsg("could not access private key file \"%s\": %m",
00760                             ssl_key_file)));
00761 
00762         /*
00763          * Require no public access to key file.
00764          *
00765          * XXX temporarily suppress check when on Windows, because there may
00766          * not be proper support for Unix-y file permissions.  Need to think
00767          * of a reasonable check to apply on Windows.  (See also the data
00768          * directory permission check in postmaster.c)
00769          */
00770 #if !defined(WIN32) && !defined(__CYGWIN__)
00771         if (!S_ISREG(buf.st_mode) || buf.st_mode & (S_IRWXG | S_IRWXO))
00772             ereport(FATAL,
00773                     (errcode(ERRCODE_CONFIG_FILE_ERROR),
00774                   errmsg("private key file \"%s\" has group or world access",
00775                          ssl_key_file),
00776                    errdetail("Permissions should be u=rw (0600) or less.")));
00777 #endif
00778 
00779         if (SSL_CTX_use_PrivateKey_file(SSL_context,
00780                                         ssl_key_file,
00781                                         SSL_FILETYPE_PEM) != 1)
00782             ereport(FATAL,
00783                     (errmsg("could not load private key file \"%s\": %s",
00784                             ssl_key_file, SSLerrmessage())));
00785 
00786         if (SSL_CTX_check_private_key(SSL_context) != 1)
00787             ereport(FATAL,
00788                     (errmsg("check of private key failed: %s",
00789                             SSLerrmessage())));
00790     }
00791 
00792     /* set up ephemeral DH keys, and disallow SSL v2 while at it */
00793     SSL_CTX_set_tmp_dh_callback(SSL_context, tmp_dh_cb);
00794     SSL_CTX_set_options(SSL_context, SSL_OP_SINGLE_DH_USE | SSL_OP_NO_SSLv2);
00795 
00796     /* set up the allowed cipher list */
00797     if (SSL_CTX_set_cipher_list(SSL_context, SSLCipherSuites) != 1)
00798         elog(FATAL, "could not set the cipher list (no valid ciphers available)");
00799 
00800     /*
00801      * Load CA store, so we can verify client certificates if needed.
00802      */
00803     if (ssl_ca_file[0])
00804     {
00805         if (SSL_CTX_load_verify_locations(SSL_context, ssl_ca_file, NULL) != 1 ||
00806             (root_cert_list = SSL_load_client_CA_file(ssl_ca_file)) == NULL)
00807             ereport(FATAL,
00808                     (errmsg("could not load root certificate file \"%s\": %s",
00809                             ssl_ca_file, SSLerrmessage())));
00810     }
00811 
00812     /*----------
00813      * Load the Certificate Revocation List (CRL).
00814      * http://searchsecurity.techtarget.com/sDefinition/0,,sid14_gci803160,00.html
00815      *----------
00816      */
00817     if (ssl_crl_file[0])
00818     {
00819         X509_STORE *cvstore = SSL_CTX_get_cert_store(SSL_context);
00820 
00821         if (cvstore)
00822         {
00823             /* Set the flags to check against the complete CRL chain */
00824             if (X509_STORE_load_locations(cvstore, ssl_crl_file, NULL) == 1)
00825             {
00826                 /* OpenSSL 0.96 does not support X509_V_FLAG_CRL_CHECK */
00827 #ifdef X509_V_FLAG_CRL_CHECK
00828                 X509_STORE_set_flags(cvstore,
00829                           X509_V_FLAG_CRL_CHECK | X509_V_FLAG_CRL_CHECK_ALL);
00830 #else
00831                 ereport(LOG,
00832                 (errmsg("SSL certificate revocation list file \"%s\" ignored",
00833                         ssl_crl_file),
00834                  errdetail("SSL library does not support certificate revocation lists.")));
00835 #endif
00836             }
00837             else
00838                 ereport(FATAL,
00839                         (errmsg("could not load SSL certificate revocation list file \"%s\": %s",
00840                                 ssl_crl_file, SSLerrmessage())));
00841         }
00842     }
00843 
00844     if (ssl_ca_file[0])
00845     {
00846         /*
00847          * Always ask for SSL client cert, but don't fail if it's not
00848          * presented.  We might fail such connections later, depending on what
00849          * we find in pg_hba.conf.
00850          */
00851         SSL_CTX_set_verify(SSL_context,
00852                            (SSL_VERIFY_PEER |
00853                             SSL_VERIFY_CLIENT_ONCE),
00854                            verify_cb);
00855 
00856         /* Set flag to remember CA store is successfully loaded */
00857         ssl_loaded_verify_locations = true;
00858 
00859         /*
00860          * Tell OpenSSL to send the list of root certs we trust to clients in
00861          * CertificateRequests.  This lets a client with a keystore select the
00862          * appropriate client certificate to send to us.
00863          */
00864         SSL_CTX_set_client_CA_list(SSL_context, root_cert_list);
00865     }
00866 }
00867 
00868 /*
00869  *  Attempt to negotiate SSL connection.
00870  */
00871 static int
00872 open_server_SSL(Port *port)
00873 {
00874     int         r;
00875     int         err;
00876 
00877     Assert(!port->ssl);
00878     Assert(!port->peer);
00879 
00880     if (!(port->ssl = SSL_new(SSL_context)))
00881     {
00882         ereport(COMMERROR,
00883                 (errcode(ERRCODE_PROTOCOL_VIOLATION),
00884                  errmsg("could not initialize SSL connection: %s",
00885                         SSLerrmessage())));
00886         close_SSL(port);
00887         return -1;
00888     }
00889     if (!my_SSL_set_fd(port->ssl, port->sock))
00890     {
00891         ereport(COMMERROR,
00892                 (errcode(ERRCODE_PROTOCOL_VIOLATION),
00893                  errmsg("could not set SSL socket: %s",
00894                         SSLerrmessage())));
00895         close_SSL(port);
00896         return -1;
00897     }
00898 
00899 aloop:
00900     r = SSL_accept(port->ssl);
00901     if (r <= 0)
00902     {
00903         err = SSL_get_error(port->ssl, r);
00904         switch (err)
00905         {
00906             case SSL_ERROR_WANT_READ:
00907             case SSL_ERROR_WANT_WRITE:
00908 #ifdef WIN32
00909                 pgwin32_waitforsinglesocket(SSL_get_fd(port->ssl),
00910                                             (err == SSL_ERROR_WANT_READ) ?
00911                         FD_READ | FD_CLOSE | FD_ACCEPT : FD_WRITE | FD_CLOSE,
00912                                             INFINITE);
00913 #endif
00914                 goto aloop;
00915             case SSL_ERROR_SYSCALL:
00916                 if (r < 0)
00917                     ereport(COMMERROR,
00918                             (errcode_for_socket_access(),
00919                              errmsg("could not accept SSL connection: %m")));
00920                 else
00921                     ereport(COMMERROR,
00922                             (errcode(ERRCODE_PROTOCOL_VIOLATION),
00923                     errmsg("could not accept SSL connection: EOF detected")));
00924                 break;
00925             case SSL_ERROR_SSL:
00926                 ereport(COMMERROR,
00927                         (errcode(ERRCODE_PROTOCOL_VIOLATION),
00928                          errmsg("could not accept SSL connection: %s",
00929                                 SSLerrmessage())));
00930                 break;
00931             case SSL_ERROR_ZERO_RETURN:
00932                 ereport(COMMERROR,
00933                         (errcode(ERRCODE_PROTOCOL_VIOLATION),
00934                    errmsg("could not accept SSL connection: EOF detected")));
00935                 break;
00936             default:
00937                 ereport(COMMERROR,
00938                         (errcode(ERRCODE_PROTOCOL_VIOLATION),
00939                          errmsg("unrecognized SSL error code: %d",
00940                                 err)));
00941                 break;
00942         }
00943         close_SSL(port);
00944         return -1;
00945     }
00946 
00947     port->count = 0;
00948 
00949     /* Get client certificate, if available. */
00950     port->peer = SSL_get_peer_certificate(port->ssl);
00951 
00952     /* and extract the Common Name from it. */
00953     port->peer_cn = NULL;
00954     if (port->peer != NULL)
00955     {
00956         int         len;
00957 
00958         len = X509_NAME_get_text_by_NID(X509_get_subject_name(port->peer),
00959                                         NID_commonName, NULL, 0);
00960         if (len != -1)
00961         {
00962             char       *peer_cn;
00963 
00964             peer_cn = MemoryContextAlloc(TopMemoryContext, len + 1);
00965             r = X509_NAME_get_text_by_NID(X509_get_subject_name(port->peer),
00966                                           NID_commonName, peer_cn, len + 1);
00967             peer_cn[len] = '\0';
00968             if (r != len)
00969             {
00970                 /* shouldn't happen */
00971                 pfree(peer_cn);
00972                 close_SSL(port);
00973                 return -1;
00974             }
00975 
00976             /*
00977              * Reject embedded NULLs in certificate common name to prevent
00978              * attacks like CVE-2009-4034.
00979              */
00980             if (len != strlen(peer_cn))
00981             {
00982                 ereport(COMMERROR,
00983                         (errcode(ERRCODE_PROTOCOL_VIOLATION),
00984                          errmsg("SSL certificate's common name contains embedded null")));
00985                 pfree(peer_cn);
00986                 close_SSL(port);
00987                 return -1;
00988             }
00989 
00990             port->peer_cn = peer_cn;
00991         }
00992     }
00993 
00994     ereport(DEBUG2,
00995             (errmsg("SSL connection from \"%s\"",
00996                     port->peer_cn ? port->peer_cn : "(anonymous)")));
00997 
00998     /* set up debugging/info callback */
00999     SSL_CTX_set_info_callback(SSL_context, info_cb);
01000 
01001     return 0;
01002 }
01003 
01004 /*
01005  *  Close SSL connection.
01006  */
01007 static void
01008 close_SSL(Port *port)
01009 {
01010     if (port->ssl)
01011     {
01012         SSL_shutdown(port->ssl);
01013         SSL_free(port->ssl);
01014         port->ssl = NULL;
01015     }
01016 
01017     if (port->peer)
01018     {
01019         X509_free(port->peer);
01020         port->peer = NULL;
01021     }
01022 
01023     if (port->peer_cn)
01024     {
01025         pfree(port->peer_cn);
01026         port->peer_cn = NULL;
01027     }
01028 }
01029 
01030 /*
01031  * Obtain reason string for last SSL error
01032  *
01033  * Some caution is needed here since ERR_reason_error_string will
01034  * return NULL if it doesn't recognize the error code.  We don't
01035  * want to return NULL ever.
01036  */
01037 static const char *
01038 SSLerrmessage(void)
01039 {
01040     unsigned long errcode;
01041     const char *errreason;
01042     static char errbuf[32];
01043 
01044     errcode = ERR_get_error();
01045     if (errcode == 0)
01046         return _("no SSL error reported");
01047     errreason = ERR_reason_error_string(errcode);
01048     if (errreason != NULL)
01049         return errreason;
01050     snprintf(errbuf, sizeof(errbuf), _("SSL error code %lu"), errcode);
01051     return errbuf;
01052 }
01053 
01054 #endif   /* USE_SSL */