Changeset 132eadc in mod_gnutls


Ignore:
Timestamp:
May 25, 2020, 1:48:25 PM (6 weeks ago)
Author:
Fiona Klute <fiona.klute@…>
Branches:
master, proxy-ticket
Children:
15ce4db
Parents:
72b0853
Message:

Implement gnutls_pull_timeout_func

According to GnuTLS documentation it's required when using a custom
pull function. It's not called by the current mod_gnutls use of
GnuTLS, but the documentation on client-side resumption explicitly
mentions it as a requirement.

Location:
src
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • src/gnutls_hooks.c

    r72b0853 r132eadc  
    12181218    /* Set pull, push & ptr functions */
    12191219    gnutls_transport_set_pull_function(ctxt->session,
    1220             mgs_transport_read);
     1220                                       mgs_transport_read);
     1221    gnutls_transport_set_pull_timeout_function(ctxt->session,
     1222                                               mgs_transport_read_ready);
    12211223    gnutls_transport_set_push_function(ctxt->session,
    1222             mgs_transport_write);
     1224                                       mgs_transport_write);
    12231225    gnutls_transport_set_ptr(ctxt->session, ctxt);
    12241226    /* Add IO filters */
  • src/gnutls_io.c

    r72b0853 r132eadc  
    830830}
    831831
     832int mgs_transport_read_ready(gnutls_transport_ptr_t ptr,
     833                             unsigned int ms)
     834{
     835    mgs_handle_t *ctxt = ptr;
     836    ap_log_cerror(APLOG_MARK, APLOG_TRACE1, APR_SUCCESS, ctxt->c,
     837                  "%s: called with %u ms wait", __func__, ms);
     838
     839    apr_pool_t *tmp = NULL;
     840    apr_status_t rv = apr_pool_create(&tmp, ctxt->c->pool);
     841    if (rv != APR_SUCCESS)
     842    {
     843        ap_log_cerror(APLOG_MARK, APLOG_ERR, APR_ENOMEM, ctxt->c,
     844                      "could not create temporary pool for %s",
     845                     __func__);
     846        return -1;
     847    }
     848
     849    apr_bucket_brigade *bb = apr_brigade_create(tmp, ctxt->c->bucket_alloc);
     850
     851    /* one byte non-blocking speculative read to see if there's data
     852     * in the filter chain */
     853    rv = ap_get_brigade(ctxt->input_filter->next, bb, AP_MODE_SPECULATIVE,
     854                        APR_NONBLOCK_READ, 1);
     855
     856    int result;
     857    if (rv == APR_SUCCESS && !APR_BRIGADE_EMPTY(bb))
     858        result = 1;
     859    else
     860        result = 0;
     861
     862    apr_brigade_destroy(bb);
     863
     864    /* If GnuTLS doesn't want to wait or we already have data,
     865     * return. */
     866    if (ms == 0 || result == 1)
     867    {
     868        apr_pool_destroy(tmp);
     869        return result;
     870    }
     871
     872    ap_log_cerror(APLOG_MARK, APLOG_TRACE1, APR_SUCCESS, ctxt->c,
     873                  "%s: waiting for data", __func__);
     874
     875    /* No data yet, and we're supposed to wait, so wait for data on
     876     * the socket. */
     877    apr_socket_t *sock = ap_get_conn_socket(ctxt->c);
     878    apr_interval_time_t timeout = -1;
     879    apr_interval_time_t original_timeout;
     880    rv = apr_socket_timeout_get(sock, &original_timeout);
     881    if (rv != APR_SUCCESS)
     882    {
     883        ap_log_cerror(APLOG_MARK, APLOG_ERR, rv, ctxt->c,
     884                      "%s: could not get socket timeout",
     885                      __func__);
     886        apr_pool_destroy(tmp);
     887        return -1;
     888    }
     889
     890    /* If GnuTLS requests an "indefinite" wait we do not want to mess
     891     * with whatever Apache does by default. Otherwise temporarily
     892     * adjust the socket timeout. */
     893    if (ms != GNUTLS_INDEFINITE_TIMEOUT)
     894    {
     895        /* apr_interval_time_t is in microseconds */
     896        if (__builtin_mul_overflow(ms, 1000, &timeout))
     897        {
     898            ap_log_cerror(APLOG_MARK, APLOG_ERR, APR_ENOMEM, ctxt->c,
     899                          "%s: overflow while calculating timeout!",
     900                          __func__);
     901            apr_pool_destroy(tmp);
     902            return -1;
     903        }
     904        rv = apr_socket_timeout_set(sock, timeout);
     905        if (rv != APR_SUCCESS)
     906        {
     907            ap_log_cerror(APLOG_MARK, APLOG_ERR, rv, ctxt->c,
     908                          "%s: could not set socket timeout",
     909                          __func__);
     910            apr_pool_destroy(tmp);
     911            return -1;
     912        }
     913    }
     914
     915#if APR_MAJOR_VERSION < 2
     916    apr_pollfd_t pollset;
     917    apr_int32_t nsds;
     918    pollset.p = tmp;
     919    pollset.desc_type = APR_POLL_SOCKET;
     920    pollset.reqevents = APR_POLLIN | APR_POLLHUP;
     921    pollset.desc.s = sock;
     922    rv = apr_poll(&pollset, 1, &nsds, timeout);
     923#else
     924    rv = apr_socket_wait(sock, APR_WAIT_READ);
     925#endif
     926    apr_pool_destroy(tmp);
     927
     928    if (ms != GNUTLS_INDEFINITE_TIMEOUT)
     929    {
     930        /* We still need "rv" below, so new variable. */
     931        apr_status_t rc = apr_socket_timeout_set(sock, original_timeout);
     932        if (rc != APR_SUCCESS)
     933        {
     934            ap_log_cerror(APLOG_MARK, APLOG_CRIT, rc, ctxt->c,
     935                          "%s: could not restore socket timeout",
     936                          __func__);
     937            return -1;
     938        }
     939    }
     940
     941    if (rv == APR_SUCCESS)
     942        return 1;
     943    else if (APR_STATUS_IS_TIMEUP(rv))
     944        return 0;
     945    else
     946    {
     947        ap_log_cerror(APLOG_MARK, APLOG_ERR, rv, ctxt->c,
     948                      "%s: waiting for data on connection socket failed",
     949                      __func__);
     950        return -1;
     951    }
     952}
     953
    832954/**
    833955 * Pull function for GnuTLS
  • src/gnutls_io.h

    r72b0853 r132eadc  
    8484                            const void *buffer, size_t len);
    8585
     86/**
     87 * mgs_transport_read is called from GnuTLS check if data is available
     88 * on the underlying transport.
     89 *
     90 * @param ptr     transport pointer, the mod_gnutls connection context
     91 * @param ms      maximum time to wait in milliseconds
     92 * @return GnuTLS requirement: "The callback should return 0 on
     93 *      timeout, a positive number if data can be received, and -1 on
     94 *      error."
     95 */
     96int mgs_transport_read_ready(gnutls_transport_ptr_t ptr,
     97                             unsigned int ms);
     98
    8699int mgs_reauth(mgs_handle_t * ctxt, request_rec *r);
    87100
Note: See TracChangeset for help on using the changeset viewer.