Changeset fcad37b in mod_gnutls for src/gnutls_io.c


Ignore:
Timestamp:
Jan 21, 2020, 3:41:33 PM (10 months ago)
Author:
Fiona Klute <fiona.klute@…>
Branches:
asyncio, master, proxy-ticket
Children:
f94938c
Parents:
9db4dcd
Message:

Retry gnutls_reauth() on transport interruptions

File:
1 edited

Legend:

Unmodified
Added
Removed
  • src/gnutls_io.c

    r9db4dcd rfcad37b  
    456456        return GNUTLS_E_INVALID_REQUEST;
    457457
    458     int rv = gnutls_reauth(ctxt->session, 0);
    459     // TODO: Handle remaining non-fatal errors: GNUTLS_E_INTERRUPTED,
    460     // GNUTLS_E_AGAIN
    461 
    462     /* GNUTLS_E_GOT_APPLICATION_DATA can (randomly, depending on
    463      * timing) happen with a request containing a body. According to
    464      * https://tools.ietf.org/html/rfc8446#appendix-E.1.2
    465      * post-handshake authentication proves that the authenticated
    466      * party is the one that did the handshake, so caching the data
    467      * is appropriate. */
    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)
     458    /* Initialize to error to avoid false-good return value. */
     459    int rv = GNUTLS_E_INTERNAL_ERROR;
     460    int tries = 0;
     461
     462    do
     463    {
     464        rv = gnutls_reauth(ctxt->session, 0);
     465        tries++;
     466
     467        /* GNUTLS_E_GOT_APPLICATION_DATA can (randomly, depending on
     468         * timing) happen with a request containing a body. According to
     469         * https://tools.ietf.org/html/rfc8446#appendix-E.1.2
     470         * post-handshake authentication proves that the authenticated
     471         * party is the one that did the handshake, so caching the data
     472         * is appropriate. */
     473        if (rv == GNUTLS_E_GOT_APPLICATION_DATA)
    476474        {
    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     }
     475            /* Fill connection input buffer using a speculative read. */
     476            apr_size_t len = sizeof(ctxt->input_buffer);
     477            ctxt->input_mode = AP_MODE_SPECULATIVE;
     478            apr_status_t status =
     479                gnutls_io_input_read(ctxt, ctxt->input_buffer, &len);
     480            if (status == APR_SUCCESS)
     481            {
     482                ap_log_rerror(APLOG_MARK, APLOG_DEBUG, status, r,
     483                              "%s: cached %" APR_SIZE_T_FMT " bytes.",
     484                              __func__, len);
     485                /* If the cache was too small to accept all pending data
     486                 * we'll get GNUTLS_E_GOT_APPLICATION_DATA again, and the
     487                 * authz hook will return HTTP_REQUEST_ENTITY_TOO_LARGE to
     488                 * the client. */
     489                rv = gnutls_reauth(ctxt->session, 0);
     490            }
     491            else
     492                ap_log_rerror(APLOG_MARK, APLOG_ERR, status, r,
     493                              "%s: buffering request data failed!",
     494                              __func__);
     495        }
     496        /* Retry on GNUTLS_E_INTERRUPTED or GNUTLS_E_AGAIN, whether
     497         * from initial gnutls_reauth() call or after buffering. */
     498    } while (tries < HANDSHAKE_MAX_TRIES
     499             && (rv == GNUTLS_E_INTERRUPTED || rv == GNUTLS_E_AGAIN));
    491500
    492501    if (rv != GNUTLS_E_SUCCESS)
Note: See TracChangeset for help on using the changeset viewer.