Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit ec4b6a8

Browse files
committed
Use BIO functions to avoid passing FILE * pointers to OpenSSL functions.
This fixes potential crashes on old versions of OpenSSL and the requirement on "Applink" in new versions when building with MSVC and using different runtimes. Dave Page with fixes from me.
1 parent c2862e3 commit ec4b6a8

File tree

1 file changed

+42
-13
lines changed

1 file changed

+42
-13
lines changed

src/interfaces/libpq/fe-secure.c

Lines changed: 42 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
*
1212
*
1313
* IDENTIFICATION
14-
* $PostgreSQL: pgsql/src/interfaces/libpq/fe-secure.c,v 1.94 2007/02/16 17:07:00 tgl Exp $
14+
* $PostgreSQL: pgsql/src/interfaces/libpq/fe-secure.c,v 1.95 2007/10/01 20:30:06 mha Exp $
1515
*
1616
* NOTES
1717
* [ Most of these notes are wrong/obsolete, but perhaps not all ]
@@ -111,6 +111,7 @@
111111

112112
#ifdef USE_SSL
113113
#include <openssl/ssl.h>
114+
#include <openssl/bio.h>
114115
#if (SSLEAY_VERSION_NUMBER >= 0x00907000L)
115116
#include <openssl/conf.h>
116117
#endif
@@ -567,6 +568,10 @@ verify_peer(PGconn *conn)
567568
* This callback is only called when the server wants a
568569
* client cert.
569570
*
571+
* Since BIO functions can set OpenSSL error codes, we must
572+
* reset the OpenSSL error stack on *every* exit from this
573+
* function once we've started using BIO.
574+
*
570575
* Must return 1 on success, 0 on no data or error.
571576
*/
572577
static int
@@ -579,8 +584,9 @@ client_cert_cb(SSL *ssl, X509 **x509, EVP_PKEY **pkey)
579584
struct stat buf2;
580585
#endif
581586
char fnbuf[MAXPGPATH];
582-
FILE *fp;
583-
PGconn *conn = (PGconn *) SSL_get_app_data(ssl);
587+
FILE *fp;
588+
BIO *bio;
589+
PGconn *conn = (PGconn *) SSL_get_app_data(ssl);
584590
char sebuf[256];
585591

586592
if (!pqGetHomeDirectory(homedir, sizeof(homedir)))
@@ -590,27 +596,34 @@ client_cert_cb(SSL *ssl, X509 **x509, EVP_PKEY **pkey)
590596
return 0;
591597
}
592598

599+
/* save OpenSSL error stack */
600+
ERR_set_mark();
601+
593602
/* read the user certificate */
594603
snprintf(fnbuf, sizeof(fnbuf), "%s/%s", homedir, USER_CERT_FILE);
595-
if ((fp = fopen(fnbuf, "r")) == NULL)
604+
if ((bio = BIO_new_file(fnbuf, "r")) == NULL)
596605
{
597606
printfPQExpBuffer(&conn->errorMessage,
598607
libpq_gettext("could not open certificate file \"%s\": %s\n"),
599608
fnbuf, pqStrerror(errno, sebuf, sizeof(sebuf)));
609+
ERR_pop_to_mark();
600610
return 0;
601611
}
602-
if (PEM_read_X509(fp, x509, NULL, NULL) == NULL)
612+
613+
if (PEM_read_bio_X509(bio, x509, NULL, NULL) == NULL)
603614
{
604615
char *err = SSLerrmessage();
605616

606617
printfPQExpBuffer(&conn->errorMessage,
607618
libpq_gettext("could not read certificate file \"%s\": %s\n"),
608619
fnbuf, err);
609620
SSLerrfree(err);
610-
fclose(fp);
621+
BIO_free(bio);
622+
ERR_pop_to_mark();
611623
return 0;
612624
}
613-
fclose(fp);
625+
626+
BIO_free(bio);
614627

