diff options
| author | Bruce Momjian <bruce@momjian.us> | 2004-10-06 09:35:23 +0000 |
|---|---|---|
| committer | Bruce Momjian <bruce@momjian.us> | 2004-10-06 09:35:23 +0000 |
| commit | 902ca3e2255411d709a1ffa28dea9eda92425f77 (patch) | |
| tree | d802e6b82f526711585211694850cfa38eaa0297 /src/backend/libpq | |
| parent | 5431393274dd9349490d56d9594782365ca8ddfc (diff) | |
| download | postgresql-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.c | 68 |
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. */ |
