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

(-)mod_ssl.c (+1 lines)
Lines 389-394 Link Here
389
static void ssl_register_hooks(apr_pool_t *p)
389
static void ssl_register_hooks(apr_pool_t *p)
390
{
390
{
391
    ssl_io_filter_register(p);
391
    ssl_io_filter_register(p);
392
    ssl_reneg_filter_register(p);
392
393
393
    ap_hook_pre_connection(ssl_hook_pre_connection,NULL,NULL, APR_HOOK_MIDDLE);
394
    ap_hook_pre_connection(ssl_hook_pre_connection,NULL,NULL, APR_HOOK_MIDDLE);
394
    ap_hook_post_config   (ssl_init_Module,        NULL,NULL, APR_HOOK_MIDDLE);
395
    ap_hook_post_config   (ssl_init_Module,        NULL,NULL, APR_HOOK_MIDDLE);
(-)mod_ssl.h (+1 lines)
Lines 675-680 Link Here
675
void         ssl_io_filter_init(conn_rec *, SSL *);
675
void         ssl_io_filter_init(conn_rec *, SSL *);
676
void         ssl_io_filter_register(apr_pool_t *);
676
void         ssl_io_filter_register(apr_pool_t *);
677
long         ssl_io_data_cb(BIO *, int, MODSSL_BIO_CB_ARG_TYPE *, int, long, long);
677
long         ssl_io_data_cb(BIO *, int, MODSSL_BIO_CB_ARG_TYPE *, int, long, long);
678
void         ssl_reneg_filter_register(apr_pool_t *p);
678
679
679
/*  PRNG  */
680
/*  PRNG  */
680
int          ssl_rand_seed(server_rec *, apr_pool_t *, ssl_rsctx_t, char *);
681
int          ssl_rand_seed(server_rec *, apr_pool_t *, ssl_rsctx_t, char *);
(-)ssl_engine_kernel.c (-231 / +293 lines)
Lines 29-34 Link Here
29
                                            -- Unknown                */
29
                                            -- Unknown                */
30
#include "mod_ssl.h"
30
#include "mod_ssl.h"
31
31
32
static int reneg_and_check(request_rec *r, int quick);
33
32
/*
34
/*
33
 *  Post Read Request Handler
35
 *  Post Read Request Handler
34
 */
36
 */
Lines 159-164 Link Here
159
    return DECLINED;
161
    return DECLINED;
160
}
162
}
161
163
164
static ap_filter_rec_t *reneg_filter_rec;
165
166
/* The renegotiation input filter is inserted into the input filter
167
 * stack to perform an SSL renegotatiation after the request body has
168
 * been read.  It runs before the HTTP input filter and waits for it to return
169
 * an EOS; at which point it is safe to perform the SSL handshake. */
170
static apr_status_t reneg_in_filter(ap_filter_t *f, 
171
                                    apr_bucket_brigade *bb,
172
                                    ap_input_mode_t mode,
173
                                    apr_read_type_e block,
174
                                    apr_off_t bytes)
