Changeset 2aaf4f5 in mod_gnutls for src/gnutls_hooks.c


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.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • 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    {
Note: See TracChangeset for help on using the changeset viewer.