Changeset e24e3bf9 in mod_gnutls


Ignore:
Timestamp:
Jan 21, 2020, 12:55:47 AM (10 months ago)
Author:
Fiona Klute <fiona.klute@…>
Branches:
master, proxy-ticket
Children:
6fa6095
Parents:
3b2edd6
Message:

Rewrite authz hook

Using the effective mode simplifies the code a lot, and the function
now only tries to rehandshake if there's no client certificate yet.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • src/gnutls_hooks.c

    r3b2edd6 re24e3bf9  
    14291429}
    14301430
    1431 int mgs_hook_authz(request_rec * r) {
    1432     int rv;
    1433     mgs_handle_t *ctxt;
    1434     mgs_dirconf_rec *dc;
    1435 
     1431int mgs_hook_authz(request_rec *r)
     1432{
    14361433    if (r == NULL)
    14371434        return DECLINED;
    14381435
    1439     dc = ap_get_module_config(r->per_dir_config, &gnutls_module);
    1440 
    1441     _gnutls_log(debug_log_fp, "%s: %d\n", __func__, __LINE__);
    1442     ctxt = get_effective_gnutls_ctxt(r->connection);
    1443 
     1436    mgs_dirconf_rec *dc = ap_get_module_config(
     1437        r->per_dir_config, &gnutls_module);
     1438
     1439    mgs_handle_t *ctxt = get_effective_gnutls_ctxt(r->connection);
    14441440    if (!ctxt || ctxt->session == NULL) {
    14451441        return DECLINED;
    14461442    }
    14471443
    1448     if (dc->client_verify_mode == GNUTLS_CERT_IGNORE) {
     1444    /* The effective verify mode. Directory configuration takes
     1445     * precedence if present (-1 means it is unset). */
     1446    int client_verify_mode = ctxt->sc->client_verify_mode;
     1447    if (dc->client_verify_mode != -1)
     1448        client_verify_mode = dc->client_verify_mode;
     1449
     1450    if (client_verify_mode == GNUTLS_CERT_IGNORE)
     1451    {
    14491452        ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r,
    1450                 "GnuTLS: Directory set to Ignore Client Certificate!");
    1451     } else {
    1452         if (ctxt->sc->client_verify_mode < dc->client_verify_mode) {
     1453                      "%s: verify mode is \"ignore\"", __func__);
     1454        return DECLINED;
     1455    }
     1456
     1457    /* At this point the verify mode is either request or require */
     1458    unsigned int cert_list_size;
     1459    const gnutls_datum_t *cert_list =
     1460        gnutls_certificate_get_peers(ctxt->session, &cert_list_size);
     1461
     1462    if (cert_list == NULL || cert_list_size == 0) {
     1463        ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r,
     1464                      "%s: No certificate, attempting to rehandshake "
     1465                      "with peer (%d)",
     1466                      __func__, client_verify_mode);
     1467
     1468        if (r->proto_num == HTTP_VERSION(2, 0))
     1469        {
    14531470            ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r,
    1454                     "GnuTLS: Attempting to rehandshake with peer. %d %d",
    1455                     ctxt->sc->client_verify_mode,
    1456                     dc->client_verify_mode);
    1457 
    1458             /* If we already have a client certificate, there's no point in
    1459              * re-handshaking... */
    1460             rv = mgs_cert_verify(r, ctxt);
    1461             if (rv != DECLINED && rv != HTTP_FORBIDDEN)
    1462                 return rv;
    1463 
    1464             if (r->proto_num == HTTP_VERSION(2, 0))
    1465             {
    1466                 ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r,
    1467                               "Rehandshake is prohibited for HTTP/2 "
    1468                               "(RFC 7540, section 9.2.1).");
    1469                 apr_table_setn(r->notes, RENEGOTIATE_FORBIDDEN_NOTE,
    1470                                "verify-client");
    1471                 return HTTP_FORBIDDEN;
    1472             }
    1473 
    1474             gnutls_certificate_server_set_request
    1475                     (ctxt->session, dc->client_verify_mode);
    1476 
    1477             if (mgs_rehandshake(ctxt) != 0) {
    1478                 return HTTP_FORBIDDEN;
    1479             }
    1480         } else if (ctxt->sc->client_verify_mode ==
    1481                 GNUTLS_CERT_IGNORE) {
    1482 #if MOD_GNUTLS_DEBUG
    1483             ap_log_rerror(APLOG_MARK, APLOG_INFO, 0, r,
    1484                     "GnuTLS: Peer is set to IGNORE");
    1485 #endif
    1486             return DECLINED;
    1487         }
    1488         rv = mgs_cert_verify(r, ctxt);
    1489         if (rv != DECLINED
    1490             && (rv != HTTP_FORBIDDEN
    1491                 || dc->client_verify_mode == GNUTLS_CERT_REQUIRE
    1492                 || (dc->client_verify_mode == -1
    1493                     && ctxt->sc->client_verify_mode == GNUTLS_CERT_REQUIRE)))
    1494         {
    1495             return rv;
    1496         }
    1497     }
    1498 
    1499     return DECLINED;
     1471                          "Rehandshake is prohibited for HTTP/2 "
     1472                          "(RFC 7540, section 9.2.1).");
     1473
     1474            /* This also applies to request mode, otherwise
     1475             * per-directory request would never work with HTTP/2. The
     1476             * note makes mod_http2 send an HTTP_1_1_REQUIRED
     1477             * error to tell the client to switch. */
     1478            apr_table_setn(r->notes, RENEGOTIATE_FORBIDDEN_NOTE,
     1479                           "verify-client");
     1480            return HTTP_FORBIDDEN;
     1481        }
     1482
     1483        gnutls_certificate_server_set_request(ctxt->session,
     1484                                              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) {
     1488            return HTTP_FORBIDDEN;
     1489        }
     1490    }
     1491
     1492    int rv = mgs_cert_verify(r, ctxt);
     1493    /* In "request" mode we always allow the request, otherwise the
     1494     * verify result decides. */
     1495    if (client_verify_mode == GNUTLS_CERT_REQUEST)
     1496        return DECLINED;
     1497    return rv;
    15001498}
    15011499
Note: See TracChangeset for help on using the changeset viewer.