Changeset c0fc11e in mod_gnutls for src/gnutls_sni.c


Ignore:
Timestamp:
Nov 5, 2018, 2:20:54 AM (15 months ago)
Author:
Fiona Klute <fiona.klute@…>
Branches:
debian/master, master
Children:
d4c1a4e
Parents:
7ff6c6c
Message:

Separate functions for default SNI and loading virtual host credentials

The default SNI method using gnutls_server_name_get() won't be
necessary with early SNI parsing, but needs to remain available as a
fallback for old GnuTLS versions.

Loading virtual host credentials should happen in a separate function
so it can easily happen in pre or post client hello hooks alike.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • src/gnutls_sni.c

    r7ff6c6c rc0fc11e  
    138138    return 0;
    139139}
     140
     141
     142
     143/**
     144 * Default buffer size for SNI data, including the terminating NULL
     145 * byte. The size matches what gnutls-cli uses initially.
     146 */
     147#define DEFAULT_SNI_HOST_LEN 256
     148
     149const char* mgs_server_name_get(mgs_handle_t *ctxt)
     150{
     151    char *sni_name = apr_palloc(ctxt->c->pool, DEFAULT_SNI_HOST_LEN);
     152    size_t sni_len = DEFAULT_SNI_HOST_LEN;
     153    unsigned int sni_type;
     154
     155    /* Search for a DNS SNI element. Note that RFC 6066 prohibits more
     156     * than one server name per type. */
     157    int sni_index = -1;
     158    int rv = 0;
     159    do {
     160        /* The sni_index is incremented before each use, so if the
     161         * loop terminates with a type match we will have the right
     162         * one stored. */
     163        rv = gnutls_server_name_get(ctxt->session, sni_name,
     164                                    &sni_len, &sni_type, ++sni_index);
     165        if (rv == GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE)
     166        {
     167            ap_log_cerror(APLOG_MARK, APLOG_TRACE1, APR_EGENERAL, ctxt->c,
     168                          "%s: no DNS SNI found (last index: %d).",
     169                          __func__, sni_index);
     170            return NULL;
     171        }
     172    } while (sni_type != GNUTLS_NAME_DNS);
     173    /* The (rv == GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE) path inside
     174     * the loop above returns, so if we reach this point we have a DNS
     175     * SNI at the current index. */
     176
     177    if (rv == GNUTLS_E_SHORT_MEMORY_BUFFER)
     178    {
     179        /* Allocate a new buffer of the right size and retry */
     180        sni_name = apr_palloc(ctxt->c->pool, sni_len);
     181        ap_log_cerror(APLOG_MARK, APLOG_TRACE1, APR_SUCCESS, ctxt->c,
     182                      "%s: reallocated SNI data buffer for %" APR_SIZE_T_FMT
     183                      " bytes.", __func__, sni_len);
     184        rv = gnutls_server_name_get(ctxt->session, sni_name,
     185                                    &sni_len, &sni_type, sni_index);
     186    }
     187
     188    /* Unless there's a bug in the GnuTLS API only GNUTLS_E_IDNA_ERROR
     189     * can occur here, but a catch all is safer and no more
     190     * complicated. */
     191    if (rv != GNUTLS_E_SUCCESS)
     192    {
     193        ap_log_cerror(APLOG_MARK, APLOG_INFO, APR_EGENERAL, ctxt->c,
     194                      "%s: error while getting SNI DNS data: '%s' (%d).",
     195                      __func__, gnutls_strerror(rv), rv);
     196        return NULL;
     197    }
     198
     199    return sni_name;
     200}
Note: See TracChangeset for help on using the changeset viewer.