Add check_cert_issuer config option to rlm_eap_tls.
authoraland <aland>
Fri, 28 Apr 2006 18:18:58 +0000 (18:18 +0000)
committeraland <aland>
Fri, 28 Apr 2006 18:18:58 +0000 (18:18 +0000)
This closes bug #346

src/modules/rlm_eap/types/rlm_eap_tls/rlm_eap_tls.c
src/modules/rlm_eap/types/rlm_eap_tls/rlm_eap_tls.h

index 9fd8afd..07a1a07 100644 (file)
@@ -64,6 +64,8 @@ static CONF_PARSER module_config[] = {
          offsetof(EAP_TLS_CONF, check_crl), NULL, "no"},
        { "check_cert_cn", PW_TYPE_STRING_PTR,
          offsetof(EAP_TLS_CONF, check_cert_cn), NULL, NULL},
+       { "check_cert_issuer", PW_TYPE_STRING_PTR,
+         offsetof(EAP_TLS_CONF, check_cert_issuer), NULL, NULL},
 
        { NULL, -1, 0, NULL, NULL }           /* end the list */
 };
@@ -140,10 +142,10 @@ static int generate_eph_rsa_key(SSL_CTX *ctx)
  */
 static int cbtls_verify(int ok, X509_STORE_CTX *ctx)
 {
-       char subject[256]; /* Used for the subject name */
-       char issuer[256]; /* Used for the issuer name */
-       char buf[256];
-       char cn_str[256];
+       char subject[1024]; /* Used for the subject name */
+       char issuer[1024]; /* Used for the issuer name */
+       char common_name[1024];
+       char cn_str[1024];
        EAP_HANDLER *handler = NULL;
        X509 *client_cert;
        SSL *ssl;
@@ -160,9 +162,6 @@ static int cbtls_verify(int ok, X509_STORE_CTX *ctx)
                        X509_verify_cert_error_string(err));
                return my_ok;
        }
-       /*
-        *      Catch too long Certificate chains
-        */
 
        /*
         * Retrieve the pointer to the SSL of the connection currently treated
@@ -176,14 +175,20 @@ static int cbtls_verify(int ok, X509_STORE_CTX *ctx)
         *      Get the Subject & Issuer
         */
        subject[0] = issuer[0] = '\0';
-       X509_NAME_oneline(X509_get_subject_name(client_cert), subject, 256);
-       X509_NAME_oneline(X509_get_issuer_name(ctx->current_cert), issuer, 256);
+       X509_NAME_oneline(X509_get_subject_name(client_cert), subject,
+                         sizeof(subject));
+       X509_NAME_oneline(X509_get_issuer_name(ctx->current_cert), issuer,
+                         sizeof(issuer));
+
+       subject[sizeof(subject) - 1] = '\0';
+       issuer[sizeof(issuer) - 1] = '\0';
 
        /*
         *      Get the Common Name
         */
        X509_NAME_get_text_by_NID(X509_get_subject_name(client_cert),
-             NID_commonName, buf, 256);
+                                 NID_commonName, common_name, sizeof(common_name));
+       common_name[sizeof(common_name) - 1] = '\0';
 
        switch (ctx->error) {
 
@@ -207,35 +212,48 @@ static int cbtls_verify(int ok, X509_STORE_CTX *ctx)
        }
 
        /*
-        *      If we're at the actual client cert and the conf tells
-        *      us to, check the CN in the cert against the xlat'ed
-        *      value
+        *      If we're at the actual client cert, apply additional
+        *      checks.
         */
-       if (depth == 0 && conf->check_cert_cn != NULL) {
-               if (!radius_xlat(cn_str, sizeof(cn_str), conf->check_cert_cn, handler->request, NULL)) {
-                       radlog(L_ERR, "rlm_eap_tls (%s): xlat failed.",
-                               conf->check_cert_cn);
-                       /* if this fails, fail the verification */
-                       my_ok = 0;
-               }
-               DEBUG2("    rlm_eap_tls: checking certificate CN (%s) with xlat'ed value (%s)", buf, cn_str);
-               if (strncmp(cn_str, buf, sizeof(buf)) != 0) {
-                       my_ok = 0;
-                       radlog(L_AUTH, "rlm_eap_tls: Certificate CN (%s) does not match specified value (%s)!", buf, cn_str);
-               }
-       }
+       if (depth == 0) {
+               /*
+                *      If the conf tells us to, check cert issuer
+                *      against the specified value and fail
+                *      verification if they don't match.
+                */
+               if (conf->check_cert_issuer && 
+                   (strcmp(issuer, conf->check_cert_issuer) != 0)) {
+                       radlog(L_AUTH, "rlm_eap_tls: Certificate issuer (%s) does not match specified value (%s)!", issuer, conf->check_cert_issuer);
+                       my_ok = 0;
+               }
+
+               /*
+                *      If the conf tells us to, check the CN in the
+                *      cert against xlat'ed value, but only if the
+                *      previous checks passed.
+                */
+               if (my_ok && conf->check_cert_cn) {
+                       if (!radius_xlat(cn_str, sizeof(cn_str), conf->check_cert_cn, handler->request, NULL)) {
+                               radlog(L_ERR, "rlm_eap_tls (%s): xlat failed.",
+                                      conf->check_cert_cn);
+                               /* if this fails, fail the verification */
+                               my_ok = 0;
+                       } else {
+                               DEBUG2("    rlm_eap_tls: checking certificate CN (%s) with xlat'ed value (%s)", common_name, cn_str);
+                               if (strcmp(cn_str, common_name) != 0) {
+                                       radlog(L_AUTH, "rlm_eap_tls: Certificate CN (%s) does not match specified value (%s)!", common_name, cn_str);
+                                       my_ok = 0;
+                               }
+                       }
+               } /* check_cert_cn */
+       } /* depth == 0 */
 
        if (debug_flag > 0) {
                radlog(L_INFO, "chain-depth=%d, ", depth);
-               /*
-                 if (depth > 0) {
-                 return ok;
-                 }
-               */
                radlog(L_INFO, "error=%d", err);
 
                radlog(L_INFO, "--> User-Name = %s", handler->identity);
-               radlog(L_INFO, "--> BUF-Name = %s", buf);
+               radlog(L_INFO, "--> BUF-Name = %s", common_name);
                radlog(L_INFO, "--> subject = %s", subject);
                radlog(L_INFO, "--> issuer  = %s", issuer);
                radlog(L_INFO, "--> verify return:%d", my_ok);
index 2f10b30..52f3ef2 100644 (file)
@@ -53,6 +53,7 @@ typedef struct eap_tls_conf {
        int             check_crl;
        char            *check_cert_cn;
        char            *cipher_list;
+       char            *check_cert_issuer;
 } EAP_TLS_CONF;
 
 /* This structure gets stored in arg */