@@ -91,7 +91,7 @@ static void info_cb(const SSL *ssl, int type, int args);
91
91
static void initialize_SSL (void );
92
92
static int open_server_SSL (Port * );
93
93
static void close_SSL (Port * );
94
- static const char * SSLerrmessage (void );
94
+ static const char * SSLerrmessage (unsigned long ecode );
95
95
#endif
96
96
97
97
/*
@@ -245,11 +245,14 @@ secure_read(Port *port, void *ptr, size_t len)
245
245
if (port -> ssl )
246
246
{
247
247
int err ;
248
+ unsigned long ecode ;
248
249
249
250
rloop :
250
251
errno = 0 ;
252
+ ERR_clear_error ();
251
253
n = SSL_read (port -> ssl , ptr , len );
252
254
err = SSL_get_error (port -> ssl , n );
255
+ ecode = (err != SSL_ERROR_NONE || n < 0 ) ? ERR_get_error () : 0 ;
253
256
switch (err )
254
257
{
255
258
case SSL_ERROR_NONE :
@@ -281,7 +284,7 @@ secure_read(Port *port, void *ptr, size_t len)
281
284
case SSL_ERROR_SSL :
282
285
ereport (COMMERROR ,
283
286
(errcode (ERRCODE_PROTOCOL_VIOLATION ),
284
- errmsg ("SSL error: %s" , SSLerrmessage ())));
287
+ errmsg ("SSL error: %s" , SSLerrmessage (ecode ))));
285
288
/* fall through */
286
289
case SSL_ERROR_ZERO_RETURN :
287
290
errno = ECONNRESET ;
@@ -321,6 +324,7 @@ secure_write(Port *port, void *ptr, size_t len)
321
324
if (port -> ssl )
322
325
{
323
326
int err ;
327
+ unsigned long ecode ;
324
328
325
329
if (ssl_renegotiation_limit && port -> count > ssl_renegotiation_limit * 1024L )
326
330
{
@@ -349,8 +353,10 @@ secure_write(Port *port, void *ptr, size_t len)
349
353
350
354
wloop :
351
355
errno = 0 ;
356
+ ERR_clear_error ();
352
357
n = SSL_write (port -> ssl , ptr , len );
353
358
err = SSL_get_error (port -> ssl , n );
359
+ ecode = (err != SSL_ERROR_NONE || n < 0 ) ? ERR_get_error () : 0 ;
354
360
switch (err )
355
361
{
356
362
case SSL_ERROR_NONE :
@@ -376,7 +382,7 @@ secure_write(Port *port, void *ptr, size_t len)
376
382
case SSL_ERROR_SSL :
377
383
ereport (COMMERROR ,
378
384
(errcode (ERRCODE_PROTOCOL_VIOLATION ),
379
- errmsg ("SSL error: %s" , SSLerrmessage ())));
385
+ errmsg ("SSL error: %s" , SSLerrmessage (ecode ))));
380
386
/* fall through */
381
387
case SSL_ERROR_ZERO_RETURN :
382
388
errno = ECONNRESET ;
@@ -536,7 +542,8 @@ load_dh_file(int keylength)
536
542
{
537
543
if (DH_check (dh , & codes ) == 0 )
538
544
{
539
- elog (LOG , "DH_check error (%s): %s" , fnbuf , SSLerrmessage ());
545
+ elog (LOG , "DH_check error (%s): %s" , fnbuf ,
546
+ SSLerrmessage (ERR_get_error ()));
540
547
return NULL ;
541
548
}
542
549
if (codes & DH_CHECK_P_NOT_PRIME )
@@ -576,7 +583,7 @@ load_dh_buffer(const char *buffer, size_t len)
576
583
if (dh == NULL )
577
584
ereport (DEBUG2 ,
578
585
(errmsg_internal ("DH load buffer: %s" ,
579
- SSLerrmessage ())));
586
+ SSLerrmessage (ERR_get_error () ))));
580
587
BIO_free (bio );
581
588
582
589
return dh ;
@@ -746,7 +753,7 @@ initialize_SSL(void)
746
753
if (!SSL_context )
747
754
ereport (FATAL ,
748
755
(errmsg ("could not create SSL context: %s" ,
749
- SSLerrmessage ())));
756
+ SSLerrmessage (ERR_get_error () ))));
750
757
751
758
/*
752
<
6D4E
td data-grid-cell-id="diff-0202c94a7fdd10c35397465259ce2c5c03c64f6d55047a485486939a25b12d88-752-759-1" data-selected="false" role="gridcell" style="background-color:var(--bgColor-default);text-align:center" tabindex="-1" valign="top" class="focusable-grid-cell diff-line-number position-relative diff-line-number-neutral left-side">759
* Disable OpenSSL's moving-write-buffer sanity check, because it
@@ -762,7 +769,7 @@ initialize_SSL(void)
762
769
ereport (FATAL ,
763
770
(errcode (ERRCODE_CONFIG_FILE_ERROR ),
764
771
errmsg ("could not load server certificate file \"%s\": %s" ,
765
- SERVER_CERT_FILE , SSLerrmessage ())));
772
+ SERVER_CERT_FILE , SSLerrmessage (ERR_get_error () ))));
766
773
767
774
if (stat (SERVER_PRIVATE_KEY_FILE , & buf ) != 0 )
768
775
ereport (FATAL ,
@@ -792,12 +799,13 @@ initialize_SSL(void)
792
799
SSL_FILETYPE_PEM ) != 1 )
793
800
ereport (FATAL ,
794
801
(errmsg ("could not load private key file \"%s\": %s" ,
795
- SERVER_PRIVATE_KEY_FILE , SSLerrmessage ())));
802
+ SERVER_PRIVATE_KEY_FILE ,
803
+ SSLerrmessage (ERR_get_error ()))));
796
804
797
805
if (SSL_CTX_check_private_key (SSL_context ) != 1 )
798
806
ereport (FATAL ,
799
807
(errmsg ("check of private key failed: %s" ,
800
- SSLerrmessage ())));
808
+ SSLerrmessage (ERR_get_error () ))));
801
809
}
802
810
803
811
/* set up ephemeral DH keys, and disallow SSL v2 while at it */
@@ -836,7 +844,7 @@ initialize_SSL(void)
836
844
*/
837
845
ereport (FATAL ,
838
846
(errmsg ("could not load root certificate file \"%s\": %s" ,
839
- ROOT_CERT_FILE , SSLerrmessage ())));
847
+ ROOT_CERT_FILE , SSLerrmessage (ERR_get_error () ))));
840
848
}
841
849
else
842
850
{
@@ -868,7 +876,7 @@ initialize_SSL(void)
868
876
/* Not fatal - we do not require CRL */
869
877
ereport (LOG ,
870
878
(errmsg ("SSL certificate revocation list file \"%s\" not found, skipping: %s" ,
871
- ROOT_CRL_FILE , SSLerrmessage ()),
879
+ ROOT_CRL_FILE , SSLerrmessage (ERR_get_error () )),
872
880
errdetail ("Certificates will not be checked against revocation list." )));
873
881
}
874
882
@@ -903,6 +911,7 @@ open_server_SSL(Port *port)
903
911
{
904
912
int r ;
905
913
int err ;
914
+ unsigned long ecode ;
906
915
907
916
Assert (!port -> ssl );
908
917
Assert (!port -> peer );
@@ -912,23 +921,43 @@ open_server_SSL(Port *port)
912
921
ereport (COMMERROR ,
913
922
(errcode (ERRCODE_PROTOCOL_VIOLATION ),
914
923
errmsg ("could not initialize SSL connection: %s" ,
915
- SSLerrmessage ())));
924
+ SSLerrmessage (ERR_get_error () ))));
916
925
return -1 ;
917
926
}
918
927
if (!my_SSL_set_fd (port -> ssl , port -> sock ))
919
928
{
920
929
ereport (COMMERROR ,
921
930
(errcode (ERRCODE_PROTOCOL_VIOLATION ),
922
931
errmsg ("could not set SSL socket: %s" ,
923
- SSLerrmessage ())));
932
+ SSLerrmessage (ERR_get_error () ))));
924
933
return -1 ;
925
934
}
926
935
927
936
aloop :
937
+ /*
938
+ * Prepare to call SSL_get_error() by clearing thread's OpenSSL error
939
+ * queue. In general, the current thread's error queue must be empty
940
+ * before the TLS/SSL I/O operation is attempted, or SSL_get_error()
941
+ * will not work reliably. An extension may have failed to clear the
942
+ * per-thread error queue following another call to an OpenSSL I/O
943
+ * routine.
944
+ */
945
+ ERR_clear_error ();
928
946
r = SSL_accept (port -> ssl );
929
947
if (r <= 0 )
930
948
{
931
949
err = SSL_get_error (port -> ssl , r );
950
+
951
+ /*
952
+ * Other clients of OpenSSL in the backend may fail to call
953
+ * ERR_get_error(), but we always do, so as to not cause problems
954
+ * for OpenSSL clients that don't call ERR_clear_error()
955
+ * defensively. Be sure that this happens by calling now.
956
+ * SSL_get_error() relies on the OpenSSL per-thread error queue
957
+ * being intact, so this is the earliest possible point
958
+ * ERR_get_error() may be called.
959
+ */
960
+ ecode = ERR_get_error ();
932
961
switch (err )
933
962
{
934
963
case SSL_ERROR_WANT_READ :
@@ -954,7 +983,7 @@ open_server_SSL(Port *port)
954
983
ereport (COMMERROR ,
955
984
(errcode (ERRCODE_PROTOCOL_VIOLATION ),
956
985
errmsg ("could not accept SSL connection: %s" ,
957
- SSLerrmessage ())));
986
+ SSLerrmessage (ecode ))));
958
987
break ;
959
988
case SSL_ERROR_ZERO_RETURN :
960
989
ereport (COMMERROR ,
@@ -1055,24 +1084,24 @@ close_SSL(Port *port)
1055
1084
/*
1056
1085
* Obtain reason string for last SSL error
1057
1086
*
1087
+ * ERR_get_error() is used by caller to get errcode to pass here.
1088
+ *
1058
1089
* Some caution is needed here since ERR_reason_error_string will
1059
1090
* return NULL if it doesn't recognize the error code. We don't
1060
1091
* want to return NULL ever.
1061
1092
*/
1062
1093
static const char *
1063
- SSLerrmessage (void )
1094
+ SSLerrmessage (unsigned long ecode )
1064
1095
{
1065
- unsigned long errcode ;
1066
1096
const char * errreason ;
1067
1097
static char errbuf [32 ];
1068
1098
1069
- errcode = ERR_get_error ();
1070
- if (errcode == 0 )
1099
+ if (ecode == 0 )
1071
1100
return _ ("no SSL error reported" );
1072
- errreason = ERR_reason_error_string (errcode );
1101
+ errreason = ERR_reason_error_string (ecode );
1073
1102
if (errreason != NULL )
1074
1103
return errreason ;
1075
- snprintf (errbuf , sizeof (errbuf ), _ ("SSL error code %lu" ), errcode );
1104
+ snprintf (errbuf , sizeof (errbuf ), _ ("SSL error code %lu" ), ecode );
1076
1105
return errbuf ;
1077
1106
}
1078
1107
0 commit comments