175
{
176
    apr_bucket *bkt;
177
    apr_status_t rv;
178
179
    /* This filter needs to buffer each brigade into memory to ensure
180
     * that when an EOS is found, all data really has been read from
181
     * the socket.  So, ensure that not too much is buffered: */
182
    if (bytes > HUGE_STRING_LEN) {
183
        bytes = HUGE_STRING_LEN;
184
    }
185
186
    rv = ap_get_brigade(f->next, bb, mode, block, bytes);
187
    if (rv != APR_SUCCESS) {
188
        return rv;
189
    }
190
191
    for (bkt = APR_BRIGADE_FIRST(bb);
192
         bkt != APR_BRIGADE_SENTINEL(bb);
193
         bkt = APR_BUCKET_NEXT(bkt))
194
    {
195
        if (APR_BUCKET_IS_EOS(bkt)) {
196
            /* No more work for this filter. */
197
            ap_remove_input_filter(f);
198
199
            /* Now really do the negotiation and access control checks. */
200
            if (reneg_and_check(f->r, 0)) {
201
                
202
                /* Access control checks failed: send a 403. */
203
                ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, f->r,
204
                              "renegotiation failed; sending 403 error");
205
                bb = apr_brigade_create(f->r->pool, f->c->bucket_alloc);
206
                bkt = ap_bucket_error_create(HTTP_FORBIDDEN, NULL,
207
                                             f->r->pool, f->c->bucket_alloc);
208
                APR_BRIGADE_INSERT_TAIL(bb, bkt);
209
                bkt = apr_bucket_eos_create(f->c->bucket_alloc);
210
                APR_BRIGADE_INSERT_TAIL(bb, bkt);
211
                
212
                rv = ap_pass_brigade(f->r->output_filters, bb);
213
                if (rv) {
214
                    ap_log_rerror(APLOG_MARK, APLOG_INFO, rv, f->r,
215
                                  "could not send 403 after renegotiation"
216
                                  " failure");
217
                }
218
                
219
                /* Don't give anything back to the caller, just return
220
                 * an error. */
221
                apr_brigade_cleanup(bb);
222
                return APR_EACCES;
223
            }
224
225
            /* ignore the rest of the brigade */
226
            break;
227
        }
228
229
        /* For any non-metadata buckets, read from the bucket to
230
         * ensure that it is morphed into a heap bucket if it's a
231
         * morphing bucket type. */
232
        if (!APR_BUCKET_IS_METADATA(bkt)) {
233
            const char *buf;
234
            apr_size_t len;
235
236
            rv = apr_bucket_read(bkt, &buf, &len, block);
237
            if (rv) {
238
                ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, f->r,
239
                              "bucket read failed");
240
                apr_brigade_cleanup(bb);
241
                return rv;
242
            }
243
        }
244
    }
245
246
    return APR_SUCCESS;
247
}
248
249
void ssl_reneg_filter_register(apr_pool_t *p)
250
{
251
    /* only requirement is that this input filter comes before the
252
     * ap_http_filter. */
253
    reneg_filter_rec =
254
        ap_register_input_filter("SSL_RENEG", reneg_in_filter, NULL,
255
                                 AP_FTYPE_PROTOCOL - 1);
256
}
257
162
/*
258
/*
163
 *  Access Handler
259
 *  Access Handler
164
 */
260
 */
Lines 169-186 Link Here
169
    SSLConnRec *sslconn = myConnConfig(r->connection);
265
    SSLConnRec *sslconn = myConnConfig(r->connection);
170
    SSL *ssl            = sslconn ? sslconn->ssl : NULL;
266
    SSL *ssl            = sslconn ? sslconn->ssl : NULL;
171
    SSL_CTX *ctx = NULL;
267
    SSL_CTX *ctx = NULL;
172
    apr_array_header_t *requires;
173
    ssl_require_t *ssl_requires;
174
    char *cp;
268
    char *cp;
175
    int ok, i;
176
    BOOL renegotiate = FALSE, renegotiate_quick = FALSE;
269
    BOOL renegotiate = FALSE, renegotiate_quick = FALSE;
177
    X509 *cert;
178
    X509 *peercert;
270
    X509 *peercert;
179
    X509_STORE *cert_store = NULL;
180
    X509_STORE_CTX cert_store_ctx;
181
    STACK_OF(SSL_CIPHER) *cipher_list_old = NULL, *cipher_list = NULL;
271
    STACK_OF(SSL_CIPHER) *cipher_list_old = NULL, *cipher_list = NULL;
182
    SSL_CIPHER *cipher = NULL;
272
    SSL_CIPHER *cipher = NULL;
183
    int depth, verify_old, verify, n;
273
    int verify_old, verify, n;
184
274
185
    if (ssl) {
275
    if (ssl) {
186
        ctx = SSL_get_SSL_CTX(ssl);
276
        ctx = SSL_get_SSL_CTX(ssl);
Lines 489-723 Link Here
489
    }
579
    }
490
#endif /* HAVE_SSL_SET_CERT_STORE */
580
#endif /* HAVE_SSL_SET_CERT_STORE */
491
581
492
    /* 
582
    if (!renegotiate) {
493
     * SSL renegotiations in conjunction with HTTP
583
        /* Nothing more to do here. */