615628
#if (SSLEAY_VERSION_NUMBER >= 0x00907000L) && !defined(OPENSSL_NO_ENGINE)
616629
if (getenv("PGSSLKEY"))
@@ -625,6 +638,7 @@ client_cert_cb(SSL *ssl, X509 **x509, EVP_PKEY **pkey)
625638
{
626639
printfPQExpBuffer(&conn->errorMessage,
627640
libpq_gettext("invalid value of PGSSLKEY environment variable\n"));
641+
ERR_pop_to_mark();
628642
return 0;
629643
}
630644

@@ -640,8 +654,9 @@ client_cert_cb(SSL *ssl, X509 **x509, EVP_PKEY **pkey)
640654
engine_str, err);
641655
SSLerrfree(err);
642656
free(engine_str);
657+
ERR_pop_to_mark();
643658
return 0;
644-
}
659+
}
645660

646661
*pkey = ENGINE_load_private_key(engine_ptr, engine_colon + 1,
647662
NULL, NULL);
@@ -654,8 +669,9 @@ client_cert_cb(SSL *ssl, X509 **x509, EVP_PKEY **pkey)
654669
engine_colon + 1, engine_str, err);
655670
SSLerrfree(err);
656671
free(engine_str);
672+
ERR_pop_to_mark();
657673
return 0;
658-
}
674+
}
659675
free(engine_str);
660676
}
661677
else
@@ -668,6 +684,7 @@ client_cert_cb(SSL *ssl, X509 **x509, EVP_PKEY **pkey)
668684
printfPQExpBuffer(&conn->errorMessage,
669685
libpq_gettext("certificate present, but not private key file \"%s\"\n"),
670686
fnbuf);
687+
ERR_pop_to_mark();
671688
return 0;
672689
}
673690
#ifndef WIN32
@@ -677,37 +694,46 @@ client_cert_cb(SSL *ssl, X509 **x509, EVP_PKEY **pkey)
677694
printfPQExpBuffer(&conn->errorMessage,
678695
libpq_gettext("private key file \"%s\" has wrong permissions\n"),
679696
fnbuf);
697+
ERR_pop_to_mark();
680698
return 0;
681699
}
682700
#endif
683-
if ((fp = fopen(fnbuf, "r")) == NULL)
701+
702+
if ((bio = BIO_new_file(fnbuf, "r")) == NULL)
684703
{
685704
printfPQExpBuffer(&conn->errorMessage,
686705
libpq_gettext("could not open private key file \"%s\": %s\n"),
687706
fnbuf, pqStrerror(errno, sebuf, sizeof(sebuf)));
707+
ERR_pop_to_mark();
688708
return 0;
689709
}
690710
#ifndef WIN32
711+
BIO_get_fp(bio, &fp);
691712
if (fstat(fileno(fp), &buf2) == -1 ||
692713
buf.st_dev != buf2.st_dev || buf.st_ino != buf2.st_ino)
693714
{
694715
printfPQExpBuffer(&conn->errorMessage,
695716
libpq_gettext("private key file \"%s\" changed during execution\n"), fnbuf);
717+
ERR_pop_to_mark();
696718
return 0;
697719
}
698720
#endif
699-
if (PEM_read_PrivateKey(fp, pkey, NULL, NULL) == NULL)
721+
722+
if (PEM_read_bio_PrivateKey(bio, pkey, NULL, NULL) == NULL)
700723
{
701724
char *err = SSLerrmessage();
702725

703726
printfPQExpBuffer(&conn->errorMessage,
704727
libpq_gettext("could not read private key file \"%s\": %s\n"),
705728
fnbuf, err);
706729
SSLerrfree(err);
707-
fclose(fp);
730+
731+
BIO_free(bio);
732+
ERR_pop_to_mark();
708733
return 0;
709734
}
710-
fclose(fp);
735+
736+
BIO_free(bio);
711737
}
712738

713739
/* verify that the cert and key go together */
@@ -719,9 +745,12 @@ client_cert_cb(SSL *ssl, X509 **x509, EVP_PKEY **pkey)
719745
libpq_gettext("certificate does not match private key file \"%s\": %s\n"),
720746
fnbuf, err);
721747
SSLerrfree(err);
748+
ERR_pop_to_mark();
722749
return 0;
723750
}
724751

752+
ERR_pop_to_mark();
753+
725754
return 1;
726755
}
727756

0 commit comments

Comments
 (0)