Changeset 2aaf4f5 in mod_gnutls


Ignore:
Timestamp:
Feb 23, 2014, 1:05:31 PM (6 years ago)
Author:
Daniel Kahn Gillmor <dkg@…>
Branches:
debian/master, debian/stretch-backports, jessie-backports, master, upstream
Children:
765cac2
Parents:
999cdec
Message:

implement GnuTLSExportCertificates control over max exported cert size

This patchset implements the proposed modification to
GnuTLSExportCertificates, allowing server administrators to choose the
maximum size of the exported certs.

Some advantages:

  • avoids large buffers on the stack
  • more configurable for server admins who expect to use larger certs
  • better visibilty for users when a too-large-cert is encountered

This also increases the default maximum exported size from 10KiB to
16KiB.

Files:
4 edited

Legend:

Unmodified
Added
Removed
  • include/mod_gnutls.h.in

    r999cdec r2aaf4f5  
    127127    int enabled;
    128128    /* Export full certificates to CGI environment: */
    129     int export_certificates_enabled;
     129    int export_certificates_size;
    130130        /* GnuTLS Priorities */
    131131    gnutls_priority_t priorities;
     
    360360const char *mgs_set_enabled(cmd_parms * parms, void *dummy,
    361361                            const char *arg);
    362 const char *mgs_set_export_certificates_enabled(cmd_parms * parms, void *dummy,
     362const char *mgs_set_export_certificates_size(cmd_parms * parms, void *dummy,
    363363                            const char *arg);
    364364const char *mgs_set_priorities(cmd_parms * parms, void *dummy,
  • src/gnutls_config.c

    r999cdec r2aaf4f5  
    1919
    2020#include "mod_gnutls.h"
     21#include "apr_lib.h"
    2122
    2223#ifdef APLOG_USE_MODULE
     
    554555}
    555556
    556 const char *mgs_set_export_certificates_enabled(cmd_parms * parms, void *dummy, const char *arg) {
     557const char *mgs_set_export_certificates_size(cmd_parms * parms, void *dummy, const char *arg) {
    557558    mgs_srvconf_rec *sc = (mgs_srvconf_rec *) ap_get_module_config(parms->server->module_config, &gnutls_module);
    558559    if (!strcasecmp(arg, "On")) {
    559         sc->export_certificates_enabled = GNUTLS_ENABLED_TRUE;
     560        sc->export_certificates_size = 16 * 1024;
    560561    } else if (!strcasecmp(arg, "Off")) {
    561         sc->export_certificates_enabled = GNUTLS_ENABLED_FALSE;
     562        sc->export_certificates_size = 0;
    562563    } else {
    563         return
    564         "GnuTLSExportCertificates must be set to 'On' or 'Off'";
     564        char* endptr;
     565        sc->export_certificates_size = strtol(arg, &endptr, 10);
     566        while (apr_isspace(*endptr)) endptr++;
     567        if (*endptr == '\0' || *endptr == 'b' || *endptr == 'B') {
     568            ;
     569        } else if (*endptr == 'k' || *endptr == 'K') {
     570            sc->export_certificates_size *= 1024;
     571        } else {
     572            return "GnuTLSExportCertificates must be set to a size (in bytes) or 'On' or 'Off'";
     573        }
    565574    }
    566575
     
    638647    sc->dh_params = NULL;
    639648    sc->proxy_enabled = GNUTLS_ENABLED_UNSET;
    640     sc->export_certificates_enabled = GNUTLS_ENABLED_UNSET;
     649    sc->export_certificates_size = -1;
    641650    sc->client_verify_method = mgs_cvm_unset;
    642651
     
    667676    gnutls_srvconf_merge(tickets, GNUTLS_ENABLED_UNSET);
    668677    gnutls_srvconf_merge(proxy_enabled, GNUTLS_ENABLED_UNSET);
    669     gnutls_srvconf_merge(export_certificates_enabled, GNUTLS_ENABLED_UNSET);
     678    gnutls_srvconf_merge(export_certificates_size, -1);
    670679    gnutls_srvconf_merge(client_verify_method, mgs_cvm_unset);
    671680    gnutls_srvconf_merge(client_verify_mode, -1);
  • src/gnutls_hooks.c

    r999cdec r2aaf4f5  
    4343static int mgs_cert_verify(request_rec * r, mgs_handle_t * ctxt);
    4444/* use side==0 for server and side==1 for client */
    45 static void mgs_add_common_cert_vars(request_rec * r, gnutls_x509_crt_t cert, int side, int export_full_cert);
    46 static void mgs_add_common_pgpcert_vars(request_rec * r, gnutls_openpgp_crt_t cert, int side, int export_full_cert);
     45static void mgs_add_common_cert_vars(request_rec * r, gnutls_x509_crt_t cert, int side, int export_cert_size);
     46static void mgs_add_common_pgpcert_vars(request_rec * r, gnutls_openpgp_crt_t cert, int side, int export_cert_size);
    4747static const char* mgs_x509_construct_uid(request_rec * pool, gnutls_x509_crt_t cert);
    4848static int mgs_status_hook(request_rec *r, int flags);
     
    373373        if (sc->tickets == GNUTLS_ENABLED_UNSET)
    374374            sc->tickets = GNUTLS_ENABLED_TRUE;
    375         if (sc->export_certificates_enabled == GNUTLS_ENABLED_UNSET)
    376             sc->export_certificates_enabled = GNUTLS_ENABLED_FALSE;
     375        if (sc->export_certificates_size < 0)
     376            sc->export_certificates_size = 0;
    377377        if (sc->client_verify_mode ==  -1)
    378378            sc->client_verify_mode = GNUTLS_CERT_IGNORE;
     
    818818
    819819    if (gnutls_certificate_type_get(ctxt->session) == GNUTLS_CRT_X509) {
    820                 mgs_add_common_cert_vars(r, ctxt->sc->certs_x509_chain[0], 0, ctxt->sc->export_certificates_enabled);
     820                mgs_add_common_cert_vars(r, ctxt->sc->certs_x509_chain[0], 0, ctxt->sc->export_certificates_size);
    821821        } else if (gnutls_certificate_type_get(ctxt->session) == GNUTLS_CRT_OPENPGP) {
    822         mgs_add_common_pgpcert_vars(r, ctxt->sc->cert_pgp, 0, ctxt->sc->export_certificates_enabled);
     822        mgs_add_common_pgpcert_vars(r, ctxt->sc->cert_pgp, 0, ctxt->sc->export_certificates_size);
    823823        }
    824824
     
    894894/* @param side is either 0 for SERVER or 1 for CLIENT
    895895 *
    896  * @param export_full_cert (boolean) export the PEM-encoded
    897  * certificate in full as an environment variable.
     896 * @param export_cert_size (int) maximum size for environment variable
     897 * to use for the PEM-encoded certificate (0 means do not export)
    898898 */
    899899#define MGS_SIDE ((side==0)?"SSL_SERVER":"SSL_CLIENT")
    900900
    901 static void mgs_add_common_cert_vars(request_rec * r, gnutls_x509_crt_t cert, int side, int export_full_cert) {
     901static void mgs_add_common_cert_vars(request_rec * r, gnutls_x509_crt_t cert, int side, int export_cert_size) {
    902902    unsigned char sbuf[64]; /* buffer to hold serials */
    903903    char buf[AP_IOBUFSIZE];
     
    913913
    914914    _gnutls_log(debug_log_fp, "%s: %d\n", __func__, __LINE__);
    915     if (export_full_cert != 0) {
    916         char cert_buf[10 * 1024];
    917         len = sizeof (cert_buf);
    918 
    919         if (gnutls_x509_crt_export(cert, GNUTLS_X509_FMT_PEM, cert_buf, &len) >= 0)
    920             apr_table_setn(env, apr_pstrcat(r->pool, MGS_SIDE, "_CERT", NULL),
    921                            apr_pstrmemdup(r->pool, cert_buf, len));
    922         else
    923             ap_log_rerror(APLOG_MARK, APLOG_INFO, 0, r,
    924                           "GnuTLS: Failed to export X.509 certificate to environment");
     915    if (export_cert_size > 0) {
     916        len = 0;
     917        ret = gnutls_x509_crt_export(cert, GNUTLS_X509_FMT_PEM, NULL, &len);
     918        if (ret == GNUTLS_E_SHORT_MEMORY_BUFFER) {
     919            if (len >= export_cert_size) {
     920                apr_table_setn(env, apr_pstrcat(r->pool, MGS_SIDE, "_CERT", NULL),
     921                               "GNUTLS_CERTIFICATE_SIZE_LIMIT_EXCEEDED");
     922                ap_log_rerror(APLOG_MARK, APLOG_INFO, 0, r,
     923                              "GnuTLS: Failed to export too-large X.509 certificate to environment");
     924            } else {
     925                char* cert_buf = apr_palloc(r->pool, len + 1);
     926                if (cert_buf != NULL && gnutls_x509_crt_export(cert, GNUTLS_X509_FMT_PEM, cert_buf, &len) >= 0) {
     927                    cert_buf[len] = 0;
     928                    apr_table_setn(env, apr_pstrcat(r->pool, MGS_SIDE, "_CERT", NULL), cert_buf);
     929                } else {
     930                    ap_log_rerror(APLOG_MARK, APLOG_WARNING, 0, r,
     931                                  "GnuTLS: failed to export X.509 certificate");
     932                }
     933            }
     934        } else {
     935            ap_log_rerror(APLOG_MARK, APLOG_WARNING, 0, r,
     936                          "GnuTLS: dazed and confused about X.509 certificate size");
     937        }
    925938    }
    926939
     
    10371050/* @param side 0: server, 1: client
    10381051 *
    1039  * @param export_full_cert (boolean) export the PEM-encoded
    1040  * certificate in full as an environment variable.
     1052 * @param export_cert_size (int) maximum size for environment variable
     1053 * to use for the PEM-encoded certificate (0 means do not export)
    10411054 */
    1042 static void mgs_add_common_pgpcert_vars(request_rec * r, gnutls_openpgp_crt_t cert, int side, int export_full_cert) {
     1055static void mgs_add_common_pgpcert_vars(request_rec * r, gnutls_openpgp_crt_t cert, int side, int export_cert_size) {
    10431056
    10441057        unsigned char sbuf[64]; /* buffer to hold serials */
     
    10541067    apr_table_t *env = r->subprocess_env;
    10551068
    1056     if (export_full_cert != 0) {
    1057         char cert_buf[10 * 1024];
    1058         len = sizeof (cert_buf);
    1059 
    1060         if (gnutls_openpgp_crt_export(cert, GNUTLS_OPENPGP_FMT_BASE64, cert_buf, &len) >= 0)
    1061             apr_table_setn(env, apr_pstrcat(r->pool, MGS_SIDE, "_CERT", NULL),
    1062                            apr_pstrmemdup(r->pool, cert_buf, len));
    1063         else
    1064             ap_log_rerror(APLOG_MARK, APLOG_INFO, 0, r,
    1065                           "GnuTLS: Failed to export OpenPGP certificate to environment");
     1069    if (export_cert_size > 0) {
     1070        len = 0;
     1071        ret = gnutls_openpgp_crt_export(cert, GNUTLS_OPENPGP_FMT_BASE64, NULL, &len);
     1072        if (ret == GNUTLS_E_SHORT_MEMORY_BUFFER) {
     1073            if (len >= export_cert_size) {
     1074                apr_table_setn(env, apr_pstrcat(r->pool, MGS_SIDE, "_CERT", NULL),
     1075                               "GNUTLS_CERTIFICATE_SIZE_LIMIT_EXCEEDED");
     1076                ap_log_rerror(APLOG_MARK, APLOG_INFO, 0, r,
     1077                              "GnuTLS: Failed to export too-large OpenPGP certificate to environment");
     1078            } else {
     1079                char* cert_buf = apr_palloc(r->pool, len + 1);
     1080                if (cert_buf != NULL && gnutls_openpgp_crt_export(cert, GNUTLS_OPENPGP_FMT_BASE64, cert_buf, &len) >= 0) {
     1081                    cert_buf[len] = 0;
     1082                    apr_table_setn(env, apr_pstrcat(r->pool, MGS_SIDE, "_CERT", NULL), cert_buf);
     1083                } else {
     1084                    ap_log_rerror(APLOG_MARK, APLOG_WARNING, 0, r,
     1085                                  "GnuTLS: failed to export OpenPGP certificate");
     1086                }
     1087            }
     1088        } else {
     1089            ap_log_rerror(APLOG_MARK, APLOG_WARNING, 0, r,
     1090                          "GnuTLS: dazed and confused about OpenPGP certificate size");
     1091        }
    10661092    }
    10671093
     
    13281354
    13291355    if (gnutls_certificate_type_get(ctxt->session) == GNUTLS_CRT_X509)
    1330         mgs_add_common_cert_vars(r, cert.x509[0], 1, ctxt->sc->export_certificates_enabled);
     1356        mgs_add_common_cert_vars(r, cert.x509[0], 1, ctxt->sc->export_certificates_size);
    13311357    else if (gnutls_certificate_type_get(ctxt->session) == GNUTLS_CRT_OPENPGP)
    1332         mgs_add_common_pgpcert_vars(r, cert.pgp, 1, ctxt->sc->export_certificates_enabled);
     1358        mgs_add_common_pgpcert_vars(r, cert.pgp, 1, ctxt->sc->export_certificates_size);
    13331359
    13341360    {
  • src/mod_gnutls.c

    r999cdec r2aaf4f5  
    181181    "Whether this server has GnuTLS Enabled. Default: Off"),
    182182    AP_INIT_TAKE1("GnuTLSExportCertificates",
    183     mgs_set_export_certificates_enabled,
     183    mgs_set_export_certificates_size,
    184184    NULL,
    185185    RSRC_CONF,
    186     "Whether to export PEM encoded certificates to CGIs. Default: Off"),
     186    "Max size to export PEM encoded certificates to CGIs (or off to disable). Default: off"),
    187187    { NULL },
    188188};
Note: See TracChangeset for help on using the changeset viewer.