]> granicus.if.org Git - postgresql/blob - src/interfaces/libpq/fe-secure.c
SSL support for ephemeral DH keys.
[postgresql] / src / interfaces / libpq / fe-secure.c
1 /*-------------------------------------------------------------------------
2  *
3  * fe-connect.c
4  *        functions related to setting up a secure connection to the backend.
5  *        Secure connections are expected to provide confidentiality,
6  *        message integrity and endpoint authentication.
7  *
8  *
9  * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
10  * Portions Copyright (c) 1994, Regents of the University of California
11  *
12  *
13  * IDENTIFICATION
14  *        $Header: /cvsroot/pgsql/src/interfaces/libpq/fe-secure.c,v 1.2 2002/06/14 04:31:49 momjian Exp $
15  *        
16  * NOTES
17  *        The client *requires* a valid server certificate.  Since
18  *        SSH tunnels provide anonymous confidentiality, the presumption
19  *        is that sites that want endpoint authentication will use the
20  *        direct SSL support, while sites that are comfortable with
21  *        anonymous connections will use SSH tunnels.
22  *
23  *        This code verifies the server certificate, to detect simple
24  *        "man-in-the-middle" and "impersonation" attacks.  The 
25  *        server certificate, or better yet the CA certificate used
26  *        to sign the server certificate, should be present in the
27  *        "$HOME/.postgresql/root.crt" file.  If this file isn't
28  *        readable, or the server certificate can't be validated, 
29  *        secure_open_client() will return an error code.
30  *
31  *        Additionally, the server certificate's "common name" must
32  *        resolve to the other end of the socket.  This makes it
33  *        substantially harder to pull off a "man-in-the-middle" or
34  *        "impersonation" attack even if the server's private key
35  *        has been stolen.  This check limits acceptable network
36  *        layers to Unix sockets (weird, but legal), TCPv4 and TCPv6.
37  *
38  *        Unfortunately neither the current front- or back-end handle
39  *        failure gracefully, resulting in the backend hiccupping.
40  *        This points out problems in each (the frontend shouldn't even
41  *        try to do SSL if secure_initialize() fails, and the backend
42  *        shouldn't crash/recover if an SSH negotiation fails.  The 
43  *        backend definitely needs to be fixed, to prevent a "denial
44  *        of service" attack, but I don't know enough about how the 
45  *        backend works (especially that pre-SSL negotiation) to identify
46  *        a fix.
47  *
48  *        ...
49  *
50  *        Unlike the server's static private key, the client's
51  *        static private key ($HOME/.postgresql/postgresql.key)
52  *        should normally be stored encrypted.  However we still
53  *        support EPH since it's useful for other reasons.
54  *
55  * OS DEPENDENCIES
56  *        The code currently assumes a POSIX password entry.  How should
57  *        Windows and Mac users be handled?
58  *
59  * PATCH LEVEL
60  *        milestone 1: fix basic coding errors
61  *        [*] existing SSL code pulled out of existing files.
62  *        [*] SSL_get_error() after SSL_read() and SSL_write(),
63  *            SSL_shutdown(), default to TLSv1.
64  *      
65  *        milestone 2: provide endpoint authentication (server)
66  *        [*] client verifies server cert
67  *        [*] client verifies server hostname
68  *
69  *        milestone 3: improve confidentially, support perfect forward secrecy
70  *        [ ] use 'random' file, read from '/dev/urandom?'
71  *        [*] emphermal DH keys, default values
72  *
73  *        milestone 4: provide endpoint authentication (client)
74  *        [ ] server verifies client certificates
75  *
76  *        milestone 5: provide informational callbacks
77  *        [ ] provide informational callbacks
78  *
79  *        other changes
80  *        [ ] tcp-wrappers
81  *        [ ] more informative psql
82  *
83  *-------------------------------------------------------------------------
84  */
85
86 #include "postgres_fe.h"
87
88 #include <sys/types.h>
89 #include <signal.h>
90 #include <fcntl.h>
91 #include <errno.h>
92 #include <ctype.h>
93 #include <string.h>
94
95 #include "libpq-fe.h"
96 #include "libpq-int.h"
97 #include "fe-auth.h"
98 #include "pqsignal.h"
99
100 #ifdef WIN32
101 #include "win32.h"
102 #else
103 #include <sys/socket.h>
104 #include <unistd.h>
105 #include <netdb.h>
106 #include <netinet/in.h>
107 #ifdef HAVE_NETINET_TCP_H
108 #include <netinet/tcp.h>
109 #endif
110 #include <arpa/inet.h>
111 #endif
112
113 #ifndef HAVE_STRDUP
114 #include "strdup.h"
115 #endif
116
117 #include <pwd.h>
118 #include <sys/stat.h>
119
120 #ifdef USE_SSL
121 #include <openssl/ssl.h>
122 #include <openssl/e_os.h>
123 #endif /* USE_SSL */
124
125 int secure_initialize(PGconn *);
126 void secure_destroy(void);
127 int secure_open_client(PGconn *);
128 void secure_close(PGconn *);
129 ssize_t secure_read(PGconn *, void *ptr, size_t len);
130 ssize_t secure_write(PGconn *, const void *ptr, size_t len);
131
132 #ifdef USE_SSL
133 static int verify_cb(int ok, X509_STORE_CTX *ctx);
134 static int verify_peer(PGconn *);
135 static DH *load_dh_file(int keylength);
136 static DH *load_dh_buffer(const char *, size_t);
137 static DH *tmp_dh_cb(SSL *s, int is_export, int keylength);
138 static int initialize_SSL(PGconn *);
139 static void destroy_SSL(void);
140 static int open_client_SSL(PGconn *);
141 static void close_SSL(PGconn *);
142 static const char *SSLerrmessage(void);
143 #endif
144
145 #ifdef USE_SSL
146 static SSL_CTX *SSL_context = NULL;
147 #endif
148
149 /* ------------------------------------------------------------ */
150 /*                       Hardcoded values                       */
151 /* ------------------------------------------------------------ */
152
153 /*
154  *      Hardcoded DH parameters, used in empheral DH keying.
155  *      As discussed above, EDH protects the confidentiality of
156  *      sessions even if the static private key is compromised,
157  *      so we are *highly* motivated to ensure that we can use
158  *      EDH even if the user... or an attacker... deletes the 
159  *      $HOME/.postgresql/dh*.pem files.
160  *
161  *      It's not critical that users have EPH keys, but it doesn't
162  *      hurt and if it's missing someone will demand it, so....
163  */
164 static const char file_dh512[] =
165 "-----BEGIN DH PARAMETERS-----\n\
166 MEYCQQD1Kv884bEpQBgRjXyEpwpy1obEAxnIByl6ypUM2Zafq9AKUJsCRtMIPWak\n\
167 XUGfnHy9iUsiGSa6q6Jew1XpKgVfAgEC\n\
168 -----END DH PARAMETERS-----\n";
169
170 static const char file_dh1024[] =
171 "-----BEGIN DH PARAMETERS-----\n\
172 MIGHAoGBAPSI/VhOSdvNILSd5JEHNmszbDgNRR0PfIizHHxbLY7288kjwEPwpVsY\n\
173 jY67VYy4XTjTNP18F1dDox0YbN4zISy1Kv884bEpQBgRjXyEpwpy1obEAxnIByl6\n\
174 ypUM2Zafq9AKUJsCRtMIPWakXUGfnHy9iUsiGSa6q6Jew1XpL3jHAgEC\n\
175 -----END DH PARAMETERS-----\n";
176
177 static const char file_dh2048[] =
178 "-----BEGIN DH PARAMETERS-----\n\
179 MIIBCAKCAQEA9kJXtwh/CBdyorrWqULzBej5UxE5T7bxbrlLOCDaAadWoxTpj0BV\n\
180 89AHxstDqZSt90xkhkn4DIO9ZekX1KHTUPj1WV/cdlJPPT2N286Z4VeSWc39uK50\n\
181 T8X8dryDxUcwYc58yWb/Ffm7/ZFexwGq01uejaClcjrUGvC/RgBYK+X0iP1YTknb\n\
182 zSC0neSRBzZrM2w4DUUdD3yIsxx8Wy2O9vPJI8BD8KVbGI2Ou1WMuF040zT9fBdX\n\
183 Q6MdGGzeMyEstSr/POGxKUAYEY18hKcKctaGxAMZyAcpesqVDNmWn6vQClCbAkbT\n\
184 CD1mpF1Bn5x8vYlLIhkmuquiXsNV6TILOwIBAg==\n\
185 -----END DH PARAMETERS-----\n";
186
187 static const char file_dh4096[] =
188 "-----BEGIN DH PARAMETERS-----\n\
189 MIICCAKCAgEA+hRyUsFN4VpJ1O8JLcCo/VWr19k3BCgJ4uk+d+KhehjdRqNDNyOQ\n\
190 l/MOyQNQfWXPeGKmOmIig6Ev/nm6Nf9Z2B1h3R4hExf+zTiHnvVPeRBhjdQi81rt\n\
191 Xeoh6TNrSBIKIHfUJWBh3va0TxxjQIs6IZOLeVNRLMqzeylWqMf49HsIXqbcokUS\n\
192 Vt1BkvLdW48j8PPv5DsKRN3tloTxqDJGo9tKvj1Fuk74A+Xda1kNhB7KFlqMyN98\n\
193 VETEJ6c7KpfOo30mnK30wqw3S8OtaIR/maYX72tGOno2ehFDkq3pnPtEbD2CScxc\n\
194 alJC+EL7RPk5c/tgeTvCngvc1KZn92Y//EI7G9tPZtylj2b56sHtMftIoYJ9+ODM\n\
195 sccD5Piz/rejE3Ome8EOOceUSCYAhXn8b3qvxVI1ddd1pED6FHRhFvLrZxFvBEM9\n\
196 ERRMp5QqOaHJkM+Dxv8Cj6MqrCbfC4u+ZErxodzuusgDgvZiLF22uxMZbobFWyte\n\
197 OvOzKGtwcTqO/1wV5gKkzu1ZVswVUQd5Gg8lJicwqRWyyNRczDDoG9jVDxmogKTH\n\
198 AaqLulO7R8Ifa1SwF2DteSGVtgWEN8gDpN3RBmmPTDngyF2DHb5qmpnznwtFKdTL\n\
199 KWbuHn491xNO25CQWMtem80uKw+pTnisBRF/454n1Jnhub144YRBoN8CAQI=\n\
200 -----END DH PARAMETERS-----\n";
201
202 /* ------------------------------------------------------------ */
203 /*           Procedures common to all secure sessions           */
204 /* ------------------------------------------------------------ */
205
206 /*
207  *      Initialize global context
208  */
209 int
210 secure_initialize (PGconn *conn)
211 {
212         int r = 0;
213
214 #ifdef USE_SSL
215         r = initialize_SSL(conn);
216 #endif
217
218         return r;
219 }
220
221 /*
222  *      Destroy global context
223  */
224 void
225 secure_destroy (void)
226 {
227 #ifdef USE_SSL
228         destroy_SSL();
229 #endif
230 }
231
232 /*
233  *      Attempt to negotiate secure session.
234  */
235 int 
236 secure_open_client (PGconn *conn)
237 {
238         int r = 0;
239
240 #ifdef USE_SSL
241         r = open_client_SSL(conn);
242 #endif
243
244         return r;
245 }
246
247 /*
248  *      Close secure session.
249  */
250 void
251 secure_close (PGconn *conn)
252 {
253 #ifdef USE_SSL
254         if (conn->ssl)
255                 close_SSL(conn);
256 #endif
257 }
258
259 /*
260  *      Read data from a secure connection.
261  */
262 ssize_t
263 secure_read (PGconn *conn, void *ptr, size_t len)
264 {
265         ssize_t n;
266
267 #ifdef USE_SSL
268         if (conn->ssl)
269         {
270                 n = SSL_read(conn->ssl, ptr, len);
271                 switch (SSL_get_error(conn->ssl, n))
272                 {
273                 case SSL_ERROR_NONE:
274                         break;
275                 case SSL_ERROR_WANT_READ:
276                         break;
277                 case SSL_ERROR_SYSCALL:
278                         SOCK_ERRNO = get_last_socket_error();
279                         printfPQExpBuffer(&conn->errorMessage,
280                                 libpq_gettext("SSL SYSCALL error: %s\n"), 
281                                 SOCK_STRERROR(SOCK_ERRNO));
282                         break;
283                 case SSL_ERROR_SSL:
284                         printfPQExpBuffer(&conn->errorMessage,
285                                 libpq_gettext("SSL error: %s\n"), SSLerrmessage());
286                         /* fall through */
287                 case SSL_ERROR_ZERO_RETURN:
288                         secure_close(conn);
289                         SOCK_ERRNO = ECONNRESET;
290                         n = -1;
291                         break;
292                 }
293         }
294         else
295 #endif
296         n = recv(conn->sock, ptr, len, 0);
297
298         return n;
299 }
300
301 /*
302  *      Write data to a secure connection.
303  */
304 ssize_t
305 secure_write (PGconn *conn, const void *ptr, size_t len)
306 {
307         ssize_t n;
308
309 #ifndef WIN32
310         pqsigfunc oldsighandler = pqsignal(SIGPIPE, SIG_IGN);
311 #endif
312
313 #ifdef USE_SSL
314         if (conn->ssl)
315         {
316                 n = SSL_write(conn->ssl, ptr, len);
317                 switch (SSL_get_error(conn->ssl, n))
318                 {
319                 case SSL_ERROR_NONE:
320                         break;
321                 case SSL_ERROR_WANT_WRITE:
322                         break;
323                 case SSL_ERROR_SYSCALL:
324                         SOCK_ERRNO = get_last_socket_error();
325                         printfPQExpBuffer(&conn->errorMessage,
326                                 libpq_gettext("SSL SYSCALL error: %s\n"),
327                                 SOCK_STRERROR(SOCK_ERRNO));
328                         break;
329                 case SSL_ERROR_SSL:
330                         printfPQExpBuffer(&conn->errorMessage,
331                                 libpq_gettext("SSL error: %s\n"), SSLerrmessage());
332                         /* fall through */
333                 case SSL_ERROR_ZERO_RETURN:
334                         secure_close(conn);
335                         SOCK_ERRNO = ECONNRESET;
336                         n = -1;
337                         break;
338                 }
339         }
340         else
341 #endif
342         n = send(conn->sock, ptr, len, 0);
343
344 #ifndef WIN32
345         pqsignal(SIGPIPE, oldsighandler);
346 #endif
347
348         return n;
349 }
350
351 /* ------------------------------------------------------------ */
352 /*                        SSL specific code                     */
353 /* ------------------------------------------------------------ */
354 #ifdef USE_SSL
355 /*
356  *      Certificate verification callback
357  *
358  *      This callback allows us to log intermediate problems during
359  *      verification, but there doesn't seem to be a clean way to get
360  *      our PGconn * structure.  So we can't log anything!
361  *
362  *      This callback also allows us to override the default acceptance
363  *      criteria (e.g., accepting self-signed or expired certs), but
364  *      for now we accept the default checks.
365  */
366 static int
367 verify_cb (int ok, X509_STORE_CTX *ctx)
368 {
369         return ok;
370 }
371
372 /*
373  *      Verify that common name resolves to peer.
374  *      This function is not thread-safe due to gethostbyname2().
375  */
376 static int
377 verify_peer (PGconn *conn)
378 {
379         struct hostent *h = NULL;
380         struct sockaddr addr;
381         struct sockaddr_in *sin;
382         struct sockaddr_in6 *sin6;
383         socklen_t len;
384         char **s;
385         unsigned long l;
386
387         /* get the address on the other side of the socket */
388         len = sizeof(addr);
389         if (getpeername(conn->sock, &addr, &len) == -1)
390         {
391                 printfPQExpBuffer(&conn->errorMessage,
392                         libpq_gettext("error querying socket: %s\n"), 
393                         SOCK_STRERROR(SOCK_ERRNO));
394                 return -1;
395         }
396
397         /* weird, but legal case */
398         if (addr.sa_family == AF_UNIX)
399                 return 0;
400
401         /* what do we know about the peer's common name? */
402         if ((h = gethostbyname2(conn->peer_cn, addr.sa_family)) == NULL)
403         {
404                 printfPQExpBuffer(&conn->errorMessage,
405                         libpq_gettext("error getting information about host (%s): %s\n"),
406                         conn->peer_cn, hstrerror(h_errno));
407                 return -1;
408         }
409
410         /* does the address match? */
411         switch (addr.sa_family)
412         {
413         case AF_INET:
414                 sin = (struct sockaddr_in *) &addr;
415                 for (s = h->h_addr_list; *s != NULL; s++)
416                 {
417                         if (!memcmp(&sin->sin_addr.s_addr, *s, h->h_length))
418                                 return 0;
419                 }
420                 break;
421
422         case AF_INET6:
423                 sin6 = (struct sockaddr_in6 *) &addr;
424                 for (s = h->h_addr_list; *s != NULL; s++)
425                 {
426                         if (!memcmp(sin6->sin6_addr.in6_u.u6_addr8, *s, h->h_length))
427                                 return 0;
428                 }
429                 break;
430
431         default:
432                 printfPQExpBuffer(&conn->errorMessage,
433                         libpq_gettext("sorry, this protocol not yet supported\n"));
434                 return -1;
435         }
436
437         /* the prior test should be definitive, but in practice
438          * it sometimes fails.  So we also check the aliases.  */
439         for (s = h->h_aliases; *s != NULL; s++)
440         {
441                 if (strcasecmp(conn->peer_cn, *s) == 0)
442                         return 0;
443         }
444
445         /* generate protocol-aware error message */
446         switch (addr.sa_family)
447         {
448         case AF_INET:
449                 sin = (struct sockaddr_in *) &addr;
450                 l = ntohl(sin->sin_addr.s_addr);
451                 printfPQExpBuffer(&conn->errorMessage,
452                         libpq_gettext(
453                                 "server common name '%s' does not resolve to %ld.%ld.%ld.%ld\n"),
454                         conn->peer_cn, (l >> 24) % 0x100, (l >> 16) % 0x100,
455                         (l >> 8) % 0x100, l % 0x100);
456                 break;
457         default:
458                 printfPQExpBuffer(&conn->errorMessage,
459                         libpq_gettext(
460                                 "server common name '%s' does not resolve to peer address\n"),
461                         conn->peer_cn);
462         }
463
464         return -1;
465 }
466
467 /*
468  *      Load precomputed DH parameters.
469  *
470  *      To prevent "downgrade" attacks, we perform a number of checks
471  *      to verify that the DBA-generated DH parameters file contains 
472  *      what we expect it to contain.
473  */
474 static DH *
475 load_dh_file (int keylength)
476 {
477         struct passwd *pwd;
478         FILE *fp;
479         char fnbuf[2048];
480         DH *dh = NULL;
481         int codes;
482
483         if ((pwd = getpwuid(getuid())) == NULL)
484                 return NULL;
485
486         /* attempt to open file.  It's not an error if it doesn't exist. */
487         snprintf(fnbuf, sizeof fnbuf, "%s/.postgresql/dh%d.pem",
488                 pwd->pw_dir, keylength);
489         if ((fp = fopen(fnbuf, "r")) == NULL)
490                 return NULL;
491
492 /*      flock(fileno(fp), LOCK_SH); */
493         dh = PEM_read_DHparams(fp, NULL, NULL, NULL);
494 /*      flock(fileno(fp), LOCK_UN); */
495         fclose(fp);
496
497         /* is the prime the correct size? */
498         if (dh != NULL && 8*DH_size(dh) < keylength)
499         {
500                 dh = NULL;
501         }
502
503         /* make sure the DH parameters are usable */
504         if (dh != NULL)
505         {
506                 if (DH_check(dh, &codes))
507                 {
508                         return NULL;
509                 }
510                 if (codes & DH_CHECK_P_NOT_PRIME)
511                 {
512                         return NULL;
513                 }
514                 if ((codes & DH_NOT_SUITABLE_GENERATOR) && 
515                         (codes & DH_CHECK_P_NOT_SAFE_PRIME))
516                 {
517                         return NULL;
518                 }
519         }
520
521         return dh;
522 }
523
524 /*
525  *      Load hardcoded DH parameters.
526  *
527  *      To prevent problems if the DH parameters files don't even
528  *      exist, we can load DH parameters hardcoded into this file.
529  */
530 static DH *
531 load_dh_buffer (const char *buffer, size_t len)
532 {
533         BIO *bio;
534         DH *dh = NULL;
535
536         bio = BIO_new_mem_buf((char *) buffer, len);
537         if (bio == NULL)
538                 return NULL;
539         dh = PEM_read_bio_DHparams(bio, NULL, NULL, NULL);
540         BIO_free(bio);
541
542         return dh;
543 }
544
545 /*
546  *      Generate an empheral DH key.  Because this can take a long
547  *      time to compute, we can use precomputed parameters of the
548  *      common key sizes.
549  *
550  *      Since few sites will bother to precompute these parameter
551  *      files, we also provide a fallback to the parameters provided
552  *      by the OpenSSL project.
553  *
554  *      These values can be static (once loaded or computed) since
555  *      the OpenSSL library can efficiently generate random keys from
556  *      the information provided.
557  */
558 static DH *
559 tmp_dh_cb (SSL *s, int is_export, int keylength)
560 {
561         DH *r = NULL;
562         static DH *dh = NULL;
563         static DH *dh512 = NULL;
564         static DH *dh1024 = NULL;
565         static DH *dh2048 = NULL;
566         static DH *dh4096 = NULL;
567
568         switch (keylength)
569         {
570         case 512:
571                 if (dh512 == NULL)
572                         dh512 = load_dh_file(keylength);
573                 if (dh512 == NULL)
574                         dh512 = load_dh_buffer(file_dh512, sizeof file_dh512);
575                 r = dh512;
576                 break;
577
578         case 1024:
579                 if (dh1024 == NULL)
580                         dh1024 = load_dh_file(keylength);
581                 if (dh1024 == NULL)
582                         dh1024 = load_dh_buffer(file_dh1024, sizeof file_dh1024);
583                 r = dh1024;
584                 break;
585
586         case 2048:
587                 if (dh2048 == NULL)
588                         dh2048 = load_dh_file(keylength);
589                 if (dh2048 == NULL)
590                         dh2048 = load_dh_buffer(file_dh2048, sizeof file_dh2048);
591                 r = dh2048;
592                 break;
593
594         case 4096:
595                 if (dh4096 == NULL)
596                         dh4096 = load_dh_file(keylength);
597                 if (dh4096 == NULL)
598                         dh4096 = load_dh_buffer(file_dh4096, sizeof file_dh4096);
599                 r = dh4096;
600                 break;
601
602         default:
603                 if (dh == NULL)
604                         dh = load_dh_file(keylength);
605                 r = dh;
606         }
607
608         /* this may take a long time, but it may be necessary... */
609         if (r == NULL || 8*DH_size(r) < keylength)
610         {
611                 r = DH_generate_parameters(keylength, DH_GENERATOR_2, NULL, NULL);
612         }
613         
614         return r;
615 }
616
617 /*
618  *      Initialize global SSL context.
619  */
620 static int
621 initialize_SSL (PGconn *conn)
622 {
623         struct stat buf;
624         struct passwd *pwd;
625         char fnbuf[2048];
626
627         if (!SSL_context)
628         {
629                 SSL_library_init();
630                 SSL_load_error_strings();
631                 SSL_context = SSL_CTX_new(TLSv1_method());
632                 if (!SSL_context)
633                 {
634                         printfPQExpBuffer(&conn->errorMessage,
635                                 libpq_gettext("could not create SSL context: %s\n"),
636                                                           SSLerrmessage());
637                         return -1;
638                 }
639         }
640
641         if ((pwd = getpwuid(getuid())) != NULL)
642         {
643                 snprintf(fnbuf, sizeof fnbuf, "%s/.postgresql/root.crt",
644                         pwd->pw_dir);
645                 if (stat(fnbuf, &buf) == -1)
646                 {
647                         printfPQExpBuffer(&conn->errorMessage,
648                                 libpq_gettext("could not read  root cert list(%s): %s"),
649                                 fnbuf, strerror(errno));
650                         return -1;
651                 }
652                 if (!SSL_CTX_load_verify_locations(SSL_context, fnbuf, 0))
653                 {
654                         printfPQExpBuffer(&conn->errorMessage,
655                                 libpq_gettext("could not read root cert list (%s): %s"),
656                                 fnbuf, SSLerrmessage());
657                         return -1;
658                 }
659         }
660
661         SSL_CTX_set_verify(SSL_context, 
662                 SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT, verify_cb);
663         SSL_CTX_set_verify_depth(SSL_context, 1);
664
665         /* set up empheral DH keys */
666         SSL_CTX_set_tmp_dh_callback(SSL_context, tmp_dh_cb);
667         SSL_CTX_set_options(SSL_context, SSL_OP_SINGLE_DH_USE);
668
669         return 0;
670 }
671
672 /*
673  *      Destroy global SSL context.
674  */
675 static void
676 destroy_SSL (void)
677 {
678         if (SSL_context)
679         {
680                 SSL_CTX_free(SSL_context);
681                 SSL_context = NULL;
682         }
683 }
684
685 /*
686  *      Attempt to negotiate SSL connection.
687  */
688 static int
689 open_client_SSL (PGconn *conn)
690 {
691         int r;
692
693         if (!(conn->ssl = SSL_new(SSL_context)) ||
694                 !SSL_set_fd(conn->ssl, conn->sock) ||
695                 SSL_connect(conn->ssl) <= 0)
696         {
697                 printfPQExpBuffer(&conn->errorMessage,
698                         libpq_gettext("could not establish SSL connection: %s\n"),
699                                                   SSLerrmessage());
700                 close_SSL(conn);
701                 return -1;
702         }
703
704         /* check the certificate chain of the server */
705         /* this eliminates simple man-in-the-middle attacks and
706          * simple impersonations */
707         r = SSL_get_verify_result(conn->ssl);
708         if (r != X509_V_OK)
709         {
710                 printfPQExpBuffer(&conn->errorMessage,
711                         libpq_gettext("certificate could not be validated: %s\n"),
712                         X509_verify_cert_error_string(r));
713                 close_SSL(conn);
714                 return -1;
715         }
716
717         /* pull out server distinguished and common names */
718         conn->peer = SSL_get_peer_certificate(conn->ssl);
719         if (conn->peer == NULL)
720         {
721                 printfPQExpBuffer(&conn->errorMessage,
722                         libpq_gettext("certificate could not be obtained: %s\n"),
723                         SSLerrmessage());
724                 close_SSL(conn);
725                 return -1;
726         }
727
728         X509_NAME_oneline(X509_get_subject_name(conn->peer),
729                 conn->peer_dn, sizeof(conn->peer_dn));
730         conn->peer_dn[sizeof(conn->peer_dn)-1] = '\0';
731
732         X509_NAME_get_text_by_NID(X509_get_subject_name(conn->peer),
733                 NID_commonName, conn->peer_cn, SM_USER);
734         conn->peer_cn[SM_USER] = '\0';
735
736         /* verify that the common name resolves to peer */
737         /* this is necessary to eliminate man-in-the-middle attacks
738          * and impersonations where the attacker somehow learned
739          * the server's private key */
740         if (verify_peer(conn) == -1)
741         {
742                 close_SSL(conn);
743                 return -1;
744         }
745
746         return 0;
747 }
748
749 /*
750  *      Close SSL connection.
751  */
752 static void
753 close_SSL (PGconn *conn)
754 {
755         if (conn->ssl)
756         {
757                 SSL_shutdown(conn->ssl);
758                 SSL_free(conn->ssl);
759                 conn->ssl = NULL;
760         }
761 }
762
763 /*
764  * Obtain reason string for last SSL error
765  *
766  * Some caution is needed here since ERR_reason_error_string will
767  * return NULL if it doesn't recognize the error code.  We don't
768  * want to return NULL ever.
769  */
770 static const char *
771 SSLerrmessage(void)
772 {
773         unsigned long   errcode;
774         const char         *errreason;
775         static char             errbuf[32];
776
777         errcode = ERR_get_error();
778         if (errcode == 0)
779                 return "No SSL error reported";
780         errreason = ERR_reason_error_string(errcode);
781         if (errreason != NULL)
782                 return errreason;
783         snprintf(errbuf, sizeof(errbuf), "SSL error code %lu", errcode);
784         return errbuf;
785 }
786
787 /*
788  *      Return pointer to SSL object.
789  */
790 SSL *
791 PQgetssl(PGconn *conn)
792 {
793         if (!conn)
794                 return NULL;
795         return conn->ssl;
796 }
797 #endif /* USE_SSL */