]> granicus.if.org Git - postgresql/blob - src/backend/libpq/be-secure.c
Cosmetic code cleanup: fix a bunch of places that used "return (expr);"
[postgresql] / src / backend / libpq / be-secure.c
1 /*-------------------------------------------------------------------------
2  *
3  * be-secure.c
4  *        functions related to setting up a secure connection to the frontend.
5  *        Secure connections are expected to provide confidentiality,
6  *        message integrity and endpoint authentication.
7  *
8  *
9  * Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
10  * Portions Copyright (c) 1994, Regents of the University of California
11  *
12  *
13  * IDENTIFICATION
14  *        $PostgreSQL: pgsql/src/backend/libpq/be-secure.c,v 1.61 2006/01/11 08:43:12 neilc Exp $
15  *
16  *        Since the server static private key ($DataDir/server.key)
17  *        will normally be stored unencrypted so that the database
18  *        backend can restart automatically, it is important that
19  *        we select an algorithm that continues to provide confidentiality
20  *        even if the attacker has the server's private key.  Empheral
21  *        DH (EDH) keys provide this, and in fact provide Perfect Forward
22  *        Secrecy (PFS) except for situations where the session can
23  *        be hijacked during a periodic handshake/renegotiation.
24  *        Even that backdoor can be closed if client certificates
25  *        are used (since the imposter will be unable to successfully
26  *        complete renegotiation).
27  *
28  *        N.B., the static private key should still be protected to
29  *        the largest extent possible, to minimize the risk of
30  *        impersonations.
31  *
32  *        Another benefit of EDH is that it allows the backend and
33  *        clients to use DSA keys.      DSA keys can only provide digital
34  *        signatures, not encryption, and are often acceptable in
35  *        jurisdictions where RSA keys are unacceptable.
36  *
37  *        The downside to EDH is that it makes it impossible to
38  *        use ssldump(1) if there's a problem establishing an SSL
39  *        session.      In this case you'll need to temporarily disable
40  *        EDH by commenting out the callback.
41  *
42  *        ...
43  *
44  *        Because the risk of cryptanalysis increases as large
45  *        amounts of data are sent with the same session key, the
46  *        session keys are periodically renegotiated.
47  *
48  * PATCH LEVEL
49  *        milestone 1: fix basic coding errors
50  *        [*] existing SSL code pulled out of existing files.
51  *        [*] SSL_get_error() after SSL_read() and SSL_write(),
52  *                SSL_shutdown(), default to TLSv1.
53  *
54  *        milestone 2: provide endpoint authentication (server)
55  *        [*] client verifies server cert
56  *        [*] client verifies server hostname
57  *
58  *        milestone 3: improve confidentially, support perfect forward secrecy
59  *        [ ] use 'random' file, read from '/dev/urandom?'
60  *        [*] emphermal DH keys, default values
61  *        [*] periodic renegotiation
62  *        [*] private key permissions
63  *
64  *        milestone 4: provide endpoint authentication (client)
65  *        [*] server verifies client certificates
66  *
67  *        milestone 5: provide informational callbacks
68  *        [*] provide informational callbacks
69  *
70  *        other changes
71  *        [ ] tcp-wrappers
72  *        [ ] more informative psql
73  *
74  *-------------------------------------------------------------------------
75  */
76
77 #include "postgres.h"
78
79 #include <sys/stat.h>
80 #include <signal.h>
81 #include <fcntl.h>
82 #include <ctype.h>
83 #include <sys/socket.h>
84 #include <unistd.h>
85 #include <netdb.h>
86 #include <netinet/in.h>
87 #ifdef HAVE_NETINET_TCP_H
88 #include <netinet/tcp.h>
89 #include <arpa/inet.h>
90 #endif
91
92 #ifdef USE_SSL
93 #include <openssl/ssl.h>
94 #include <openssl/dh.h>
95 #endif
96
97 #include "libpq/libpq.h"
98 #include "miscadmin.h"
99 #include "tcop/tcopprot.h"
100
101
102 #ifdef USE_SSL
103
104 #define ROOT_CERT_FILE                  "root.crt"
105 #define SERVER_CERT_FILE                "server.crt"
106 #define SERVER_PRIVATE_KEY_FILE "server.key"
107
108 static DH  *load_dh_file(int keylength);
109 static DH  *load_dh_buffer(const char *, size_t);
110 static DH  *tmp_dh_cb(SSL *s, int is_export, int keylength);
111 static int      verify_cb(int, X509_STORE_CTX *);
112 static void info_cb(const SSL *ssl, int type, int args);
113 static int      initialize_SSL(void);
114 static void destroy_SSL(void);
115 static int      open_server_SSL(Port *);
116 static void close_SSL(Port *);
117 static const char *SSLerrmessage(void);
118 #endif
119
120 #ifdef USE_SSL
121 /*
122  *      How much data can be sent across a secure connection
123  *      (total in both directions) before we require renegotiation.
124  */
125 #define RENEGOTIATION_LIMIT (512 * 1024 * 1024)
126
127 static SSL_CTX *SSL_context = NULL;
128 #endif
129
130 /* ------------------------------------------------------------ */
131 /*                                               Hardcoded values                                               */
132 /* ------------------------------------------------------------ */
133
134 /*
135  *      Hardcoded DH parameters, used in empheral DH keying.
136  *      As discussed above, EDH protects the confidentiality of
137  *      sessions even if the static private key is compromised,
138  *      so we are *highly* motivated to ensure that we can use
139  *      EDH even if the DBA... or an attacker... deletes the
140  *      $DataDir/dh*.pem files.
141  *
142  *      We could refuse SSL connections unless a good DH parameter
143  *      file exists, but some clients may quietly renegotiate an
144  *      unsecured connection without fully informing the user.
145  *      Very uncool.
146  *
147  *      Alternately, the backend could attempt to load these files
148  *      on startup if SSL is enabled - and refuse to start if any
149  *      do not exist - but this would tend to piss off DBAs.
150  *
151  *      If you want to create your own hardcoded DH parameters
152  *      for fun and profit, review "Assigned Number for SKIP
153  *      Protocols" (http://www.skip-vpn.org/spec/numbers.html)
154  *      for suggestions.
155  */
156 #ifdef USE_SSL
157
158 static const char file_dh512[] =
159 "-----BEGIN DH PARAMETERS-----\n\
160 MEYCQQD1Kv884bEpQBgRjXyEpwpy1obEAxnIByl6ypUM2Zafq9AKUJsCRtMIPWak\n\
161 XUGfnHy9iUsiGSa6q6Jew1XpKgVfAgEC\n\
162 -----END DH PARAMETERS-----\n";
163
164 static const char file_dh1024[] =
165 "-----BEGIN DH PARAMETERS-----\n\
166 MIGHAoGBAPSI/VhOSdvNILSd5JEHNmszbDgNRR0PfIizHHxbLY7288kjwEPwpVsY\n\
167 jY67VYy4XTjTNP18F1dDox0YbN4zISy1Kv884bEpQBgRjXyEpwpy1obEAxnIByl6\n\
168 ypUM2Zafq9AKUJsCRtMIPWakXUGfnHy9iUsiGSa6q6Jew1XpL3jHAgEC\n\
169 -----END DH PARAMETERS-----\n";
170
171 static const char file_dh2048[] =
172 "-----BEGIN DH PARAMETERS-----\n\
173 MIIBCAKCAQEA9kJXtwh/CBdyorrWqULzBej5UxE5T7bxbrlLOCDaAadWoxTpj0BV\n\
174 89AHxstDqZSt90xkhkn4DIO9ZekX1KHTUPj1WV/cdlJPPT2N286Z4VeSWc39uK50\n\
175 T8X8dryDxUcwYc58yWb/Ffm7/ZFexwGq01uejaClcjrUGvC/RgBYK+X0iP1YTknb\n\
176 zSC0neSRBzZrM2w4DUUdD3yIsxx8Wy2O9vPJI8BD8KVbGI2Ou1WMuF040zT9fBdX\n\
177 Q6MdGGzeMyEstSr/POGxKUAYEY18hKcKctaGxAMZyAcpesqVDNmWn6vQClCbAkbT\n\
178 CD1mpF1Bn5x8vYlLIhkmuquiXsNV6TILOwIBAg==\n\
179 -----END DH PARAMETERS-----\n";
180
181 static const char file_dh4096[] =
182 "-----BEGIN DH PARAMETERS-----\n\
183 MIICCAKCAgEA+hRyUsFN4VpJ1O8JLcCo/VWr19k3BCgJ4uk+d+KhehjdRqNDNyOQ\n\
184 l/MOyQNQfWXPeGKmOmIig6Ev/nm6Nf9Z2B1h3R4hExf+zTiHnvVPeRBhjdQi81rt\n\
185 Xeoh6TNrSBIKIHfUJWBh3va0TxxjQIs6IZOLeVNRLMqzeylWqMf49HsIXqbcokUS\n\
186 Vt1BkvLdW48j8PPv5DsKRN3tloTxqDJGo9tKvj1Fuk74A+Xda1kNhB7KFlqMyN98\n\
187 VETEJ6c7KpfOo30mnK30wqw3S8OtaIR/maYX72tGOno2ehFDkq3pnPtEbD2CScxc\n\
188 alJC+EL7RPk5c/tgeTvCngvc1KZn92Y//EI7G9tPZtylj2b56sHtMftIoYJ9+ODM\n\
189 sccD5Piz/rejE3Ome8EOOceUSCYAhXn8b3qvxVI1ddd1pED6FHRhFvLrZxFvBEM9\n\
190 ERRMp5QqOaHJkM+Dxv8Cj6MqrCbfC4u+ZErxodzuusgDgvZiLF22uxMZbobFWyte\n\
191 OvOzKGtwcTqO/1wV5gKkzu1ZVswVUQd5Gg8lJicwqRWyyNRczDDoG9jVDxmogKTH\n\
192 AaqLulO7R8Ifa1SwF2DteSGVtgWEN8gDpN3RBmmPTDngyF2DHb5qmpnznwtFKdTL\n\
193 KWbuHn491xNO25CQWMtem80uKw+pTnisBRF/454n1Jnhub144YRBoN8CAQI=\n\
194 -----END DH PARAMETERS-----\n";
195 #endif
196
197 /* ------------------------------------------------------------ */
198 /*                       Procedures common to all secure sessions                       */
199 /* ------------------------------------------------------------ */
200
201 /*
202  *      Initialize global context
203  */
204 int
205 secure_initialize(void)
206 {
207         int                     r = 0;
208
209 #ifdef USE_SSL
210         r = initialize_SSL();
211 #endif
212
213         return r;
214 }
215
216 /*
217  *      Destroy global context
218  */
219 void
220 secure_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 secure_open_server(Port *port)
232 {
233         int                     r = 0;
234
235 #ifdef USE_SSL
236         r = open_server_SSL(port);
237 #endif
238
239         return r;
240 }
241
242 /*
243  *      Close secure session.
244  */
245 void
246 secure_close(Port *port)
247 {
248 #ifdef USE_SSL
249         if (port->ssl)
250                 close_SSL(port);
251 #endif
252 }
253
254 /*
255  *      Read data from a secure connection.
256  */
257 ssize_t
258 secure_read(Port *port, void *ptr, size_t len)
259 {
260         ssize_t         n;
261
262 #ifdef USE_SSL
263         if (port->ssl)
264         {
265                 int                     err;
266
267 rloop:
268                 n = SSL_read(port->ssl, ptr, len);
269                 err = SSL_get_error(port->ssl, n);
270                 switch (err)
271                 {
272                         case SSL_ERROR_NONE:
273                                 port->count += n;
274                                 break;
275                         case SSL_ERROR_WANT_READ:
276                         case SSL_ERROR_WANT_WRITE:
277 #ifdef WIN32
278                                 pgwin32_waitforsinglesocket(SSL_get_fd(port->ssl),
279                                                                                         (err == SSL_ERROR_WANT_READ) ?
280                                                                    FD_READ | FD_CLOSE : FD_WRITE | FD_CLOSE);
281 #endif
282                                 goto rloop;
283                         case SSL_ERROR_SYSCALL:
284                                 if (n == -1)
285                                         ereport(COMMERROR,
286                                                         (errcode_for_socket_access(),
287                                                          errmsg("SSL SYSCALL error: %m")));
288                                 else
289                                 {
290                                         ereport(COMMERROR,
291                                                         (errcode(ERRCODE_PROTOCOL_VIOLATION),
292                                                          errmsg("SSL SYSCALL error: EOF detected")));
293                                         errno = ECONNRESET;
294                                         n = -1;
295                                 }
296                                 break;
297                         case SSL_ERROR_SSL:
298                                 ereport(COMMERROR,
299                                                 (errcode(ERRCODE_PROTOCOL_VIOLATION),
300                                                  errmsg("SSL error: %s", SSLerrmessage())));
301                                 /* fall through */
302                         case SSL_ERROR_ZERO_RETURN:
303                                 errno = ECONNRESET;
304                                 n = -1;
305                                 break;
306                         default:
307                                 ereport(COMMERROR,
308                                                 (errcode(ERRCODE_PROTOCOL_VIOLATION),
309                                                  errmsg("unrecognized SSL error code: %d",
310                                                                 err)));
311                                 n = -1;
312                                 break;
313                 }
314         }
315         else
316 #endif
317         {
318                 prepare_for_client_read();
319
320                 n = recv(port->sock, ptr, len, 0);
321
322                 client_read_ended();
323         }
324
325         return n;
326 }
327
328 /*
329  *      Write data to a secure connection.
330  */
331 ssize_t
332 secure_write(Port *port, void *ptr, size_t len)
333 {
334         ssize_t         n;
335
336 #ifdef USE_SSL
337         if (port->ssl)
338         {
339                 int                     err;
340
341                 if (port->count > RENEGOTIATION_LIMIT)
342                 {
343                         SSL_set_session_id_context(port->ssl, (void *) &SSL_context,
344                                                                            sizeof(SSL_context));
345                         if (SSL_renegotiate(port->ssl) <= 0)
346                                 ereport(COMMERROR,
347                                                 (errcode(ERRCODE_PROTOCOL_VIOLATION),
348                                                  errmsg("SSL renegotiation failure")));
349                         if (SSL_do_handshake(port->ssl) <= 0)
350                                 ereport(COMMERROR,
351                                                 (errcode(ERRCODE_PROTOCOL_VIOLATION),
352                                                  errmsg("SSL renegotiation failure")));
353                         if (port->ssl->state != SSL_ST_OK)
354                                 ereport(COMMERROR,
355                                                 (errcode(ERRCODE_PROTOCOL_VIOLATION),
356                                                  errmsg("SSL failed to send renegotiation request")));
357                         port->ssl->state |= SSL_ST_ACCEPT;
358                         SSL_do_handshake(port->ssl);
359                         if (port->ssl->state != SSL_ST_OK)
360                                 ereport(COMMERROR,
361                                                 (errcode(ERRCODE_PROTOCOL_VIOLATION),
362                                                  errmsg("SSL renegotiation failure")));
363                         port->count = 0;
364                 }
365
366 wloop:
367                 n = SSL_write(port->ssl, ptr, len);
368                 err = SSL_get_error(port->ssl, n);
369                 switch (err)
370                 {
371                         case SSL_ERROR_NONE:
372                                 port->count += n;
373                                 break;
374                         case SSL_ERROR_WANT_READ:
375                         case SSL_ERROR_WANT_WRITE:
376 #ifdef WIN32
377                                 pgwin32_waitforsinglesocket(SSL_get_fd(port->ssl),
378                                                                                         (err == SSL_ERROR_WANT_READ) ?
379                                                                    FD_READ | FD_CLOSE : FD_WRITE | FD_CLOSE);
380 #endif
381                                 goto wloop;
382                         case SSL_ERROR_SYSCALL:
383                                 if (n == -1)
384                                         ereport(COMMERROR,
385                                                         (errcode_for_socket_access(),
386                                                          errmsg("SSL SYSCALL error: %m")));
387                                 else
388                                 {
389                                         ereport(COMMERROR,
390                                                         (errcode(ERRCODE_PROTOCOL_VIOLATION),
391                                                          errmsg("SSL SYSCALL error: EOF detected")));
392                                         errno = ECONNRESET;
393                                         n = -1;
394                                 }
395                                 break;
396                         case SSL_ERROR_SSL:
397                                 ereport(COMMERROR,
398                                                 (errcode(ERRCODE_PROTOCOL_VIOLATION),
399                                                  errmsg("SSL error: %s", SSLerrmessage())));
400                                 /* fall through */
401                         case SSL_ERROR_ZERO_RETURN:
402                                 errno = ECONNRESET;
403                                 n = -1;
404                                 break;
405                         default:
406                                 ereport(COMMERROR,
407                                                 (errcode(ERRCODE_PROTOCOL_VIOLATION),
408                                                  errmsg("unrecognized SSL error code: %d",
409                                                                 err)));
410                                 n = -1;
411                                 break;
412                 }
413         }
414         else
415 #endif
416                 n = send(port->sock, ptr, len, 0);
417
418         return n;
419 }
420
421 /* ------------------------------------------------------------ */
422 /*                                                SSL specific code                                             */
423 /* ------------------------------------------------------------ */
424 #ifdef USE_SSL
425
426 /*
427  * Private substitute BIO: this wraps the SSL library's standard socket BIO
428  * so that we can enable and disable interrupts just while calling recv().
429  * We cannot have interrupts occurring while the bulk of openssl runs,
430  * because it uses malloc() and possibly other non-reentrant libc facilities.
431  *
432  * As of openssl 0.9.7, we can use the reasonably clean method of interposing
433  * a wrapper around the standard socket BIO's sock_read() method.  This relies
434  * on the fact that sock_read() doesn't call anything non-reentrant, in fact
435  * not much of anything at all except recv().  If this ever changes we'd
436  * probably need to duplicate the code of sock_read() in order to push the
437  * interrupt enable/disable down yet another level.
438  */
439
440 static bool my_bio_initialized = false;
441 static BIO_METHOD my_bio_methods;
442 static int      (*std_sock_read) (BIO *h, char *buf, int size);
443
444 static int
445 my_sock_read(BIO *h, char *buf, int size)
446 {
447         int                     res;
448
449         prepare_for_client_read();
450
451         res = std_sock_read(h, buf, size);
452
453         client_read_ended();
454
455         return res;
456 }
457
458 static BIO_METHOD *
459 my_BIO_s_socket(void)
460 {
461         if (!my_bio_initialized)
462         {
463                 memcpy(&my_bio_methods, BIO_s_socket(), sizeof(BIO_METHOD));
464                 std_sock_read = my_bio_methods.bread;
465                 my_bio_methods.bread = my_sock_read;
466                 my_bio_initialized = true;
467         }
468         return &my_bio_methods;
469 }
470
471 /* This should exactly match openssl's SSL_set_fd except for using my BIO */
472 static int
473 my_SSL_set_fd(SSL *s, int fd)
474 {
475         int                     ret = 0;
476         BIO                *bio = NULL;
477
478         bio = BIO_new(my_BIO_s_socket());
479
480         if (bio == NULL)
481         {
482                 SSLerr(SSL_F_SSL_SET_FD, ERR_R_BUF_LIB);
483                 goto err;
484         }
485         BIO_set_fd(bio, fd, BIO_NOCLOSE);
486         SSL_set_bio(s, bio, bio);
487         ret = 1;
488 err:
489         return ret;
490 }
491
492 /*
493  *      Load precomputed DH parameters.
494  *
495  *      To prevent "downgrade" attacks, we perform a number of checks
496  *      to verify that the DBA-generated DH parameters file contains
497  *      what we expect it to contain.
498  */
499 static DH  *
500 load_dh_file(int keylength)
501 {
502         FILE       *fp;
503         char            fnbuf[MAXPGPATH];
504         DH                 *dh = NULL;
505         int                     codes;
506
507         /* attempt to open file.  It's not an error if it doesn't exist. */
508         snprintf(fnbuf, sizeof(fnbuf), "dh%d.pem", keylength);
509         if ((fp = fopen(fnbuf, "r")) == NULL)
510                 return NULL;
511
512 /*      flock(fileno(fp), LOCK_SH); */
513         dh = PEM_read_DHparams(fp, NULL, NULL, NULL);
514 /*      flock(fileno(fp), LOCK_UN); */
515         fclose(fp);
516
517         /* is the prime the correct size? */
518         if (dh != NULL && 8 * DH_size(dh) < keylength)
519         {
520                 elog(LOG, "DH errors (%s): %d bits expected, %d bits found",
521                          fnbuf, keylength, 8 * DH_size(dh));
522                 dh = NULL;
523         }
524
525         /* make sure the DH parameters are usable */
526         if (dh != NULL)
527         {
528                 if (DH_check(dh, &codes))
529                 {
530                         elog(LOG, "DH_check error (%s): %s", fnbuf, SSLerrmessage());
531                         return NULL;
532                 }
533                 if (codes & DH_CHECK_P_NOT_PRIME)
534                 {
535                         elog(LOG, "DH error (%s): p is not prime", fnbuf);
536                         return NULL;
537                 }
538                 if ((codes & DH_NOT_SUITABLE_GENERATOR) &&
539                         (codes & DH_CHECK_P_NOT_SAFE_PRIME))
540                 {
541                         elog(LOG,
542                                  "DH error (%s): neither suitable generator or safe prime",
543                                  fnbuf);
544                         return NULL;
545                 }
546         }
547
548         return dh;
549 }
550
551 /*
552  *      Load hardcoded DH parameters.
553  *
554  *      To prevent problems if the DH parameters files don't even
555  *      exist, we can load DH parameters hardcoded into this file.
556  */
557 static DH  *
558 load_dh_buffer(const char *buffer, size_t len)
559 {
560         BIO                *bio;
561         DH                 *dh = NULL;
562
563         bio = BIO_new_mem_buf((char *) buffer, len);
564         if (bio == NULL)
565                 return NULL;
566         dh = PEM_read_bio_DHparams(bio, NULL, NULL, NULL);
567         if (dh == NULL)
568                 ereport(DEBUG2,
569                                 (errmsg_internal("DH load buffer: %s",
570                                                                  SSLerrmessage())));
571         BIO_free(bio);
572
573         return dh;
574 }
575
576 /*
577  *      Generate an empheral DH key.  Because this can take a long
578  *      time to compute, we can use precomputed parameters of the
579  *      common key sizes.
580  *
581  *      Since few sites will bother to precompute these parameter
582  *      files, we also provide a fallback to the parameters provided
583  *      by the OpenSSL project.
584  *
585  *      These values can be static (once loaded or computed) since
586  *      the OpenSSL library can efficiently generate random keys from
587  *      the information provided.
588  */
589 static DH  *
590 tmp_dh_cb(SSL *s, int is_export, int keylength)
591 {
592         DH                 *r = NULL;
593         static DH  *dh = NULL;
594         static DH  *dh512 = NULL;
595         static DH  *dh1024 = NULL;
596         static DH  *dh2048 = NULL;
597         static DH  *dh4096 = NULL;
598
599         switch (keylength)
600         {
601                 case 512:
602                         if (dh512 == NULL)
603                                 dh512 = load_dh_file(keylength);
604                         if (dh512 == NULL)
605                                 dh512 = load_dh_buffer(file_dh512, sizeof file_dh512);
606                         r = dh512;
607                         break;
608
609                 case 1024:
610                         if (dh1024 == NULL)
611                                 dh1024 = load_dh_file(keylength);
612                         if (dh1024 == NULL)
613                                 dh1024 = load_dh_buffer(file_dh1024, sizeof file_dh1024);
614                         r = dh1024;
615                         break;
616
617                 case 2048:
618                         if (dh2048 == NULL)
619                                 dh2048 = load_dh_file(keylength);
620                         if (dh2048 == NULL)
621                                 dh2048 = load_dh_buffer(file_dh2048, sizeof file_dh2048);
622                         r = dh2048;
623                         break;
624
625                 case 4096:
626                         if (dh4096 == NULL)
627                                 dh4096 = load_dh_file(keylength);
628                         if (dh4096 == NULL)
629                                 dh4096 = load_dh_buffer(file_dh4096, sizeof file_dh4096);
630                         r = dh4096;
631                         break;
632
633                 default:
634                         if (dh == NULL)
635                                 dh = load_dh_file(keylength);
636                         r = dh;
637         }
638
639         /* this may take a long time, but it may be necessary... */
640         if (r == NULL || 8 * DH_size(r) < keylength)
641         {
642                 ereport(DEBUG2,
643                                 (errmsg_internal("DH: generating parameters (%d bits)....",
644                                                                  keylength)));
645                 r = DH_generate_parameters(keylength, DH_GENERATOR_2, NULL, NULL);
646         }
647
648         return r;
649 }
650
651 /*
652  *      Certificate verification callback
653  *
654  *      This callback allows us to log intermediate problems during
655  *      verification, but for now we'll see if the final error message
656  *      contains enough information.
657  *
658  *      This callback also allows us to override the default acceptance
659  *      criteria (e.g., accepting self-signed or expired certs), but
660  *      for now we accept the default checks.
661  */
662 static int
663 verify_cb(int ok, X509_STORE_CTX *ctx)
664 {
665         return ok;
666 }
667
668 /*
669  *      This callback is used to copy SSL information messages
670  *      into the PostgreSQL log.
671  */
672 static void
673 info_cb(const SSL *ssl, int type, int args)
674 {
675         switch (type)
676         {
677                 case SSL_CB_HANDSHAKE_START:
678                         ereport(DEBUG4,
679                                         (errmsg_internal("SSL: handshake start")));
680                         break;
681                 case SSL_CB_HANDSHAKE_DONE:
682                         ereport(DEBUG4,
683                                         (errmsg_internal("SSL: handshake done")));
684                         break;
685                 case SSL_CB_ACCEPT_LOOP:
686                         ereport(DEBUG4,
687                                         (errmsg_internal("SSL: accept loop")));
688                         break;
689                 case SSL_CB_ACCEPT_EXIT:
690                         ereport(DEBUG4,
691                                         (errmsg_internal("SSL: accept exit (%d)", args)));
692                         break;
693                 case SSL_CB_CONNECT_LOOP:
694                         ereport(DEBUG4,
695                                         (errmsg_internal("SSL: connect loop")));
696                         break;
697                 case SSL_CB_CONNECT_EXIT:
698                         ereport(DEBUG4,
699                                         (errmsg_internal("SSL: connect exit (%d)", args)));
700                         break;
701                 case SSL_CB_READ_ALERT:
702                         ereport(DEBUG4,
703                                         (errmsg_internal("SSL: read alert (0x%04x)", args)));
704                         break;
705                 case SSL_CB_WRITE_ALERT:
706                         ereport(DEBUG4,
707                                         (errmsg_internal("SSL: write alert (0x%04x)", args)));
708                         break;
709         }
710 }
711
712 /*
713  *      Initialize global SSL context.
714  */
715 static int
716 initialize_SSL(void)
717 {
718         struct stat buf;
719
720         if (!SSL_context)
721         {
722                 SSL_library_init();
723                 SSL_load_error_strings();
724                 SSL_context = SSL_CTX_new(SSLv23_method());
725                 if (!SSL_context)
726                         ereport(FATAL,
727                                         (errmsg("could not create SSL context: %s",
728                                                         SSLerrmessage())));
729
730                 /*
731                  * Load and verify certificate and private key
732                  */
733                 if (!SSL_CTX_use_certificate_file(SSL_context,
734                                                                                   SERVER_CERT_FILE,
735                                                                                   SSL_FILETYPE_PEM))
736                         ereport(FATAL,
737                                         (errcode(ERRCODE_CONFIG_FILE_ERROR),
738                                   errmsg("could not load server certificate file \"%s\": %s",
739                                                  SERVER_CERT_FILE, SSLerrmessage())));
740
741                 if (stat(SERVER_PRIVATE_KEY_FILE, &buf) == -1)
742                         ereport(FATAL,
743                                         (errcode_for_file_access(),
744                                          errmsg("could not access private key file \"%s\": %m",
745                                                         SERVER_PRIVATE_KEY_FILE)));
746
747                 /*
748                  * Require no public access to key file.
749                  *
750                  * XXX temporarily suppress check when on Windows, because there may
751                  * not be proper support for Unix-y file permissions.  Need to think
752                  * of a reasonable check to apply on Windows.  (See also the data
753                  * directory permission check in postmaster.c)
754                  */
755 #if !defined(WIN32) && !defined(__CYGWIN__)
756                 if (!S_ISREG(buf.st_mode) || (buf.st_mode & (S_IRWXG | S_IRWXO)) ||
757                         buf.st_uid != geteuid())
758                         ereport(FATAL,
759                                         (errcode(ERRCODE_CONFIG_FILE_ERROR),
760                                          errmsg("unsafe permissions on private key file \"%s\"",
761                                                         SERVER_PRIVATE_KEY_FILE),
762                                          errdetail("File must be owned by the database user and must have no permissions for \"group\" or \"other\".")));
763 #endif
764
765                 if (!SSL_CTX_use_PrivateKey_file(SSL_context,
766                                                                                  SERVER_PRIVATE_KEY_FILE,
767                                                                                  SSL_FILETYPE_PEM))
768                         ereport(FATAL,
769                                         (errmsg("could not load private key file \"%s\": %s",
770                                                         SERVER_PRIVATE_KEY_FILE, SSLerrmessage())));
771
772                 if (!SSL_CTX_check_private_key(SSL_context))
773                         ereport(FATAL,
774                                         (errmsg("check of private key failed: %s",
775                                                         SSLerrmessage())));
776         }
777
778         /* set up empheral DH keys */
779         SSL_CTX_set_tmp_dh_callback(SSL_context, tmp_dh_cb);
780         SSL_CTX_set_options(SSL_context, SSL_OP_SINGLE_DH_USE | SSL_OP_NO_SSLv2);
781
782         /* setup the allowed cipher list */
783         if (SSL_CTX_set_cipher_list(SSL_context, "ALL:!ADH:!LOW:!EXP:!MD5:@STRENGTH") != 1)
784                 elog(FATAL, "could not set the cipher list (no valid ciphers available)");
785
786         /*
787          * Require and check client certificates only if we have a root.crt file.
788          */
789         if (!SSL_CTX_load_verify_locations(SSL_context, ROOT_CERT_FILE, NULL))
790         {
791                 /* Not fatal - we do not require client certificates */
792                 ereport(LOG,
793                                 (errmsg("could not load root certificate file \"%s\": %s",
794                                                 ROOT_CERT_FILE, SSLerrmessage()),
795                                  errdetail("Will not verify client certificates.")));
796         }
797         else
798         {
799                 SSL_CTX_set_verify(SSL_context,
800                                                    (SSL_VERIFY_PEER |
801                                                         SSL_VERIFY_FAIL_IF_NO_PEER_CERT |
802                                                         SSL_VERIFY_CLIENT_ONCE),
803                                                    verify_cb);
804         }
805
806         return 0;
807 }
808
809 /*
810  *      Destroy global SSL context.
811  */
812 static void
813 destroy_SSL(void)
814 {
815         if (SSL_context)
816         {
817                 SSL_CTX_free(SSL_context);
818                 SSL_context = NULL;
819         }
820 }
821
822 /*
823  *      Attempt to negotiate SSL connection.
824  */
825 static int
826 open_server_SSL(Port *port)
827 {
828         int                     r;
829         int                     err;
830
831         Assert(!port->ssl);
832         Assert(!port->peer);
833
834         if (!(port->ssl = SSL_new(SSL_context)))
835         {
836                 ereport(COMMERROR,
837                                 (errcode(ERRCODE_PROTOCOL_VIOLATION),
838                                  errmsg("could not initialize SSL connection: %s",
839                                                 SSLerrmessage())));
840                 close_SSL(port);
841                 return -1;
842         }
843         if (!my_SSL_set_fd(port->ssl, port->sock))
844         {
845                 ereport(COMMERROR,
846                                 (errcode(ERRCODE_PROTOCOL_VIOLATION),
847                                  errmsg("could not set SSL socket: %s",
848                                                 SSLerrmessage())));
849                 close_SSL(port);
850                 return -1;
851         }
852
853 aloop:
854         r = SSL_accept(port->ssl);
855         if (r <= 0)
856         {
857                 err = SSL_get_error(port->ssl, r);
858                 switch (err)
859                 {
860                         case SSL_ERROR_WANT_READ:
861                         case SSL_ERROR_WANT_WRITE:
862 #ifdef WIN32
863                                 pgwin32_waitforsinglesocket(SSL_get_fd(port->ssl),
864                                                                                         (err == SSL_ERROR_WANT_READ) ?
865                                            FD_READ | FD_CLOSE | FD_ACCEPT : FD_WRITE | FD_CLOSE);
866 #endif
867                                 goto aloop;
868                         case SSL_ERROR_SYSCALL:
869                                 if (r < 0)
870                                         ereport(COMMERROR,
871                                                         (errcode_for_socket_access(),
872                                                          errmsg("could not accept SSL connection: %m")));
873                                 else
874                                         ereport(COMMERROR,
875                                                         (errcode(ERRCODE_PROTOCOL_VIOLATION),
876                                         errmsg("could not accept SSL connection: EOF detected")));
877                                 break;
878                         case SSL_ERROR_SSL:
879                                 ereport(COMMERROR,
880                                                 (errcode(ERRCODE_PROTOCOL_VIOLATION),
881                                                  errmsg("could not accept SSL connection: %s",
882                                                                 SSLerrmessage())));
883                                 break;
884                         case SSL_ERROR_ZERO_RETURN:
885                                 ereport(COMMERROR,
886                                                 (errcode(ERRCODE_PROTOCOL_VIOLATION),
887                                    errmsg("could not accept SSL connection: EOF detected")));
888                                 break;
889                         default:
890                                 ereport(COMMERROR,
891                                                 (errcode(ERRCODE_PROTOCOL_VIOLATION),
892                                                  errmsg("unrecognized SSL error code: %d",
893                                                                 err)));
894                                 break;
895                 }
896                 close_SSL(port);
897                 return -1;
898         }
899
900         port->count = 0;
901
902         /* get client certificate, if available. */
903         port->peer = SSL_get_peer_certificate(port->ssl);
904         if (port->peer == NULL)
905         {
906                 strncpy(port->peer_dn, "(anonymous)", sizeof(port->peer_dn));
907                 strncpy(port->peer_cn, "(anonymous)", sizeof(port->peer_cn));
908         }
909         else
910         {
911                 X509_NAME_oneline(X509_get_subject_name(port->peer),
912                                                   port->peer_dn, sizeof(port->peer_dn));
913                 port->peer_dn[sizeof(port->peer_dn) - 1] = '\0';
914                 X509_NAME_get_text_by_NID(X509_get_subject_name(port->peer),
915                                            NID_commonName, port->peer_cn, sizeof(port->peer_cn));
916                 port->peer_cn[sizeof(port->peer_cn) - 1] = '\0';
917         }
918         ereport(DEBUG2,
919                         (errmsg("SSL connection from \"%s\"", port->peer_cn)));
920
921         /* set up debugging/info callback */
922         SSL_CTX_set_info_callback(SSL_context, info_cb);
923
924         return 0;
925 }
926
927 /*
928  *      Close SSL connection.
929  */
930 static void
931 close_SSL(Port *port)
932 {
933         if (port->ssl)
934         {
935                 SSL_shutdown(port->ssl);
936                 SSL_free(port->ssl);
937                 port->ssl = NULL;
938         }
939
940         if (port->peer)
941         {
942                 X509_free(port->peer);
943                 port->peer = NULL;
944         }
945 }
946
947 /*
948  * Obtain reason string for last SSL error
949  *
950  * Some caution is needed here since ERR_reason_error_string will
951  * return NULL if it doesn't recognize the error code.  We don't
952  * want to return NULL ever.
953  */
954 static const char *
955 SSLerrmessage(void)
956 {
957         unsigned long errcode;
958         const char *errreason;
959         static char errbuf[32];
960
961         errcode = ERR_get_error();
962         if (errcode == 0)
963                 return "No SSL error reported";
964         errreason = ERR_reason_error_string(errcode);
965         if (errreason != NULL)
966                 return errreason;
967         snprintf(errbuf, sizeof(errbuf), "SSL error code %lu", errcode);
968         return errbuf;
969 }
970
971 #endif   /* USE_SSL */