1 /*-------------------------------------------------------------------------
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.
9 * Portions Copyright (c) 1996-2006, PostgreSQL Global Development Group
10 * Portions Copyright (c) 1994, Regents of the University of California
14 * $PostgreSQL: pgsql/src/interfaces/libpq/fe-secure.c,v 1.89 2006/10/06 17:14:01 petere Exp $
17 * [ Most of these notes are wrong/obsolete, but perhaps not all ]
19 * The client *requires* a valid server certificate. Since
20 * SSH tunnels provide anonymous confidentiality, the presumption
21 * is that sites that want endpoint authentication will use the
22 * direct SSL support, while sites that are comfortable with
23 * anonymous connections will use SSH tunnels.
25 * This code verifies the server certificate, to detect simple
26 * "man-in-the-middle" and "impersonation" attacks. The
27 * server certificate, or better yet the CA certificate used
28 * to sign the server certificate, should be present in the
29 * "~/.postgresql/root.crt" file. If this file isn't
30 * readable, or the server certificate can't be validated,
31 * pqsecure_open_client() will return an error code.
33 * Additionally, the server certificate's "common name" must
34 * resolve to the other end of the socket. This makes it
35 * substantially harder to pull off a "man-in-the-middle" or
36 * "impersonation" attack even if the server's private key
37 * has been stolen. This check limits acceptable network
38 * layers to Unix sockets (weird, but legal), TCPv4 and TCPv6.
40 * Unfortunately neither the current front- or back-end handle
41 * failure gracefully, resulting in the backend hiccupping.
42 * This points out problems in each (the frontend shouldn't even
43 * try to do SSL if pqsecure_initialize() fails, and the backend
44 * shouldn't crash/recover if an SSH negotiation fails. The
45 * backend definitely needs to be fixed, to prevent a "denial
46 * of service" attack, but I don't know enough about how the
47 * backend works (especially that pre-SSL negotiation) to identify
52 * Unlike the server's static private key, the client's
53 * static private key (~/.postgresql/postgresql.key)
54 * should normally be stored encrypted. However we still
55 * support EPH since it's useful for other reasons.
59 * Client certificates are supported, if the server requests
60 * or requires them. Client certificates can be used for
61 * authentication, to prevent sessions from being hijacked,
62 * or to allow "road warriors" to access the database while
63 * keeping it closed to everyone else.
65 * The user's certificate and private key are located in
66 * ~/.postgresql/postgresql.crt
68 * ~/.postgresql/postgresql.key
73 * We don't provide informational callbacks here (like
74 * info_cb() in be-secure.c), since there's mechanism to
75 * display that information to the client.
77 *-------------------------------------------------------------------------
80 #include "postgres_fe.h"
93 #include <sys/socket.h>
96 #include <netinet/in.h>
97 #ifdef HAVE_NETINET_TCP_H
98 #include <netinet/tcp.h>
100 #include <arpa/inet.h>
102 #include <sys/stat.h>
104 #ifdef ENABLE_THREAD_SAFETY
106 #include "pthread-win32.h"
113 #include <openssl/ssl.h>
120 #define USER_CERT_FILE ".postgresql/postgresql.crt"
121 #define USER_KEY_FILE ".postgresql/postgresql.key"
122 #define ROOT_CERT_FILE ".postgresql/root.crt"
123 #define ROOT_CRL_FILE ".postgresql/root.crl"
125 /* On Windows, the "home" directory is already PostgreSQL-specific */
126 #define USER_CERT_FILE "postgresql.crt"
127 #define USER_KEY_FILE "postgresql.key"
128 #define ROOT_CERT_FILE "root.crt"
129 #define ROOT_CRL_FILE "root.crl"
133 static int verify_peer(PGconn *);
135 static int verify_cb(int ok, X509_STORE_CTX *ctx);
136 static int client_cert_cb(SSL *, X509 **, EVP_PKEY **);
137 static int init_ssl_system(PGconn *conn);
138 static int initialize_SSL(PGconn *);
139 static void destroy_SSL(void);
140 static PostgresPollingStatusType open_client_SSL(PGconn *);
141 static void close_SSL(PGconn *);
142 static char *SSLerrmessage(void);
143 static void SSLerrfree(char *buf);
147 static bool pq_initssllib = true;
149 static SSL_CTX *SSL_context = NULL;
152 /* ------------------------------------------------------------ */
153 /* Procedures common to all secure sessions */
154 /* ------------------------------------------------------------ */
158 * Exported function to allow application to tell us it's already
159 * initialized OpenSSL.
162 PQinitSSL(int do_init)
165 pq_initssllib = do_init;
170 * Initialize global context
173 pqsecure_initialize(PGconn *conn)
178 r = initialize_SSL(conn);
185 * Destroy global context
188 pqsecure_destroy(void)
196 * Attempt to negotiate secure session.
198 PostgresPollingStatusType
199 pqsecure_open_client(PGconn *conn)
202 /* First time through? */
203 if (conn->ssl == NULL)
205 if (!(conn->ssl = SSL_new(SSL_context)) ||
206 !SSL_set_app_data(conn->ssl, conn) ||
207 !SSL_set_fd(conn->ssl, conn->sock))
209 char *err = SSLerrmessage();
211 printfPQExpBuffer(&conn->errorMessage,
212 libpq_gettext("could not establish SSL connection: %s\n"),
216 return PGRES_POLLING_FAILED;
220 * Initialize errorMessage to empty. This allows open_client_SSL() to
221 * detect whether client_cert_cb() has stored a message.
223 resetPQExpBuffer(&conn->errorMessage);
225 /* Begin or continue the actual handshake */
226 return open_client_SSL(conn);
228 /* shouldn't get here */
229 return PGRES_POLLING_FAILED;
234 * Close secure session.
237 pqsecure_close(PGconn *conn)
246 * Read data from a secure connection.
249 pqsecure_read(PGconn *conn, void *ptr, size_t len)
259 n = SSL_read(conn->ssl, ptr, len);
260 err = SSL_get_error(conn->ssl, n);
265 case SSL_ERROR_WANT_READ:
268 case SSL_ERROR_WANT_WRITE:
271 * Returning 0 here would cause caller to wait for read-ready,
272 * which is not correct since what SSL wants is wait for
273 * write-ready. The former could get us stuck in an infinite
274 * wait, so don't risk it; busy-loop instead.
277 case SSL_ERROR_SYSCALL:
282 printfPQExpBuffer(&conn->errorMessage,
283 libpq_gettext("SSL SYSCALL error: %s\n"),
284 SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf)));
287 printfPQExpBuffer(&conn->errorMessage,
288 libpq_gettext("SSL SYSCALL error: EOF detected\n"));
290 SOCK_ERRNO_SET(ECONNRESET);
297 char *err = SSLerrmessage();
299 printfPQExpBuffer(&conn->errorMessage,
300 libpq_gettext("SSL error: %s\n"), err);
304 case SSL_ERROR_ZERO_RETURN:
305 SOCK_ERRNO_SET(ECONNRESET);
309 printfPQExpBuffer(&conn->errorMessage,
310 libpq_gettext("unrecognized SSL error code: %d\n"),
318 n = recv(conn->sock, ptr, len, 0);
324 * Write data to a secure connection.
327 pqsecure_write(PGconn *conn, const void *ptr, size_t len)
332 #ifdef ENABLE_THREAD_SAFETY
334 bool sigpipe_pending;
335 bool got_epipe = false;
338 if (pq_block_sigpipe(&osigmask, &sigpipe_pending) < 0)
341 pqsigfunc oldsighandler = pqsignal(SIGPIPE, SIG_IGN);
342 #endif /* ENABLE_THREAD_SAFETY */
350 n = SSL_write(conn->ssl, ptr, len);
351 err = SSL_get_error(conn->ssl, n);
356 case SSL_ERROR_WANT_READ:
359 * Returning 0 here causes caller to wait for write-ready,
360 * which is not really the right thing, but it's the best we
365 case SSL_ERROR_WANT_WRITE:
368 case SSL_ERROR_SYSCALL:
374 #if defined(ENABLE_THREAD_SAFETY) && !defined(WIN32)
375 if (SOCK_ERRNO == EPIPE)
378 printfPQExpBuffer(&conn->errorMessage,
379 libpq_gettext("SSL SYSCALL error: %s\n"),
380 SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf)));
384 printfPQExpBuffer(&conn->errorMessage,
385 libpq_gettext("SSL SYSCALL error: EOF detected\n"));
386 SOCK_ERRNO_SET(ECONNRESET);
393 char *err = SSLerrmessage();
395 printfPQExpBuffer(&conn->errorMessage,
396 libpq_gettext("SSL error: %s\n"), err);
400 case SSL_ERROR_ZERO_RETURN:
401 SOCK_ERRNO_SET(ECONNRESET);
405 printfPQExpBuffer(&conn->errorMessage,
406 libpq_gettext("unrecognized SSL error code: %d\n"),
415 n = send(conn->sock, ptr, len, 0);
416 #if defined(ENABLE_THREAD_SAFETY) && !defined(WIN32)
417 if (n < 0 && SOCK_ERRNO == EPIPE)
423 #ifdef ENABLE_THREAD_SAFETY
424 pq_reset_sigpipe(&osigmask, sigpipe_pending, got_epipe);
426 pqsignal(SIGPIPE, oldsighandler);
427 #endif /* ENABLE_THREAD_SAFETY */
433 /* ------------------------------------------------------------ */
434 /* SSL specific code */
435 /* ------------------------------------------------------------ */
439 * Certificate verification callback
441 * This callback allows us to log intermediate problems during
442 * verification, but there doesn't seem to be a clean way to get
443 * our PGconn * structure. So we can't log anything!
445 * This callback also allows us to override the default acceptance
446 * criteria (e.g., accepting self-signed or expired certs), but
447 * for now we accept the default checks.
450 verify_cb(int ok, X509_STORE_CTX *ctx)
457 * Verify that common name resolves to peer.
460 verify_peer(PGconn *conn)
462 struct hostent *h = NULL;
463 struct sockaddr addr;
464 struct sockaddr_in *sin;
465 ACCEPT_TYPE_ARG3 len;
469 /* get the address on the other side of the socket */
471 if (getpeername(conn->sock, &addr, &len) == -1)
475 printfPQExpBuffer(&conn->errorMessage,
476 libpq_gettext("error querying socket: %s\n"),
477 SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf)));
481 /* weird, but legal case */
482 if (addr.sa_family == AF_UNIX)
486 struct hostent hpstr;
491 * Currently, pqGethostbyname() is used only on platforms that don't
492 * have getaddrinfo(). If you enable this function, you should
493 * convert the pqGethostbyname() function call to use getaddrinfo().
495 pqGethostbyname(conn->peer_cn, &hpstr, buf, sizeof(buf),
499 /* what do we know about the peer's common name? */
502 printfPQExpBuffer(&conn->errorMessage,
503 libpq_gettext("could not get information about host \"%s\": %s\n"),
504 conn->peer_cn, hstrerror(h_errno));
508 /* does the address match? */
509 switch (addr.sa_family)
512 sin = (struct sockaddr_in *) & addr;
513 for (s = h->h_addr_list; *s != NULL; s++)
515 if (!memcmp(&sin->sin_addr.s_addr, *s, h->h_length))
521 printfPQExpBuffer(&conn->errorMessage,
522 libpq_gettext("unsupported protocol\n"));
527 * the prior test should be definitive, but in practice it sometimes
528 * fails. So we also check the aliases.
530 for (s = h->h_aliases; *s != NULL; s++)
532 if (pg_strcasecmp(conn->peer_cn, *s) == 0)
536 /* generate protocol-aware error message */
537 switch (addr.sa_family)
540 sin = (struct sockaddr_in *) & addr;
541 l = ntohl(sin->sin_addr.s_addr);
542 printfPQExpBuffer(&conn->errorMessage,
544 "server common name \"%s\" does not resolve to %ld.%ld.%ld.%ld\n"),
545 conn->peer_cn, (l >> 24) % 0x100, (l >> 16) % 0x100,
546 (l >> 8) % 0x100, l % 0x100);
549 printfPQExpBuffer(&conn->errorMessage,
551 "server common name \"%s\" does not resolve to peer address\n"),
557 #endif /* NOT_USED */
560 * Callback used by SSL to load client cert and key.
561 * This callback is only called when the server wants a
564 * Must return 1 on success, 0 on no data or error.
567 client_cert_cb(SSL *ssl, X509 **x509, EVP_PKEY **pkey)
569 char homedir[MAXPGPATH];
575 char fnbuf[MAXPGPATH];
577 PGconn *conn = (PGconn *) SSL_get_app_data(ssl);
578 int (*cb) () = NULL; /* how to read user password */
581 if (!pqGetHomeDirectory(homedir, sizeof(homedir)))
583 printfPQExpBuffer(&conn->errorMessage,
584 libpq_gettext("could not get user information\n"));
588 /* read the user certificate */
589 snprintf(fnbuf, sizeof(fnbuf), "%s/%s", homedir, USER_CERT_FILE);
590 if ((fp = fopen(fnbuf, "r")) == NULL)
592 printfPQExpBuffer(&conn->errorMessage,
593 libpq_gettext("could not open certificate file \"%s\": %s\n"),
594 fnbuf, pqStrerror(errno, sebuf, sizeof(sebuf)));
597 if (PEM_read_X509(fp, x509, NULL, NULL) == NULL)
599 char *err = SSLerrmessage();
601 printfPQExpBuffer(&conn->errorMessage,
602 libpq_gettext("could not read certificate file \"%s\": %s\n"),
610 /* read the user key */
611 snprintf(fnbuf, sizeof(fnbuf), "%s/%s", homedir, USER_KEY_FILE);
612 if (stat(fnbuf, &buf) == -1)
614 printfPQExpBuffer(&conn->errorMessage,
615 libpq_gettext("certificate present, but not private key file \"%s\"\n"),
620 if (!S_ISREG(buf.st_mode) || (buf.st_mode & 0077) ||
621 buf.st_uid != geteuid())
623 printfPQExpBuffer(&conn->errorMessage,
624 libpq_gettext("private key file \"%s\" has wrong permissions\n"),
629 if ((fp = fopen(fnbuf, "r")) == NULL)
631 printfPQExpBuffer(&conn->errorMessage,
632 libpq_gettext("could not open private key file \"%s\": %s\n"),
633 fnbuf, pqStrerror(errno, sebuf, sizeof(sebuf)));
637 if (fstat(fileno(fp), &buf2) == -1 ||
638 buf.st_dev != buf2.st_dev || buf.st_ino != buf2.st_ino)
640 printfPQExpBuffer(&conn->errorMessage,
641 libpq_gettext("private key file \"%s\" changed during execution\n"), fnbuf);
645 if (PEM_read_PrivateKey(fp, pkey, cb, NULL) == NULL)
647 char *err = SSLerrmessage();
649 printfPQExpBuffer(&conn->errorMessage,
650 libpq_gettext("could not read private key file \"%s\": %s\n"),
658 /* verify that the cert and key go together */
659 if (!X509_check_private_key(*x509, *pkey))
661 char *err = SSLerrmessage();
663 printfPQExpBuffer(&conn->errorMessage,
664 libpq_gettext("certificate does not match private key file \"%s\": %s\n"),
673 #ifdef ENABLE_THREAD_SAFETY
676 pq_threadidcallback(void)
679 * This is not standards-compliant. pthread_self() returns pthread_t, and
680 * shouldn't be cast to unsigned long, but CRYPTO_set_id_callback requires
681 * it, so we have to do it.
683 return (unsigned long) pthread_self();
686 static pthread_mutex_t *pq_lockarray;
689 pq_lockingcallback(int mode, int n, const char *file, int line)
691 if (mode & CRYPTO_LOCK)
692 pthread_mutex_lock(&pq_lockarray[n]);
694 pthread_mutex_unlock(&pq_lockarray[n]);
696 #endif /* ENABLE_THREAD_SAFETY */
699 init_ssl_system(PGconn *conn)
701 #ifdef ENABLE_THREAD_SAFETY
703 static pthread_mutex_t init_mutex = PTHREAD_MUTEX_INITIALIZER;
705 static pthread_mutex_t init_mutex = NULL;
706 static long mutex_initlock = 0;
708 if (init_mutex == NULL)
710 while (InterlockedExchange(&mutex_initlock, 1) == 1)
711 /* loop, another thread own the lock */ ;
712 if (init_mutex == NULL)
713 pthread_mutex_init(&init_mutex, NULL);
714 InterlockedExchange(&mutex_initlock, 0);
717 pthread_mutex_lock(&init_mutex);
719 if (pq_initssllib && pq_lockarray == NULL)
723 CRYPTO_set_id_callback(pq_threadidcallback);
725 pq_lockarray = malloc(sizeof(pthread_mutex_t) * CRYPTO_num_locks());
728 pthread_mutex_unlock(&init_mutex);
731 for (i = 0; i < CRYPTO_num_locks(); i++)
732 pthread_mutex_init(&pq_lockarray[i], NULL);
734 CRYPTO_set_locking_callback(pq_lockingcallback);
742 SSL_load_error_strings();
744 SSL_context = SSL_CTX_new(TLSv1_method());
747 char *err = SSLerrmessage();
749 printfPQExpBuffer(&conn->errorMessage,
750 libpq_gettext("could not create SSL context: %s\n"),
753 #ifdef ENABLE_THREAD_SAFETY
754 pthread_mutex_unlock(&init_mutex);
759 #ifdef ENABLE_THREAD_SAFETY
760 pthread_mutex_unlock(&init_mutex);
766 * Initialize global SSL context.
769 initialize_SSL(PGconn *conn)
772 char homedir[MAXPGPATH];
773 char fnbuf[MAXPGPATH];
775 if (init_ssl_system(conn))
778 /* Set up to verify server cert, if root.crt is present */
779 if (pqGetHomeDirectory(homedir, sizeof(homedir)))
781 snprintf(fnbuf, sizeof(fnbuf), "%s/%s", homedir, ROOT_CERT_FILE);
782 if (stat(fnbuf, &buf) == 0)
786 if (!SSL_CTX_load_verify_locations(SSL_context, fnbuf, NULL))
788 char *err = SSLerrmessage();
790 printfPQExpBuffer(&conn->errorMessage,
791 libpq_gettext("could not read root certificate file \"%s\": %s\n"),
797 if ((cvstore = SSL_CTX_get_cert_store(SSL_context)) != NULL)
799 /* setting the flags to check against the complete CRL chain */
800 if (X509_STORE_load_locations(cvstore, ROOT_CRL_FILE, NULL) != 0)
801 /* OpenSSL 0.96 does not support X509_V_FLAG_CRL_CHECK */
802 #ifdef X509_V_FLAG_CRL_CHECK
803 X509_STORE_set_flags(cvstore,
804 X509_V_FLAG_CRL_CHECK | X509_V_FLAG_CRL_CHECK_ALL);
805 /* if not found, silently ignore; we do not require CRL */
808 char *err = SSLerrmessage();
810 printfPQExpBuffer(&conn->errorMessage,
811 libpq_gettext("SSL library does not support CRL certificates (file \"%s\")\n"),
819 SSL_CTX_set_verify(SSL_context, SSL_VERIFY_PEER, verify_cb);
823 /* set up mechanism to provide client certificate, if available */
824 SSL_CTX_set_client_cert_cb(SSL_context, client_cert_cb);
830 * Destroy global SSL context.
837 SSL_CTX_free(SSL_context);
843 * Attempt to negotiate SSL connection.
845 static PostgresPollingStatusType
846 open_client_SSL(PGconn *conn)
850 r = SSL_connect(conn->ssl);
853 int err = SSL_get_error(conn->ssl, r);
857 case SSL_ERROR_WANT_READ:
858 return PGRES_POLLING_READING;
860 case SSL_ERROR_WANT_WRITE:
861 return PGRES_POLLING_WRITING;
863 case SSL_ERROR_SYSCALL:
868 printfPQExpBuffer(&conn->errorMessage,
869 libpq_gettext("SSL SYSCALL error: %s\n"),
870 SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf)));
872 printfPQExpBuffer(&conn->errorMessage,
873 libpq_gettext("SSL SYSCALL error: EOF detected\n"));
875 return PGRES_POLLING_FAILED;
880 * If there are problems with the local certificate files,
881 * these will be detected by client_cert_cb() which is
882 * called from SSL_connect(). We want to return that
883 * error message and not the rather unhelpful error that
884 * OpenSSL itself returns. So check to see if an error
885 * message was already stored.
887 if (conn->errorMessage.len == 0)
889 char *err = SSLerrmessage();
891 printfPQExpBuffer(&conn->errorMessage,
892 libpq_gettext("SSL error: %s\n"),
897 return PGRES_POLLING_FAILED;
901 printfPQExpBuffer(&conn->errorMessage,
902 libpq_gettext("unrecognized SSL error code: %d\n"),
905 return PGRES_POLLING_FAILED;
909 /* check the certificate chain of the server */
912 /* CLIENT CERTIFICATES NOT REQUIRED bjm 2002-09-26 */
915 * this eliminates simple man-in-the-middle attacks and simple
918 r = SSL_get_verify_result(conn->ssl);
921 printfPQExpBuffer(&conn->errorMessage,
922 libpq_gettext("certificate could not be validated: %s\n"),
923 X509_verify_cert_error_string(r));
925 return PGRES_POLLING_FAILED;
929 /* pull out server distinguished and common names */
930 conn->peer = SSL_get_peer_certificate(conn->ssl);
931 if (conn->peer == NULL)
933 char *err = SSLerrmessage();
935 printfPQExpBuffer(&conn->errorMessage,
936 libpq_gettext("certificate could not be obtained: %s\n"),
940 return PGRES_POLLING_FAILED;
943 X509_NAME_oneline(X509_get_subject_name(conn->peer),
944 conn->peer_dn, sizeof(conn->peer_dn));
945 conn->peer_dn[sizeof(conn->peer_dn) - 1] = '\0';
947 X509_NAME_get_text_by_NID(X509_get_subject_name(conn->peer),
948 NID_commonName, conn->peer_cn, SM_USER);
949 conn->peer_cn[SM_USER] = '\0';
951 /* verify that the common name resolves to peer */
954 /* CLIENT CERTIFICATES NOT REQUIRED bjm 2002-09-26 */
957 * this is necessary to eliminate man-in-the-middle attacks and
958 * impersonations where the attacker somehow learned the server's private
961 if (verify_peer(conn) == -1)
964 return PGRES_POLLING_FAILED;
968 /* SSL handshake is complete */
969 return PGRES_POLLING_OK;
973 * Close SSL connection.
976 close_SSL(PGconn *conn)
980 SSL_shutdown(conn->ssl);
987 X509_free(conn->peer);
993 * Obtain reason string for last SSL error
995 * Some caution is needed here since ERR_reason_error_string will
996 * return NULL if it doesn't recognize the error code. We don't
997 * want to return NULL ever.
999 static char ssl_nomem[] = "out of memory allocating error description";
1001 #define SSL_ERR_LEN 128
1006 unsigned long errcode;
1007 const char *errreason;
1010 errbuf = malloc(SSL_ERR_LEN);
1013 errcode = ERR_get_error();
1016 snprintf(errbuf, SSL_ERR_LEN, libpq_gettext("no SSL error reported"));
1019 errreason = ERR_reason_error_string(errcode);
1020 if (errreason != NULL)
1022 strncpy(errbuf, errreason, SSL_ERR_LEN - 1);
1023 errbuf[SSL_ERR_LEN - 1] = '\0';
1026 snprintf(errbuf, SSL_ERR_LEN, libpq_gettext("SSL error code %lu"), errcode);
1031 SSLerrfree(char *buf)
1033 if (buf != ssl_nomem)
1038 * Return pointer to OpenSSL object.
1041 PQgetssl(PGconn *conn)
1047 #else /* !USE_SSL */
1050 PQgetssl(PGconn *conn)
1054 #endif /* USE_SSL */
1056 #if defined(ENABLE_THREAD_SAFETY) && !defined(WIN32)
1059 * Block SIGPIPE for this thread. This prevents send()/write() from exiting
1063 pq_block_sigpipe(sigset_t *osigset, bool *sigpipe_pending)
1065 sigset_t sigpipe_sigset;
1068 sigemptyset(&sigpipe_sigset);
1069 sigaddset(&sigpipe_sigset, SIGPIPE);
1071 /* Block SIGPIPE and save previous mask for later reset */
1072 SOCK_ERRNO_SET(pthread_sigmask(SIG_BLOCK, &sigpipe_sigset, osigset));
1076 /* We can have a pending SIGPIPE only if it was blocked before */
1077 if (sigismember(osigset, SIGPIPE))
1079 /* Is there a pending SIGPIPE? */
1080 if (sigpending(&sigset) != 0)
1083 if (sigismember(&sigset, SIGPIPE))
1084 *sigpipe_pending = true;
1086 *sigpipe_pending = false;
1089 *sigpipe_pending = false;
1095 * Discard any pending SIGPIPE and reset the signal mask.
1097 * Note: we are effectively assuming here that the C library doesn't queue
1098 * up multiple SIGPIPE events. If it did, then we'd accidentally leave
1099 * ours in the queue when an event was already pending and we got another.
1100 * As long as it doesn't queue multiple events, we're OK because the caller
1101 * can't tell the difference.
1103 * The caller should say got_epipe = FALSE if it is certain that it
1104 * didn't get an EPIPE error; in that case we'll skip the clear operation
1105 * and things are definitely OK, queuing or no. If it got one or might have
1106 * gotten one, pass got_epipe = TRUE.
1108 * We do not want this to change errno, since if it did that could lose
1109 * the error code from a preceding send(). We essentially assume that if
1110 * we were able to do pq_block_sigpipe(), this can't fail.
1113 pq_reset_sigpipe(sigset_t *osigset, bool sigpipe_pending, bool got_epipe)
1115 int save_errno = SOCK_ERRNO;
1119 /* Clear SIGPIPE only if none was pending */
1120 if (got_epipe && !sigpipe_pending)
1122 if (sigpending(&sigset) == 0 &&
1123 sigismember(&sigset, SIGPIPE))
1125 sigset_t sigpipe_sigset;
1127 sigemptyset(&sigpipe_sigset);
1128 sigaddset(&sigpipe_sigset, SIGPIPE);
1130 sigwait(&sigpipe_sigset, &signo);
1134 /* Restore saved block mask */
1135 pthread_sigmask(SIG_SETMASK, osigset, NULL);
1137 SOCK_ERRNO_SET(save_errno);
1140 #endif /* ENABLE_THREAD_SAFETY */