Update the GPL boilerplate with the new address of the FSF.
[freeradius.git] / src / modules / rlm_eap / types / rlm_eap_tls / rlm_eap_tls.c
index d861af2..3d6216b 100644 (file)
  *
  *   You should have received a copy of the GNU General Public License
  *   along with this program; if not, write to the Free Software
- *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
  *
  * Copyright 2001  hereUare Communications, Inc. <raghud@hereuare.com>
  * Copyright 2003  Alan DeKok <aland@freeradius.org>
  */
 
-#include "autoconf.h"
+#include <freeradius-devel/autoconf.h>
 #include "eap_tls.h"
 
 #ifdef HAVE_OPENSSL_RAND_H
@@ -39,15 +39,15 @@ static CONF_PARSER module_config[] = {
          offsetof(EAP_TLS_CONF, dh_key_length), NULL, "512" },
        { "verify_depth", PW_TYPE_INTEGER,
          offsetof(EAP_TLS_CONF, verify_depth), NULL, "0" },
-       { "CA_path", PW_TYPE_STRING_PTR,
+       { "CA_path", PW_TYPE_FILENAME,
          offsetof(EAP_TLS_CONF, ca_path), NULL, NULL },
        { "pem_file_type", PW_TYPE_BOOLEAN,
          offsetof(EAP_TLS_CONF, file_type), NULL, "yes" },
-       { "private_key_file", PW_TYPE_STRING_PTR,
+       { "private_key_file", PW_TYPE_FILENAME,
          offsetof(EAP_TLS_CONF, private_key_file), NULL, NULL },
-       { "certificate_file", PW_TYPE_STRING_PTR,
+       { "certificate_file", PW_TYPE_FILENAME,
          offsetof(EAP_TLS_CONF, certificate_file), NULL, NULL },
-       { "CA_file", PW_TYPE_STRING_PTR,
+       { "CA_file", PW_TYPE_FILENAME,
          offsetof(EAP_TLS_CONF, ca_file), NULL, NULL },
        { "private_key_password", PW_TYPE_STRING_PTR,
          offsetof(EAP_TLS_CONF, private_key_password), NULL, NULL },
@@ -61,6 +61,8 @@ static CONF_PARSER module_config[] = {
          offsetof(EAP_TLS_CONF, include_length), NULL, "yes" },
        { "check_crl", PW_TYPE_BOOLEAN,
          offsetof(EAP_TLS_CONF, check_crl), NULL, "no"},
+       { "check_cert_cn", PW_TYPE_STRING_PTR,
+         offsetof(EAP_TLS_CONF, check_cert_cn), NULL, NULL},
 
        { NULL, -1, 0, NULL, NULL }           /* end the list */
 };
@@ -145,16 +147,7 @@ static SSL_CTX *init_tls_ctx(EAP_TLS_CONF *conf)
                type = SSL_FILETYPE_ASN1;
        }
 
-       /* Load the CAs we trust */
-       if (!(SSL_CTX_load_verify_locations(ctx, conf->ca_file, conf->ca_path)) ||
-           (!SSL_CTX_set_default_verify_paths(ctx))) {
-               ERR_print_errors_fp(stderr);
-               radlog(L_ERR, "rlm_eap_tls: Error reading Trusted root CA list");
-               return NULL;
-       }
-       SSL_CTX_set_client_CA_list(ctx, SSL_load_client_CA_file(conf->ca_file));
-
-       /* 
+       /*
         * Set the password to load private key
         */
        if (conf->private_key_password) {
@@ -162,13 +155,38 @@ static SSL_CTX *init_tls_ctx(EAP_TLS_CONF *conf)
                SSL_CTX_set_default_passwd_cb(ctx, cbtls_password);
        }
 
-       /* Load our keys and certificates*/
-       if (!(SSL_CTX_use_certificate_file(ctx, conf->certificate_file, type))) {
+       /*
+        *      Load our keys and certificates
+        *
+        *      If certificates are of type PEM then we can make use
+        *      of cert chain authentication using openssl api call
+        *      SSL_CTX_use_certificate_chain_file.  Please see how
+        *      the cert chain needs to be given in PEM from
+        *      openSSL.org
+        */
+       if (type == SSL_FILETYPE_PEM) {
+               radlog(L_INFO, "rlm_eap_tls: Loading the certificate file as a chain");
+               if (!(SSL_CTX_use_certificate_chain_file(ctx, conf->certificate_file))) {
+                       ERR_print_errors_fp(stderr);
+                       radlog(L_ERR, "rlm_eap_tls: Error reading certificate file");
+                       return NULL;
+               }
+
+       } else if (!(SSL_CTX_use_certificate_file(ctx, conf->certificate_file, type))) {
                ERR_print_errors_fp(stderr);
                radlog(L_ERR, "rlm_eap_tls: Error reading certificate file");
                return NULL;
        }
 
+
+       /* Load the CAs we trust */
+       if (!SSL_CTX_load_verify_locations(ctx, conf->ca_file, conf->ca_path)) {
+               ERR_print_errors_fp(stderr);
+               radlog(L_ERR, "rlm_eap_tls: Error reading Trusted root CA list");
+               return NULL;
+       }
+       SSL_CTX_set_client_CA_list(ctx, SSL_load_client_CA_file(conf->ca_file));
+
        if (!(SSL_CTX_use_PrivateKey_file(ctx, conf->private_key_file, type))) {
                ERR_print_errors_fp(stderr);
                radlog(L_ERR, "rlm_eap_tls: Error reading private key file");
@@ -189,7 +207,7 @@ static SSL_CTX *init_tls_ctx(EAP_TLS_CONF *conf)
        ctx_options |= SSL_OP_NO_SSLv2;
        ctx_options |= SSL_OP_NO_SSLv3;
 
-       /* 
+       /*
         *      SSL_OP_SINGLE_DH_USE must be used in order to prevent
         *      small subgroup attacks and forward secrecy. Always
         *      using
@@ -279,7 +297,7 @@ static int eaptls_detach(void *arg)
                conf->private_key_password = NULL;
                if (conf->random_file) free(conf->random_file);
                conf->random_file = NULL;
-               
+
                free(inst->conf);
                inst->conf = NULL;
        }
@@ -415,7 +433,8 @@ static int eaptls_initiate(void *type_arg, EAP_HANDLER *handler)
         *      NOTE: If we want to set each item sepearately then
         *      this index should be global.
         */
-       SSL_set_ex_data(ssn->ssl, 0, (void *)handler->identity);
+       SSL_set_ex_data(ssn->ssl, 0, (void *)handler);
+       SSL_set_ex_data(ssn->ssl, 1, (void *)inst->conf);
 
        ssn->length_flag = inst->conf->include_length;
 
@@ -508,6 +527,25 @@ static int eaptls_authenticate(void *arg UNUSED, EAP_HANDLER *handler)
                 */
        case EAPTLS_OK:
                DEBUG2("  rlm_eap_tls: Received unexpected tunneled data after successful handshake.");
+#ifndef NDEBUG
+               if (debug_flag > 2) {
+                       unsigned int i;
+                       unsigned int data_len;
+                       unsigned char buffer[1024];
+
+                       data_len = (tls_session->record_minus)(&tls_session->dirty_in,
+                                               buffer, sizeof(buffer));
+                       log_debug("  Tunneled data (%u bytes)\n", data_len);
+                       for (i = 0; i < data_len; i++) {
+                               if ((i & 0x0f) == 0x00) printf("  %x: ", i);
+                               if ((i & 0x0f) == 0x0f) printf("\n");
+
+                               printf("%02x ", buffer[i]);
+                       }
+                       printf("\n");
+               }
+#endif
+
                eaptls_fail(handler->eap_ds, 0);
                return 0;
                break;
@@ -523,7 +561,7 @@ static int eaptls_authenticate(void *arg UNUSED, EAP_HANDLER *handler)
         *      Success: Return MPPE keys.
         */
        eaptls_success(handler->eap_ds, 0);
-       eaptls_gen_mppe_keys(&handler->request->reply->vps, 
+       eaptls_gen_mppe_keys(&handler->request->reply->vps,
                             tls_session->ssl,
                             "client EAP encryption");
        return 1;