aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMagnus Hagander <magnus@hagander.net>2008-12-14 19:39:37 +0000
committerMagnus Hagander <magnus@hagander.net>2008-12-14 19:39:37 +0000
commitb8753e5955db8735107eb769fa0004b9f28a0c4e (patch)
tree5e3eb88399d65eba6d558970413b470b37b2623e
parent65e3ea76417d1baab158fd8305ebed4f43141c7a (diff)
downloadpostgresql-b8753e5955db8735107eb769fa0004b9f28a0c4e.tar.gz
postgresql-b8753e5955db8735107eb769fa0004b9f28a0c4e.zip
Replace both send and receive BIO routines in the SSL code with our own,
calling recv() and send(). This makes the calls go through the socket emulation code on Win32, making them for example properly interruptible.
-rw-r--r--src/backend/libpq/be-secure.c56
1 files changed, 41 insertions, 15 deletions
diff --git a/src/backend/libpq/be-secure.c b/src/backend/libpq/be-secure.c
index db41179b78e..e5c6ccfd926 100644
--- a/src/backend/libpq/be-secure.c
+++ b/src/backend/libpq/be-secure.c
@@ -11,7 +11,7 @@
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/libpq/be-secure.c,v 1.87 2008/12/03 20:04:26 mha Exp $
+ * $PostgreSQL: pgsql/src/backend/libpq/be-secure.c,v 1.88 2008/12/14 19:39:37 mha Exp $
*
* Since the server static private key ($DataDir/server.key)
* will normally be stored unencrypted so that the database
@@ -394,45 +394,71 @@ wloop:
#ifdef USE_SSL
/*
- * Private substitute BIO: this wraps the SSL library's standard socket BIO
- * so that we can enable and disable interrupts just while calling recv().
- * We cannot have interrupts occurring while the bulk of openssl runs,
- * because it uses malloc() and possibly other non-reentrant libc facilities.
+ * Private substitute BIO: this does the sending and receiving using send() and
+ * recv() instead. This is so that we can enable and disable interrupts
+ * just while calling recv(). We cannot have interrupts occurring while
+ * the bulk of openssl runs, because it uses malloc() and possibly other
+ * non-reentrant libc facilities. We also need to call send() and recv()
+ * directly so it gets passed through the socket/signals layer on Win32.
+ *
+ * They are closely modelled on the original socket implementations in OpenSSL.
*
- * As of openssl 0.9.7, we can use the reasonably clean method of interposing
- * a wrapper around the standard socket BIO's sock_read() method. This relies
- * on the fact that sock_read() doesn't call anything non-reentrant, in fact
- * not much of anything at all except recv(). If this ever changes we'd
- * probably need to duplicate the code of sock_read() in order to push the
- * interrupt enable/disable down yet another level.
*/
static bool my_bio_initialized = false;
static BIO_METHOD my_bio_methods;
-static int (*std_sock_read) (BIO *h, char *buf, int size);
static int
my_sock_read(BIO *h, char *buf, int size)
{
- int res;
+ int res = 0;
prepare_for_client_read();
- res = std_sock_read(h, buf, size);
+ if (buf != NULL)
+ {
+ res = recv(h->num, buf, size, 0);
+ BIO_clear_retry_flags(h);
+ if (res <= 0)
+ {
+ /* If we were interrupted, tell caller to retry */
+ if (errno == EINTR)
+ {
+ BIO_set_retry_read(h);
+ }
+ }
+ }
client_read_ended();
return res;
}
+static int
+my_sock_write(BIO *h, const char *buf, int size)
+{
+ int res = 0;
+
+ res = send(h->num, buf, size, 0);
+ if (res <= 0)
+ {
+ if (errno == EINTR)
+ {
+ BIO_set_retry_write(h);
+ }
+ }
+
+ return res;
+}
+
static BIO_METHOD *
my_BIO_s_socket(void)
{
if (!my_bio_initialized)
{
memcpy(&my_bio_methods, BIO_s_socket(), sizeof(BIO_METHOD));
- std_sock_read = my_bio_methods.bread;
my_bio_methods.bread = my_sock_read;
+ my_bio_methods.bwrite = my_sock_write;
my_bio_initialized = true;
}
return &my_bio_methods;