Dave Page wrote:
> Dave Page wrote:
>> I did stumble across this text on a mailing list in response to someone
>> with a similar problem in some JNI code. I know little of the OpenSSL
>> API, but perhaps it rings bells with you before I spend my evening
>> trying to figure it out?
>
> OK, I think I've figured out a fix. Working up a patch now...
Patch attached.
It appears to work fine except that if the client certificate is
missing, instead of:
could not open certificate file "C:\Documents and
Settings\Dave\Application Data/postgresql/postgresql.crt": No such file
or directory
I get:
Error connecting to the server: SSL SYSCALL error: Operation would block
(0x00002733/10035)
for reasons that are not clear to me. Any ideas?
Regards, Dave
Index: src/interfaces/libpq/fe-secure.c
===================================================================
RCS file: /projects/cvsroot/pgsql/src/interfaces/libpq/fe-secure.c,v
retrieving revision 1.94
diff -c -r1.94 fe-secure.c
*** src/interfaces/libpq/fe-secure.c 16 Feb 2007 17:07:00 -0000 1.94
--- src/interfaces/libpq/fe-secure.c 28 Sep 2007 20:15:17 -0000
***************
*** 111,116 ****
--- 111,119 ----
#ifdef USE_SSL
#include <openssl/ssl.h>
+ #ifdef WIN32
+ #include <openssl/bio.h>
+ #endif
#if (SSLEAY_VERSION_NUMBER >= 0x00907000L)
#include <openssl/conf.h>
#endif
***************
*** 567,572 ****
--- 570,581 ----
* This callback is only called when the server wants a
* client cert.
*
+ * Note: On Windows we use OpenSSL's BIO functions to
+ * handle I/O to avoid issues passing FILE pointers to
+ * incompatible runtimes. We don't use them on other
+ * platforms because we couldn't then stat the keys to
+ * check for changes during execution.
+ *
* Must return 1 on success, 0 on no data or error.
*/
static int
***************
*** 579,585 ****
--- 588,598 ----
struct stat buf2;
#endif
char fnbuf[MAXPGPATH];
+ #ifndef WIN32
FILE *fp;
+ #else
+ BIO *bio;
+ #endif
PGconn *conn = (PGconn *) SSL_get_app_data(ssl);
char sebuf[256];
***************
*** 592,605 ****
--- 605,626 ----
/* read the user certificate */
snprintf(fnbuf, sizeof(fnbuf), "%s/%s", homedir, USER_CERT_FILE);
+ #ifndef WIN32
if ((fp = fopen(fnbuf, "r")) == NULL)
+ #else
+ if ((bio = BIO_new_file(fnbuf, "r")) == NULL)
+ #endif
{
printfPQExpBuffer(&conn->errorMessage,
libpq_gettext("could not open certificate file \"%s\": %s\n"),
fnbuf, pqStrerror(errno, sebuf, sizeof(sebuf)));
return 0;
}
+ #ifndef WIN32
if (PEM_read_X509(fp, x509, NULL, NULL) == NULL)
+ #else
+ if (PEM_read_bio_X509(bio, x509, NULL, NULL) == NULL)
+ #endif
{
char *err = SSLerrmessage();
***************
*** 607,616 ****
--- 628,645 ----
libpq_gettext("could not read certificate file \"%s\": %s\n"),
fnbuf, err);
SSLerrfree(err);
+ #ifndef WIN32
fclose(fp);
+ #else
+ BIO_free(bio);
+ #endif
return 0;
}
+ #ifndef WIN32
fclose(fp);
+ #else
+ BIO_free(bio);
+ #endif
#if (SSLEAY_VERSION_NUMBER >= 0x00907000L) && !defined(OPENSSL_NO_ENGINE)
if (getenv("PGSSLKEY"))
***************
*** 641,647 ****
SSLerrfree(err);
free(engine_str);
return 0;
! }
*pkey = ENGINE_load_private_key(engine_ptr, engine_colon + 1,
NULL, NULL);
--- 670,676 ----
SSLerrfree(err);
free(engine_str);
return 0;
! }
*pkey = ENGINE_load_private_key(engine_ptr, engine_colon + 1,
NULL, NULL);
***************
*** 655,661 ****
SSLerrfree(err);
free(engine_str);
return 0;
! }
free(engine_str);
}
else
--- 684,690 ----
SSLerrfree(err);
free(engine_str);
return 0;
! }
free(engine_str);
}
else
***************
*** 679,686 ****
fnbuf);
return 0;
}
! #endif
if ((fp = fopen(fnbuf, "r")) == NULL)
{
printfPQExpBuffer(&conn->errorMessage,
libpq_gettext("could not open private key file \"%s\": %s\n"),
--- 708,718 ----
fnbuf);
return 0;
}
!
if ((fp = fopen(fnbuf, "r")) == NULL)
+ #else
+ if ((bio = BIO_new_file(fnbuf, "r")) == NULL)
+ #endif
{
printfPQExpBuffer(&conn->errorMessage,
libpq_gettext("could not open private key file \"%s\": %s\n"),
***************
*** 695,702 ****
libpq_gettext("private key file \"%s\" changed during execution\n"), fnbuf);
return 0;
}
! #endif
if (PEM_read_PrivateKey(fp, pkey, NULL, NULL) == NULL)
{
char *err = SSLerrmessage();
--- 727,737 ----
libpq_gettext("private key file \"%s\" changed during execution\n"), fnbuf);
return 0;
}
!
if (PEM_read_PrivateKey(fp, pkey, NULL, NULL) == NULL)
+ #else
+ if (PEM_read_bio_PrivateKey(bio, pkey, NULL, NULL) == NULL)
+ #endif
{
char *err = SSLerrmessage();
***************
*** 704,713 ****
--- 739,756 ----
libpq_gettext("could not read private key file \"%s\": %s\n"),
fnbuf, err);
SSLerrfree(err);
+ #ifndef WIN32
fclose(fp);
+ #else
+ BIO_free(bio);
+ #endif
return 0;
}
+ #ifndef WIN32
fclose(fp);
+ #else
+ BIO_free(bio);
+ #endif
}
/* verify that the cert and key go together */
---------------------------(end of broadcast)---------------------------
TIP 1: if posting/reading through Usenet, please send an appropriate
subscribe-nomail command to [EMAIL PROTECTED] so that your
message can get through to the mailing list cleanly