Changeset 19e80a5 in mod_gnutls for src/gnutls_io.c


Ignore:
Timestamp:
Jan 28, 2019, 2:50:38 PM (13 months ago)
Author:
Fiona Klute <fiona.klute@…>
Branches:
debian/master
Children:
102aa67
Parents:
0931b35 (diff), ea9c699 (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the (diff) links above to see all the changes relative to each parent.
Message:

Update upstream source from tag 'upstream/0.9.0'

Update to upstream version '0.9.0'
with Debian dir 619b546038886b240d2c8e61ee1a1b13ce0867d7

File:
1 edited

Legend:

Unmodified
Added
Removed
  • src/gnutls_io.c

    r0931b35 r19e80a5  
    33 *  Copyright 2008 Nikos Mavrogiannopoulos
    44 *  Copyright 2011 Dash Shendy
    5  *  Copyright 2015-2017 Fiona Klute
     5 *  Copyright 2015-2019 Fiona Klute
    66 *
    77 *  Licensed under the Apache License, Version 2.0 (the "License");
     
    1919
    2020#include "mod_gnutls.h"
     21#include "gnutls_proxy.h"
    2122
    2223#ifdef APLOG_USE_MODULE
     
    6667                      "GnuTLS handshake failed: HTTP spoken on HTTPS port; "
    6768                      "trying to send HTML error page");
    68         mgs_srvconf_rec *sc = (mgs_srvconf_rec *)
    69             ap_get_module_config(f->c->base_server->module_config,
    70                                  &gnutls_module);
    7169        ctxt->status = -1;
    72         sc->non_ssl_request = 1;
    7370
    7471        /* fake the request line */
     
    246243    while (1)
    247244    {
     245        /* Note: The pull function sets ctxt->input_rc */
    248246        rc = gnutls_record_recv(ctxt->session, buf + bytes, wanted - bytes);
    249 
    250         if (rc == GNUTLS_E_INTERRUPTED)
    251             ctxt->input_rc = APR_EINTR;
    252         else if (rc == GNUTLS_E_AGAIN)
    253             ctxt->input_rc = APR_EAGAIN;
    254247
    255248        if (rc > 0) {
     
    262255            return ctxt->input_rc;
    263256        } else if (rc == 0) {
    264             /* If EAGAIN, we will loop given a blocking read,
    265              * otherwise consider ourselves at EOF.
    266              */
    267             if (APR_STATUS_IS_EAGAIN(ctxt->input_rc)
    268                     || APR_STATUS_IS_EINTR(ctxt->input_rc)) {
    269                 /* Already read something, return APR_SUCCESS instead.
    270                  * On win32 in particular, but perhaps on other kernels,
    271                  * a blocking call isn't 'always' blocking.
    272                  */
    273                 if (*len > 0) {
    274                     ctxt->input_rc = APR_SUCCESS;
    275                     break;
    276                 }
    277                 if (ctxt->input_block == APR_NONBLOCK_READ) {
    278                     break;
    279                 }
     257            /* EOF, return code depends on whether we still have data
     258             * to return. */
     259            if (*len > 0) {
     260                ctxt->input_rc = APR_SUCCESS;
    280261            } else {
    281                 if (*len > 0) {
    282                     ctxt->input_rc = APR_SUCCESS;
    283                 } else {
    284                     ctxt->input_rc = APR_EOF;
    285                 }
    286                 break;
    287             }
     262                ctxt->input_rc = APR_EOF;
     263            }
     264            break;
    288265        } else { /* (rc < 0) */
    289266
    290             if (rc == GNUTLS_E_REHANDSHAKE) {
     267            if (rc == GNUTLS_E_INTERRUPTED || rc == GNUTLS_E_AGAIN)
     268            {
     269                ap_log_cerror(APLOG_MARK, APLOG_TRACE2, ctxt->input_rc, ctxt->c,
     270                              "%s: looping recv after '%s' (%d)",
     271                              __func__, gnutls_strerror(rc), rc);
     272                /* For a blocking read, loop and try again
     273                 * immediately. Otherwise just notify the caller. */
     274                if (ctxt->input_block != APR_NONBLOCK_READ)
     275                    continue;
     276                else
     277                    ctxt->input_rc =
     278                        (rc == GNUTLS_E_AGAIN ? APR_EAGAIN : APR_EINTR);
     279            } else if (rc == GNUTLS_E_REHANDSHAKE) {
    291280                /* A client has asked for a new Hankshake. Currently, we don't do it */
    292281                ap_log_cerror(APLOG_MARK, APLOG_INFO,
     
    395384    }
    396385
    397     /* Enable SNI for proxy connections */
     386    /* Enable SNI and ALPN for proxy connections */
    398387    if (ctxt->is_proxy == GNUTLS_ENABLED_TRUE)
    399     {
    400         /* Get peer hostname from note left by mod_proxy */
    401         const char *peer_hostname =
    402             apr_table_get(ctxt->c->notes, PROXY_SNI_NOTE);
    403         /* Used only as target for apr_ipsubnet_create() */
    404         apr_ipsubnet_t *probe;
    405         /* Check if the note is present (!= NULL) and NOT an IP
    406          * address */
    407         if ((peer_hostname) != NULL
    408             && (apr_ipsubnet_create(&probe, peer_hostname, NULL, ctxt->c->pool)
    409                 != APR_SUCCESS))
    410         {
    411             ret = gnutls_server_name_set(ctxt->session, GNUTLS_NAME_DNS,
    412                                          peer_hostname, strlen(peer_hostname));
    413             if (ret != GNUTLS_E_SUCCESS)
    414                 ap_log_cerror(APLOG_MARK, APLOG_ERR, ret, ctxt->c,
    415                               "Could not set SNI '%s' for proxy connection: "
    416                               "%s (%d)",
    417                               peer_hostname, gnutls_strerror(ret), ret);
    418         }
    419     }
     388        mgs_set_proxy_handshake_ext(ctxt);
    420389
    421390tryagain:
     
    567536    }
    568537
    569     if (ctxt->status < 0) {
    570         ap_log_cerror(APLOG_MARK, APLOG_DEBUG, 0, ctxt->c,
    571                       "%s %s: ap_get_brigade", __func__, IS_PROXY_STR(ctxt));
    572         return ap_get_brigade(f->next, bb, mode, block, readbytes);
     538    if (ctxt->status < 0)
     539    {
     540        ap_log_cerror(APLOG_MARK, APLOG_TRACE1, 0, ctxt->c,
     541                      "%s: %sconnection failed, cannot provide data!",
     542                      __func__, IS_PROXY_STR(ctxt));
     543        apr_bucket *bucket =
     544                apr_bucket_eos_create(f->c->bucket_alloc);
     545        APR_BRIGADE_INSERT_TAIL(bb, bucket);
     546        return APR_ECONNABORTED;
    573547    }
    574548
     
    708682                          "%s: TLS %sconnection opened.",
    709683                          __func__, IS_PROXY_STR(ctxt));
    710     }
    711 
    712     if (ctxt->status < 0) {
    713         return ap_pass_brigade(f->next, bb);
     684        else if (ctxt->is_proxy)
     685        {
     686            /* If mod_proxy receives an error while trying to send its
     687             * request it sends an "invalid request" error to the
     688             * client. By pretending we could send the request
     689             * mod_proxy continues its processing and sends a proper
     690             * "proxy error" message when there's no response to read. */
     691            apr_bucket *bucket = apr_bucket_eos_create(f->c->bucket_alloc);
     692            APR_BRIGADE_INSERT_TAIL(bb, bucket);
     693            return APR_SUCCESS;
     694        }
     695        /* No final else here, the "ctxt->status < 0" check below will
     696         * catch that. */
     697    }
     698
     699    if (ctxt->status < 0)
     700    {
     701        ap_log_cerror(APLOG_MARK, APLOG_TRACE1, 0, ctxt->c,
     702                      "%s: %sconnection failed, refusing to send.",
     703                      __func__, IS_PROXY_STR(ctxt));
     704        return APR_ECONNABORTED;
    714705    }
    715706
     
    864855                && APR_BRIGADE_EMPTY(ctxt->input_bb)))
    865856        {
    866             if (APR_STATUS_IS_EOF(ctxt->input_rc))
    867             {
    868                 return 0;
    869             }
    870             else
    871             {
    872                 gnutls_transport_set_errno(ctxt->session,
    873                                            EAI_APR_TO_RAW(ctxt->input_rc));
    874                 return -1;
    875             }
     857            /* Turning APR_SUCCESS into APR_EINTR isn't ideal, but
     858             * it's the best matching error code for "didn't get data,
     859             * but read didn't permanently fail either." */
     860            ctxt->input_rc = (rc != APR_SUCCESS ? rc : APR_EINTR);
     861            gnutls_transport_set_errno(ctxt->session,
     862                                       EAI_APR_TO_RAW(ctxt->input_rc));
     863            return -1;
     864        }
     865
     866        /* Blocking ap_get_brigade() can return a timeout status,
     867         * sometimes after a very short time. "Don't give up, just
     868         * return the timeout" is what mod_ssl does. */
     869        if (ctxt->input_block == APR_BLOCK_READ
     870            && APR_STATUS_IS_TIMEUP(rc)
     871            && APR_BRIGADE_EMPTY(ctxt->input_bb))
     872        {
     873            ctxt->input_rc = rc;
     874            gnutls_transport_set_errno(ctxt->session, EAGAIN);
     875            return -1;
    876876        }
    877877
     
    879879        {
    880880            /* Unexpected errors discard the brigade */
     881            ap_log_cerror(APLOG_MARK, APLOG_INFO, rc, ctxt->c,
     882                          "%s: Unexpected error!", __func__);
    881883            apr_brigade_cleanup(ctxt->input_bb);
    882884            ctxt->input_bb = NULL;
Note: See TracChangeset for help on using the changeset viewer.