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

(-)modules/ssl/mod_ssl.c (+1 lines)
Lines 469-474 Link Here
469
static void ssl_register_hooks(apr_pool_t *p)
469
static void ssl_register_hooks(apr_pool_t *p)
470
{
470
{
471
    ssl_io_filter_register(p);
471
    ssl_io_filter_register(p);
472
    ssl_reneg_filter_register(p);
472
473
473
    ap_hook_pre_connection(ssl_hook_pre_connection,NULL,NULL, APR_HOOK_MIDDLE);
474
    ap_hook_pre_connection(ssl_hook_pre_connection,NULL,NULL, APR_HOOK_MIDDLE);
474
    ap_hook_post_config   (ssl_init_Module,        NULL,NULL, APR_HOOK_MIDDLE);
475
    ap_hook_post_config   (ssl_init_Module,        NULL,NULL, APR_HOOK_MIDDLE);
(-)modules/ssl/ssl_engine_kernel.c (-97 / +155 lines)
Lines 29-34 Link Here
29
                                            -- Unknown                */
29
                                            -- Unknown                */
30
#include "ssl_private.h"
30
#include "ssl_private.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_ERR, rv, f->r,
215
                                  "could not send 403 after renegotiation"
216
                                  " failure");
217
                
218
                /* Don't give anything back to the caller, just return
219
                 * an error. */
220
                apr_brigade_cleanup(bb);
221
                return APR_EACCES;
222
            }
223
224
            /* ignore the rest of the brigade */
225
            break;
226
        }
227
228
        /* For any non-metadata buckets, read from the bucket to
229
         * ensure that it is morphed into a heap bucket if it's a
230
         * morphing bucket type. */
231
        if (!APR_BUCKET_IS_METADATA(bkt)) {
232
            const char *buf;
233
            apr_size_t len;
234
235
            rv = apr_bucket_read(bkt, &buf, &len, block);
236
            if (rv) {
237
                ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, f->r,
238
                              "bucket read failed");
239
                apr_brigade_cleanup(bb);
240
                return rv;
241
            }
242
        }
243
    }
244
245
    return APR_SUCCESS;
246
}
247
248
void ssl_reneg_filter_register(apr_pool_t *p)
249
{
250
    /* only requirement is that this input filter comes before the
251
     * ap_http_filter. */
252
    reneg_filter_rec =
253
        ap_register_input_filter("SSL_RENEG", reneg_in_filter, NULL,
254
                                 AP_FTYPE_PROTOCOL - 1);
255
}
256
162
/*
257
/*
163
 *  Access Handler
258
 *  Access Handler
164
 */
259
 */
Lines 169-186 Link Here
169
    SSLConnRec *sslconn = myConnConfig(r->connection);
264
    SSLConnRec *sslconn = myConnConfig(r->connection);
170
    SSL *ssl            = sslconn ? sslconn->ssl : NULL;
265
    SSL *ssl            = sslconn ? sslconn->ssl : NULL;
171
    SSL_CTX *ctx = NULL;
266
    SSL_CTX *ctx = NULL;
172
    apr_array_header_t *requires;
173
    ssl_require_t *ssl_requires;
174
    char *cp;
267
    char *cp;
175
    int ok, i;
176
    BOOL renegotiate = FALSE, renegotiate_quick = FALSE;
268
    BOOL renegotiate = FALSE, renegotiate_quick = FALSE;
177
    X509 *cert;
178
    X509 *peercert;
269
    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;
270
    STACK_OF(SSL_CIPHER) *cipher_list_old = NULL, *cipher_list = NULL;
182
    SSL_CIPHER *cipher = NULL;
271
    SSL_CIPHER *cipher = NULL;
183
    int depth, verify_old, verify, n;
272
    int verify_old, verify, n;
184
273
185
    if (ssl) {
274
    if (ssl) {
186
        ctx = SSL_get_SSL_CTX(ssl);
275
        ctx = SSL_get_SSL_CTX(ssl);
Lines 499-577 Link Here
499
    }
588
    }
500
#endif /* HAVE_SSL_SET_CERT_STORE */
589
#endif /* HAVE_SSL_SET_CERT_STORE */
501
590
502
    /* 
591
    if (!renegotiate) {
503
     * SSL renegotiations in conjunction with HTTP
592
        /* Nothing more to do here. */