494
     * requests using the POST method are not supported.
584
        return DECLINED;
495
     *
496
     * Background:
497
     *
498
     * 1. When the client sends a HTTP/HTTPS request, Apache's core code
499
     * reads only the request line ("METHOD /path HTTP/x.y") and the
500
     * attached MIME headers ("Foo: bar") up to the terminating line ("CR
501
     * LF"). An attached request body (for instance the data of a POST
502
     * method) is _NOT_ read. Instead it is read by mod_cgi's content
503
     * handler and directly passed to the CGI script.
504
     *
505
     * 2. mod_ssl supports per-directory re-configuration of SSL parameters.
506
     * This is implemented by performing an SSL renegotiation of the
507
     * re-configured parameters after the request is read, but before the
508
     * response is sent. In more detail: the renegotiation happens after the
509
     * request line and MIME headers were read, but _before_ the attached
510
     * request body is read. The reason simply is that in the HTTP protocol
511
     * usually there is no acknowledgment step between the headers and the
512
     * body (there is the 100-continue feature and the chunking facility
513
     * only), so Apache has no API hook for this step.
514
     *
515
     * 3. the problem now occurs when the client sends a POST request for
516
     * URL /foo via HTTPS the server and the server has SSL parameters
517
     * re-configured on a per-URL basis for /foo. Then mod_ssl has to
518
     * perform an SSL renegotiation after the request was read and before
519
     * the response is sent. But the problem is the pending POST body data
520
     * in the receive buffer of SSL (which Apache still has not read - it's
521
     * pending until mod_cgi sucks it in). When mod_ssl now tries to perform
522
     * the renegotiation the pending data leads to an I/O error.
523
     *
524
     * Solution Idea:
525
     *
526
     * There are only two solutions: Either to simply state that POST
527
     * requests to URLs with SSL re-configurations are not allowed, or to
528
     * renegotiate really after the _complete_ request (i.e. including
529
     * the POST body) was read. Obviously the latter would be preferred,
530
     * but it cannot be done easily inside Apache, because as already
531
     * mentioned, there is no API step between the body reading and the body
532
     * processing. And even when we mod_ssl would hook directly into the
533
     * loop of mod_cgi, we wouldn't solve the problem for other handlers, of
534
     * course. So the only general solution is to suck in the pending data
535
     * of the request body from the OpenSSL BIO into the Apache BUFF. Then
536
     * the renegotiation can be done and after this step Apache can proceed
537
     * processing the request as before.
538
     *
539
     * Solution Implementation:
540
     *
541
     * We cannot simply suck in the data via an SSL_read-based loop because of
542
     * HTTP chunking. Instead we _have_ to use the Apache API for this step which
543
     * is aware of HTTP chunking. So the trick is to suck in the pending request
544
     * data via the Apache API (which uses Apache's BUFF code and in the
545
     * background mod_ssl's I/O glue code) and re-inject it later into the Apache
546
     * BUFF code again. This way the data flows twice through the Apache BUFF, of
547
     * course. But this way the solution doesn't depend on any Apache specifics
548
     * and is fully transparent to Apache modules.
549
     *
550
     * !! BUT ALL THIS IS STILL NOT RE-IMPLEMENTED FOR APACHE 2.0 !!
551
     */
552
    if (renegotiate && !renegotiate_quick && (r->method_number == M_POST)) {
553
        ap_log_error(APLOG_MARK, APLOG_ERR, 0, r->server,
554
                     "SSL Re-negotiation in conjunction "
555
                     "with POST method not supported!\n"
556
                     "hint: try SSLOptions +OptRenegotiate");
557
558
        return HTTP_METHOD_NOT_ALLOWED;
559
    }
585
    }
560
586
561
    /*
587
    /* This function is called after reading the request-header.  If
562
     * now do the renegotiation if anything was actually reconfigured
588
     * the HTTP request includes a message body, then the client may
563
     */
589
     * already have sent all the SSL records containing that body.
