Changeset e5bbda4 in mod_gnutls for src/gnutls_hooks.c


Ignore:
Timestamp:
Dec 15, 2007, 8:26:01 AM (12 years ago)
Author:
Nokis Mavrogiannopoulos <nmav@…>
Branches:
debian/master, debian/stretch-backports, jessie-backports, master, msva, upstream
Children:
5542bc6
Parents:
d2439b9
git-author:
Nikos Mavrogiannopoulos <nmav@…> (12/15/07 08:26:01)
git-committer:
Nokis Mavrogiannopoulos <nmav@…> (12/15/07 08:26:01)
Message:

Initial support for openpgp keys

File:
1 edited

Legend:

Unmodified
Added
Removed
  • src/gnutls_hooks.c

    rd2439b9 re5bbda4  
    3737static int mgs_cert_verify(request_rec * r, mgs_handle_t * ctxt);
    3838/* use side==0 for server and side==1 for client */
    39 static void mgs_add_common_cert_vars(request_rec * r, gnutls_x509_crt cert,
     39static void mgs_add_common_cert_vars(request_rec * r, gnutls_x509_crt_t cert,
     40                                     int side,
     41                                     int export_certificates_enabled);
     42static void mgs_add_common_pgpcert_vars(request_rec * r, gnutls_openpgp_crt_t cert,
    4043                                     int side,
    4144                                     int export_certificates_enabled);
     
    7073
    7174    ret = gnutls_global_init();
     75    if (ret < 0) /* FIXME: can we print here? */
     76        exit(ret);
     77
     78    ret = gnutls_global_init_extra();
    7279    if (ret < 0) /* FIXME: can we print here? */
    7380        exit(ret);
     
    8895}
    8996
    90 /* We don't support openpgp certificates, yet */
    91 const static int cert_type_prio[2] = { GNUTLS_CRT_X509, 0 };
    92 
    9397static int mgs_select_virtual_server_cb(gnutls_session_t session)
    9498{
     
    96100    mgs_srvconf_rec *tsc;
    97101    int ret;
     102    int cprio[3] = { GNUTLS_CRT_X509, GNUTLS_CRT_OPENPGP, 0 };
    98103
    99104    ctxt = gnutls_transport_get_ptr(session);
     
    127132     */
    128133    ret = gnutls_priority_set(session, ctxt->sc->priorities);
    129     gnutls_certificate_type_set_priority(session, cert_type_prio);
    130 
     134
     135    /* Do not allow the user to override certificate priorities. We know
     136     * better if the certificate of certain type is enabled. */
     137    if (ctxt->sc->cert_pgp != NULL && ctxt->sc->certs_x509[0] != NULL) {
     138        gnutls_certificate_type_set_priority( session, cprio);
     139    } else if (ctxt->sc->certs_x509[0] != NULL) {
     140        cprio[0] = GNUTLS_CRT_X509;
     141        cprio[1] = 0;
     142        gnutls_certificate_type_set_priority( session, cprio);
     143    } else if (ctxt->sc->cert_pgp != NULL) {
     144        cprio[0] = GNUTLS_CRT_OPENPGP;
     145        cprio[1] = 0;
     146        gnutls_certificate_type_set_priority( session, cprio);
     147    }
    131148
    132149    /* actually it shouldn't fail since we have checked at startup */
     
    144161    ctxt = gnutls_transport_get_ptr(session);
    145162
    146     ret->type = GNUTLS_CRT_X509;
    147     ret->ncerts = ctxt->sc->certs_x509_num;
    148     ret->deinit_all = 0;
    149 
    150     ret->cert.x509 = ctxt->sc->certs_x509;
    151     ret->key.x509 = ctxt->sc->privkey_x509;
    152     return 0;
     163    if (gnutls_certificate_type_get( session) == GNUTLS_CRT_X509) {
     164        ret->type = GNUTLS_CRT_X509;
     165        ret->ncerts = ctxt->sc->certs_x509_num;
     166        ret->deinit_all = 0;
     167
     168        ret->cert.x509 = ctxt->sc->certs_x509;
     169        ret->key.x509 = ctxt->sc->privkey_x509;
     170       
     171        return 0;
     172    } else if (gnutls_certificate_type_get( session) == GNUTLS_CRT_OPENPGP) {
     173        ret->type = GNUTLS_CRT_OPENPGP;
     174        ret->ncerts = 1;
     175        ret->deinit_all = 0;
     176
     177        ret->cert.pgp = ctxt->sc->cert_pgp;
     178        ret->key.pgp = ctxt->sc->privkey_pgp;
     179
     180        return 0;
     181   
     182    }
     183
     184    return GNUTLS_E_INTERNAL_ERROR;
    153185}
    154186
     
    168200 */
    169201static int read_crt_cn(server_rec * s, apr_pool_t * p,
    170                        gnutls_x509_crt cert, char **cert_cn)
     202                       gnutls_x509_crt_t cert, char **cert_cn)
    171203{
    172204    int rv = 0, i;
     
    176208    *cert_cn = NULL;
    177209
     210    data_len = 0;
    178211    rv = gnutls_x509_crt_get_dn_by_oid(cert,
    179212                                       GNUTLS_OID_X520_COMMON_NAME,
     
    187220    } else {                    /* No CN return subject alternative name */
    188221        ap_log_error(APLOG_MARK, APLOG_INFO, 0, s,
    189                      "No common name found in certificate for '%s:%d'. Looking for subject alternative name.",
     222                     "No common name found in certificate for '%s:%d'. Looking for subject alternative name...",
    190223                     s->server_hostname, s->port);
    191224        rv = 0;
     
    215248
    216249    return rv;
    217 
    218 }
     250}
     251
     252static int read_pgpcrt_cn(server_rec * s, apr_pool_t * p,
     253                       gnutls_openpgp_crt_t cert, char **cert_cn)
     254{
     255    int rv = 0;
     256    size_t data_len;
     257
     258
     259    *cert_cn = NULL;
     260
     261    data_len = 0;
     262    rv = gnutls_openpgp_crt_get_name(cert, 0, NULL, &data_len);
     263
     264    if (rv == GNUTLS_E_SHORT_MEMORY_BUFFER && data_len > 1) {
     265        *cert_cn = apr_palloc(p, data_len);
     266        rv = gnutls_openpgp_crt_get_name(cert, 0, *cert_cn, &data_len);
     267    } else {                    /* No CN return subject alternative name */
     268        ap_log_error(APLOG_MARK, APLOG_INFO, 0, s,
     269                     "No name found in PGP certificate for '%s:%d'.",
     270                     s->server_hostname, s->port);
     271    }
     272
     273    return rv;
     274}
     275
    219276
    220277int
     
    351408            if (sc->enabled == GNUTLS_ENABLED_TRUE) {
    352409                rv = read_crt_cn(s, p, sc->certs_x509[0], &sc->cert_cn);
     410                if (rv < 0)  /* try openpgp certificate */
     411                    rv = read_pgpcrt_cn(s, p, sc->cert_pgp, &sc->cert_cn);
     412
    353413                if (rv < 0) {
    354414                    ap_log_error(APLOG_MARK, APLOG_EMERG, 0, s,
     
    479539    ctxt = gnutls_transport_get_ptr(session);
    480540
    481     sni_type = gnutls_certificate_type_get(session);
    482     if (sni_type != GNUTLS_CRT_X509) {
    483         /* In theory, we could support OpenPGP Certificates. Theory != code. */
    484         ap_log_error(APLOG_MARK, APLOG_CRIT, 0,
    485                      ctxt->c->base_server,
    486                      "GnuTLS: Only x509 Certificates are currently supported.");
    487         return NULL;
    488     }
    489 
    490541    rv = gnutls_server_name_get(ctxt->session, sni_name,
    491542                                &data_len, &sni_type, 0);
     
    685736    apr_table_setn(env, "SSL_SESSION_ID", apr_pstrdup(r->pool, tmp));
    686737
    687     mgs_add_common_cert_vars(r, ctxt->sc->certs_x509[0], 0,
     738    if (gnutls_certificate_type_get( ctxt->session) == GNUTLS_CRT_X509)
     739        mgs_add_common_cert_vars(r, ctxt->sc->certs_x509[0], 0,
     740                             ctxt->sc->export_certificates_enabled);
     741    else if (gnutls_certificate_type_get( ctxt->session) == GNUTLS_CRT_OPENPGP)
     742        mgs_add_common_pgpcert_vars(r, ctxt->sc->cert_pgp, 0,
    688743                             ctxt->sc->export_certificates_enabled);
    689744
     
    747802#define MGS_SIDE ((side==0)?"SSL_SERVER":"SSL_CLIENT")
    748803static void
    749 mgs_add_common_cert_vars(request_rec * r, gnutls_x509_crt cert, int side,
     804mgs_add_common_cert_vars(request_rec * r, gnutls_x509_crt_t cert, int side,
    750805                         int export_certificates_enabled)
    751806{
     
    853908        }
    854909    }
    855 
    856 
    857 }
    858 
    859 
     910}
     911
     912static void
     913mgs_add_common_pgpcert_vars(request_rec * r, gnutls_openpgp_crt_t cert, int side,
     914                         int export_certificates_enabled)
     915{
     916    unsigned char sbuf[64];     /* buffer to hold serials */
     917    char buf[AP_IOBUFSIZE];
     918    const char *tmp;
     919    size_t len;
     920    int ret;
     921
     922    apr_table_t *env = r->subprocess_env;
     923
     924    if (export_certificates_enabled != 0) {
     925        char cert_buf[10 * 1024];
     926        len = sizeof(cert_buf);
     927
     928        if (gnutls_openpgp_crt_export
     929            (cert, GNUTLS_OPENPGP_FMT_BASE64, cert_buf, &len) >= 0)
     930            apr_table_setn(env,
     931                           apr_pstrcat(r->pool, MGS_SIDE, "_CERT", NULL),
     932                           apr_pstrmemdup(r->pool, cert_buf, len));
     933
     934    }
     935
     936    len = sizeof(buf);
     937    gnutls_openpgp_crt_get_name(cert, 0, buf, &len);
     938    apr_table_setn(env, apr_pstrcat(r->pool, MGS_SIDE, "_NAME", NULL),
     939                   apr_pstrmemdup(r->pool, buf, len));
     940
     941    len = sizeof(sbuf);
     942    gnutls_openpgp_crt_get_fingerprint(cert, sbuf, &len);
     943    tmp = mgs_session_id2sz(sbuf, len, buf, sizeof(buf));
     944    apr_table_setn(env, apr_pstrcat(r->pool, MGS_SIDE, "_FINGERPRINT", NULL),
     945                   apr_pstrdup(r->pool, tmp));
     946
     947    ret = gnutls_openpgp_crt_get_version(cert);
     948    if (ret > 0)
     949        apr_table_setn(env,
     950                       apr_pstrcat(r->pool, MGS_SIDE, "_M_VERSION", NULL),
     951                       apr_psprintf(r->pool, "%u", ret));
     952
     953    apr_table_setn(env,
     954       apr_pstrcat(r->pool, MGS_SIDE, "_CERT_TYPE", NULL), "OPENPGP");
     955
     956    tmp =
     957        mgs_time2sz(gnutls_openpgp_crt_get_expiration_time
     958                    (cert), buf, sizeof(buf));
     959    apr_table_setn(env, apr_pstrcat(r->pool, MGS_SIDE, "_V_END", NULL),
     960                   apr_pstrdup(r->pool, tmp));
     961
     962    tmp =
     963        mgs_time2sz(gnutls_openpgp_crt_get_creation_time
     964                    (cert), buf, sizeof(buf));
     965    apr_table_setn(env, apr_pstrcat(r->pool, MGS_SIDE, "_V_START", NULL),
     966                   apr_pstrdup(r->pool, tmp));
     967
     968    ret = gnutls_openpgp_crt_get_pk_algorithm(cert, NULL);
     969    if (ret >= 0) {
     970        apr_table_setn(env, apr_pstrcat(r->pool, MGS_SIDE, "_A_KEY", NULL),
     971                       gnutls_pk_algorithm_get_name(ret));
     972    }
     973
     974}
     975
     976/* FIXME: Allow client sending a certificate chain */
    860977static int mgs_cert_verify(request_rec * r, mgs_handle_t * ctxt)
    861978{
     
    863980    unsigned int cert_list_size, status, expired;
    864981    int rv, ret;
    865     gnutls_x509_crt_t cert;
     982    union {
     983      gnutls_x509_crt_t x509;
     984      gnutls_openpgp_crt_t pgp;
     985    } cert;
    866986    apr_time_t activation_time, expiration_time, cur_time;
    867987
     
    8891009    }
    8901010
    891     gnutls_x509_crt_init(&cert);
    892     rv = gnutls_x509_crt_import(cert, &cert_list[0], GNUTLS_X509_FMT_DER);
     1011    if (gnutls_certificate_type_get( ctxt->session) == GNUTLS_CRT_X509) {
     1012        gnutls_x509_crt_init(&cert.x509);
     1013        rv = gnutls_x509_crt_import(cert.x509, &cert_list[0], GNUTLS_X509_FMT_DER);
     1014    } else if (gnutls_certificate_type_get( ctxt->session) == GNUTLS_CRT_OPENPGP) {
     1015        gnutls_openpgp_crt_init(&cert.pgp);
     1016        rv = gnutls_openpgp_crt_import(cert.pgp, &cert_list[0], GNUTLS_OPENPGP_FMT_RAW);
     1017    } else return HTTP_FORBIDDEN;
     1018 
    8931019    if (rv < 0) {
    894         ap_log_rerror(APLOG_MARK, APLOG_INFO, 0, r,
     1020       ap_log_rerror(APLOG_MARK, APLOG_INFO, 0, r,
    8951021                      "GnuTLS: Failed to Verify Peer: "
    8961022                      "Failed to import peer certificates.");
    897         ret = HTTP_FORBIDDEN;
    898         goto exit;
    899     }
    900 
    901     apr_time_ansi_put(&expiration_time,
    902                       gnutls_x509_crt_get_expiration_time(cert));
    903     apr_time_ansi_put(&activation_time,
    904                       gnutls_x509_crt_get_activation_time(cert));
    905 
    906     rv = gnutls_x509_crt_verify(cert, ctxt->sc->ca_list,
     1023       ret = HTTP_FORBIDDEN;
     1024       goto exit;
     1025    }
     1026
     1027    if (gnutls_certificate_type_get( ctxt->session) == GNUTLS_CRT_X509) {
     1028        apr_time_ansi_put(&expiration_time,
     1029                      gnutls_x509_crt_get_expiration_time(cert.x509));
     1030        apr_time_ansi_put(&activation_time,
     1031                      gnutls_x509_crt_get_activation_time(cert.x509));
     1032
     1033        rv = gnutls_x509_crt_verify(cert.x509, ctxt->sc->ca_list,
    9071034                                ctxt->sc->ca_list_size, 0, &status);
     1035    } else {
     1036        apr_time_ansi_put(&expiration_time,
     1037                      gnutls_openpgp_crt_get_expiration_time(cert.pgp));
     1038        apr_time_ansi_put(&activation_time,
     1039                      gnutls_openpgp_crt_get_creation_time(cert.pgp));
     1040
     1041        rv = gnutls_openpgp_crt_verify_ring(cert.pgp, ctxt->sc->pgp_list,
     1042                      0, &status);
     1043    }
     1044
    9081045
    9091046    if (rv < 0) {
     
    9581095//    rv = mgs_authz_lua(r);
    9591096
    960     mgs_add_common_cert_vars(r, cert, 1,
     1097    if (gnutls_certificate_type_get( ctxt->session) == GNUTLS_CRT_X509)
     1098        mgs_add_common_cert_vars(r, cert.x509, 1,
     1099                             ctxt->sc->export_certificates_enabled);
     1100    else if (gnutls_certificate_type_get( ctxt->session) == GNUTLS_CRT_OPENPGP)
     1101        mgs_add_common_pgpcert_vars(r, cert.pgp, 1,
    9611102                             ctxt->sc->export_certificates_enabled);
    9621103
     
    9821123
    9831124  exit:
    984     gnutls_x509_crt_deinit(cert);
     1125    if (gnutls_certificate_type_get( ctxt->session) == GNUTLS_CRT_X509)
     1126        gnutls_x509_crt_deinit(cert.x509);
     1127    else if (gnutls_certificate_type_get( ctxt->session) == GNUTLS_CRT_OPENPGP)
     1128        gnutls_openpgp_crt_deinit(cert.pgp);
    9851129    return ret;
    9861130
Note: See TracChangeset for help on using the changeset viewer.