504
     * requests using the POST method are not supported.
593
        return DECLINED;
505
     *
594
    }
506
     * Background:
507
     *
508
     * 1. When the client sends a HTTP/HTTPS request, Apache's core code
509
     * reads only the request line ("METHOD /path HTTP/x.y") and the
510
     * attached MIME headers ("Foo: bar") up to the terminating line ("CR
511
     * LF"). An attached request body (for instance the data of a POST
512
     * method) is _NOT_ read. Instead it is read by mod_cgi's content
513
     * handler and directly passed to the CGI script.
514
     *
515
     * 2. mod_ssl supports per-directory re-configuration of SSL parameters.
516
     * This is implemented by performing an SSL renegotiation of the
517
     * re-configured parameters after the request is read, but before the
518
     * response is sent. In more detail: the renegotiation happens after the
519
     * request line and MIME headers were read, but _before_ the attached
520
     * request body is read. The reason simply is that in the HTTP protocol
521
     * usually there is no acknowledgment step between the headers and the
522
     * body (there is the 100-continue feature and the chunking facility
523
     * only), so Apache has no API hook for this step.
524
     *
525
     * 3. the problem now occurs when the client sends a POST request for
526
     * URL /foo via HTTPS the server and the server has SSL parameters
527
     * re-configured on a per-URL basis for /foo. Then mod_ssl has to
528
     * perform an SSL renegotiation after the request was read and before
529
     * the response is sent. But the problem is the pending POST body data
530
     * in the receive buffer of SSL (which Apache still has not read - it's
531
     * pending until mod_cgi sucks it in). When mod_ssl now tries to perform
532
     * the renegotiation the pending data leads to an I/O error.
533
     *
534
     * Solution Idea:
535
     *
536
     * There are only two solutions: Either to simply state that POST
537
     * requests to URLs with SSL re-configurations are not allowed, or to
538
     * renegotiate really after the _complete_ request (i.e. including
539
     * the POST body) was read. Obviously the latter would be preferred,
540
     * but it cannot be done easily inside Apache, because as already
541
     * mentioned, there is no API step between the body reading and the body
542
     * processing. And even when we mod_ssl would hook directly into the
543
     * loop of mod_cgi, we wouldn't solve the problem for other handlers, of
544
     * course. So the only general solution is to suck in the pending data
545
     * of the request body from the OpenSSL BIO into the Apache BUFF. Then
546
     * the renegotiation can be done and after this step Apache can proceed
547
     * processing the request as before.
548
     *
549
     * Solution Implementation:
550
     *
551
     * We cannot simply suck in the data via an SSL_read-based loop because of
552
     * HTTP chunking. Instead we _have_ to use the Apache API for this step which
553
     * is aware of HTTP chunking. So the trick is to suck in the pending request
