View | Details | Raw Unified | Return to bug 63097
Collapse All | Expand All

(-)a/modules/ssl/ssl_engine_kernel.c (-94 / +125 lines)
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

Return to bug 63097