564
    if (renegotiate) {
590
     * It's not possible to do a renegotiation until all those SSL
565
        /*
591
     * records have been read and processed, so the renegotiation has
566
         * Now we force the SSL renegotation by sending the Hello Request
592
     * to be delayed until that point (when an EOS is returned by the
567
         * message to the client. Here we have to do a workaround: Actually
593
     * HTTP input filter). */
568
         * OpenSSL returns immediately after sending the Hello Request (the
594
569
         * intent AFAIK is because the SSL/TLS protocol says it's not a must
595
    if (!renegotiate_quick &&
570
         * that the client replies to a Hello Request). But because we insist
596
        (apr_table_get(r->headers_in, "Transfer-Encoding") ||
571
         * on a reply (anything else is an error for us) we have to go to the
597
         ((cp = (char *)apr_table_get(r->headers_in, "Content-Length")) != NULL
572
         * ACCEPT state manually. Using SSL_set_accept_state() doesn't work
598
          && strcmp(cp, "0")))) {
573
         * here because it resets too much of the connection.  So we set the
574
         * state explicitly and continue the handshake manually.
575
         */
576
        ap_log_error(APLOG_MARK, APLOG_INFO, 0, r->server,
599
        ap_log_error(APLOG_MARK, APLOG_INFO, 0, r->server,
577
                     "Requesting connection re-negotiation");
600
                     "SSL re-negotiation needed for request with body: "
578
601
                     "delaying until after body has been read");
579
        if (renegotiate_quick) {
602
        ap_add_input_filter_handle(reneg_filter_rec, NULL, r, r->connection);
580
            STACK_OF(X509) *cert_stack;
581
582
            /* perform just a manual re-verification of the peer */
583
            ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server,
584
                         "Performing quick renegotiation: "
585
                         "just re-verifying the peer");
586
587
            cert_stack = (STACK_OF(X509) *)SSL_get_peer_cert_chain(ssl);
588
589
            cert = SSL_get_peer_certificate(ssl);
590
591
            if (!cert_stack && cert) {
592
                /* client cert is in the session cache, but there is
593
                 * no chain, since ssl3_get_client_certificate()
594
                 * sk_X509_shift-ed the peer cert out of the chain.
595
                 * we put it back here for the purpose of quick_renegotiation.
596
                 */
597
                cert_stack = sk_new_null();
598
                sk_X509_push(cert_stack, MODSSL_PCHAR_CAST cert);
599
            }
600
601
            if (!cert_stack || (sk_X509_num(cert_stack) == 0)) {
602
                ap_log_error(APLOG_MARK, APLOG_ERR, 0, r->server,
603
                             "Cannot find peer certificate chain");
604
605
                return HTTP_FORBIDDEN;
606
            }
607
608
            if (!(cert_store ||
609
                  (cert_store = SSL_CTX_get_cert_store(ctx))))
610
            {
611
                ap_log_error(APLOG_MARK, APLOG_ERR, 0, r->server,
612
                             "Cannot find certificate storage");
613
614
                return HTTP_FORBIDDEN;
615
            }
616
617
            if (!cert) {
618
                cert = sk_X509_value(cert_stack, 0);
619
            }
620
621
            X509_STORE_CTX_init(&cert_store_ctx, cert_store, cert, cert_stack);
622
            depth = SSL_get_verify_depth(ssl);
623
603
624
            if (depth >= 0) {
604
        return DECLINED;
625
                X509_STORE_CTX_set_depth(&cert_store_ctx, depth);
605
    }
626
            }
627
628
            X509_STORE_CTX_set_ex_data(&cert_store_ctx,
629
                                       SSL_get_ex_data_X509_STORE_CTX_idx(),
630
                                       (char *)ssl);
631
606
632
            if (!modssl_X509_verify_cert(&cert_store_ctx)) {
607
    /* Now actually perform the SSL renegotiation; return DECLINED on
633
                ap_log_error(APLOG_MARK, APLOG_ERR, 0, r->server,
608
     * success, to allow mod_auth and other modules to deny access. */
634
                             "Re-negotiation verification step failed");
609
    return (reneg_and_check(r, renegotiate_quick) 
635
                ssl_log_ssl_error(APLOG_MARK, APLOG_ERR, r->server);
610
            ? HTTP_FORBIDDEN : DECLINED);
636
            }
