Lines 476-481
static int ssl_check_post_client_verify(request_rec *r, SSLSrvConfigRec *sc,
Link Here
|
476 |
return OK; |
476 |
return OK; |
477 |
} |
477 |
} |
478 |
|
478 |
|
|
|
479 |
static int ssl_renegotiate_quick(request_rec *r, SSL *ssl) |
480 |
{ |
481 |
SSL_CTX *ctx = ssl ? SSL_get_SSL_CTX(ssl) : NULL; |
482 |
X509_STORE *cert_store = NULL; |
483 |
X509_STORE_CTX *cert_store_ctx; |
484 |
STACK_OF(X509) *cert_stack; |
485 |
X509 *cert; |
486 |
int depth; |
487 |
|
488 |
/* perform just a manual re-verification of the peer */ |
489 |
ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(02258) |
490 |
"Performing quick renegotiation: " |
491 |
"just re-verifying the peer"); |
492 |
|
493 |
cert_stack = (STACK_OF(X509) *)SSL_get_peer_cert_chain(ssl); |
494 |
|
495 |
cert = SSL_get_peer_certificate(ssl); |
496 |
|
497 |
if (!cert_stack || (sk_X509_num(cert_stack) == 0)) { |
498 |
if (!cert) { |
499 |
ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(02222) |
500 |
"Cannot find peer certificate chain"); |
501 |
|
502 |
return HTTP_FORBIDDEN; |
503 |
} |
504 |
|
505 |
/* client cert is in the session cache, but there is |
506 |
* no chain, since ssl3_get_client_certificate() |
507 |
* sk_X509_shift-ed the peer cert out of the chain. |
508 |
* we put it back here for the purpose of quick_renegotiation. |
509 |
*/ |
510 |
cert_stack = sk_X509_new_null(); |
511 |
sk_X509_push(cert_stack, cert); |
512 |
} |
513 |
|
514 |
if (!(cert_store || |
515 |
(cert_store = SSL_CTX_get_cert_store(ctx)))) |
516 |
{ |
517 |
ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(02223) |
518 |
"Cannot find certificate storage"); |
519 |
|
520 |
return HTTP_FORBIDDEN; |
521 |
} |
522 |
|
523 |
if (!cert) { |
524 |
cert = sk_X509_value(cert_stack, 0); |
525 |
} |
526 |
|
527 |
cert_store_ctx = X509_STORE_CTX_new(); |
528 |
X509_STORE_CTX_init(cert_store_ctx, cert_store, cert, cert_stack); |
529 |
depth = SSL_get_verify_depth(ssl); |
530 |
|
531 |
if (depth >= 0) { |
532 |
X509_STORE_CTX_set_depth(cert_store_ctx, depth); |
533 |
} |
534 |
|
535 |
X509_STORE_CTX_set_ex_data(cert_store_ctx, |
536 |
SSL_get_ex_data_X509_STORE_CTX_idx(), |
537 |
(char *)ssl); |
538 |
|
539 |
if (!X509_verify_cert(cert_store_ctx)) { |
540 |
ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(02224) |
541 |
"Re-negotiation verification step failed"); |
542 |
ssl_log_ssl_error(SSLLOG_MARK, APLOG_ERR, r->server); |
543 |
} |
544 |
|
545 |
SSL_set_verify_result(ssl, X509_STORE_CTX_get_error(cert_store_ctx)); |
546 |
X509_STORE_CTX_cleanup(cert_store_ctx); |
547 |
X509_STORE_CTX_free(cert_store_ctx); |
548 |
|
549 |
if (cert_stack != SSL_get_peer_cert_chain(ssl)) { |
550 |
/* we created this ourselves, so free it */ |
551 |
sk_X509_pop_free(cert_stack, X509_free); |
552 |
} |
553 |
|
554 |
return OK; |
555 |
} |
556 |
|
479 |
/* |
557 |
/* |
480 |
* Access Handler, classic flavour, for SSL/TLS up to v1.2 |
558 |
* Access Handler, classic flavour, for SSL/TLS up to v1.2 |
481 |
* where everything can be renegotiated and no one is happy. |
559 |
* where everything can be renegotiated and no one is happy. |
Lines 485-498
static int ssl_hook_Access_classic(request_rec *r, SSLSrvConfigRec *sc, SSLDirCo
Link Here
|
485 |
{ |
563 |
{ |
486 |
server_rec *handshakeserver = sslconn ? sslconn->server : NULL; |
564 |
server_rec *handshakeserver = sslconn ? sslconn->server : NULL; |
487 |
SSLSrvConfigRec *hssc = handshakeserver? mySrvConfig(handshakeserver) : NULL; |
565 |
SSLSrvConfigRec *hssc = handshakeserver? mySrvConfig(handshakeserver) : NULL; |
488 |
SSL_CTX *ctx = ssl ? SSL_get_SSL_CTX(ssl) : NULL; |
|
|
489 |
BOOL renegotiate = FALSE, renegotiate_quick = FALSE; |
566 |
BOOL renegotiate = FALSE, renegotiate_quick = FALSE; |
490 |
X509 *peercert; |
567 |
X509 *peercert; |
491 |
X509_STORE *cert_store = NULL; |
|
|
492 |
X509_STORE_CTX *cert_store_ctx; |
493 |
STACK_OF(SSL_CIPHER) *cipher_list_old = NULL, *cipher_list = NULL; |
568 |
STACK_OF(SSL_CIPHER) *cipher_list_old = NULL, *cipher_list = NULL; |
494 |
const SSL_CIPHER *cipher = NULL; |
569 |
const SSL_CIPHER *cipher = NULL; |
495 |
int depth, verify_old, verify, n, rc; |
570 |
int verify_old, verify, n, rc; |
496 |
const char *ncipher_suite; |
571 |
const char *ncipher_suite; |
497 |
|
572 |
|
498 |
#ifdef HAVE_SRP |
573 |
#ifdef HAVE_SRP |
Lines 871-943
static int ssl_hook_Access_classic(request_rec *r, SSLSrvConfigRec *sc, SSLDirCo
Link Here
|
871 |
"Requesting connection re-negotiation"); |
946 |
"Requesting connection re-negotiation"); |
872 |
|
947 |
|
873 |
if (renegotiate_quick) { |
948 |
if (renegotiate_quick) { |
874 |
STACK_OF(X509) *cert_stack; |
949 |
if (OK != (rc = ssl_renegotiate_quick(r, ssl))) { |
875 |
X509 *cert; |
950 |
return rc; |
876 |
|
|
|
877 |
/* perform just a manual re-verification of the peer */ |
878 |
ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(02258) |
879 |
"Performing quick renegotiation: " |
880 |
"just re-verifying the peer"); |
881 |
|
882 |
cert_stack = (STACK_OF(X509) *)SSL_get_peer_cert_chain(ssl); |
883 |
|
884 |
cert = SSL_get_peer_certificate(ssl); |
885 |
|
886 |
if (!cert_stack || (sk_X509_num(cert_stack) == 0)) { |
887 |
if (!cert) { |
888 |
ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(02222) |
889 |
"Cannot find peer certificate chain"); |
890 |
|
891 |
return HTTP_FORBIDDEN; |
892 |
} |
893 |
|
894 |
/* client cert is in the session cache, but there is |
895 |
* no chain, since ssl3_get_client_certificate() |
896 |
* sk_X509_shift-ed the peer cert out of the chain. |
897 |
* we put it back here for the purpose of quick_renegotiation. |
898 |
*/ |
899 |
cert_stack = sk_X509_new_null(); |
900 |
sk_X509_push(cert_stack, cert); |
901 |
} |
902 |
|
903 |
if (!(cert_store || |
904 |
(cert_store = SSL_CTX_get_cert_store(ctx)))) |
905 |
{ |
906 |
ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(02223) |
907 |
"Cannot find certificate storage"); |
908 |
|
909 |
return HTTP_FORBIDDEN; |
910 |
} |
911 |
|
912 |
if (!cert) { |
913 |
cert = sk_X509_value(cert_stack, 0); |
914 |
} |
915 |
|
916 |
cert_store_ctx = X509_STORE_CTX_new(); |
917 |
X509_STORE_CTX_init(cert_store_ctx, cert_store, cert, cert_stack); |
918 |
depth = SSL_get_verify_depth(ssl); |
919 |
|
920 |
if (depth >= 0) { |
921 |
X509_STORE_CTX_set_depth(cert_store_ctx, depth); |
922 |
} |
923 |
|
924 |
X509_STORE_CTX_set_ex_data(cert_store_ctx, |
925 |
SSL_get_ex_data_X509_STORE_CTX_idx(), |
926 |
(char *)ssl); |
927 |
|
928 |
if (!X509_verify_cert(cert_store_ctx)) { |
929 |
ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(02224) |
930 |
"Re-negotiation verification step failed"); |
931 |
ssl_log_ssl_error(SSLLOG_MARK, APLOG_ERR, r->server); |
932 |
} |
933 |
|
934 |
SSL_set_verify_result(ssl, X509_STORE_CTX_get_error(cert_store_ctx)); |
935 |
X509_STORE_CTX_cleanup(cert_store_ctx); |
936 |
X509_STORE_CTX_free(cert_store_ctx); |
937 |
|
938 |
if (cert_stack != SSL_get_peer_cert_chain(ssl)) { |
939 |
/* we created this ourselves, so free it */ |
940 |
sk_X509_pop_free(cert_stack, X509_free); |
941 |
} |
951 |
} |
942 |
} |
952 |
} |
943 |
else { |
953 |
else { |
Lines 1066-1071
static int ssl_hook_Access_modern(request_rec *r, SSLSrvConfigRec *sc, SSLDirCon
Link Here
|
1066 |
(sc->server->auth.verify_mode != SSL_CVERIFY_UNSET)) { |
1076 |
(sc->server->auth.verify_mode != SSL_CVERIFY_UNSET)) { |
1067 |
int vmode_inplace, vmode_needed; |
1077 |
int vmode_inplace, vmode_needed; |
1068 |
int change_vmode = FALSE; |
1078 |
int change_vmode = FALSE; |
|
|
1079 |
BOOL renegotiate_quick = FALSE; |
1069 |
int old_state, n, rc; |
1080 |
int old_state, n, rc; |
1070 |
|
1081 |
|
1071 |
vmode_inplace = SSL_get_verify_mode(ssl); |
1082 |
vmode_inplace = SSL_get_verify_mode(ssl); |
Lines 1097-1104
static int ssl_hook_Access_modern(request_rec *r, SSLSrvConfigRec *sc, SSLDirCon
Link Here
|
1097 |
&& (vmode_needed & SSL_VERIFY_PEER)) |
1108 |
&& (vmode_needed & SSL_VERIFY_PEER)) |
1098 |
|| (!(vmode_inplace & SSL_VERIFY_FAIL_IF_NO_PEER_CERT) |
1109 |
|| (!(vmode_inplace & SSL_VERIFY_FAIL_IF_NO_PEER_CERT) |
1099 |
&& (vmode_needed & SSL_VERIFY_FAIL_IF_NO_PEER_CERT))) { |
1110 |
&& (vmode_needed & SSL_VERIFY_FAIL_IF_NO_PEER_CERT))) { |
|
|
1111 |
|
1112 |
X509 *peercert; |
1113 |
|
1100 |
/* need to change the effective verify mode */ |
1114 |
/* need to change the effective verify mode */ |
1101 |
change_vmode = TRUE; |
1115 |
change_vmode = TRUE; |
|
|
1116 |
|
1117 |
/* optimization */ |
1118 |
|
1119 |
if ((dc->nOptions & SSL_OPT_OPTRENEGOTIATE) && |
1120 |
(vmode_inplace == SSL_VERIFY_NONE) && |
1121 |
((peercert = SSL_get_peer_certificate(ssl)) != NULL)) |
1122 |
{ |
1123 |
renegotiate_quick = TRUE; |
1124 |
X509_free(peercert); |
1125 |
} |
1102 |
} |
1126 |
} |
1103 |
else { |
1127 |
else { |
1104 |
/* FIXME: does this work with TLSv1.3? Is this more than re-inspecting |
1128 |
/* FIXME: does this work with TLSv1.3? Is this more than re-inspecting |
Lines 1133-1140
static int ssl_hook_Access_modern(request_rec *r, SSLSrvConfigRec *sc, SSLDirCon
Link Here
|
1133 |
} |
1157 |
} |
1134 |
|
1158 |
|
1135 |
if (change_vmode) { |
1159 |
if (change_vmode) { |
1136 |
char peekbuf[1]; |
|
|
1137 |
|
1138 |
if (r->connection->master) { |
1160 |
if (r->connection->master) { |
1139 |
/* FIXME: modifying the SSL on a slave connection is no good. |
1161 |
/* FIXME: modifying the SSL on a slave connection is no good. |
1140 |
* We would need to push this back to the master connection |
1162 |
* We would need to push this back to the master connection |
Lines 1146-1175
static int ssl_hook_Access_modern(request_rec *r, SSLSrvConfigRec *sc, SSLDirCon
Link Here
|
1146 |
|
1168 |
|
1147 |
ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(10129) "verify client post handshake"); |
1169 |
ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(10129) "verify client post handshake"); |
1148 |
|
1170 |
|
1149 |
SSL_set_verify(ssl, vmode_needed, ssl_callback_SSLVerify); |
1171 |
if (renegotiate_quick) { |
1150 |
|
1172 |
if (OK != (rc = ssl_renegotiate_quick(r, ssl))) { |
1151 |
if (SSL_verify_client_post_handshake(ssl) != 1) { |
1173 |
return rc; |
1152 |
ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(10158) |
1174 |
} |
1153 |
"cannot perform post-handshake authentication"); |
|
|
1154 |
ssl_log_ssl_error(SSLLOG_MARK, APLOG_ERR, r->server); |
1155 |
apr_table_setn(r->notes, "error-notes", |
1156 |
"Reason: Cannot perform Post-Handshake Authentication.<br />"); |
1157 |
return HTTP_FORBIDDEN; |
1158 |
} |
1175 |
} |
1159 |
|
1176 |
else { |
1160 |
old_state = sslconn->reneg_state; |
1177 |
char peekbuf[1]; |
1161 |
sslconn->reneg_state = RENEG_ALLOW; |
|
|
1162 |
modssl_set_app_data2(ssl, r); |
1163 |
|
1178 |
|
1164 |
SSL_do_handshake(ssl); |
1179 |
SSL_set_verify(ssl, vmode_needed, ssl_callback_SSLVerify); |
1165 |
/* Need to trigger renegotiation handshake by reading. |
1180 |
|
1166 |
* Peeking 0 bytes actually works. |
1181 |
if (SSL_verify_client_post_handshake(ssl) != 1) { |
1167 |
* See: http://marc.info/?t=145493359200002&r=1&w=2 |
1182 |
ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(10158) |
1168 |
*/ |
1183 |
"cannot perform post-handshake authentication"); |
1169 |
SSL_peek(ssl, peekbuf, 0); |
1184 |
ssl_log_ssl_error(SSLLOG_MARK, APLOG_ERR, r->server); |
|
|
1185 |
apr_table_setn(r->notes, "error-notes", |
1186 |
"Reason: Cannot perform Post-Handshake Authentication.<br />"); |
1187 |
return HTTP_FORBIDDEN; |
1188 |
} |
1189 |
|
1190 |
old_state = sslconn->reneg_state; |
1191 |
sslconn->reneg_state = RENEG_ALLOW; |
1192 |
modssl_set_app_data2(ssl, r); |
1170 |
|
1193 |
|
1171 |
sslconn->reneg_state = old_state; |
1194 |
SSL_do_handshake(ssl); |
1172 |
modssl_set_app_data2(ssl, NULL); |
1195 |
/* Need to trigger renegotiation handshake by reading. |
|
|
1196 |
* Peeking 0 bytes actually works. |
1197 |
* See: http://marc.info/?t=145493359200002&r=1&w=2 |
1198 |
*/ |
1199 |
SSL_peek(ssl, peekbuf, 0); |
1200 |
|
1201 |
sslconn->reneg_state = old_state; |
1202 |
modssl_set_app_data2(ssl, NULL); |
1203 |
} |
1173 |
|
1204 |
|
1174 |
/* |
1205 |
/* |
1175 |
* Finally check for acceptable renegotiation results |
1206 |
* Finally check for acceptable renegotiation results |