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