611
}
637
612
638
            SSL_set_verify_result(ssl, cert_store_ctx.error);
613
/* Do an SSL renegotiation and perform access control checks; do a
639
            X509_STORE_CTX_cleanup(&cert_store_ctx);
614
 * "quick" renegotation (which doesn't actually perform an SSL
615
 * handshake), if 'quick' is non-zero.  Returns non-zero if access
616
 * control checks failed. */
617
static int reneg_and_check(request_rec *r, int quick)
618
{
619
    SSLDirConfigRec *dc = myDirConfig(r);
620
    SSLConnRec *sslconn = myConnConfig(r->connection);
621
    SSL *ssl            = sslconn ? sslconn->ssl : NULL;
622
    apr_array_header_t *requires;
623
    ssl_require_t *ssl_requires;
624
    X509_STORE *cert_store = NULL;
625
    X509_STORE_CTX cert_store_ctx;
626
    X509 *cert;
627
    SSL_CTX *ctx = SSL_get_SSL_CTX(ssl);
628
    int depth, i, ok;
629
    char *cp;
640
630
641
            if (cert_stack != SSL_get_peer_cert_chain(ssl)) {
631
    /*
642
                /* we created this ourselves, so free it */
632
     * Now we force the SSL renegotation by sending the Hello Request
643
                sk_X509_pop_free(cert_stack, X509_free);
633
     * message to the client. Here we have to do a workaround: Actually
644
            }
634
     * OpenSSL returns immediately after sending the Hello Request (the
635
     * intent AFAIK is because the SSL/TLS protocol says it's not a must
636
     * that the client replies to a Hello Request). But because we insist
637
     * on a reply (anything else is an error for us) we have to go to the
638
     * ACCEPT state manually. Using SSL_set_accept_state() doesn't work
639
     * here because it resets too much of the connection.  So we set the
640
     * state explicitly and continue the handshake manually.
641
     */
642
    ap_log_error(APLOG_MARK, APLOG_INFO, 0, r->server,
643
                 "Requesting connection re-negotiation");
644
    
645
    if (quick) {
646
        STACK_OF(X509) *cert_stack;
647
        
648
        /* perform just a manual re-verification of the peer */
649
        ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server,
650
                     "Performing quick renegotiation: "
651
                     "just re-verifying the peer");
652
        
653
        cert_stack = (STACK_OF(X509) *)SSL_get_peer_cert_chain(ssl);
654
        
655
        cert = SSL_get_peer_certificate(ssl);
656
        
657
        if (!cert_stack && cert) {
658
            /* client cert is in the session cache, but there is
659
             * no chain, since ssl3_get_client_certificate()
660
             * sk_X509_shift-ed the peer cert out of the chain.
661
             * we put it back here for the purpose of quick_renegotiation.
662
             */
663
            cert_stack = sk_new_null();
664
            sk_X509_push(cert_stack, MODSSL_PCHAR_CAST cert);
645
        }
665
        }
646
        else {
666
        
647
            request_rec *id = r->main ? r->main : r;
667
        if (!cert_stack || (sk_X509_num(cert_stack) == 0)) {
648
668
            ap_log_error(APLOG_MARK, APLOG_ERR, 0, r->server,
649
            /* do a full renegotiation */
669
                         "Cannot find peer certificate chain");
650
            ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server,
670
            
651
                         "Performing full renegotiation: "
671
            return 1;
652
                         "complete handshake protocol");
653
654
            SSL_set_session_id_context(ssl,
655
                                       (unsigned char *)&id,
656
                                       sizeof(id));
657
658
            SSL_renegotiate(ssl);
659
            SSL_do_handshake(ssl);
660
661
            if (SSL_get_state(ssl) != SSL_ST_OK) {
662
                ap_log_error(APLOG_MARK, APLOG_ERR, 0, r->server,
663
                             "Re-negotiation request failed");
664
665
                r->connection->aborted = 1;
666
                return HTTP_FORBIDDEN;
667
            }
668
669
            ap_log_error(APLOG_MARK, APLOG_INFO, 0, r->server,
670
                         "Awaiting re-negotiation handshake");
671
672
            SSL_set_state(ssl, SSL_ST_ACCEPT);
673
            SSL_do_handshake(ssl);
674
675
            if (SSL_get_state(ssl) != SSL_ST_OK) {
676
                ap_log_error(APLOG_MARK, APLOG_ERR, 0, r->server,
677
                             "Re-negotiation handshake failed: "
678
                        "Not accepted by client!?");
679
680
                r->connection->aborted = 1;
681
                return HTTP_FORBIDDEN;
682
            }
683
        }
