Changeset e924ddd in mod_gnutls


Ignore:
Timestamp:
Apr 21, 2005, 8:26:57 PM (15 years ago)
Author:
Paul Querna <chip@…>
Branches:
debian/master, debian/stretch-backports, jessie-backports, master, msva, upstream
Children:
316bd8c
Parents:
31645b2
Message:

client auth is sort of working.

Files:
3 edited

Legend:

Unmodified
Added
Removed
  • include/mod_gnutls.h.in

    r31645b2 re924ddd  
    7272typedef struct
    7373{
    74     gnutls_certificate_request_t client_verify_mode;
     74    int client_verify_mode;
    7575} mod_gnutls_dirconf_rec;
    7676
     
    7878{
    7979    gnutls_certificate_credentials_t certs;
     80    char* cert_cn;
    8081    gnutls_x509_crt_t cert_x509;
    8182    gnutls_x509_privkey_t privkey_x509;
     
    9293    const char* rsa_params_file;
    9394    const char* dh_params_file;
    94     gnutls_certificate_request_t client_verify_mode;
     95    int client_verify_mode;
    9596} mod_gnutls_srvconf_rec;
    9697
     
    180181
    181182
     183int mod_gnutls_rehandshake(mod_gnutls_handle_t * ctxt);
     184
     185
     186
    182187/**
    183188 * Init the Cache after Configuration is done
  • src/gnutls_io.c

    r31645b2 re924ddd  
    359359    int errcode;
    360360    if (ctxt->status != 0) {
    361         return 0;
     361        return -1;
    362362    }
    363363
    364364tryagain:
    365 
    366     ret = gnutls_handshake(ctxt->session);
     365    do {
     366        ret = gnutls_handshake(ctxt->session);
     367    } while (ret == GNUTLS_E_AGAIN);
     368   
    367369    if (ret < 0) {
    368370        if (ret == GNUTLS_E_WARNING_ALERT_RECEIVED
     
    393395        /* all done with the handshake */
    394396        ctxt->status = 1;
    395         return ret;
     397        return 0;
    396398    }
    397399}
     
    412414    ctxt->status = 0;
    413415
    414     gnutls_do_handshake(ctxt);
    415    
    416     if (ctxt->status == 1) {
    417         return 0;
    418     }
    419     else {
    420         return -1;
    421     }
     416    rv = gnutls_do_handshake(ctxt);
     417
     418    return rv;
    422419}
    423420
  • src/mod_gnutls.c

    r31645b2 re924ddd  
    1717
    1818#include "mod_gnutls.h"
     19#include "http_vhost.h"
    1920
    2021extern server_rec *ap_server_conf;
     
    112113{
    113114    int rv;
     115    int data_len;
    114116    server_rec *s;
    115117    gnutls_dh_params_t dh_params;
     
    216218                exit(-1);
    217219            }
    218             {
    219                 int rv;
    220                 int data_len = 255;
    221                 char crt_name[255];
    222                 for (rv = 0; rv < data_len; rv++) {
    223                     crt_name[rv] = '\0';
    224                 }
    225                 rv = gnutls_x509_crt_get_dn_by_oid(sc->cert_x509,
    226                                                    GNUTLS_OID_X520_COMMON_NAME, 0, 0,
    227                                                    crt_name, &data_len);
    228                
     220           
     221            rv = gnutls_x509_crt_get_dn_by_oid(sc->cert_x509,
     222                                               GNUTLS_OID_X520_COMMON_NAME, 0, 0,
     223                                               NULL, &data_len);
     224           
     225            if (data_len < 1) {
     226                sc->enabled = GNUTLS_ENABLED_FALSE;
     227                sc->cert_cn = NULL;
     228                continue;
     229            }
     230           
     231            sc->cert_cn = apr_palloc(p, data_len);
     232            rv = gnutls_x509_crt_get_dn_by_oid(sc->cert_x509,
     233                                               GNUTLS_OID_X520_COMMON_NAME, 0, 0,
     234                                               sc->cert_cn, &data_len);
    229235            ap_log_error(APLOG_MARK, APLOG_DEBUG, 0,
    230236                         s,
    231                          "GnuTLS: sni-x509 cn: %s/%d pk: %s s: 0x%08X sc: 0x%08X", crt_name, rv,
     237                         "GnuTLS: sni-x509 cn: %s/%d pk: %s s: 0x%08X sc: 0x%08X", sc->cert_cn, rv,
    232238                         gnutls_pk_algorithm_get_name(gnutls_x509_privkey_get_pk_algorithm(sc->privkey_x509)),
    233239                         (unsigned int)s, (unsigned int)sc);
    234             }
    235240        }
    236241    }
     
    288293}
    289294
     295static void mod_gnutls_changed_servers(mod_gnutls_handle_t *ctxt)
     296{
     297    gnutls_credentials_set(ctxt->session, GNUTLS_CRD_CERTIFICATE, ctxt->sc->certs);
     298    gnutls_certificate_server_set_request(ctxt->session, ctxt->sc->client_verify_mode);
     299}
     300
    290301#define MAX_HOST_LEN 255
     302
     303#if USING_2_1_RECENT
     304typedef struct
     305{
     306    mod_gnutls_handle_t *ctxt;
     307    gnutls_retr_st* ret;
     308    const char* sni_name;
     309} vhost_cb_rec;
     310
     311int vhost_cb (void* baton, conn_rec* conn, server_rec* s)
     312{
     313    mod_gnutls_srvconf_rec *tsc;
     314    vhost_cb_rec* x = baton;
     315
     316    tsc = (mod_gnutls_srvconf_rec *) ap_get_module_config(s->module_config,
     317                                                          &gnutls_module);
     318   
     319    if (tsc->enabled != GNUTLS_ENABLED_TRUE || tsc->cert_cn == NULL) {
     320        return 0;
     321    }
     322   
     323    /* The CN can contain a * -- this will match those too. */
     324    if (ap_strcasecmp_match(x->sni_name, tsc->cert_cn) == 0) {
     325        /* found a match */
     326        x->ret->cert.x509 = &tsc->cert_x509;
     327        x->ret->key.x509 = tsc->privkey_x509;
     328#if MOD_GNUTLS_DEBUG
     329        ap_log_error(APLOG_MARK, APLOG_DEBUG, 0,
     330                     x->ctxt->c->base_server,
     331                     "GnuTLS: Virtual Host CB: "
     332                     "'%s' == '%s'", tsc->cert_cn, x->sni_name);
     333#endif
     334        /* Because we actually change the server used here, we need to reset
     335         * things like ClientVerify.
     336         */
     337        x->ctxt->sc = tsc;
     338        mod_gnutls_changed_servers(x->ctxt);
     339        return 1;
     340    }
     341    return 0;
     342}
     343#endif
     344
    291345static int cert_retrieve_fn(gnutls_session_t session, gnutls_retr_st* ret)
    292346{
     
    295349    int data_len = MAX_HOST_LEN;
    296350    char sni_name[MAX_HOST_LEN];
    297     char crt_name[MAX_HOST_LEN];
    298351    mod_gnutls_handle_t *ctxt;
    299     mod_gnutls_srvconf_rec *tsc;
     352#if USING_2_1_RECENT
     353    vhost_cb_rec cbx;
     354#else
    300355    server_rec* s;
     356    mod_gnutls_srvconf_rec *tsc;   
     357#endif
    301358   
    302359    ctxt = gnutls_transport_get_ptr(session);
     
    334391     * for this IP/Port combo.  Trust that the core did the 'right' thing.
    335392     */
     393#if USING_2_1_RECENT
     394    cbx.ctxt = ctxt;
     395    cbx.ret = ret;
     396    cbx.sni_name = sni_name;
     397
     398    rv = ap_vhost_iterate_given_conn(ctxt->c, vhost_cb, &cbx);
     399    if (rv == 1) {
     400        return 0;
     401    }
     402#else
    336403    for (s = ap_server_conf; s; s = s->next) {
    337404       
     
    341408            continue;
    342409        }
    343        
    344         data_len = MAX_HOST_LEN;
    345         rv = gnutls_x509_crt_get_dn_by_oid(tsc->cert_x509,
    346                                            GNUTLS_OID_X520_COMMON_NAME, 0, 0,
    347                                            crt_name, &data_len);
     410#if MOD_GNUTLS_DEBUG
    348411        ap_log_error(APLOG_MARK, APLOG_DEBUG, 0,
    349412                     ctxt->c->base_server,
    350                      "GnuTLS: sni-x509 cn: %s/%d pk: %s s: 0x%08X s->n: 0x%08X  sc: 0x%08X", crt_name, rv,
     413                     "GnuTLS: sni-x509 cn: %s/%d pk: %s s: 0x%08X s->n: 0x%08X  sc: 0x%08X", tsc->cert_cn, rv,
    351414                     gnutls_pk_algorithm_get_name(gnutls_x509_privkey_get_pk_algorithm(ctxt->sc->privkey_x509)),
    352415                     (unsigned int)s, (unsigned int)s->next, (unsigned int)tsc);
    353 
    354         if (rv != 0) {
    355             continue;
    356         }
    357            
     416#endif           
    358417        /* The CN can contain a * -- this will match those too. */
    359         if (ap_strcasecmp_match(sni_name, crt_name) == 0) {
     418        if (ap_strcasecmp_match(sni_name, tsc->cert_cn) == 0) {
    360419            /* found a match */
    361420            ret->cert.x509 = &tsc->cert_x509;
     
    365424                         ctxt->c->base_server,
    366425                         "GnuTLS: Virtual Host: "
    367                          "'%s' == '%s'", crt_name, sni_name);
    368 #endif
     426                         "'%s' == '%s'", tsc->cert_cn, sni_name);
     427#endif
     428            ctxt->sc = tsc;
     429            mod_gnutls_changed_servers(ctxt);
    369430            return 0;
    370431        }
    371432    }
    372 
     433#endif
    373434   
    374435    /**
     
    377438     */
    378439use_default_crt:
    379     data_len = MAX_HOST_LEN;
    380     rv = gnutls_x509_crt_get_dn_by_oid(ctxt->sc->cert_x509,
    381                                   GNUTLS_OID_X520_COMMON_NAME, 0, 0,
    382                                   crt_name, &data_len);
    383        
    384     ap_log_error(APLOG_MARK, APLOG_DEBUG, 0,
    385                      ctxt->c->base_server,
    386                      "GnuTLS: x509 cn: %s/%d pk: %s", crt_name, rv,
    387                  gnutls_pk_algorithm_get_name(gnutls_x509_privkey_get_pk_algorithm(ctxt->sc->privkey_x509)));
    388    
    389440    ret->cert.x509 = &ctxt->sc->cert_x509;
    390441    ret->key.x509 = ctxt->sc->privkey_x509;
     
    428479    gnutls_certificate_type_set_priority(ctxt->session, sc->cert_types);
    429480
    430     gnutls_credentials_set(ctxt->session, GNUTLS_CRD_CERTIFICATE, sc->certs);
    431 
    432     gnutls_certificate_server_set_request(ctxt->session, sc->client_verify_mode);
    433 
    434481    mod_gnutls_cache_session_init(ctxt);
    435482
    436     /* TODO: Finish Support for Server Name Indication */
    437483    gnutls_certificate_server_set_retrieve_function(sc->certs, cert_retrieve_fn);
     484
     485    mod_gnutls_changed_servers(ctxt);
    438486    return ctxt;
    439487}
     
    575623    }
    576624   
    577     //apr_pool_destroy(spool);
     625    apr_pool_destroy(spool);
    578626    return NULL;
    579627}
     
    606654                            gnutls_strerror(ret));
    607655    }
    608     //apr_pool_destroy(spool);
     656    apr_pool_destroy(spool);
    609657    return NULL;
    610658}
     
    674722                                            const char *arg)
    675723{
    676     gnutls_certificate_request_t mode;
    677 
    678     if (strcasecmp("none", arg) == 0  || strcasecmp("ignore", arg) == 0) {
     724    int mode;
     725
     726    if (strcasecmp("none", arg) == 0 || strcasecmp("ignore", arg) == 0) {
    679727        mode = GNUTLS_CERT_IGNORE;
    680728    }
     
    682730        mode = GNUTLS_CERT_REQUEST;
    683731    }
    684     else if (strcasecmp("optional", arg) == 0) {
     732    else if (strcasecmp("require", arg) == 0) {
    685733        mode = GNUTLS_CERT_REQUIRE;
    686734    }
     
    704752    return NULL;
    705753}
     754
     755static const char *gnutls_set_client_ca_file(cmd_parms * parms, void *dummy,
     756                                            const char *arg)
     757{
     758    int rv;
     759    const char* file;
     760    mod_gnutls_srvconf_rec *sc =
     761        (mod_gnutls_srvconf_rec *) ap_get_module_config(parms->server->
     762                                                        module_config,
     763                                                        &gnutls_module);       
     764    file = ap_server_root_relative(parms->pool, arg);
     765    rv = gnutls_certificate_set_x509_trust_file(sc->certs,
     766                                                file, GNUTLS_X509_FMT_PEM);
     767   
     768    if (rv < 0) {
     769        return apr_psprintf(parms->pool, "GnuTLS: Failed to load "
     770                            "Client CA File '%s': (%d) %s", file, rv,
     771                            gnutls_strerror(rv));   
     772    }
     773    return NULL;
     774}
     775
     776
    706777static const char *gnutls_set_enabled(cmd_parms * parms, void *dummy,
    707778                                      const char *arg)
     
    729800                  RSRC_CONF|OR_AUTHCFG,
    730801                  "Set Verification Requirements of the Client Certificate"),
     802    AP_INIT_TAKE1("GnuTLSClientCAFile", gnutls_set_client_ca_file,
     803                  NULL,
     804                  RSRC_CONF,
     805                  "Set the CA File for Client Certificates"),
    731806    AP_INIT_TAKE1("GnuTLSCertificateFile", gnutls_set_cert_file,
    732807                  NULL,
     
    752827};
    753828
    754 /* TODO: CACertificateFile & Client Authentication
    755  *    AP_INIT_TAKE1("GnuTLSCACertificateFile", ap_set_server_string_slot,
    756  *                 (void *) APR_OFFSETOF(gnutls_srvconf_rec, key_file), NULL,
    757  *                 RSRC_CONF,
    758  *                 "CA"),
    759  */
    760 
    761829int mod_gnutls_hook_authz(request_rec *r)
    762830{
    763     return OK;
    764 #if 0
     831    int rv;
     832    int status;
    765833    mod_gnutls_handle_t *ctxt;
    766834    mod_gnutls_dirconf_rec *dc = ap_get_module_config(r->per_dir_config,
     
    769837    ctxt = ap_get_module_config(r->connection->conn_config, &gnutls_module);
    770838
    771     if (dc->client_verify_mode == -1 ||
    772         dc->client_verify_mode == GNUTLS_CERT_IGNORE ||
    773         ctxt->sc->client_verify_mode > dc->client_verify_mode) {
     839    if (dc->client_verify_mode == GNUTLS_CERT_IGNORE) {
     840        ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r,
     841                      "GnuTLS: Ignoring Client Certificate!");
    774842        return DECLINED;
    775843    }
    776844
    777     gnutls_certificate_server_set_request(ctxt->session, dc->client_verify_mode);
    778     if (mod_gnutls_rehandshake(ctxt) != 0) {
     845    if (ctxt->sc->client_verify_mode < dc->client_verify_mode) {
     846        ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r,
     847                     "GnuTLS: Attempting to rehandshake with peer. %d %d",
     848                      ctxt->sc->client_verify_mode, dc->client_verify_mode);
     849       
     850        gnutls_certificate_server_set_request(ctxt->session,
     851                                              dc->client_verify_mode);
     852   
     853        if (mod_gnutls_rehandshake(ctxt) != 0) {
     854            return HTTP_FORBIDDEN;
     855        }
     856    }
     857    else if (ctxt->sc->client_verify_mode == GNUTLS_CERT_IGNORE) {
     858        ap_log_rerror(APLOG_MARK, APLOG_INFO, 0, r,
     859                      "GnuTLS: Peer is set to IGNORE");
     860        return DECLINED;
     861    }
     862   
     863    rv = gnutls_certificate_verify_peers2(ctxt->session, &status);
     864
     865    if (rv < 0) {
     866        ap_log_rerror(APLOG_MARK, APLOG_INFO, 0, r,
     867                     "GnuTLS: Failed to Verify Peer: (%d) %s",
     868                     rv, gnutls_strerror(rv));
    779869        return HTTP_FORBIDDEN;
    780870    }
    781 #endif   
     871   
     872    if (status < 0) {
     873        ap_log_rerror(APLOG_MARK, APLOG_INFO, 0, r,
     874                     "GnuTLS: Peer Status is invalid.");
     875        return HTTP_FORBIDDEN;
     876    }
     877   
     878    if (status & GNUTLS_CERT_SIGNER_NOT_FOUND) {
     879        ap_log_rerror(APLOG_MARK, APLOG_INFO, 0, r,
     880                     "GnuTLS: Could not find Signer for Peer Certificate");
     881    }
     882   
     883    if (status & GNUTLS_CERT_SIGNER_NOT_CA) {
     884        ap_log_rerror(APLOG_MARK, APLOG_INFO, 0, r,
     885                     "GnuTLS: Could not find CA for Peer Certificate");
     886    }
     887   
     888    if (status & GNUTLS_CERT_INVALID) {
     889        ap_log_rerror(APLOG_MARK, APLOG_INFO, 0, r,
     890                     "GnuTLS: Peer Certificate is invalid.");
     891        return HTTP_FORBIDDEN;
     892    }
     893    else if (status & GNUTLS_CERT_REVOKED) {
     894        ap_log_rerror(APLOG_MARK, APLOG_INFO, 0, r,
     895                     "GnuTLS: Peer Certificate is revoked.");
     896        return HTTP_FORBIDDEN;
     897    }
     898   
     899    /* TODO: OpenPGP Certificates */
     900    if (gnutls_certificate_type_get(ctxt->session) != GNUTLS_CRT_X509) {
     901        ap_log_rerror(APLOG_MARK, APLOG_CRIT, 0, r,
     902                     "GnuTLS: Only x509 is supported for client certificates");         
     903        return HTTP_FORBIDDEN;
     904    }
     905    /* TODO: Further Verification. */
     906    ap_log_rerror(APLOG_MARK, APLOG_CRIT, 0, r,
     907                 "GnuTLS: Verified Peer.");             
     908    return OK;
    782909}
    783910
     
    802929                       APR_HOOK_MIDDLE);
    803930   
    804     ap_hook_auth_checker(mod_gnutls_hook_authz, NULL, NULL, APR_HOOK_MIDDLE);
    805    
     931    ap_hook_access_checker(mod_gnutls_hook_authz, NULL, NULL, APR_HOOK_REALLY_FIRST);
     932
    806933    ap_hook_fixups(mod_gnutls_hook_fixups, NULL, NULL, APR_HOOK_REALLY_FIRST);
    807934
Note: See TracChangeset for help on using the changeset viewer.