554
     * data via the Apache API (which uses Apache's BUFF code and in the
555
     * background mod_ssl's I/O glue code) and re-inject it later into the Apache
556
     * BUFF code again. This way the data flows twice through the Apache BUFF, of
557
     * course. But this way the solution doesn't depend on any Apache specifics
558
     * and is fully transparent to Apache modules.
559
     *
560
     * !! BUT ALL THIS IS STILL NOT RE-IMPLEMENTED FOR APACHE 2.0 !!
561
     */
562
    if (renegotiate && !renegotiate_quick && (r->method_number == M_POST)) {
563
        ap_log_error(APLOG_MARK, APLOG_ERR, 0, r->server,
564
                     "SSL Re-negotiation in conjunction "
565
                     "with POST method not supported!\n"
566
                     "hint: try SSLOptions +OptRenegotiate");
567
595
568
        return HTTP_METHOD_NOT_ALLOWED;
596
    /* This function is called after reading the request-header.  If
597
     * the HTTP request includes a message body, then the client may
598
     * already have sent all the SSL records containing that body.
599
     * It's not possible to do a renegotiation until all those SSL
600
     * records have been read and processed, so the renegotiation has
601
     * to be delayed until that point (when an EOS is returned by the
602
     * HTTP input filter). */
603
604
    if (!renegotiate_quick &&
605
        (apr_table_get(r->headers_in, "Transfer-Encoding") ||
606
         ((cp = (char *)apr_table_get(r->headers_in, "Content-Length")) != NULL
607
          && strcmp(cp, "0")))) {
608
        ap_log_error(APLOG_MARK, APLOG_INFO, 0, r->server,
609
                     "SSL re-negotiation needed for request with body: "
610
                     "delaying until after body has been read");
611
        ap_add_input_filter_handle(reneg_filter_rec, NULL, r, r->connection);
612
613
        return DECLINED;
569
    }
614
    }
570
615
571
    /*
616
    /* Now actually perform the SSL renegotiation; return DECLINED
572
     * now do the renegotiation if anything was actually reconfigured
617
     * here instead of OK, to allow mod_auth and other modules to deny
573
     */
618
     * access. */
574
    if (renegotiate) {
619
    return (reneg_and_check(r, renegotiate_quick) 
620
            ? HTTP_FORBIDDEN : DECLINED);
621
}
622
623
/* Do an SSL renegotiation and perform access control checks; do a
624
 * "quick" renegotation (which doesn't actually perform an SSL
625
 * handshake), if 'quick' is non-zero.  Returns non-zero if access
626
 * control checks failed. */
627
static int reneg_and_check(request_rec *r, int quick)
628
{
629
    SSLDirConfigRec *dc = myDirConfig(r);
630
    SSLConnRec *sslconn = myConnConfig(r->connection);
631
    SSL *ssl            = sslconn ? sslconn->ssl : NULL;
632
    apr_array_header_t *requires;
633
    ssl_require_t *ssl_requires;
634
    X509_STORE *cert_store = NULL;
635
    X509_STORE_CTX cert_store_ctx;
636
    X509 *cert;
637
    SSL_CTX *ctx = SSL_get_SSL_CTX(ssl);
638
    int depth, i, ok;
639
    char *cp;
640
575
        /*
641
        /*
576
         * Now we force the SSL renegotation by sending the Hello Request
642
         * Now we force the SSL renegotation by sending the Hello Request
577
         * message to the client. Here we have to do a workaround: Actually
643
         * message to the client. Here we have to do a workaround: Actually
Lines 586-592 Link Here
586
        ap_log_error(APLOG_MARK, APLOG_INFO, 0, r->server,
652
        ap_log_error(APLOG_MARK, APLOG_INFO, 0, r->server,
587
                     "Requesting connection re-negotiation");
653
                     "Requesting connection re-negotiation");
588
654
589
        if (renegotiate_quick) {
655
    if (quick) {
590
            STACK_OF(X509) *cert_stack;
656
            STACK_OF(X509) *cert_stack;
591
657
592
            /* perform just a manual re-verification of the peer */
658
            /* perform just a manual re-verification of the peer */
Lines 612-618 Link Here
612
                ap_log_error(APLOG_MARK, APLOG_ERR, 0, r->server,
678
                ap_log_error(APLOG_MARK, APLOG_ERR, 0, r->server,
613
                             "Cannot find peer certificate chain");
679
                             "Cannot find peer certificate chain");
614
680
615
                return HTTP_FORBIDDEN;
681
            return 1;
616
            }
682
            }
617
683
618
            if (!(cert_store ||
684
            if (!(cert_store ||
Lines 621-627 Link Here
621
                ap_log_error(APLOG_MARK, APLOG_ERR, 0, r->server,
687
                ap_log_error(APLOG_MARK, APLOG_ERR, 0, r->server,
622
                             "Cannot find certificate storage");
688
                             "Cannot find certificate storage");
623
689
624
                return HTTP_FORBIDDEN;
690
            return 1;
625
            }
691
            }
626
692
627
            if (!cert) {
693
            if (!cert) {
Lines 673-679 Link Here
673
                             "Re-negotiation request failed");
739
                             "Re-negotiation request failed");
674
740
675
                r->connection->aborted = 1;
741
                r->connection->aborted = 1;
676
                return HTTP_FORBIDDEN;
742
            return 1;
677
            }
743
            }
