Changeset 9db4dcd in mod_gnutls


Ignore:
Timestamp:
Jan 21, 2020, 3:24:32 PM (10 months ago)
Author:
Fiona Klute <fiona.klute@…>
Branches:
asyncio, master, proxy-ticket
Children:
fcad37b
Parents:
4a22ee6
Message:

Handle GNUTLS_E_GOT_APPLICATION_DATA on gnutls_reauth()

Pending application data is cached in the connection input buffer, so
repeated attempts won't cause more memory allocations. If the buffer
is too small HTTP_REQUEST_ENTITY_TOO_LARGE is sent to the client.

The reauthentication test now contains a POST request so this code
path may (!) be taken during the test suite run.

Files:
1 added
5 edited

Legend:

Unmodified
Added
Removed
  • src/gnutls_hooks.c

    r4a22ee6 r9db4dcd  
    14911491        gnutls_certificate_server_set_request(ctxt->session,
    14921492                                              client_verify_mode);
    1493         if (mgs_reauth(ctxt) != GNUTLS_E_SUCCESS) {
    1494             return HTTP_FORBIDDEN;
    1495         }
    1496     }
    1497 
    1498     int rv = mgs_cert_verify(r, ctxt);
     1493        int rv = mgs_reauth(ctxt, r);
     1494        if (rv != GNUTLS_E_SUCCESS) {
     1495            if (rv == GNUTLS_E_GOT_APPLICATION_DATA)
     1496                return HTTP_REQUEST_ENTITY_TOO_LARGE;
     1497            else
     1498                return HTTP_FORBIDDEN;
     1499        }
     1500    }
     1501
     1502    int ret = mgs_cert_verify(r, ctxt);
    14991503    /* In "request" mode we always allow the request, otherwise the
    15001504     * verify result decides. */
    15011505    if (client_verify_mode == GNUTLS_CERT_REQUEST)
    15021506        return DECLINED;
    1503     return rv;
     1507    return ret;
    15041508}
    15051509
  • src/gnutls_io.c

    r4a22ee6 r9db4dcd  
    451451
    452452
    453 int mgs_reauth(mgs_handle_t * ctxt)
     453int mgs_reauth(mgs_handle_t *ctxt, request_rec *r)
    454454{
    455455    if (ctxt->session == NULL)
     
    457457
    458458    int rv = gnutls_reauth(ctxt->session, 0);
    459     // TODO: Handle non-fatal errors: GNUTLS_E_INTERRUPTED,
    460     // GNUTLS_E_AGAIN, GNUTLS_E_GOT_APPLICATION_DATA
     459    // TODO: Handle remaining non-fatal errors: GNUTLS_E_INTERRUPTED,
     460    // GNUTLS_E_AGAIN
    461461
    462462    /* GNUTLS_E_GOT_APPLICATION_DATA can (randomly, depending on
     
    466466     * party is the one that did the handshake, so caching the data
    467467     * is appropriate. */
    468     /* Allocate cache to content-length (if available), with an upper
    469      * limit to prevent resource exhaustion attacks. Do we have to
    470      * prevent creating multiple caches for one connection? */
    471     /* ap_log_rerror(APLOG_MARK, APLOG_INFO, 0, r, */
    472     /*               "Request content: %s bytes", */
    473     /*               apr_table_get(r->headers_in, "Content-Length")); */
    474     /* If the cache is too small,
    475      * a) return HTTP_REQUEST_ENTITY_TOO_LARGE to the client
    476      * b) IF reauth was successful set Retry-After to immediately: */
    477     /* apr_table_setn(r->err_headers_out, "Retry-After", "0"); */
     468    if (rv == GNUTLS_E_GOT_APPLICATION_DATA)
     469    {
     470        /* Fill connection input buffer using a speculative read. */
     471        apr_size_t len = sizeof(ctxt->input_buffer);
     472        ctxt->input_mode = AP_MODE_SPECULATIVE;
     473        apr_status_t status =
     474            gnutls_io_input_read(ctxt, ctxt->input_buffer, &len);
     475        if (status == APR_SUCCESS)
     476        {
     477            ap_log_rerror(APLOG_MARK, APLOG_DEBUG, status, r,
     478                          "%s: cached %" APR_SIZE_T_FMT " bytes.",
     479                          __func__, len);
     480            /* If the cache was too small to accept all pending data
     481             * we'll get GNUTLS_E_GOT_APPLICATION_DATA again, and the
     482             * authz hook will return HTTP_REQUEST_ENTITY_TOO_LARGE to
     483             * the client. */
     484            rv = gnutls_reauth(ctxt->session, 0);
     485        }
     486        else
     487            ap_log_rerror(APLOG_MARK, APLOG_ERR, status, r,
     488                          "%s: buffering request data failed!",
     489                          __func__);
     490    }
    478491
    479492    if (rv != GNUTLS_E_SUCCESS)
    480493    {
    481         ap_log_cerror(APLOG_MARK, APLOG_WARNING, 0, ctxt->c,
    482                       "Reauthentication failed: %s (%d)",
    483                       gnutls_strerror(rv), rv);
     494        ap_log_rerror(APLOG_MARK, APLOG_WARNING, 0, r,
     495                      "%s: Reauthentication failed: %s (%d)",
     496                      __func__, gnutls_strerror(rv), rv);
    484497        return rv;
    485498    }
  • src/gnutls_io.h

    r4a22ee6 r9db4dcd  
    8484                            const void *buffer, size_t len);
    8585
    86 int mgs_reauth(mgs_handle_t * ctxt);
     86int mgs_reauth(mgs_handle_t * ctxt, request_rec *r);
    8787
    8888#endif /* __MOD_GNUTLS_IO_H__ */
  • test/Makefile.am

    r4a22ee6 r9db4dcd  
    249249# Apache configuration and data files
    250250apache_data = base_apache.conf cgi_module.conf data/dump.cgi data/ocsp.cgi \
    251         data/test.txt mime.types proxy_mods.conf
     251        data/test.txt data/secret/mirror.cgi data/secret/test.txt \
     252        mime.types proxy_mods.conf
    252253
    253254# Documentation for the test system
  • test/tests/35_client_reauth/test.yml

    r4a22ee6 r9db4dcd  
    1717          test
    1818  - !request
    19     method: GET
    20     path: /secret/test.txt
     19    method: POST
     20    path: /secret/mirror.cgi
     21    body: |
     22      GNUTLS_E_GOT_APPLICATION_DATA can (randomly, depending on
     23      timing) happen with a request containing a body. According to
     24      https://tools.ietf.org/html/rfc8446#appendix-E.1.2
     25      post-handshake authentication proves that the authenticated
     26      party is the one that did the handshake, so caching the data
     27      is appropriate.
    2128    expect:
    2229      status: 200
    2330      body:
    2431        exactly: |
    25           top secret
     32          GNUTLS_E_GOT_APPLICATION_DATA can (randomly, depending on
     33          timing) happen with a request containing a body. According to
     34          https://tools.ietf.org/html/rfc8446#appendix-E.1.2
     35          post-handshake authentication proves that the authenticated
     36          party is the one that did the handshake, so caching the data
     37          is appropriate.
    2638  - !request
    2739    method: GET
Note: See TracChangeset for help on using the changeset viewer.