]> granicus.if.org Git - postgresql/blob - src/interfaces/libpq/fe-secure.c
From the SSL_CTX_new man page:
[postgresql] / src / interfaces / libpq / fe-secure.c
1 /*-------------------------------------------------------------------------
2  *
3  * fe-secure.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-2002, 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.18 2002/12/18 13:15:15 pgsql 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  *        pqsecure_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 pqsecure_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  *        ...
56  *
57  *        Client certificates are supported, if the server requests
58  *        or requires them.  Client certificates can be used for
59  *        authentication, to prevent sessions from being hijacked,
60  *        or to allow "road warriors" to access the database while
61  *        keeping it closed to everyone else.
62  *
63  *        The user's certificate and private key are located in
64  *              $HOME/.postgresql/postgresql.crt
65  *        and
66  *              $HOME/.postgresql/postgresql.key
67  *        respectively.
68  *
69  *        ...
70  *
71  *        We don't provide informational callbacks here (like
72  *        info_cb() in be-secure.c), since there's mechanism to
73  *        display that information to the client.
74  *
75  * OS DEPENDENCIES
76  *        The code currently assumes a POSIX password entry.  How should
77  *        Windows and Mac users be handled?
78  *
79  *-------------------------------------------------------------------------
80  */
81
82 #include "postgres_fe.h"
83
84 #include <sys/types.h>
85 #include <signal.h>
86 #include <fcntl.h>
87 #include <errno.h>
88 #include <ctype.h>
89 #include <string.h>
90
91 #include "libpq-fe.h"
92 #include "libpq-int.h"
93 #include "fe-auth.h"
94 #include "pqsignal.h"
95
96 #ifdef WIN32
97 #include "win32.h"
98 #else
99 #include <sys/socket.h>
100 #include <unistd.h>
101 #include <netdb.h>
102 #include <netinet/in.h>
103 #ifdef HAVE_NETINET_TCP_H
104 #include <netinet/tcp.h>
105 #endif
106 #include <arpa/inet.h>
107 #endif
108
109 #ifndef HAVE_STRDUP
110 #include "strdup.h"
111 #endif
112
113 #ifndef WIN32
114 #include <pwd.h>
115 #endif
116 #include <sys/stat.h>
117
118 #ifdef USE_SSL
119 #include <openssl/ssl.h>
120 #include <openssl/dh.h>
121 #endif   /* USE_SSL */
122
123
124 #ifdef USE_SSL
125 static int      verify_cb(int ok, X509_STORE_CTX *ctx);
126 #ifdef NOT_USED
127 static int      verify_peer(PGconn *);
128 #endif
129 static DH  *load_dh_file(int keylength);
130 static DH  *load_dh_buffer(const char *, size_t);
131 static DH  *tmp_dh_cb(SSL *s, int is_export, int keylength);
132 static int      client_cert_cb(SSL *, X509 **, EVP_PKEY **);
133 static int      initialize_SSL(PGconn *);
134 static void destroy_SSL(void);
135 static int      open_client_SSL(PGconn *);
136 static void close_SSL(PGconn *);
137 static const char *SSLerrmessage(void);
138 #endif
139
140 #ifdef USE_SSL
141 static SSL_CTX *SSL_context = NULL;
142 #endif
143
144 /* ------------------------------------------------------------ */
145 /*                                               Hardcoded values                                               */
146 /* ------------------------------------------------------------ */
147
148 /*
149  *      Hardcoded DH parameters, used in empheral DH keying.
150  *      As discussed above, EDH protects the confidentiality of
151  *      sessions even if the static private key is compromised,
152  *      so we are *highly* motivated to ensure that we can use
153  *      EDH even if the user... or an attacker... deletes the
154  *      $HOME/.postgresql/dh*.pem files.
155  *
156  *      It's not critical that users have EPH keys, but it doesn't
157  *      hurt and if it's missing someone will demand it, so....
158  */
159 static const char file_dh512[] =
160 "-----BEGIN DH PARAMETERS-----\n\
161 MEYCQQD1Kv884bEpQBgRjXyEpwpy1obEAxnIByl6ypUM2Zafq9AKUJsCRtMIPWak\n\
162 XUGfnHy9iUsiGSa6q6Jew1XpKgVfAgEC\n\
163 -----END DH PARAMETERS-----\n";
164
165 static const char file_dh1024[] =
166 "-----BEGIN DH PARAMETERS-----\n\
167 MIGHAoGBAPSI/VhOSdvNILSd5JEHNmszbDgNRR0PfIizHHxbLY7288kjwEPwpVsY\n\
168 jY67VYy4XTjTNP18F1dDox0YbN4zISy1Kv884bEpQBgRjXyEpwpy1obEAxnIByl6\n\
169 ypUM2Zafq9AKUJsCRtMIPWakXUGfnHy9iUsiGSa6q6Jew1XpL3jHAgEC\n\
170 -----END DH PARAMETERS-----\n";
171
172 static const char file_dh2048[] =
173 "-----BEGIN DH PARAMETERS-----\n\
174 MIIBCAKCAQEA9kJXtwh/CBdyorrWqULzBej5UxE5T7bxbrlLOCDaAadWoxTpj0BV\n\
175 89AHxstDqZSt90xkhkn4DIO9ZekX1KHTUPj1WV/cdlJPPT2N286Z4VeSWc39uK50\n\
176 T8X8dryDxUcwYc58yWb/Ffm7/ZFexwGq01uejaClcjrUGvC/RgBYK+X0iP1YTknb\n\
177 zSC0neSRBzZrM2w4DUUdD3yIsxx8Wy2O9vPJI8BD8KVbGI2Ou1WMuF040zT9fBdX\n\
178 Q6MdGGzeMyEstSr/POGxKUAYEY18hKcKctaGxAMZyAcpesqVDNmWn6vQClCbAkbT\n\
179 CD1mpF1Bn5x8vYlLIhkmuquiXsNV6TILOwIBAg==\n\
180 -----END DH PARAMETERS-----\n";
181
182 static const char file_dh4096[] =
183 "-----BEGIN DH PARAMETERS-----\n\
184 MIICCAKCAgEA+hRyUsFN4VpJ1O8JLcCo/VWr19k3BCgJ4uk+d+KhehjdRqNDNyOQ\n\
185 l/MOyQNQfWXPeGKmOmIig6Ev/nm6Nf9Z2B1h3R4hExf+zTiHnvVPeRBhjdQi81rt\n\
186 Xeoh6TNrSBIKIHfUJWBh3va0TxxjQIs6IZOLeVNRLMqzeylWqMf49HsIXqbcokUS\n\
187 Vt1BkvLdW48j8PPv5DsKRN3tloTxqDJGo9tKvj1Fuk74A+Xda1kNhB7KFlqMyN98\n\
188 VETEJ6c7KpfOo30mnK30wqw3S8OtaIR/maYX72tGOno2ehFDkq3pnPtEbD2CScxc\n\
189 alJC+EL7RPk5c/tgeTvCngvc1KZn92Y//EI7G9tPZtylj2b56sHtMftIoYJ9+ODM\n\
190 sccD5Piz/rejE3Ome8EOOceUSCYAhXn8b3qvxVI1ddd1pED6FHRhFvLrZxFvBEM9\n\
191 ERRMp5QqOaHJkM+Dxv8Cj6MqrCbfC4u+ZErxodzuusgDgvZiLF22uxMZbobFWyte\n\
192 OvOzKGtwcTqO/1wV5gKkzu1ZVswVUQd5Gg8lJicwqRWyyNRczDDoG9jVDxmogKTH\n\
193 AaqLulO7R8Ifa1SwF2DteSGVtgWEN8gDpN3RBmmPTDngyF2DHb5qmpnznwtFKdTL\n\
194 KWbuHn491xNO25CQWMtem80uKw+pTnisBRF/454n1Jnhub144YRBoN8CAQI=\n\
195 -----END DH PARAMETERS-----\n";
196
197 /* ------------------------------------------------------------ */
198 /*                       Procedures common to all secure sessions                       */
199 /* ------------------------------------------------------------ */
200
201 /*
202  *      Initialize global context
203  */
204 int
205 pqsecure_initialize(PGconn *conn)
206 {
207         int                     r = 0;
208
209 #ifdef USE_SSL
210         r = initialize_SSL(conn);
211 #endif
212
213         return r;
214 }
215
216 /*
217  *      Destroy global context
218  */
219 void
220 pqsecure_destroy(void)
221 {
222 #ifdef USE_SSL
223         destroy_SSL();
224 #endif
225 }
226
227 /*
228  *      Attempt to negotiate secure session.
229  */
230 int
231 pqsecure_open_client(PGconn *conn)
232 {
233         int                     r = 0;
234
235 #ifdef USE_SSL
236         r = open_client_SSL(conn);
237 #endif
238
239         return r;
240 }
241
242 /*
243  *      Close secure session.
244  */
245 void
246 pqsecure_close(PGconn *conn)
247 {
248 #ifdef USE_SSL
249         if (conn->ssl)
250                 close_SSL(conn);
251 #endif
252 }
253
254 /*
255  *      Read data from a secure connection.
256  */
257 ssize_t
258 pqsecure_read(PGconn *conn, void *ptr, size_t len)
259 {
260         ssize_t         n;
261
262 #ifdef USE_SSL
263         if (conn->ssl)
264         {
265                 n = SSL_read(conn->ssl, ptr, len);
266                 switch (SSL_get_error(conn->ssl, n))
267                 {
268                         case SSL_ERROR_NONE:
269                                 break;
270                         case SSL_ERROR_WANT_READ:
271                                 break;
272                         case SSL_ERROR_SYSCALL:
273                                 if (n == -1)
274                                         printfPQExpBuffer(&conn->errorMessage,
275                                                                 libpq_gettext("SSL SYSCALL error: %s\n"),
276                                                                   SOCK_STRERROR(SOCK_ERRNO));
277                                 break;
278                         case SSL_ERROR_SSL:
279                                 printfPQExpBuffer(&conn->errorMessage,
280                                           libpq_gettext("SSL error: %s\n"), SSLerrmessage());
281                                 /* fall through */
282                         case SSL_ERROR_ZERO_RETURN:
283                                 pqsecure_close(conn);
284                                 SOCK_ERRNO = ECONNRESET;
285                                 n = -1;
286                                 break;
287                 }
288         }
289         else
290 #endif
291                 n = recv(conn->sock, ptr, len, 0);
292
293         return n;
294 }
295
296 /*
297  *      Write data to a secure connection.
298  */
299 ssize_t
300 pqsecure_write(PGconn *conn, const void *ptr, size_t len)
301 {
302         ssize_t         n;
303
304 #ifndef WIN32
305         pqsigfunc       oldsighandler = pqsignal(SIGPIPE, SIG_IGN);
306 #endif
307
308 #ifdef USE_SSL
309         if (conn->ssl)
310         {
311                 n = SSL_write(conn->ssl, ptr, len);
312                 switch (SSL_get_error(conn->ssl, n))
313                 {
314                         case SSL_ERROR_NONE:
315                                 break;
316                         case SSL_ERROR_WANT_WRITE:
317                                 break;
318                         case SSL_ERROR_SYSCALL:
319                                 if (n == -1)
320                                         printfPQExpBuffer(&conn->errorMessage,
321                                                                 libpq_gettext("SSL SYSCALL error: %s\n"),
322                                                                   SOCK_STRERROR(SOCK_ERRNO));
323                                 break;
324                         case SSL_ERROR_SSL:
325                                 printfPQExpBuffer(&conn->errorMessage,
326                                           libpq_gettext("SSL error: %s\n"), SSLerrmessage());
327                                 /* fall through */
328                         case SSL_ERROR_ZERO_RETURN:
329                                 pqsecure_close(conn);
330                                 SOCK_ERRNO = ECONNRESET;
331                                 n = -1;
332                                 break;
333                 }
334         }
335         else
336 #endif
337                 n = send(conn->sock, ptr, len, 0);
338
339 #ifndef WIN32
340         pqsignal(SIGPIPE, oldsighandler);
341 #endif
342
343         return n;
344 }
345
346 /* ------------------------------------------------------------ */
347 /*                                                SSL specific code                                             */
348 /* ------------------------------------------------------------ */
349 #ifdef USE_SSL
350 /*
351  *      Certificate verification callback
352  *
353  *      This callback allows us to log intermediate problems during
354  *      verification, but there doesn't seem to be a clean way to get
355  *      our PGconn * structure.  So we can't log anything!
356  *
357  *      This callback also allows us to override the default acceptance
358  *      criteria (e.g., accepting self-signed or expired certs), but
359  *      for now we accept the default checks.
360  */
361 static int
362 verify_cb(int ok, X509_STORE_CTX *ctx)
363 {
364         return ok;
365 }
366
367 #ifdef NOT_USED
368 /*
369  *      Verify that common name resolves to peer.
370  *      This function is not thread-safe due to gethostbyname().
371  */
372 static int
373 verify_peer(PGconn *conn)
374 {
375         struct hostent *h = NULL;
376         struct sockaddr addr;
377         struct sockaddr_in *sin;
378         socklen_t       len;
379         char      **s;
380         unsigned long l;
381
382         /* get the address on the other side of the socket */
383         len = sizeof(addr);
384         if (getpeername(conn->sock, &addr, &len) == -1)
385         {
386                 printfPQExpBuffer(&conn->errorMessage,
387                                                   libpq_gettext("error querying socket: %s\n"),
388                                                   SOCK_STRERROR(SOCK_ERRNO));
389                 return -1;
390         }
391
392         /* weird, but legal case */
393         if (addr.sa_family == AF_UNIX)
394                 return 0;
395
396         /* what do we know about the peer's common name? */
397         if ((h = gethostbyname(conn->peer_cn)) == NULL)
398         {
399                 printfPQExpBuffer(&conn->errorMessage,
400                 libpq_gettext("could not get information about host (%s): %s\n"),
401                                                   conn->peer_cn, hstrerror(h_errno));
402                 return -1;
403         }
404
405         /* does the address match? */
406         switch (addr.sa_family)
407         {
408                 case AF_INET:
409                         sin = (struct sockaddr_in *) & addr;
410                         for (s = h->h_addr_list; *s != NULL; s++)
411                         {
412                                 if (!memcmp(&sin->sin_addr.s_addr, *s, h->h_length))
413                                         return 0;
414                         }
415                         break;
416
417                 default:
418                         printfPQExpBuffer(&conn->errorMessage,
419                           libpq_gettext("unsupported protocol\n"));
420                         return -1;
421         }
422
423         /*
424          * the prior test should be definitive, but in practice it sometimes
425          * fails.  So we also check the aliases.
426          */
427         for (s = h->h_aliases; *s != NULL; s++)
428         {
429                 if (strcasecmp(conn->peer_cn, *s) == 0)
430                         return 0;
431         }
432
433         /* generate protocol-aware error message */
434         switch (addr.sa_family)
435         {
436                 case AF_INET:
437                         sin = (struct sockaddr_in *) & addr;
438                         l = ntohl(sin->sin_addr.s_addr);
439                         printfPQExpBuffer(&conn->errorMessage,
440                                                           libpq_gettext(
441                                                                                         "server common name \"%s\" does not resolve to %ld.%ld.%ld.%ld\n"),
442                                          conn->peer_cn, (l >> 24) % 0x100, (l >> 16) % 0x100,
443                                                           (l >> 8) % 0x100, l % 0x100);
444                         break;
445                 default:
446                         printfPQExpBuffer(&conn->errorMessage,
447                                                           libpq_gettext(
448                         "server common name \"%s\" does not resolve to peer address\n"),
449                                                           conn->peer_cn);
450         }
451
452         return -1;
453 }
454 #endif
455
456 /*
457  *      Load precomputed DH parameters.
458  *
459  *      To prevent "downgrade" attacks, we perform a number of checks
460  *      to verify that the DBA-generated DH parameters file contains
461  *      what we expect it to contain.
462  */
463 static DH  *
464 load_dh_file(int keylength)
465 {
466         struct passwd *pwd;
467         FILE       *fp;
468         char            fnbuf[2048];
469         DH                 *dh = NULL;
470         int                     codes;
471
472         if ((pwd = getpwuid(getuid())) == NULL)
473                 return NULL;
474
475         /* attempt to open file.  It's not an error if it doesn't exist. */
476         snprintf(fnbuf, sizeof fnbuf, "%s/.postgresql/dh%d.pem",
477                          pwd->pw_dir, keylength);
478         if ((fp = fopen(fnbuf, "r")) == NULL)
479                 return NULL;
480
481 /*      flock(fileno(fp), LOCK_SH); */
482         dh = PEM_read_DHparams(fp, NULL, NULL, NULL);
483 /*      flock(fileno(fp), LOCK_UN); */
484         fclose(fp);
485
486         /* is the prime the correct size? */
487         if (dh != NULL && 8 * DH_size(dh) < keylength)
488                 dh = NULL;
489
490         /* make sure the DH parameters are usable */
491         if (dh != NULL)
492         {
493                 if (DH_check(dh, &codes))
494                         return NULL;
495                 if (codes & DH_CHECK_P_NOT_PRIME)
496                         return NULL;
497                 if ((codes & DH_NOT_SUITABLE_GENERATOR) &&
498                         (codes & DH_CHECK_P_NOT_SAFE_PRIME))
499                         return NULL;
500         }
501
502         return dh;
503 }
504
505 /*
506  *      Load hardcoded DH parameters.
507  *
508  *      To prevent problems if the DH parameters files don't even
509  *      exist, we can load DH parameters hardcoded into this file.
510  */
511 static DH  *
512 load_dh_buffer(const char *buffer, size_t len)
513 {
514         BIO                *bio;
515         DH                 *dh = NULL;
516
517         bio = BIO_new_mem_buf((char *) buffer, len);
518         if (bio == NULL)
519                 return NULL;
520         dh = PEM_read_bio_DHparams(bio, NULL, NULL, NULL);
521         BIO_free(bio);
522
523         return dh;
524 }
525
526 /*
527  *      Generate an empheral DH key.  Because this can take a long
528  *      time to compute, we can use precomputed parameters of the
529  *      common key sizes.
530  *
531  *      Since few sites will bother to precompute these parameter
532  *      files, we also provide a fallback to the parameters provided
533  *      by the OpenSSL project.
534  *
535  *      These values can be static (once loaded or computed) since
536  *      the OpenSSL library can efficiently generate random keys from
537  *      the information provided.
538  */
539 static DH  *
540 tmp_dh_cb(SSL *s, int is_export, int keylength)
541 {
542         DH                 *r = NULL;
543         static DH  *dh = NULL;
544         static DH  *dh512 = NULL;
545         static DH  *dh1024 = NULL;
546         static DH  *dh2048 = NULL;
547         static DH  *dh4096 = NULL;
548
549         switch (keylength)
550         {
551                 case 512:
552                         if (dh512 == NULL)
553                                 dh512 = load_dh_file(keylength);
554                         if (dh512 == NULL)
555                                 dh512 = load_dh_buffer(file_dh512, sizeof file_dh512);
556                         r = dh512;
557                         break;
558
559                 case 1024:
560                         if (dh1024 == NULL)
561                                 dh1024 = load_dh_file(keylength);
562                         if (dh1024 == NULL)
563                                 dh1024 = load_dh_buffer(file_dh1024, sizeof file_dh1024);
564                         r = dh1024;
565                         break;
566
567                 case 2048:
568                         if (dh2048 == NULL)
569                                 dh2048 = load_dh_file(keylength);
570                         if (dh2048 == NULL)
571                                 dh2048 = load_dh_buffer(file_dh2048, sizeof file_dh2048);
572                         r = dh2048;
573                         break;
574
575                 case 4096:
576                         if (dh4096 == NULL)
577                                 dh4096 = load_dh_file(keylength);
578                         if (dh4096 == NULL)
579                                 dh4096 = load_dh_buffer(file_dh4096, sizeof file_dh4096);
580                         r = dh4096;
581                         break;
582
583                 default:
584                         if (dh == NULL)
585                                 dh = load_dh_file(keylength);
586                         r = dh;
587         }
588
589         /* this may take a long time, but it may be necessary... */
590         if (r == NULL || 8 * DH_size(r) < keylength)
591                 r = DH_generate_parameters(keylength, DH_GENERATOR_2, NULL, NULL);
592
593         return r;
594 }
595
596 /*
597  *      Callback used by SSL to load client cert and key.
598  *      This callback is only called when the server wants a
599  *      client cert.
600  *
601  *      Returns 1 on success, 0 on no data, -1 on error.
602  */
603 static int
604 client_cert_cb(SSL *ssl, X509 **x509, EVP_PKEY **pkey)
605 {
606         struct passwd *pwd;
607         struct stat buf,
608                                 buf2;
609         char            fnbuf[2048];
610         FILE       *fp;
611         PGconn     *conn = (PGconn *) SSL_get_app_data(ssl);
612         int                     (*cb) () = NULL;        /* how to read user password */
613
614         if ((pwd = getpwuid(getuid())) == NULL)
615         {
616                 printfPQExpBuffer(&conn->errorMessage,
617                                           libpq_gettext("could not get user information\n"));
618                 return -1;
619         }
620
621         /* read the user certificate */
622         snprintf(fnbuf, sizeof fnbuf, "%s/.postgresql/postgresql.crt",
623                          pwd->pw_dir);
624         if (stat(fnbuf, &buf) == -1)
625                 return 0;
626         if ((fp = fopen(fnbuf, "r")) == NULL)
627         {
628                 printfPQExpBuffer(&conn->errorMessage,
629                                   libpq_gettext("could not open certificate (%s): %s\n"),
630                                                   fnbuf, strerror(errno));
631                 return -1;
632         }
633         if (PEM_read_X509(fp, x509, NULL, NULL) == NULL)
634         {
635                 printfPQExpBuffer(&conn->errorMessage,
636                                   libpq_gettext("could not read certificate (%s): %s\n"),
637                                                   fnbuf, SSLerrmessage());
638                 fclose(fp);
639                 return -1;
640         }
641         fclose(fp);
642
643         /* read the user key */
644         snprintf(fnbuf, sizeof fnbuf, "%s/.postgresql/postgresql.key",
645                          pwd->pw_dir);
646         if (stat(fnbuf, &buf) == -1)
647         {
648                 printfPQExpBuffer(&conn->errorMessage,
649                 libpq_gettext("certificate present, but not private key (%s)\n"),
650                                                   fnbuf);
651                 X509_free(*x509);
652                 return 0;
653         }
654         if (!S_ISREG(buf.st_mode) || (buf.st_mode & 0077) ||
655                 buf.st_uid != getuid())
656         {
657                 printfPQExpBuffer(&conn->errorMessage,
658                                                   libpq_gettext("private key (%s) has wrong permissions\n"), fnbuf);
659                 X509_free(*x509);
660                 return -1;
661         }
662         if ((fp = fopen(fnbuf, "r")) == NULL)
663         {
664                 printfPQExpBuffer(&conn->errorMessage,
665                          libpq_gettext("could not open private key file (%s): %s\n"),
666                                                   fnbuf, strerror(errno));
667                 X509_free(*x509);
668                 return -1;
669         }
670         if (fstat(fileno(fp), &buf2) == -1 ||
671                 buf.st_dev != buf2.st_dev || buf.st_ino != buf2.st_ino)
672         {
673                 printfPQExpBuffer(&conn->errorMessage,
674                         libpq_gettext("private key (%s) changed during execution\n"), fnbuf);
675                 X509_free(*x509);
676                 return -1;
677         }
678         if (PEM_read_PrivateKey(fp, pkey, cb, NULL) == NULL)
679         {
680                 printfPQExpBuffer(&conn->errorMessage,
681                                   libpq_gettext("could not read private key (%s): %s\n"),
682                                                   fnbuf, SSLerrmessage());
683                 X509_free(*x509);
684                 fclose(fp);
685                 return -1;
686         }
687         fclose(fp);
688
689         /* verify that the cert and key go together */
690         if (!X509_check_private_key(*x509, *pkey))
691         {
692                 printfPQExpBuffer(&conn->errorMessage,
693                         libpq_gettext("certificate/private key mismatch (%s): %s\n"),
694                                                   fnbuf, SSLerrmessage());
695                 X509_free(*x509);
696                 EVP_PKEY_free(*pkey);
697                 return -1;
698         }
699
700         return 1;
701 }
702
703 /*
704  *      Initialize global SSL context.
705  */
706 static int
707 initialize_SSL(PGconn *conn)
708 {
709         struct stat buf;
710         struct passwd *pwd;
711         char            fnbuf[2048];
712
713         if (!SSL_context)
714         {
715                 SSL_library_init();
716                 SSL_load_error_strings();
717                 SSL_context = SSL_CTX_new(SSLv23_method());
718                 if (!SSL_context)
719                 {
720                         printfPQExpBuffer(&conn->errorMessage,
721                                          libpq_gettext("could not create SSL context: %s\n"),
722                                                           SSLerrmessage());
723                         return -1;
724                 }
725         }
726
727         if ((pwd = getpwuid(getuid())) != NULL)
728         {
729                 snprintf(fnbuf, sizeof fnbuf, "%s/.postgresql/root.crt",
730                                  pwd->pw_dir);
731                 if (stat(fnbuf, &buf) == -1)
732                 {
733                         return 0;
734 #ifdef NOT_USED
735                         /* CLIENT CERTIFICATES NOT REQUIRED  bjm 2002-09-26 */
736                         printfPQExpBuffer(&conn->errorMessage,
737                                  libpq_gettext("could not read root certificate list (%s): %s\n"),
738                                                           fnbuf, strerror(errno));
739                         return -1;
740 #endif
741                 }
742                 if (!SSL_CTX_load_verify_locations(SSL_context, fnbuf, 0))
743                 {
744                         printfPQExpBuffer(&conn->errorMessage,
745                                  libpq_gettext("could not read root certificate list (%s): %s\n"),
746                                                           fnbuf, SSLerrmessage());
747                         return -1;
748                 }
749         }
750
751         SSL_CTX_set_verify(SSL_context,
752                    SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT, verify_cb);
753         SSL_CTX_set_verify_depth(SSL_context, 1);
754
755         /* set up empheral DH keys */
756         SSL_CTX_set_tmp_dh_callback(SSL_context, tmp_dh_cb);
757         SSL_CTX_set_options(SSL_context, SSL_OP_SINGLE_DH_USE);
758
759         /* set up mechanism to provide client certificate, if available */
760         SSL_CTX_set_client_cert_cb(SSL_context, client_cert_cb);
761
762         return 0;
763 }
764
765 /*
766  *      Destroy global SSL context.
767  */
768 static void
769 destroy_SSL(void)
770 {
771         if (SSL_context)
772         {
773                 SSL_CTX_free(SSL_context);
774                 SSL_context = NULL;
775         }
776 }
777
778 /*
779  *      Attempt to negotiate SSL connection.
780  */
781 static int
782 open_client_SSL(PGconn *conn)
783 {
784 #ifdef NOT_USED
785         int                     r;
786 #endif
787
788         if (!(conn->ssl = SSL_new(SSL_context)) ||
789                 !SSL_set_app_data(conn->ssl, conn) ||
790                 !SSL_set_fd(conn->ssl, conn->sock) ||
791                 SSL_connect(conn->ssl) <= 0)
792         {
793                 printfPQExpBuffer(&conn->errorMessage,
794                            libpq_gettext("could not establish SSL connection: %s\n"),
795                                                   SSLerrmessage());
796                 close_SSL(conn);
797                 return -1;
798         }
799
800         /* check the certificate chain of the server */
801
802 #ifdef NOT_USED
803         /* CLIENT CERTIFICATES NOT REQUIRED  bjm 2002-09-26 */
804         /*
805          * this eliminates simple man-in-the-middle attacks and simple
806          * impersonations
807          */
808         r = SSL_get_verify_result(conn->ssl);
809         if (r != X509_V_OK)
810         {
811                 printfPQExpBuffer(&conn->errorMessage,
812                            libpq_gettext("certificate could not be validated: %s\n"),
813                                                   X509_verify_cert_error_string(r));
814                 close_SSL(conn);
815                 return -1;
816         }
817 #endif
818
819         /* pull out server distinguished and common names */
820         conn->peer = SSL_get_peer_certificate(conn->ssl);
821         if (conn->peer == NULL)
822         {
823                 printfPQExpBuffer(&conn->errorMessage,
824                                 libpq_gettext("certificate could not be obtained: %s\n"),
825                                                   SSLerrmessage());
826                 close_SSL(conn);
827                 return -1;
828         }
829
830         X509_NAME_oneline(X509_get_subject_name(conn->peer),
831                                           conn->peer_dn, sizeof(conn->peer_dn));
832         conn->peer_dn[sizeof(conn->peer_dn) - 1] = '\0';
833
834         X509_NAME_get_text_by_NID(X509_get_subject_name(conn->peer),
835                                                           NID_commonName, conn->peer_cn, SM_USER);
836         conn->peer_cn[SM_USER] = '\0';
837
838         /* verify that the common name resolves to peer */
839
840 #ifdef NOT_USED
841         /* CLIENT CERTIFICATES NOT REQUIRED  bjm 2002-09-26 */
842         /*
843          * this is necessary to eliminate man-in-the-middle attacks and
844          * impersonations where the attacker somehow learned the server's
845          * private key
846          */
847         if (verify_peer(conn) == -1)
848         {
849                 close_SSL(conn);
850                 return -1;
851         }
852 #endif
853
854         return 0;
855 }
856
857 /*
858  *      Close SSL connection.
859  */
860 static void
861 close_SSL(PGconn *conn)
862 {
863         if (conn->ssl)
864         {
865                 SSL_shutdown(conn->ssl);
866                 SSL_free(conn->ssl);
867                 conn->ssl = NULL;
868         }
869 }
870
871 /*
872  * Obtain reason string for last SSL error
873  *
874  * Some caution is needed here since ERR_reason_error_string will
875  * return NULL if it doesn't recognize the error code.  We don't
876  * want to return NULL ever.
877  */
878 static const char *
879 SSLerrmessage(void)
880 {
881         unsigned long errcode;
882         const char *errreason;
883         static char errbuf[32];
884
885         errcode = ERR_get_error();
886         if (errcode == 0)
887                 return "No SSL error reported";
888         errreason = ERR_reason_error_string(errcode);
889         if (errreason != NULL)
890                 return errreason;
891         snprintf(errbuf, sizeof(errbuf), "SSL error code %lu", errcode);
892         return errbuf;
893 }
894
895 /*
896  *      Return pointer to SSL object.
897  */
898 SSL *
899 PQgetssl(PGconn *conn)
900 {
901         if (!conn)
902                 return NULL;
903         return conn->ssl;
904 }
905
906 #endif   /* USE_SSL */