Changeset 6fa6095 in mod_gnutls


Ignore:
Timestamp:
Jan 21, 2020, 2:29:27 AM (3 months ago)
Author:
Fiona Klute <fiona.klute@…>
Branches:
master
Children:
1c76ea7
Parents:
e24e3bf9
Message:

Partial post-handshake auth support

Needs proper error handling, especially for
GNUTLS_E_GOT_APPLICATION_DATA, which can randomly happen with requests
containing a body.

Files:
3 added
5 edited

Legend:

Unmodified
Added
Removed
  • src/gnutls_hooks.c

    re24e3bf9 r6fa6095  
    11711171    {
    11721172        /* incoming connection, server mode */
    1173         err = gnutls_init(&ctxt->session, GNUTLS_SERVER);
     1173        err = gnutls_init(&ctxt->session,
     1174                          GNUTLS_SERVER | GNUTLS_POST_HANDSHAKE_AUTH);
    11741175        if (err != GNUTLS_E_SUCCESS)
    11751176            ap_log_cerror(APLOG_MARK, APLOG_ERR, err, c,
     
    14601461        gnutls_certificate_get_peers(ctxt->session, &cert_list_size);
    14611462
    1462     if (cert_list == NULL || cert_list_size == 0) {
     1463    /* We can reauthenticate the client if using TLS 1.3 and the
     1464     * client annouced support. Note that there may still not be any
     1465     * client certificate after. */
     1466    if ((cert_list == NULL || cert_list_size == 0)
     1467        && gnutls_protocol_get_version(ctxt->session) == GNUTLS_TLS1_3
     1468        && (gnutls_session_get_flags(ctxt->session)
     1469            & GNUTLS_SFLAGS_POST_HANDSHAKE_AUTH))
     1470    {
    14631471        ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r,
    1464                       "%s: No certificate, attempting to rehandshake "
    1465                       "with peer (%d)",
     1472                      "%s: No certificate, attempting to reauthenticate "
     1473                      "peer (%d)",
    14661474                      __func__, client_verify_mode);
    14671475
     
    14831491        gnutls_certificate_server_set_request(ctxt->session,
    14841492                                              client_verify_mode);
    1485         /* TODO: rehandshake code is broken and has been for years,
    1486          * replace with TLS 1.3 post-handshake auth. */
    1487         if (mgs_rehandshake(ctxt) != 0) {
     1493        if (mgs_reauth(ctxt) != GNUTLS_E_SUCCESS) {
    14881494            return HTTP_FORBIDDEN;
    14891495        }
  • src/gnutls_io.c

    re24e3bf9 r6fa6095  
    33 *  Copyright 2008 Nikos Mavrogiannopoulos
    44 *  Copyright 2011 Dash Shendy
    5  *  Copyright 2015-2019 Fiona Klute
     5 *  Copyright 2015-2020 Fiona Klute
    66 *
    77 *  Licensed under the Apache License, Version 2.0 (the "License");
     
    449449}
    450450
    451 int mgs_rehandshake(mgs_handle_t * ctxt) {
    452     int rv;
    453 
     451
     452
     453int mgs_reauth(mgs_handle_t * ctxt)
     454{
    454455    if (ctxt->session == NULL)
    455         return -1;
    456 
    457     rv = gnutls_rehandshake(ctxt->session);
    458 
    459     if (rv != 0) {
    460         /* the client did not want to rehandshake. goodbye */
     456        return GNUTLS_E_INVALID_REQUEST;
     457
     458    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
     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    /* 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"); */
     478
     479    if (rv != GNUTLS_E_SUCCESS)
     480    {
    461481        ap_log_cerror(APLOG_MARK, APLOG_WARNING, 0, ctxt->c,
    462                       "GnuTLS: Client Refused Rehandshake request.");
    463         return -1;
    464     }
    465 
    466     ctxt->status = 0;
    467 
    468     rv = gnutls_do_handshake(ctxt);
    469 
    470     return rv;
     482                      "Reauthentication failed: %s (%d)",
     483                      gnutls_strerror(rv), rv);
     484        return rv;
     485    }
     486
     487    return GNUTLS_E_SUCCESS;
    471488}
    472489
  • src/gnutls_io.h

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

    re24e3bf9 r6fa6095  
    4242        test-32_vhost_SNI_serveralias_mismatch.bash \
    4343        test-33_vhost_SNI_serveralias_missinghost.bash \
    44         test-34_TLS_reverse_proxy_h2.bash
     44        test-34_TLS_reverse_proxy_h2.bash \
     45        test-35_client_reauth.bash
    4546
    4647MOSTLYCLEANFILES = $(test_scripts)
  • test/tests/Makefile.am

    re24e3bf9 r6fa6095  
    3434        32_vhost_SNI_serveralias_mismatch/apache.conf 32_vhost_SNI_serveralias_mismatch/test.yml \
    3535        33_vhost_SNI_serveralias_missinghost/apache.conf 33_vhost_SNI_serveralias_missinghost/test.yml \
    36         34_TLS_reverse_proxy_h2/apache.conf 34_TLS_reverse_proxy_h2/hooks.py 34_TLS_reverse_proxy_h2/backend.conf 34_TLS_reverse_proxy_h2/test.yml
     36        34_TLS_reverse_proxy_h2/apache.conf 34_TLS_reverse_proxy_h2/hooks.py 34_TLS_reverse_proxy_h2/backend.conf 34_TLS_reverse_proxy_h2/test.yml \
     37        35_client_reauth/apache.conf 35_client_reauth/test.yml
Note: See TracChangeset for help on using the changeset viewer.