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.85 2006/07/14 16:59:19 tgl 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"
117 #include <openssl/ssl.h>
124 #define USER_CERT_FILE ".postgresql/postgresql.crt"
125 #define USER_KEY_FILE ".postgresql/postgresql.key"
126 #define ROOT_CERT_FILE ".postgresql/root.crt"
127 #define ROOT_CRL_FILE ".postgresql/root.crl"
129 /* On Windows, the "home" directory is already PostgreSQL-specific */
130 #define USER_CERT_FILE "postgresql.crt"
131 #define USER_KEY_FILE "postgresql.key"
132 #define ROOT_CERT_FILE "root.crt"
133 #define ROOT_CRL_FILE "root.crl"
137 static int verify_peer(PGconn *);
139 static int verify_cb(int ok, X509_STORE_CTX *ctx);
140 static int client_cert_cb(SSL *, X509 **, EVP_PKEY **);
141 static int init_ssl_system(PGconn *conn);
142 static int initialize_SSL(PGconn *);
143 static void destroy_SSL(void);
144 static PostgresPollingStatusType open_client_SSL(PGconn *);
145 static void close_SSL(PGconn *);
146 static char *SSLerrmessage(void);
147 static void SSLerrfree(char *buf);
151 static bool pq_initssllib = true;
153 static SSL_CTX *SSL_context = NULL;
156 /* ------------------------------------------------------------ */
157 /* Procedures common to all secure sessions */
158 /* ------------------------------------------------------------ */
162 * Exported function to allow application to tell us it's already
163 * initialized OpenSSL.
166 PQinitSSL(int do_init)
169 pq_initssllib = do_init;
174 * Initialize global context
177 pqsecure_initialize(PGconn *conn)
182 r = initialize_SSL(conn);
189 * Destroy global context
192 pqsecure_destroy(void)
200 * Attempt to negotiate secure session.
202 PostgresPollingStatusType
203 pqsecure_open_client(PGconn *conn)
206 /* First time through? */
207 if (conn->ssl == NULL)
209 if (!(conn->ssl = SSL_new(SSL_context)) ||
210 !SSL_set_app_data(conn->ssl, conn) ||
211 !SSL_set_fd(conn->ssl, conn->sock))
213 char *err = SSLerrmessage();
215 printfPQExpBuffer(&conn->errorMessage,
216 libpq_gettext("could not establish SSL connection: %s\n"),
220 return PGRES_POLLING_FAILED;
224 * Initialize errorMessage to empty. This allows open_client_SSL() to
225 * detect whether client_cert_cb() has stored a message.
227 resetPQExpBuffer(&conn->errorMessage);
229 /* Begin or continue the actual handshake */
230 return open_client_SSL(conn);
232 /* shouldn't get here */
233 return PGRES_POLLING_FAILED;
238 * Close secure session.
241 pqsecure_close(PGconn *conn)
250 * Read data from a secure connection.
253 pqsecure_read(PGconn *conn, void *ptr, size_t len)
263 n = SSL_read(conn->ssl, ptr, len);
264 err = SSL_get_error(conn->ssl, n);
269 case SSL_ERROR_WANT_READ:
272 case SSL_ERROR_WANT_WRITE:
275 * Returning 0 here would cause caller to wait for read-ready,
276 * which is not correct since what SSL wants is wait for
277 * write-ready. The former could get us stuck in an infinite
278 * wait, so don't risk it; busy-loop instead.
281 case SSL_ERROR_SYSCALL:
286 printfPQExpBuffer(&conn->errorMessage,
287 libpq_gettext("SSL SYSCALL error: %s\n"),
288 SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf)));
291 printfPQExpBuffer(&conn->errorMessage,
292 libpq_gettext("SSL SYSCALL error: EOF detected\n"));
294 SOCK_ERRNO_SET(ECONNRESET);
301 char *err = SSLerrmessage();
303 printfPQExpBuffer(&conn->errorMessage,
304 libpq_gettext("SSL error: %s\n"), err);
308 case SSL_ERROR_ZERO_RETURN:
309 SOCK_ERRNO_SET(ECONNRESET);
313 printfPQExpBuffer(&conn->errorMessage,
314 libpq_gettext("unrecognized SSL error code: %d\n"),
322 n = recv(conn->sock, ptr, len, 0);
328 * Write data to a secure connection.
331 pqsecure_write(PGconn *conn, const void *ptr, size_t len)
336 #ifdef ENABLE_THREAD_SAFETY
338 bool sigpipe_pending;
339 bool got_epipe = false;
342 if (pq_block_sigpipe(&osigmask, &sigpipe_pending) < 0)
345 pqsigfunc oldsighandler = pqsignal(SIGPIPE, SIG_IGN);
346 #endif /* ENABLE_THREAD_SAFETY */
354 n = SSL_write(conn->ssl, ptr, len);
355 err = SSL_get_error(conn->ssl, n);
360 case SSL_ERROR_WANT_READ:
363 * Returning 0 here causes caller to wait for write-ready,
364 * which is not really the right thing, but it's the best we
369 case SSL_ERROR_WANT_WRITE:
372 case SSL_ERROR_SYSCALL:
378 #if defined(ENABLE_THREAD_SAFETY) && !defined(WIN32)
379 if (SOCK_ERRNO == EPIPE)
382 printfPQExpBuffer(&conn->errorMessage,
383 libpq_gettext("SSL SYSCALL error: %s\n"),
384 SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf)));
388 printfPQExpBuffer(&conn->errorMessage,
389 libpq_gettext("SSL SYSCALL error: EOF detected\n"));
390 SOCK_ERRNO_SET(ECONNRESET);
397 char *err = SSLerrmessage();
399 printfPQExpBuffer(&conn->errorMessage,
400 libpq_gettext("SSL error: %s\n"), err);
404 case SSL_ERROR_ZERO_RETURN:
405 SOCK_ERRNO_SET(ECONNRESET);
409 printfPQExpBuffer(&conn->errorMessage,
410 libpq_gettext("unrecognized SSL error code: %d\n"),
419 n = send(conn->sock, ptr, len, 0);
420 #if defined(ENABLE_THREAD_SAFETY) && !defined(WIN32)
421 if (n < 0 && SOCK_ERRNO == EPIPE)
427 #ifdef ENABLE_THREAD_SAFETY
428 pq_reset_sigpipe(&osigmask, sigpipe_pending, got_epipe);
430 pqsignal(SIGPIPE, oldsighandler);
431 #endif /* ENABLE_THREAD_SAFETY */
437 /* ------------------------------------------------------------ */
438 /* SSL specific code */
439 /* ------------------------------------------------------------ */
443 * Certificate verification callback
445 * This callback allows us to log intermediate problems during
446 * verification, but there doesn't seem to be a clean way to get
447 * our PGconn * structure. So we can't log anything!
449 * This callback also allows us to override the default acceptance
450 * criteria (e.g., accepting self-signed or expired certs), but
451 * for now we accept the default checks.
454 verify_cb(int ok, X509_STORE_CTX *ctx)
461 * Verify that common name resolves to peer.
464 verify_peer(PGconn *conn)
466 struct hostent *h = NULL;
467 struct sockaddr addr;
468 struct sockaddr_in *sin;
469 ACCEPT_TYPE_ARG3 len;
473 /* get the address on the other side of the socket */
475 if (getpeername(conn->sock, &addr, &len) == -1)
479 printfPQExpBuffer(&conn->errorMessage,
480 libpq_gettext("error querying socket: %s\n"),
481 SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf)));
485 /* weird, but legal case */
486 if (addr.sa_family == AF_UNIX)
490 struct hostent hpstr;
495 * Currently, pqGethostbyname() is used only on platforms that don't
496 * have getaddrinfo(). If you enable this function, you should
497 * convert the pqGethostbyname() function call to use getaddrinfo().
499 pqGethostbyname(conn->peer_cn, &hpstr, buf, sizeof(buf),
503 /* what do we know about the peer's common name? */
506 printfPQExpBuffer(&conn->errorMessage,
507 libpq_gettext("could not get information about host \"%s\": %s\n"),
508 conn->peer_cn, hstrerror(h_errno));
512 /* does the address match? */
513 switch (addr.sa_family)
516 sin = (struct sockaddr_in *) & addr;
517 for (s = h->h_addr_list; *s != NULL; s++)
519 if (!memcmp(&sin->sin_addr.s_addr, *s, h->h_length))
525 printfPQExpBuffer(&conn->errorMessage,
526 libpq_gettext("unsupported protocol\n"));
531 * the prior test should be definitive, but in practice it sometimes
532 * fails. So we also check the aliases.
534 for (s = h->h_aliases; *s != NULL; s++)
536 if (pg_strcasecmp(conn->peer_cn, *s) == 0)
540 /* generate protocol-aware error message */
541 switch (addr.sa_family)
544 sin = (struct sockaddr_in *) & addr;
545 l = ntohl(sin->sin_addr.s_addr);
546 printfPQExpBuffer(&conn->errorMessage,
548 "server common name \"%s\" does not resolve to %ld.%ld.%ld.%ld\n"),
549 conn->peer_cn, (l >> 24) % 0x100, (l >> 16) % 0x100,
550 (l >> 8) % 0x100, l % 0x100);
553 printfPQExpBuffer(&conn->errorMessage,
555 "server common name \"%s\" does not resolve to peer address\n"),
561 #endif /* NOT_USED */
564 * Callback used by SSL to load client cert and key.
565 * This callback is only called when the server wants a
568 * Must return 1 on success, 0 on no data or error.
571 client_cert_cb(SSL *ssl, X509 **x509, EVP_PKEY **pkey)
573 char homedir[MAXPGPATH];
579 char fnbuf[MAXPGPATH];
581 PGconn *conn = (PGconn *) SSL_get_app_data(ssl);
582 int (*cb) () = NULL; /* how to read user password */
585 if (!pqGetHomeDirectory(homedir, sizeof(homedir)))
587 printfPQExpBuffer(&conn->errorMessage,
588 libpq_gettext("could not get user information\n"));
592 /* read the user certificate */
593 snprintf(fnbuf, sizeof(fnbuf), "%s/%s", homedir, USER_CERT_FILE);
594 if ((fp = fopen(fnbuf, "r")) == NULL)
596 printfPQExpBuffer(&conn->errorMessage,
597 libpq_gettext("could not open certificate file \"%s\": %s\n"),
598 fnbuf, pqStrerror(errno, sebuf, sizeof(sebuf)));
601 if (PEM_read_X509(fp, x509, NULL, NULL) == NULL)
603 char *err = SSLerrmessage();
605 printfPQExpBuffer(&conn->errorMessage,
606 libpq_gettext("could not read certificate file \"%s\": %s\n"),
614 /* read the user key */
615 snprintf(fnbuf, sizeof(fnbuf), "%s/%s", homedir, USER_KEY_FILE);
616 if (stat(fnbuf, &buf) == -1)
618 printfPQExpBuffer(&conn->errorMessage,
619 libpq_gettext("certificate present, but not private key file \"%s\"\n"),
624 if (!S_ISREG(buf.st_mode) || (buf.st_mode & 0077) ||
625 buf.st_uid != geteuid())
627 printfPQExpBuffer(&conn->errorMessage,
628 libpq_gettext("private key file \"%s\" has wrong permissions\n"),
633 if ((fp = fopen(fnbuf, "r")) == NULL)
635 printfPQExpBuffer(&conn->errorMessage,
636 libpq_gettext("could not open private key file \"%s\": %s\n"),
637 fnbuf, pqStrerror(errno, sebuf, sizeof(sebuf)));
641 if (fstat(fileno(fp), &buf2) == -1 ||
642 buf.st_dev != buf2.st_dev || buf.st_ino != buf2.st_ino)
644 printfPQExpBuffer(&conn->errorMessage,
645 libpq_gettext("private key file \"%s\" changed during execution\n"), fnbuf);
649 if (PEM_read_PrivateKey(fp, pkey, cb, NULL) == NULL)
651 char *err = SSLerrmessage();
653 printfPQExpBuffer(&conn->errorMessage,
654 libpq_gettext("could not read private key file \"%s\": %s\n"),
662 /* verify that the cert and key go together */
663 if (!X509_check_private_key(*x509, *pkey))
665 char *err = SSLerrmessage();
667 printfPQExpBuffer(&conn->errorMessage,
668 libpq_gettext("certificate does not match private key file \"%s\": %s\n"),
677 #ifdef ENABLE_THREAD_SAFETY
680 pq_threadidcallback(void)
683 * This is not standards-compliant. pthread_self() returns pthread_t, and
684 * shouldn't be cast to unsigned long, but CRYPTO_set_id_callback requires
685 * it, so we have to do it.
687 return (unsigned long) pthread_self();
690 static pthread_mutex_t *pq_lockarray;
693 pq_lockingcallback(int mode, int n, const char *file, int line)
695 if (mode & CRYPTO_LOCK)
696 pthread_mutex_lock(&pq_lockarray[n]);
698 pthread_mutex_unlock(&pq_lockarray[n]);
700 #endif /* ENABLE_THREAD_SAFETY */
703 init_ssl_system(PGconn *conn)
705 #ifdef ENABLE_THREAD_SAFETY
707 static pthread_mutex_t init_mutex = PTHREAD_MUTEX_INITIALIZER;
709 static pthread_mutex_t init_mutex = NULL;
710 static long mutex_initlock = 0;
712 if (init_mutex == NULL)
714 while (InterlockedExchange(&mutex_initlock, 1) == 1)
715 /* loop, another thread own the lock */ ;
716 if (init_mutex == NULL)
717 pthread_mutex_init(&init_mutex, NULL);
718 InterlockedExchange(&mutex_initlock, 0);
721 pthread_mutex_lock(&init_mutex);
723 if (pq_initssllib && pq_lockarray == NULL)
727 CRYPTO_set_id_callback(pq_threadidcallback);
729 pq_lockarray = malloc(sizeof(pthread_mutex_t) * CRYPTO_num_locks());
732 pthread_mutex_unlock(&init_mutex);
735 for (i = 0; i < CRYPTO_num_locks(); i++)
736 pthread_mutex_init(&pq_lockarray[i], NULL);
738 CRYPTO_set_locking_callback(pq_lockingcallback);
746 SSL_load_error_strings();
748 SSL_context = SSL_CTX_new(TLSv1_method());
751 char *err = SSLerrmessage();
753 printfPQExpBuffer(&conn->errorMessage,
754 libpq_gettext("could not create SSL context: %s\n"),
757 #ifdef ENABLE_THREAD_SAFETY
758 pthread_mutex_unlock(&init_mutex);
763 #ifdef ENABLE_THREAD_SAFETY
764 pthread_mutex_unlock(&init_mutex);
770 * Initialize global SSL context.
773 initialize_SSL(PGconn *conn)
776 char homedir[MAXPGPATH];
777 char fnbuf[MAXPGPATH];
779 if (init_ssl_system(conn))
782 /* Set up to verify server cert, if root.crt is present */
783 if (pqGetHomeDirectory(homedir, sizeof(homedir)))
785 snprintf(fnbuf, sizeof(fnbuf), "%s/%s", homedir, ROOT_CERT_FILE);
786 if (stat(fnbuf, &buf) == 0)
790 if (!SSL_CTX_load_verify_locations(SSL_context, fnbuf, NULL))
792 char *err = SSLerrmessage();
794 printfPQExpBuffer(&conn->errorMessage,
795 libpq_gettext("could not read root certificate file \"%s\": %s\n"),
801 if ((cvstore = SSL_CTX_get_cert_store(SSL_context)) != NULL)
803 /* setting the flags to check against the complete CRL chain */
804 if (X509_STORE_load_locations(cvstore, ROOT_CRL_FILE, NULL) != 0)
805 /* OpenSSL 0.96 does not support X509_V_FLAG_CRL_CHECK */
806 #ifdef X509_V_FLAG_CRL_CHECK
807 X509_STORE_set_flags(cvstore,
808 X509_V_FLAG_CRL_CHECK|X509_V_FLAG_CRL_CHECK_ALL);
809 /* if not found, silently ignore; we do not require CRL */
812 char *err = SSLerrmessage();
814 printfPQExpBuffer(&conn->errorMessage,
815 libpq_gettext("Installed SSL library does not support CRL certificates, file \"%s\"\n"),
823 SSL_CTX_set_verify(SSL_context, SSL_VERIFY_PEER, verify_cb);
827 /* set up mechanism to provide client certificate, if available */
828 SSL_CTX_set_client_cert_cb(SSL_context, client_cert_cb);
834 * Destroy global SSL context.
841 SSL_CTX_free(SSL_context);
847 * Attempt to negotiate SSL connection.
849 static PostgresPollingStatusType
850 open_client_SSL(PGconn *conn)
854 r = SSL_connect(conn->ssl);
857 int err = SSL_get_error(conn->ssl, r);
861 case SSL_ERROR_WANT_READ:
862 return PGRES_POLLING_READING;
864 case SSL_ERROR_WANT_WRITE:
865 return PGRES_POLLING_WRITING;
867 case SSL_ERROR_SYSCALL:
872 printfPQExpBuffer(&conn->errorMessage,
873 libpq_gettext("SSL SYSCALL error: %s\n"),
874 SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf)));
876 printfPQExpBuffer(&conn->errorMessage,
877 libpq_gettext("SSL SYSCALL error: EOF detected\n"));
879 return PGRES_POLLING_FAILED;
884 * If there are problems with the local certificate files,
885 * these will be detected by client_cert_cb() which is
886 * called from SSL_connect(). We want to return that
887 * error message and not the rather unhelpful error that
888 * OpenSSL itself returns. So check to see if an error
889 * message was already stored.
891 if (conn->errorMessage.len == 0)
893 char *err = SSLerrmessage();
895 printfPQExpBuffer(&conn->errorMessage,
896 libpq_gettext("SSL error: %s\n"),
901 return PGRES_POLLING_FAILED;
905 printfPQExpBuffer(&conn->errorMessage,
906 libpq_gettext("unrecognized SSL error code: %d\n"),
909 return PGRES_POLLING_FAILED;
913 /* check the certificate chain of the server */
916 /* CLIENT CERTIFICATES NOT REQUIRED bjm 2002-09-26 */
919 * this eliminates simple man-in-the-middle attacks and simple
922 r = SSL_get_verify_result(conn->ssl);
925 printfPQExpBuffer(&conn->errorMessage,
926 libpq_gettext("certificate could not be validated: %s\n"),
927 X509_verify_cert_error_string(r));
929 return PGRES_POLLING_FAILED;
933 /* pull out server distinguished and common names */
934 conn->peer = SSL_get_peer_certificate(conn->ssl);
935 if (conn->peer == NULL)
937 char *err = SSLerrmessage();
939 printfPQExpBuffer(&conn->errorMessage,
940 libpq_gettext("certificate could not be obtained: %s\n"),
944 return PGRES_POLLING_FAILED;
947 X509_NAME_oneline(X509_get_subject_name(conn->peer),
948 conn->peer_dn, sizeof(conn->peer_dn));
949 conn->peer_dn[sizeof(conn->peer_dn) - 1] = '\0';
951 X509_NAME_get_text_by_NID(X509_get_subject_name(conn->peer),
952 NID_commonName, conn->peer_cn, SM_USER);
953 conn->peer_cn[SM_USER] = '\0';
955 /* verify that the common name resolves to peer */
958 /* CLIENT CERTIFICATES NOT REQUIRED bjm 2002-09-26 */
961 * this is necessary to eliminate man-in-the-middle attacks and
962 * impersonations where the attacker somehow learned the server's private
965 if (verify_peer(conn) == -1)
968 return PGRES_POLLING_FAILED;
972 /* SSL handshake is complete */
973 return PGRES_POLLING_OK;
977 * Close SSL connection.
980 close_SSL(PGconn *conn)
984 SSL_shutdown(conn->ssl);
991 X509_free(conn->peer);
997 * Obtain reason string for last SSL error
999 * Some caution is needed here since ERR_reason_error_string will
1000 * return NULL if it doesn't recognize the error code. We don't
1001 * want to return NULL ever.
1003 static char ssl_nomem[] = "Out of memory allocating error description";
1005 #define SSL_ERR_LEN 128
1010 unsigned long errcode;
1011 const char *errreason;
1014 errbuf = malloc(SSL_ERR_LEN);
1017 errcode = ERR_get_error();
1020 strcpy(errbuf, "No SSL error reported");
1023 errreason = ERR_reason_error_string(errcode);
1024 if (errreason != NULL)
1026 strncpy(errbuf, errreason, SSL_ERR_LEN - 1);
1027 errbuf[SSL_ERR_LEN - 1] = '\0';
1030 snprintf(errbuf, SSL_ERR_LEN, "SSL error code %lu", errcode);
1035 SSLerrfree(char *buf)
1037 if (buf != ssl_nomem)
1042 * Return pointer to OpenSSL object.
1045 PQgetssl(PGconn *conn)
1051 #else /* !USE_SSL */
1054 PQgetssl(PGconn *conn)
1058 #endif /* USE_SSL */
1060 #if defined(ENABLE_THREAD_SAFETY) && !defined(WIN32)
1063 * Block SIGPIPE for this thread. This prevents send()/write() from exiting
1067 pq_block_sigpipe(sigset_t *osigset, bool *sigpipe_pending)
1069 sigset_t sigpipe_sigset;
1072 sigemptyset(&sigpipe_sigset);
1073 sigaddset(&sigpipe_sigset, SIGPIPE);
1075 /* Block SIGPIPE and save previous mask for later reset */
1076 SOCK_ERRNO_SET(pthread_sigmask(SIG_BLOCK, &sigpipe_sigset, osigset));
1080 /* We can have a pending SIGPIPE only if it was blocked before */
1081 if (sigismember(osigset, SIGPIPE))
1083 /* Is there a pending SIGPIPE? */
1084 if (sigpending(&sigset) != 0)
1087 if (sigismember(&sigset, SIGPIPE))
1088 *sigpipe_pending = true;
1090 *sigpipe_pending = false;
1093 *sigpipe_pending = false;
1099 * Discard any pending SIGPIPE and reset the signal mask.
1101 * Note: we are effectively assuming here that the C library doesn't queue
1102 * up multiple SIGPIPE events. If it did, then we'd accidentally leave
1103 * ours in the queue when an event was already pending and we got another.
1104 * As long as it doesn't queue multiple events, we're OK because the caller
1105 * can't tell the difference.
1107 * The caller should say got_epipe = FALSE if it is certain that it
1108 * didn't get an EPIPE error; in that case we'll skip the clear operation
1109 * and things are definitely OK, queuing or no. If it got one or might have
1110 * gotten one, pass got_epipe = TRUE.
1112 * We do not want this to change errno, since if it did that could lose
1113 * the error code from a preceding send(). We essentially assume that if
1114 * we were able to do pq_block_sigpipe(), this can't fail.
1117 pq_reset_sigpipe(sigset_t *osigset, bool sigpipe_pending, bool got_epipe)
1119 int save_errno = SOCK_ERRNO;
1123 /* Clear SIGPIPE only if none was pending */
1124 if (got_epipe && !sigpipe_pending)
1126 if (sigpending(&sigset) == 0 &&
1127 sigismember(&sigset, SIGPIPE))
1129 sigset_t sigpipe_sigset;
1131 sigemptyset(&sigpipe_sigset);
1132 sigaddset(&sigpipe_sigset, SIGPIPE);
1134 sigwait(&sigpipe_sigset, &signo);
1138 /* Restore saved block mask */
1139 pthread_sigmask(SIG_SETMASK, osigset, NULL);
1141 SOCK_ERRNO_SET(save_errno);
1144 #endif /* ENABLE_THREAD_SAFETY */