summaryrefslogtreecommitdiff
path: root/src/backend/libpq
diff options
context:
space:
mode:
authorBruce Momjian <bruce@momjian.us>2004-10-06 09:35:23 +0000
committerBruce Momjian <bruce@momjian.us>2004-10-06 09:35:23 +0000
commit902ca3e2255411d709a1ffa28dea9eda92425f77 (patch)
treed802e6b82f526711585211694850cfa38eaa0297 /src/backend/libpq
parent5431393274dd9349490d56d9594782365ca8ddfc (diff)
downloadpostgresql-902ca3e2255411d709a1ffa28dea9eda92425f77.tar.gz
Here is a patch to fix win32 ssl builds. Summary of changes:
* Links with -leay32 and -lssleay32 instead of crypto and ssl. On win32, "crypto and ssl" is only used for static linking. * Initializes SSL in the backend and not just in the postmaster. We cannot pass the SSL context from the postmaster through the parameter file, because it contains function pointers. * Split one error check in be-secure.c. Previously we could not tell which of three calls actually failed. The previous code also returned incorrect error messages if SSL_accept() failed - that function needs to use SSL_get_error() on the return value, can't just use the error queue. * Since the win32 implementation uses non-blocking sockets "behind the scenes" in order to deliver signals correctly, implements a version of SSL_accept() that can handle this. Also, add a wait function in case SSL_read or SSL_write() needs more data. Magnus Hagander
Diffstat (limited to 'src/backend/libpq')
-rw-r--r--src/backend/libpq/be-secure.c68
1 files changed, 64 insertions, 4 deletions
diff --git a/src/backend/libpq/be-secure.c b/src/backend/libpq/be-secure.c
index eee9ad2836..efe7d7c118 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.51 2004/09/26 22:51:49 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/libpq/be-secure.c,v 1.52 2004/10/06 09:35:20 momjian Exp $
*
* Since the server static private key ($DataDir/server.key)
* will normally be stored unencrypted so that the database
@@ -268,6 +268,11 @@ rloop:
break;
case SSL_ERROR_WANT_READ:
case SSL_ERROR_WANT_WRITE:
+#ifdef WIN32
+ pgwin32_waitforsinglesocket(SSL_get_fd(port->ssl),
+ (err==SSL_ERROR_WANT_READ) ?
+ FD_READ|FD_CLOSE : FD_WRITE|FD_CLOSE);
+#endif
goto rloop;
case SSL_ERROR_SYSCALL:
if (n == -1)
@@ -356,6 +361,11 @@ wloop:
break;
case SSL_ERROR_WANT_READ:
case SSL_ERROR_WANT_WRITE:
+#ifdef WIN32
+ pgwin32_waitforsinglesocket(SSL_get_fd(port->ssl),
+ (err==SSL_ERROR_WANT_READ) ?
+ FD_READ|FD_CLOSE : FD_WRITE|FD_CLOSE);
+#endif
goto wloop;
case SSL_ERROR_SYSCALL:
if (n == -1)
@@ -717,6 +727,38 @@ initialize_SSL(void)
return 0;
}
+#ifdef WIN32
+/*
+ * Win32 socket code uses nonblocking sockets. We ned to deal with that
+ * by waiting on the socket if the SSL accept operation didn't complete
+ * right away.
+ */
+static int pgwin32_SSL_accept(SSL *ssl)
+{
+ int r;
+
+ while (1)
+ {
+ int rc;
+ int waitfor;
+
+ printf("uhh\n");fflush(stdout);
+ r = SSL_accept(ssl);
+ if (r == 1)
+ return 1;
+
+ rc = SSL_get_error(ssl, r);
+ if (rc != SSL_ERROR_WANT_READ && rc != SSL_ERROR_WANT_WRITE)
+ return r;
+
+ waitfor = (rc == SSL_ERROR_WANT_READ)?FD_READ|FD_CLOSE|FD_ACCEPT:FD_WRITE|FD_CLOSE;
+ if (pgwin32_waitforsinglesocket(SSL_get_fd(ssl), waitfor) == 0)
+ return -1;
+ }
+}
+#define SSL_accept(ssl) pgwin32_SSL_accept(ssl)
+#endif
+
/*
* Destroy global SSL context.
*/
@@ -736,12 +778,11 @@ destroy_SSL(void)
static int
open_server_SSL(Port *port)
{
+ int r;
Assert(!port->ssl);
Assert(!port->peer);
- if (!(port->ssl = SSL_new(SSL_context)) ||
- !SSL_set_fd(port->ssl, port->sock) ||
- SSL_accept(port->ssl) <= 0)
+ if (!(port->ssl = SSL_new(SSL_context)))
{
ereport(COMMERROR,
(errcode(ERRCODE_PROTOCOL_VIOLATION),
@@ -750,6 +791,25 @@ open_server_SSL(Port *port)
close_SSL(port);
return -1;
}
+ if (!SSL_set_fd(port->ssl, port->sock))
+ {
+ ereport(COMMERROR,
+ (errcode(ERRCODE_PROTOCOL_VIOLATION),
+ errmsg("could not set SSL socket: %s",
+ SSLerrmessage())));
+ close_SSL(port);
+ return -1;
+ }
+ if ((r=SSL_accept(port->ssl)) <= 0)
+ {
+ ereport(COMMERROR,
+ (errcode(ERRCODE_PROTOCOL_VIOLATION),
+ errmsg("could not accept SSL connection: %i",
+ SSL_get_error(port->ssl,r))));
+ close_SSL(port);
+ return -1;
+ }
+
port->count = 0;
/* get client certificate, if available. */