678
744
679
            ap_log_error(APLOG_MARK, APLOG_INFO, 0, r->server,
745
            ap_log_error(APLOG_MARK, APLOG_INFO, 0, r->server,
Lines 692-698 Link Here
692
                        "Not accepted by client!?");
758
                        "Not accepted by client!?");
693
759
694
                r->connection->aborted = 1;
760
                r->connection->aborted = 1;
695
                return HTTP_FORBIDDEN;
761
            return 1;
696
            }
762
            }
697
        }
763
        }
698
764
Lines 717-739 Link Here
717
                ap_log_error(APLOG_MARK, APLOG_ERR, 0, r->server,
783
                ap_log_error(APLOG_MARK, APLOG_ERR, 0, r->server,
718
                             "Re-negotiation handshake failed: "
784
                             "Re-negotiation handshake failed: "
719
                             "Client verification failed");
785
                             "Client verification failed");
720
786
            return 1;
721
                return HTTP_FORBIDDEN;
722
            }
787
            }
723
788
724
            if (do_verify) {
789
            if (do_verify) {
790
            X509 *peercert;
791
725
                if ((peercert = SSL_get_peer_certificate(ssl)) == NULL) {
792
                if ((peercert = SSL_get_peer_certificate(ssl)) == NULL) {
726
                    ap_log_error(APLOG_MARK, APLOG_ERR, 0, r->server,
793
                    ap_log_error(APLOG_MARK, APLOG_ERR, 0, r->server,
727
                                 "Re-negotiation handshake failed: "
794
                                 "Re-negotiation handshake failed: "
728
                                 "Client certificate missing");
795
                                 "Client certificate missing");
729
796
                return 1;
730
                    return HTTP_FORBIDDEN;
731
                }
797
                }
732
798
733
                X509_free(peercert);
799
                X509_free(peercert);
734
            }
800
            }
735
        }
801
        }
736
    }
737
802
738
    /*
803
    /*
739
     * Check SSLRequire boolean expressions
804
     * Check SSLRequire boolean expressions
Lines 758-764 Link Here
758
            /* remember forbidden access for strict require option */
823
            /* remember forbidden access for strict require option */
759
            apr_table_setn(r->notes, "ssl-access-forbidden", "1");
824
            apr_table_setn(r->notes, "ssl-access-forbidden", "1");
760
825
761
            return HTTP_FORBIDDEN;
826
            return 1;
762
        }
827
        }
763
828
764
        if (ok != 1) {
829
        if (ok != 1) {
Lines 779-796 Link Here
779
            /* remember forbidden access for strict require option */
844
            /* remember forbidden access for strict require option */
780
            apr_table_setn(r->notes, "ssl-access-forbidden", "1");
845
            apr_table_setn(r->notes, "ssl-access-forbidden", "1");
781
846
782
            return HTTP_FORBIDDEN;
847
            return 1;
783
        }
848
        }
784
    }
849
    }
785
850
786
    /*
851
    return 0;
787
     * Else access is granted from our point of view (except vendor
788
     * handlers override). But we have to return DECLINED here instead
789
     * of OK, because mod_auth and other modules still might want to
790
     * deny access.
791
     */
792
793
    return DECLINED;
794
}
852
}
795
853
796
/*
854
/*
(-)modules/ssl/ssl_private.h (+1 lines)
Lines 577-582 Link Here
577
void         ssl_io_filter_init(conn_rec *, SSL *);
577
void         ssl_io_filter_init(conn_rec *, SSL *);
578
void         ssl_io_filter_register(apr_pool_t *);
578
void         ssl_io_filter_register(apr_pool_t *);
579
long         ssl_io_data_cb(BIO *, int, MODSSL_BIO_CB_ARG_TYPE *, int, long, long);
579
long         ssl_io_data_cb(BIO *, int, MODSSL_BIO_CB_ARG_TYPE *, int, long, long);
580
void         ssl_reneg_filter_register(apr_pool_t *p);
580
581
581
/*  PRNG  */
582
/*  PRNG  */
582
int          ssl_rand_seed(server_rec *, apr_pool_t *, ssl_rsctx_t, char *);
583
int          ssl_rand_seed(server_rec *, apr_pool_t *, ssl_rsctx_t, char *);

Return to bug 12355