672
        }
684
673
        
685
        /*
674
        if (!(cert_store ||
686
         * Remember the peer certificate's DN
675
              (cert_store = SSL_CTX_get_cert_store(ctx))))
687
         */
676
        {
688
        if ((cert = SSL_get_peer_certificate(ssl))) {
677
            ap_log_error(APLOG_MARK, APLOG_ERR, 0, r->server,
689
            if (sslconn->client_cert) {
678
                         "Cannot find certificate storage");
690
                X509_free(sslconn->client_cert);
679
            
691
            }
680
            return 1;
692
            sslconn->client_cert = cert;
693
            sslconn->client_dn = NULL;
694
        }
681
        }
695
682
        
696
        /*
683
        if (!cert) {
697
         * Finally check for acceptable renegotiation results
684
            cert = sk_X509_value(cert_stack, 0);
685
        }
686
        
687
        X509_STORE_CTX_init(&cert_store_ctx, cert_store, cert, cert_stack);
688
        depth = SSL_get_verify_depth(ssl);
689
        
690
        if (depth >= 0) {
691
            X509_STORE_CTX_set_depth(&cert_store_ctx, depth);
692
        }
693
        
694
        X509_STORE_CTX_set_ex_data(&cert_store_ctx,
695
                                   SSL_get_ex_data_X509_STORE_CTX_idx(),
696
                                   (char *)ssl);
697
        
698
        if (!modssl_X509_verify_cert(&cert_store_ctx)) {
699
            ap_log_error(APLOG_MARK, APLOG_ERR, 0, r->server,
700
                         "Re-negotiation verification step failed");
701
            ssl_log_ssl_error(APLOG_MARK, APLOG_ERR, r->server);
702
        }
703
        
704
        SSL_set_verify_result(ssl, cert_store_ctx.error);
705
        X509_STORE_CTX_cleanup(&cert_store_ctx);
706
        
707
        if (cert_stack != SSL_get_peer_cert_chain(ssl)) {
708
            /* we created this ourselves, so free it */
709
            sk_X509_pop_free(cert_stack, X509_free);
710
        }
711
    }
712
    else {
713
        request_rec *id = r->main ? r->main : r;
714
        
715
        /* do a full renegotiation */
716
        ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server,
717
                     "Performing full renegotiation: "
718
                     "complete handshake protocol");
719
        
720
        SSL_set_session_id_context(ssl,
721
                                   (unsigned char *)&id,
722
                                   sizeof(id));
723
        
724
        SSL_renegotiate(ssl);
725
        SSL_do_handshake(ssl);
726
        
727
        if (SSL_get_state(ssl) != SSL_ST_OK) {
728
            ap_log_error(APLOG_MARK, APLOG_ERR, 0, r->server,
729
                         "Re-negotiation request failed");
730
            
731
            r->connection->aborted = 1;
732
            return 1;
733
        }
734
        
735
        ap_log_error(APLOG_MARK, APLOG_INFO, 0, r->server,
736
                     "Awaiting re-negotiation handshake");
737
        
738
        /* XXX: Should replace SSL_set_state with SSL_renegotiate(ssl);
739
         * However, this causes failures in perl-framework currently, 
740
         * perhaps pre-test if we have already negotiated?
698
         */
741
         */
