Re: OpenSSL Applink - Mailing list pgsql-patches

From Dave Page
Subject Re: OpenSSL Applink
Date
Msg-id 46FD6289.6070806@postgresql.org
Whole thread Raw
In response to Re: OpenSSL Applink  (Dave Page <dpage@postgresql.org>)
Responses Re: OpenSSL Applink  (Magnus Hagander <magnus@hagander.net>)
List pgsql-patches
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 */

pgsql-patches by date:

Previous
From: Dave Page
Date:
Subject: Re: OpenSSL Applink
Next
From: Hannes Eder
Date:
Subject: msvc >= VC7 understands __FUNCTION__