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.81 2006/05/11 23:27:35 momjian 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"
87 #include "libpq-int.h"
94 #include <sys/socket.h>
97 #include <netinet/in.h>
98 #ifdef HAVE_NETINET_TCP_H
99 #include <netinet/tcp.h>
101 #include <arpa/inet.h>
103 #include <sys/stat.h>
105 #ifdef ENABLE_THREAD_SAFETY
107 #include "pthread-win32.h"
118 #include <openssl/ssl.h>
125 #define USER_CERT_FILE ".postgresql/postgresql.crt"
126 #define USER_KEY_FILE ".postgresql/postgresql.key"
127 #define ROOT_CERT_FILE ".postgresql/root.crt"
128 #define ROOT_CRL_FILE ".postgresql/root.crl"
130 /* On Windows, the "home" directory is already PostgreSQL-specific */
131 #define USER_CERT_FILE "postgresql.crt"
132 #define USER_KEY_FILE "postgresql.key"
133 #define ROOT_CERT_FILE "root.crt"
134 #define ROOT_CRL_FILE "root.crl"
138 static int verify_peer(PGconn *);
140 static int verify_cb(int ok, X509_STORE_CTX *ctx);
141 static int client_cert_cb(SSL *, X509 **, EVP_PKEY **);
142 static int init_ssl_system(PGconn *conn);
143 static int initialize_SSL(PGconn *);
144 static void destroy_SSL(void);
145 static PostgresPollingStatusType open_client_SSL(PGconn *);
146 static void close_SSL(PGconn *);
147 static char *SSLerrmessage(void);
148 static void SSLerrfree(char *buf);
152 static bool pq_initssllib = true;
154 static SSL_CTX *SSL_context = NULL;
157 /* ------------------------------------------------------------ */
158 /* Procedures common to all secure sessions */
159 /* ------------------------------------------------------------ */
163 * Exported function to allow application to tell us it's already
164 * initialized OpenSSL.
167 PQinitSSL(int do_init)
170 pq_initssllib = do_init;
175 * Initialize global context
178 pqsecure_initialize(PGconn *conn)
183 r = initialize_SSL(conn);
190 * Destroy global context
193 pqsecure_destroy(void)
201 * Attempt to negotiate secure session.
203 PostgresPollingStatusType
204 pqsecure_open_client(PGconn *conn)
207 /* First time through? */
208 if (conn->ssl == NULL)
210 if (!(conn->ssl = SSL_new(SSL_context)) ||
211 !SSL_set_app_data(conn->ssl, conn) ||
212 !SSL_set_fd(conn->ssl, conn->sock))
214 char *err = SSLerrmessage();
216 printfPQExpBuffer(&conn->errorMessage,
217 libpq_gettext("could not establish SSL connection: %s\n"),
221 return PGRES_POLLING_FAILED;
225 * Initialize errorMessage to empty. This allows open_client_SSL() to
226 * detect whether client_cert_cb() has stored a message.
228 resetPQExpBuffer(&conn->errorMessage);
230 /* Begin or continue the actual handshake */
231 return open_client_SSL(conn);
233 /* shouldn't get here */
234 return PGRES_POLLING_FAILED;
239 * Close secure session.
242 pqsecure_close(PGconn *conn)
251 * Read data from a secure connection.
254 pqsecure_read(PGconn *conn, void *ptr, size_t len)
264 n = SSL_read(conn->ssl, ptr, len);
265 err = SSL_get_error(conn->ssl, n);
270 case SSL_ERROR_WANT_READ:
273 case SSL_ERROR_WANT_WRITE:
276 * Returning 0 here would cause caller to wait for read-ready,
277 * which is not correct since what SSL wants is wait for
278 * write-ready. The former could get us stuck in an infinite
279 * wait, so don't risk it; busy-loop instead.
282 case SSL_ERROR_SYSCALL:
287 printfPQExpBuffer(&conn->errorMessage,
288 libpq_gettext("SSL SYSCALL error: %s\n"),
289 SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf)));
292 printfPQExpBuffer(&conn->errorMessage,
293 libpq_gettext("SSL SYSCALL error: EOF detected\n"));
295 SOCK_ERRNO_SET(ECONNRESET);
302 char *err = SSLerrmessage();
304 printfPQExpBuffer(&conn->errorMessage,
305 libpq_gettext("SSL error: %s\n"), err);
309 case SSL_ERROR_ZERO_RETURN:
310 SOCK_ERRNO_SET(ECONNRESET);
314 printfPQExpBuffer(&conn->errorMessage,
315 libpq_gettext("unrecognized SSL error code: %d\n"),
323 n = recv(conn->sock, ptr, len, 0);
329 * Write data to a secure connection.
332 pqsecure_write(PGconn *conn, const void *ptr, size_t len)
337 #ifdef ENABLE_THREAD_SAFETY
339 bool sigpipe_pending;
340 bool got_epipe = false;
343 if (pq_block_sigpipe(&osigmask, &sigpipe_pending) < 0)
346 pqsigfunc oldsighandler = pqsignal(SIGPIPE, SIG_IGN);
347 #endif /* ENABLE_THREAD_SAFETY */
355 n = SSL_write(conn->ssl, ptr, len);
356 err = SSL_get_error(conn->ssl, n);
361 case SSL_ERROR_WANT_READ:
364 * Returning 0 here causes caller to wait for write-ready,
365 * which is not really the right thing, but it's the best we
370 case SSL_ERROR_WANT_WRITE:
373 case SSL_ERROR_SYSCALL:
379 #if defined(ENABLE_THREAD_SAFETY) && !defined(WIN32)
380 if (SOCK_ERRNO == EPIPE)
383 printfPQExpBuffer(&conn->errorMessage,
384 libpq_gettext("SSL SYSCALL error: %s\n"),
385 SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf)));
389 printfPQExpBuffer(&conn->errorMessage,
390 libpq_gettext("SSL SYSCALL error: EOF detected\n"));
391 SOCK_ERRNO_SET(ECONNRESET);
398 char *err = SSLerrmessage();
400 printfPQExpBuffer(&conn->errorMessage,
401 libpq_gettext("SSL error: %s\n"), err);
405 case SSL_ERROR_ZERO_RETURN:
406 SOCK_ERRNO_SET(ECONNRESET);
410 printfPQExpBuffer(&conn->errorMessage,
411 libpq_gettext("unrecognized SSL error code: %d\n"),
420 n = send(conn->sock, ptr, len, 0);
421 #if defined(ENABLE_THREAD_SAFETY) && !defined(WIN32)
422 if (n < 0 && SOCK_ERRNO == EPIPE)
428 #ifdef ENABLE_THREAD_SAFETY
429 pq_reset_sigpipe(&osigmask, sigpipe_pending, got_epipe);
431 pqsignal(SIGPIPE, oldsighandler);
432 #endif /* ENABLE_THREAD_SAFETY */
438 /* ------------------------------------------------------------ */
439 /* SSL specific code */
440 /* ------------------------------------------------------------ */
444 * Certificate verification callback
446 * This callback allows us to log intermediate problems during
447 * verification, but there doesn't seem to be a clean way to get
448 * our PGconn * structure. So we can't log anything!
450 * This callback also allows us to override the default acceptance
451 * criteria (e.g., accepting self-signed or expired certs), but
452 * for now we accept the default checks.
455 verify_cb(int ok, X509_STORE_CTX *ctx)
462 * Verify that common name resolves to peer.
465 verify_peer(PGconn *conn)
467 struct hostent *h = NULL;
468 struct sockaddr addr;
469 struct sockaddr_in *sin;
470 ACCEPT_TYPE_ARG3 len;
474 /* get the address on the other side of the socket */
476 if (getpeername(conn->sock, &addr, &len) == -1)
480 printfPQExpBuffer(&conn->errorMessage,
481 libpq_gettext("error querying socket: %s\n"),
482 SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf)));
486 /* weird, but legal case */
487 if (addr.sa_family == AF_UNIX)
491 struct hostent hpstr;
496 * Currently, pqGethostbyname() is used only on platforms that don't
497 * have getaddrinfo(). If you enable this function, you should
498 * convert the pqGethostbyname() function call to use getaddrinfo().
500 pqGethostbyname(conn->peer_cn, &hpstr, buf, sizeof(buf),
504 /* what do we know about the peer's common name? */
507 printfPQExpBuffer(&conn->errorMessage,
508 libpq_gettext("could not get information about host \"%s\": %s\n"),
509 conn->peer_cn, hstrerror(h_errno));
513 /* does the address match? */
514 switch (addr.sa_family)
517 sin = (struct sockaddr_in *) & addr;
518 for (s = h->h_addr_list; *s != NULL; s++)
520 if (!memcmp(&sin->sin_addr.s_addr, *s, h->h_length))
526 printfPQExpBuffer(&conn->errorMessage,
527 libpq_gettext("unsupported protocol\n"));
532 * the prior test should be definitive, but in practice it sometimes
533 * fails. So we also check the aliases.
535 for (s = h->h_aliases; *s != NULL; s++)
537 if (pg_strcasecmp(conn->peer_cn, *s) == 0)
541 /* generate protocol-aware error message */
542 switch (addr.sa_family)
545 sin = (struct sockaddr_in *) & addr;
546 l = ntohl(sin->sin_addr.s_addr);
547 printfPQExpBuffer(&conn->errorMessage,
549 "server common name \"%s\" does not resolve to %ld.%ld.%ld.%ld\n"),
550 conn->peer_cn, (l >> 24) % 0x100, (l >> 16) % 0x100,
551 (l >> 8) % 0x100, l % 0x100);
554 printfPQExpBuffer(&conn->errorMessage,
556 "server common name \"%s\" does not resolve to peer address\n"),
562 #endif /* NOT_USED */
565 * Callback used by SSL to load client cert and key.
566 * This callback is only called when the server wants a
569 * Must return 1 on success, 0 on no data or error.
572 client_cert_cb(SSL *ssl, X509 **x509, EVP_PKEY **pkey)
574 char homedir[MAXPGPATH];
580 char fnbuf[MAXPGPATH];
582 PGconn *conn = (PGconn *) SSL_get_app_data(ssl);
583 int (*cb) () = NULL; /* how to read user password */
586 if (!pqGetHomeDirectory(homedir, sizeof(homedir)))
588 printfPQExpBuffer(&conn->errorMessage,
589 libpq_gettext("could not get user information\n"));
593 /* read the user certificate */
594 snprintf(fnbuf, sizeof(fnbuf), "%s/%s", homedir, USER_CERT_FILE);
595 if ((fp = fopen(fnbuf, "r")) == NULL)
597 printfPQExpBuffer(&conn->errorMessage,
598 libpq_gettext("could not open certificate file \"%s\": %s\n"),
599 fnbuf, pqStrerror(errno, sebuf, sizeof(sebuf)));
602 if (PEM_read_X509(fp, x509, NULL, NULL) == NULL)
604 char *err = SSLerrmessage();
606 printfPQExpBuffer(&conn->errorMessage,
607 libpq_gettext("could not read certificate file \"%s\": %s\n"),
615 /* read the user key */
616 snprintf(fnbuf, sizeof(fnbuf), "%s/%s", homedir, USER_KEY_FILE);
617 if (stat(fnbuf, &buf) == -1)
619 printfPQExpBuffer(&conn->errorMessage,
620 libpq_gettext("certificate present, but not private key file \"%s\"\n"),
625 if (!S_ISREG(buf.st_mode) || (buf.st_mode & 0077) ||
626 buf.st_uid != geteuid())
628 printfPQExpBuffer(&conn->errorMessage,
629 libpq_gettext("private key file \"%s\" has wrong permissions\n"),
634 if ((fp = fopen(fnbuf, "r")) == NULL)
636 printfPQExpBuffer(&conn->errorMessage,
637 libpq_gettext("could not open private key file \"%s\": %s\n"),
638 fnbuf, pqStrerror(errno, sebuf, sizeof(sebuf)));
642 if (fstat(fileno(fp), &buf2) == -1 ||
643 buf.st_dev != buf2.st_dev || buf.st_ino != buf2.st_ino)
645 printfPQExpBuffer(&conn->errorMessage,
646 libpq_gettext("private key file \"%s\" changed during execution\n"), fnbuf);
650 if (PEM_read_PrivateKey(fp, pkey, cb, NULL) == NULL)
652 char *err = SSLerrmessage();
654 printfPQExpBuffer(&conn->errorMessage,
655 libpq_gettext("could not read private key file \"%s\": %s\n"),
663 /* verify that the cert and key go together */
664 if (!X509_check_private_key(*x509, *pkey))
666 char *err = SSLerrmessage();
668 printfPQExpBuffer(&conn->errorMessage,
669 libpq_gettext("certificate does not match private key file \"%s\": %s\n"),
678 #ifdef ENABLE_THREAD_SAFETY
681 pq_threadidcallback(void)
684 * This is not standards-compliant. pthread_self() returns pthread_t, and
685 * shouldn't be cast to unsigned long, but CRYPTO_set_id_callback requires
686 * it, so we have to do it.
688 return (unsigned long) pthread_self();
691 static pthread_mutex_t *pq_lockarray;
694 pq_lockingcallback(int mode, int n, const char *file, int line)
696 if (mode & CRYPTO_LOCK)
697 pthread_mutex_lock(&pq_lockarray[n]);
699 pthread_mutex_unlock(&pq_lockarray[n]);
701 #endif /* ENABLE_THREAD_SAFETY */
704 init_ssl_system(PGconn *conn)
706 #ifdef ENABLE_THREAD_SAFETY
708 static pthread_mutex_t init_mutex = PTHREAD_MUTEX_INITIALIZER;
710 static pthread_mutex_t init_mutex = NULL;
711 static long mutex_initlock = 0;
713 if (init_mutex == NULL)
715 while (InterlockedExchange(&mutex_initlock, 1) == 1)
716 /* loop, another thread own the lock */ ;
717 if (init_mutex == NULL)
718 pthread_mutex_init(&init_mutex, NULL);
719 InterlockedExchange(&mutex_initlock, 0);
722 pthread_mutex_lock(&init_mutex);
724 if (pq_initssllib && pq_lockarray == NULL)
728 CRYPTO_set_id_callback(pq_threadidcallback);
730 pq_lockarray = malloc(sizeof(pthread_mutex_t) * CRYPTO_num_locks());
733 pthread_mutex_unlock(&init_mutex);
736 for (i = 0; i < CRYPTO_num_locks(); i++)
737 pthread_mutex_init(&pq_lockarray[i], NULL);
739 CRYPTO_set_locking_callback(pq_lockingcallback);
747 SSL_load_error_strings();
749 SSL_context = SSL_CTX_new(TLSv1_method());
752 char *err = SSLerrmessage();
754 printfPQExpBuffer(&conn->errorMessage,
755 libpq_gettext("could not create SSL context: %s\n"),
758 #ifdef ENABLE_THREAD_SAFETY
759 pthread_mutex_unlock(&init_mutex);
764 #ifdef ENABLE_THREAD_SAFETY
765 pthread_mutex_unlock(&init_mutex);
771 * Initialize global SSL context.
774 initialize_SSL(PGconn *conn)
777 char homedir[MAXPGPATH];
778 char fnbuf[MAXPGPATH];
780 if (init_ssl_system(conn))
783 /* Set up to verify server cert, if root.crt is present */
784 if (pqGetHomeDirectory(homedir, sizeof(homedir)))
786 snprintf(fnbuf, sizeof(fnbuf), "%s/%s", homedir, ROOT_CERT_FILE);
787 if (stat(fnbuf, &buf) == 0)
791 if (!SSL_CTX_load_verify_locations(SSL_context, fnbuf, NULL))
793 char *err = SSLerrmessage();
795 printfPQExpBuffer(&conn->errorMessage,
796 libpq_gettext("could not read root certificate file \"%s\": %s\n"),
802 if ((cvstore = SSL_CTX_get_cert_store(SSL_context)) != NULL)
804 /* setting the flags to check against the complete CRL chain */
805 if (X509_STORE_load_locations(cvstore, ROOT_CRL_FILE, NULL) != 0)
806 /* OpenSSL 0.96 does not support X509_V_FLAG_CRL_CHECK */
807 #ifdef X509_V_FLAG_CRL_CHECK
808 X509_STORE_set_flags(cvstore,
809 X509_V_FLAG_CRL_CHECK|X509_V_FLAG_CRL_CHECK_ALL);
810 /* if not found, silently ignore; we do not require CRL */
813 char *err = SSLerrmessage();
815 printfPQExpBuffer(&conn->errorMessage,
816 libpq_gettext("Installed SSL library does not support CRL certificates, file \"%s\"\n"),
824 SSL_CTX_set_verify(SSL_context, SSL_VERIFY_PEER, verify_cb);
828 /* set up mechanism to provide client certificate, if available */
829 SSL_CTX_set_client_cert_cb(SSL_context, client_cert_cb);
835 * Destroy global SSL context.
842 SSL_CTX_free(SSL_context);
848 * Attempt to negotiate SSL connection.
850 static PostgresPollingStatusType
851 open_client_SSL(PGconn *conn)
855 r = SSL_connect(conn->ssl);
858 int err = SSL_get_error(conn->ssl, r);
862 case SSL_ERROR_WANT_READ:
863 return PGRES_POLLING_READING;
865 case SSL_ERROR_WANT_WRITE:
866 return PGRES_POLLING_WRITING;
868 case SSL_ERROR_SYSCALL:
873 printfPQExpBuffer(&conn->errorMessage,
874 libpq_gettext("SSL SYSCALL error: %s\n"),
875 SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf)));
877 printfPQExpBuffer(&conn->errorMessage,
878 libpq_gettext("SSL SYSCALL error: EOF detected\n"));
880 return PGRES_POLLING_FAILED;
885 * If there are problems with the local certificate files,
886 * these will be detected by client_cert_cb() which is
887 * called from SSL_connect(). We want to return that
888 * error message and not the rather unhelpful error that
889 * OpenSSL itself returns. So check to see if an error
890 * message was already stored.
892 if (conn->errorMessage.len == 0)
894 char *err = SSLerrmessage();
896 printfPQExpBuffer(&conn->errorMessage,
897 libpq_gettext("SSL error: %s\n"),
902 return PGRES_POLLING_FAILED;
906 printfPQExpBuffer(&conn->errorMessage,
907 libpq_gettext("unrecognized SSL error code: %d\n"),
910 return PGRES_POLLING_FAILED;
914 /* check the certificate chain of the server */
917 /* CLIENT CERTIFICATES NOT REQUIRED bjm 2002-09-26 */
920 * this eliminates simple man-in-the-middle attacks and simple
923 r = SSL_get_verify_result(conn->ssl);
926 printfPQExpBuffer(&conn->errorMessage,
927 libpq_gettext("certificate could not be validated: %s\n"),
928 X509_verify_cert_error_string(r));
930 return PGRES_POLLING_FAILED;
934 /* pull out server distinguished and common names */
935 conn->peer = SSL_get_peer_certificate(conn->ssl);
936 if (conn->peer == NULL)
938 char *err = SSLerrmessage();
940 printfPQExpBuffer(&conn->errorMessage,
941 libpq_gettext("certificate could not be obtained: %s\n"),
945 return PGRES_POLLING_FAILED;
948 X509_NAME_oneline(X509_get_subject_name(conn->peer),
949 conn->peer_dn, sizeof(conn->peer_dn));
950 conn->peer_dn[sizeof(conn->peer_dn) - 1] = '\0';
952 X509_NAME_get_text_by_NID(X509_get_subject_name(conn->peer),
953 NID_commonName, conn->peer_cn, SM_USER);
954 conn->peer_cn[SM_USER] = '\0';
956 /* verify that the common name resolves to peer */
959 /* CLIENT CERTIFICATES NOT REQUIRED bjm 2002-09-26 */
962 * this is necessary to eliminate man-in-the-middle attacks and
963 * impersonations where the attacker somehow learned the server's private
966 if (verify_peer(conn) == -1)
969 return PGRES_POLLING_FAILED;
973 /* SSL handshake is complete */
974 return PGRES_POLLING_OK;
978 * Close SSL connection.
981 close_SSL(PGconn *conn)
985 SSL_shutdown(conn->ssl);
992 X509_free(conn->peer);
998 * Obtain reason string for last SSL error
1000 * Some caution is needed here since ERR_reason_error_string will
1001 * return NULL if it doesn't recognize the error code. We don't
1002 * want to return NULL ever.
1004 static char ssl_nomem[] = "Out of memory allocating error description";
1006 #define SSL_ERR_LEN 128
1011 unsigned long errcode;
1012 const char *errreason;
1015 errbuf = malloc(SSL_ERR_LEN);
1018 errcode = ERR_get_error();
1021 strcpy(errbuf, "No SSL error reported");
1024 errreason = ERR_reason_error_string(errcode);
1025 if (errreason != NULL)
1027 strncpy(errbuf, errreason, SSL_ERR_LEN - 1);
1028 errbuf[SSL_ERR_LEN - 1] = '\0';
1031 snprintf(errbuf, SSL_ERR_LEN, "SSL error code %lu", errcode);
1036 SSLerrfree(char *buf)
1038 if (buf != ssl_nomem)
1043 * Return pointer to OpenSSL object.
1046 PQgetssl(PGconn *conn)
1052 #else /* !USE_SSL */
1055 PQgetssl(PGconn *conn)
1059 #endif /* USE_SSL */
1061 #if defined(ENABLE_THREAD_SAFETY) && !defined(WIN32)
1064 * Block SIGPIPE for this thread. This prevents send()/write() from exiting
1068 pq_block_sigpipe(sigset_t *osigset, bool *sigpipe_pending)
1070 sigset_t sigpipe_sigset;
1073 sigemptyset(&sigpipe_sigset);
1074 sigaddset(&sigpipe_sigset, SIGPIPE);
1076 /* Block SIGPIPE and save previous mask for later reset */
1077 SOCK_ERRNO_SET(pthread_sigmask(SIG_BLOCK, &sigpipe_sigset, osigset));
1081 /* We can have a pending SIGPIPE only if it was blocked before */
1082 if (sigismember(osigset, SIGPIPE))
1084 /* Is there a pending SIGPIPE? */
1085 if (sigpending(&sigset) != 0)
1088 if (sigismember(&sigset, SIGPIPE))
1089 *sigpipe_pending = true;
1091 *sigpipe_pending = false;
1094 *sigpipe_pending = false;
1100 * Discard any pending SIGPIPE and reset the signal mask.
1102 * Note: we are effectively assuming here that the C library doesn't queue
1103 * up multiple SIGPIPE events. If it did, then we'd accidentally leave
1104 * ours in the queue when an event was already pending and we got another.
1105 * As long as it doesn't queue multiple events, we're OK because the caller
1106 * can't tell the difference.
1108 * The caller should say got_epipe = FALSE if it is certain that it
1109 * didn't get an EPIPE error; in that case we'll skip the clear operation
1110 * and things are definitely OK, queuing or no. If it got one or might have
1111 * gotten one, pass got_epipe = TRUE.
1113 * We do not want this to change errno, since if it did that could lose
1114 * the error code from a preceding send(). We essentially assume that if
1115 * we were able to do pq_block_sigpipe(), this can't fail.
1118 pq_reset_sigpipe(sigset_t *osigset, bool sigpipe_pending, bool got_epipe)
1120 int save_errno = SOCK_ERRNO;
1124 /* Clear SIGPIPE only if none was pending */
1125 if (got_epipe && !sigpipe_pending)
1127 if (sigpending(&sigset) == 0 &&
1128 sigismember(&sigset, SIGPIPE))
1130 sigset_t sigpipe_sigset;
1132 sigemptyset(&sigpipe_sigset);
1133 sigaddset(&sigpipe_sigset, SIGPIPE);
1135 sigwait(&sigpipe_sigset, &signo);
1139 /* Restore saved block mask */
1140 pthread_sigmask(SIG_SETMASK, osigset, NULL);
1142 SOCK_ERRNO_SET(save_errno);
1145 #endif /* ENABLE_THREAD_SAFETY */