Changeset 7e2b223 in mod_gnutls for src


Ignore:
Timestamp:
Sep 27, 2004, 3:46:17 PM (15 years ago)
Author:
Paul Querna <chip@…>
Branches:
debian/master, debian/stretch-backports, jessie-backports, master, msva, upstream
Children:
2e12226
Parents:
aa99b13
Message:

break up the IO functions into their own file

Location:
src
Files:
1 added
2 edited

Legend:

Unmodified
Added
Removed
  • src/Makefile.am

    raa99b13 r7e2b223  
    11CLEANFILES = .libs/libmod_gnutls *~
    22
    3 libmod_gnutls_la_SOURCES = mod_gnutls.c
     3libmod_gnutls_la_SOURCES = mod_gnutls.c gnutls_io.c
    44libmod_gnutls_la_CFLAGS = -Wall ${MODULE_CFLAGS}
    55libmod_gnutls_la_LDFLAGS = ${MODULE_LIBS}
  • src/mod_gnutls.c

    raa99b13 r7e2b223  
    1616 */
    1717
    18 #include "httpd.h"
    19 #include "http_config.h"
    20 #include "http_protocol.h"
    21 #include "http_connection.h"
    22 #include "http_core.h"
    23 #include "http_log.h"
    24 #include "apr_buckets.h"
    25 #include "apr_strings.h"
    26 #include "apr_tables.h"
    27 
    28 #include <gcrypt.h>
    29 #include <gnutls/gnutls.h>
     18#include "mod_gnutls.h"
    3019
    3120#if APR_HAS_THREADS
    3221GCRY_THREAD_OPTION_PTHREAD_IMPL;
    3322#endif
    34 
    35 module AP_MODULE_DECLARE_DATA gnutls_module;
    36 
    37 #ifdef GNUTLS_AS_FILTER
    38 #define GNUTLS_OUTPUT_FILTER_NAME "GnuTLS Output Filter"
    39 #define GNUTLS_INPUT_FILTER_NAME "GnuTLS Input Filter"
    40 #endif
    41 
    42 #define GNUTLS_ENABLED_FALSE 0
    43 #define GNUTLS_ENABLED_TRUE  1
    44 
    45 
    46 typedef struct {
    47     gnutls_certificate_credentials_t certs;
    48     gnutls_anon_server_credentials_t anoncred;
    49     char *key_file;
    50     char *cert_file;
    51     int enabled;
    52     int ciphers[16];
    53     int key_exchange[16];
    54     int macs[16];
    55     int protocol[16];
    56     int compression[16];
    57 } gnutls_srvconf_rec;
    58 
    59 typedef struct gnutls_handle_t gnutls_handle_t;
    60 struct gnutls_handle_t
    61 {
    62     gnutls_srvconf_rec *sc;
    63     gnutls_session_t session;
    64     ap_filter_t *input_filter;
    65     apr_bucket_brigade *input_bb;
    66     apr_read_type_e input_block;
    67     int status;
    68     int non_https;
    69 };
    70 
    71 static apr_status_t gnutls_filter_input(ap_filter_t * f,
    72                                         apr_bucket_brigade * bb,
    73                                         ap_input_mode_t mode,
    74                                         apr_read_type_e block,
    75                                         apr_off_t readbytes)
    76 {
    77     apr_status_t status = APR_SUCCESS;
    78     gnutls_handle_t *ctxt = (gnutls_handle_t *) f->ctx;
    79 
    80     if (f->c->aborted) {
    81         apr_bucket *bucket = apr_bucket_eos_create(f->c->bucket_alloc);
    82         APR_BRIGADE_INSERT_TAIL(bb, bucket);
    83         return APR_ECONNABORTED;
    84     }
    85 
    86 
    87     for (b = APR_BRIGADE_FIRST(bb);
    88          b != APR_BRIGADE_SENTINEL(bb); b = APR_BUCKET_NEXT(b)) {
    89         if (APR_BUCKET_IS_EOS(b)) {
    90             /* end of connection */
    91         }
    92         else if (apr_bucket_read(b, &buf, &bytes, APR_BLOCK_READ)
    93                  == APR_SUCCESS) {
    94             /* more data */
    95         }
    96     }
    97 
    98     return status;
    99 }
    100 
    101 #define HANDSHAKE_ATTEMPTS 10
    102 
    103 static apr_status_t gnutls_filter_output(ap_filter_t * f,
    104                                          apr_bucket_brigade * bb)
    105 {
    106     int ret, i;
    107     const char *buf = 0;
    108     apr_size_t bytes = 0;
    109     gnutls_handle_t *ctxt = (gnutls_handle_t *) f->ctx;
    110     apr_status_t status = APR_SUCCESS;
    111     apr_read_type_e rblock = APR_NONBLOCK_READ;
    112 
    113     if (f->c->aborted) {
    114         apr_brigade_cleanup(bb);
    115         return APR_ECONNABORTED;
    116     }
    117 
    118     if(ctxt->status == 0) {
    119         for (i=HANDSHAKE_ATTEMPTS; i>0; i--){
    120             ret = gnutls_handshake(ctxt->session);
    121 
    122             if(ret == GNUTLS_E_INTERRUPTED || ret == GNUTLS_E_AGAIN){
    123                 continue;
    124             }
    125 
    126             if (ret < 0) {
    127                 if (ret == GNUTLS_E_WARNING_ALERT_RECEIVED || ret == GNUTLS_E_FATAL_ALERT_RECEIVED) {
    128                     ret = gnutls_alert_get(ctxt->session);
    129                     ap_log_error(APLOG_MARK, APLOG_ERR, 0, f->c->base_server,
    130                         "GnuTLS: Hanshake Alert (%d) '%s'.\n", ret, gnutls_alert_get_name(ret));
    131                 }
    132 
    133                 if (gnutls_error_is_fatal(ret) != 0) {
    134                     gnutls_deinit(ctxt->session);
    135                     ap_log_error(APLOG_MARK, APLOG_ERR, 0, f->c->base_server,
    136                          "GnuTLS: Handshake Failed (%d) '%s'",ret, gnutls_strerror(ret));
    137                     ctxt->status = -1;
    138                     break;
    139                 }
    140             }
    141             else {
    142                 ctxt->status = 1;
    143                 break; /* all done with the handshake */
    144             }
    145         }
    146     }
    147 
    148     if (ctxt->status < 0) {
    149         return ap_pass_brigade(f->next, bb);
    150     }
    151 
    152     while (!APR_BRIGADE_EMPTY(bb)) {
    153         apr_bucket *bucket = APR_BRIGADE_FIRST(bb);
    154         if (APR_BUCKET_IS_EOS(bucket) || APR_BUCKET_IS_FLUSH(bucket)) {
    155             /** TODO: GnuTLS doesn't have a special flush method? **/
    156             if ((status = ap_pass_brigade(f->next, bb)) != APR_SUCCESS) {
    157                 return status;
    158             }
    159             break;
    160         }
    161         else if(AP_BUCKET_IS_EOC(bucket)) {
    162             gnutls_bye(ctxt->session, GNUTLS_SHUT_WR);
    163 
    164             if ((status = ap_pass_brigade(f->next, bb)) != APR_SUCCESS) {
    165                 return status;
    166             }
    167             break;
    168         }
    169         else {
    170             /* filter output */
    171             const char *data;
    172             apr_size_t len;
    173 
    174             status = apr_bucket_read(bucket, &data, &len, rblock);
    175 
    176             if (APR_STATUS_IS_EAGAIN(status)) {
    177                  rblock = APR_BLOCK_READ;
    178                  continue; /* and try again with a blocking read. */
    179             }
    180 
    181             rblock = APR_NONBLOCK_READ;
    182 
    183             if (!APR_STATUS_IS_EOF(status) && (status != APR_SUCCESS)) {
    184                 break;
    185             }
    186 
    187             ret = gnutls_record_send(ctxt->session, data, len);
    188             status = ssl_filter_write(f, data, len);
    189             if(ret < 0) {
    190                 /* error sending output */
    191             }
    192             else if ((apr_size_t)res != len) {
    193                 /* not all of the data was sent. */
    194                 /* mod_ssl basicly errors out here.. this doesn't seem right? */
    195             }
    196             else {
    197                 /* send complete */
    198                
    199             }
    200 
    201             apr_bucket_delete(bucket);
    202 
    203             if (status != APR_SUCCESS) {
    204                 break;
    205             }
    206 
    207         }
    208     }
    209 
    210     return status;
    211 }
    21223
    21324static apr_status_t gnutls_cleanup_pre_config(void *data)
     
    25465    for (s = base_server; s; s = s->next) {
    25566        sc = (gnutls_srvconf_rec *) ap_get_module_config(s->module_config,
    256                                                        &gnutls_module);
     67                                                         &gnutls_module);
    25768        if (sc->cert_file != NULL && sc->key_file != NULL) {
    25869            gnutls_certificate_set_x509_key_file(sc->certs, sc->cert_file,
     
    26273//          gnutls_certificate_set_dh_params(sc->certs, dh_params);
    26374        }
    264         else if(sc->enabled == GNUTLS_ENABLED_TRUE ){
     75        else if (sc->enabled == GNUTLS_ENABLED_TRUE) {
    26576            ap_log_error(APLOG_MARK, APLOG_EMERG, 0, s,
    26677                         "[GnuTLS] - Host '%s:%d' is missing a Cert and Key File!",
     
    27889    gnutls_srvconf_rec *sc =
    27990        (gnutls_srvconf_rec *) ap_get_module_config(r->server->module_config,
    280                                                   &gnutls_module);
     91                                                    &gnutls_module);
    28192
    28293    if (sc->enabled == GNUTLS_ENABLED_FALSE) {
     
    291102    gnutls_srvconf_rec *sc =
    292103        (gnutls_srvconf_rec *) ap_get_module_config(r->server->module_config,
    293                                                   &gnutls_module);
     104                                                    &gnutls_module);
    294105
    295106    if (sc->enabled == GNUTLS_ENABLED_FALSE) {
     
    300111}
    301112
    302 /**
    303  * From mod_ssl / ssl_engine_io.c
    304  * This function will read from a brigade and discard the read buckets as it
    305  * proceeds.  It will read at most *len bytes.
    306  */
    307 static apr_status_t brigade_consume(apr_bucket_brigade * bb,
    308                                     apr_read_type_e block,
    309                                     char *c, apr_size_t * len)
    310 {
    311     apr_size_t actual = 0;
    312     apr_status_t status = APR_SUCCESS;
    313 
    314     while (!APR_BRIGADE_EMPTY(bb)) {
    315         apr_bucket *b = APR_BRIGADE_FIRST(bb);
    316         const char *str;
    317         apr_size_t str_len;
    318         apr_size_t consume;
    319 
    320         /* Justin points out this is an http-ism that might
    321          * not fit if brigade_consume is added to APR.  Perhaps
    322          * apr_bucket_read(eos_bucket) should return APR_EOF?
    323          * Then this becomes mainline instead of a one-off.
    324          */
    325         if (APR_BUCKET_IS_EOS(b)) {
    326             status = APR_EOF;
    327             break;
    328         }
    329 
    330         /* The reason I'm not offering brigade_consume yet
    331          * across to apr-util is that the following call
    332          * illustrates how borked that API really is.  For
    333          * this sort of case (caller provided buffer) it
    334          * would be much more trivial for apr_bucket_consume
    335          * to do all the work that follows, based on the
    336          * particular characteristics of the bucket we are
    337          * consuming here.
    338          */
    339         status = apr_bucket_read(b, &str, &str_len, block);
    340 
    341         if (status != APR_SUCCESS) {
    342             if (APR_STATUS_IS_EOF(status)) {
    343                 /* This stream bucket was consumed */
    344                 apr_bucket_delete(b);
    345                 continue;
    346             }
    347             break;
    348         }
    349 
    350         if (str_len > 0) {
    351             /* Do not block once some data has been consumed */
    352             block = APR_NONBLOCK_READ;
    353 
    354             /* Assure we don't overflow. */
    355             consume = (str_len + actual > *len) ? *len - actual : str_len;
    356 
    357             memcpy(c, str, consume);
    358 
    359             c += consume;
    360             actual += consume;
    361 
    362             if (consume >= b->length) {
    363                 /* This physical bucket was consumed */
    364                 apr_bucket_delete(b);
    365             }
    366             else {
    367                 /* Only part of this physical bucket was consumed */
    368                 b->start += consume;
    369                 b->length -= consume;
    370             }
    371         }
    372         else if (b->length == 0) {
    373             apr_bucket_delete(b);
    374         }
    375 
    376         /* This could probably be actual == *len, but be safe from stray
    377          * photons. */
    378         if (actual >= *len) {
    379             break;
    380         }
    381     }
    382 
    383     *len = actual;
    384     return status;
    385 }
    386 
    387 
    388 static ssize_t gnutls_transport_read(gnutls_transport_ptr_t ptr,
    389                                      void *buffer, size_t len)
    390 {
    391     gnutls_handle_t *ctxt = ptr;
    392     apr_status_t rc;
    393     apr_size_t in = len;
    394     /* If Len = 0, we don't do anything. */
    395     if (!len)
    396         return 0;
    397 
    398     if (APR_BRIGADE_EMPTY(ctxt->input_bb)) {
    399 
    400         rc = ap_get_brigade(ctxt->input_filter->next, ctxt->input_bb,
    401                             AP_MODE_READBYTES, ctxt->input_block, in);
    402 
    403         /* Not a problem, there was simply no data ready yet.
    404          */
    405         if (APR_STATUS_IS_EAGAIN(rc) || APR_STATUS_IS_EINTR(rc)
    406             || (rc == APR_SUCCESS && APR_BRIGADE_EMPTY(ctxt->input_bb))) {
    407             return 0;
    408         }
    409 
    410         if (rc != APR_SUCCESS) {
    411             /* Unexpected errors discard the brigade */
    412             apr_brigade_cleanup(ctxt->input_bb);
    413             ctxt->input_bb = NULL;
    414             return -1;
    415         }
    416     }
    417 
    418 //    brigade_consume(ctxt->input_bb, ctxt->input_block, buffer, &len);
    419 
    420 
    421     ap_get_brigade(ctxt->input_filter->next, ctxt->input_bb,
    422                    AP_MODE_READBYTES, ctxt->input_block, len);
    423 
    424     return len;
    425 }
    426 
    427 static ssize_t gnutls_transport_write(gnutls_transport_ptr_t ptr,
    428                                       const void *buffer, size_t len)
    429 {
    430     gnutls_handle_t *ctxt = ptr;
    431 
    432 //    apr_bucket *bucket = apr_bucket_transient_create(in, inl,
    433 //                                                     outctx->bb->
    434 //                                                     bucket_alloc);
    435 
    436     //  outctx->length += inl;
    437     //APR_BRIGADE_INSERT_TAIL(outctx->bb, bucket);
    438     return 0;
    439 }
    440 
    441113static int gnutls_hook_pre_connection(conn_rec * c, void *csd)
    442114{
     
    444116    gnutls_srvconf_rec *sc =
    445117        (gnutls_srvconf_rec *) ap_get_module_config(c->base_server->
    446                                                   module_config,
    447                                                   &gnutls_module);
     118                                                    module_config,
     119                                                    &gnutls_module);
    448120
    449121    if (!(sc && (sc->enabled == GNUTLS_ENABLED_TRUE))) {
     
    471143
    472144//    gnutls_dh_set_prime_bits(ctxt->session, DH_BITS);
    473  
     145
    474146
    475147    ap_set_module_config(c->conn_config, &gnutls_module, ctxt);
    476148
    477     gnutls_transport_set_pull_function(ctxt->session, gnutls_transport_read);
    478     gnutls_transport_set_push_function(ctxt->session, gnutls_transport_write);
     149    gnutls_transport_set_pull_function(ctxt->session,
     150                                       mod_gnutls_transport_read);
     151    gnutls_transport_set_push_function(ctxt->session,
     152                                       mod_gnutls_transport_write);
    479153    gnutls_transport_set_ptr(ctxt->session, ctxt);
    480154    ap_add_input_filter(GNUTLS_INPUT_FILTER_NAME, ctxt, NULL, c);
     
    485159
    486160static const char *gnutls_set_cert_file(cmd_parms * parms, void *dummy,
    487                                       const char *arg)
     161                                        const char *arg)
    488162{
    489163    gnutls_srvconf_rec *sc =
    490164        (gnutls_srvconf_rec *) ap_get_module_config(parms->server->
    491                                                   module_config,
    492                                                   &gnutls_module);
     165                                                    module_config,
     166                                                    &gnutls_module);
    493167    sc->cert_file = apr_pstrdup(parms->pool, arg);
    494168    return NULL;
     
    496170
    497171static const char *gnutls_set_key_file(cmd_parms * parms, void *dummy,
    498                                       const char *arg)
     172                                       const char *arg)
    499173{
    500174    gnutls_srvconf_rec *sc =
    501175        (gnutls_srvconf_rec *) ap_get_module_config(parms->server->
    502                                                   module_config,
    503                                                   &gnutls_module);
    504     sc->key_file =  apr_pstrdup(parms->pool, arg);
     176                                                    module_config,
     177                                                    &gnutls_module);
     178    sc->key_file = apr_pstrdup(parms->pool, arg);
    505179    return NULL;
    506180}
     
    511185    gnutls_srvconf_rec *sc =
    512186        (gnutls_srvconf_rec *) ap_get_module_config(parms->server->
    513                                                   module_config,
    514                                                   &gnutls_module);
     187                                                    module_config,
     188                                                    &gnutls_module);
    515189    if (!strcasecmp(arg, "On")) {
    516190        sc->enabled = GNUTLS_ENABLED_TRUE;
     
    536210                  "SSL Server Certificate file"),
    537211    AP_INIT_TAKE1("GnuTLSEnable", gnutls_set_enabled,
    538                  NULL, RSRC_CONF,
    539                  "Whether this server has GnuTLS Enabled. Default: Off"),
     212                  NULL, RSRC_CONF,
     213                  "Whether this server has GnuTLS Enabled. Default: Off"),
    540214
    541215    {NULL}
     
    563237     *          ssl_io_filter_Upgrade, NULL, AP_FTYPE_PROTOCOL + 5);
    564238     */
    565     ap_register_input_filter(GNUTLS_INPUT_FILTER_NAME, gnutls_filter_input,
    566                              NULL, AP_FTYPE_CONNECTION + 5);
    567     ap_register_output_filter(GNUTLS_OUTPUT_FILTER_NAME, gnutls_filter_output,
    568                               NULL, AP_FTYPE_CONNECTION + 5);
     239    ap_register_input_filter(GNUTLS_INPUT_FILTER_NAME,
     240                             mod_gnutls_filter_input, NULL,
     241                             AP_FTYPE_CONNECTION + 5);
     242    ap_register_output_filter(GNUTLS_OUTPUT_FILTER_NAME,
     243                              mod_gnutls_filter_output, NULL,
     244                              AP_FTYPE_CONNECTION + 5);
    569245}
    570246
     
    575251
    576252    sc->enabled = GNUTLS_ENABLED_FALSE;
    577     sc->non_https = 0;
    578253
    579254    gnutls_certificate_allocate_credentials(&sc->certs);
     
    587262    sc->ciphers[i++] = GNUTLS_CIPHER_3DES_CBC;
    588263    sc->ciphers[i++] = GNUTLS_CIPHER_ARCFOUR_40;
    589     sc->ciphers[i]   = 0;
     264    sc->ciphers[i] = 0;
    590265
    591266    i = 0;
Note: See TracChangeset for help on using the changeset viewer.