699
        if (dc->nVerifyClient != SSL_CVERIFY_NONE) {
742
        SSL_set_state(ssl, SSL_ST_ACCEPT);
700
            BOOL do_verify = (dc->nVerifyClient == SSL_CVERIFY_REQUIRE);
743
        SSL_do_handshake(ssl);
744
        
745
        if (SSL_get_state(ssl) != SSL_ST_OK) {
746
            ap_log_error(APLOG_MARK, APLOG_ERR, 0, r->server,
747
                         "Re-negotiation handshake failed: "
748
                         "Not accepted by client!?");
749
            
750
            r->connection->aborted = 1;
751
            return 1;
752
        }
753
    }
754
    
755
    /*
756
     * Remember the peer certificate's DN
757
     */
758
    if ((cert = SSL_get_peer_certificate(ssl))) {
759
        if (sslconn->client_cert) {
760
            X509_free(sslconn->client_cert);
761
        }
762
        sslconn->client_cert = cert;
763
        sslconn->client_dn = NULL;
764
    }
765
    
766
    /*
767
     * Finally check for acceptable renegotiation results
768
     */
769
    if (dc->nVerifyClient != SSL_CVERIFY_NONE) {
770
        BOOL do_verify = (dc->nVerifyClient == SSL_CVERIFY_REQUIRE);
771
        
772
        if (do_verify && (SSL_get_verify_result(ssl) != X509_V_OK)) {
773
            ap_log_error(APLOG_MARK, APLOG_ERR, 0, r->server,
774
                         "Re-negotiation handshake failed: "
775
                         "Client verification failed");
776
            return 1;
777
        }
778
        
779
        if (do_verify) {
780
            X509 *peercert;
701
781
702
            if (do_verify && (SSL_get_verify_result(ssl) != X509_V_OK)) {
782
            if ((peercert = SSL_get_peer_certificate(ssl)) == NULL) {
703
                ap_log_error(APLOG_MARK, APLOG_ERR, 0, r->server,
783
                ap_log_error(APLOG_MARK, APLOG_ERR, 0, r->server,
704
                             "Re-negotiation handshake failed: "
784
                             "Re-negotiation handshake failed: "
705
                             "Client verification failed");
785
                             "Client certificate missing");
706
786
                return 1;
707
                return HTTP_FORBIDDEN;
708
            }
709
710
            if (do_verify) {
711
                if ((peercert = SSL_get_peer_certificate(ssl)) == NULL) {
712
                    ap_log_error(APLOG_MARK, APLOG_ERR, 0, r->server,
713
                                 "Re-negotiation handshake failed: "
714
                                 "Client certificate missing");
715
716
                    return HTTP_FORBIDDEN;
717
                }
718
719
                X509_free(peercert);
720
            }
787
            }
788
            
789
            X509_free(peercert);
721
        }
790
        }
722
    }
791
    }
723
792
Lines 744-750 Link Here
744
            /* remember forbidden access for strict require option */
813
            /* remember forbidden access for strict require option */
745
            apr_table_setn(r->notes, "ssl-access-forbidden", "1");
814
            apr_table_setn(r->notes, "ssl-access-forbidden", "1");
746
815
747
            return HTTP_FORBIDDEN;
816
            return 1;
748
        }
817
        }
749
818
750
        if (ok != 1) {
819
        if (ok != 1) {
Lines 765-782 Link Here
765
            /* remember forbidden access for strict require option */
834
            /* remember forbidden access for strict require option */
766
            apr_table_setn(r->notes, "ssl-access-forbidden", "1");
835
            apr_table_setn(r->notes, "ssl-access-forbidden", "1");
767
836
768
            return HTTP_FORBIDDEN;
837
            return 1;
769
        }
838
        }
770
    }
839
    }
771
840
772
    /*
841
    return 0;
773
     * Else access is granted from our point of view (except vendor
774
     * handlers override). But we have to return DECLINED here instead
775
     * of OK, because mod_auth and other modules still might want to
776
     * deny access.
777
     */
778
779
    return DECLINED;
780
}
842
}
781
843
782
/*
844
/*

Return to bug 12355