# 3) uncomment the line below.
# 5) Restart radiusd
# check_crl = yes
- # CA_path = /path/to/directory/with/ca_certs/and/crls/
+ CA_path = ${cadir}
#
# If check_cert_issuer is set, the value will
#
max_entries = 255
}
+
+ #
+ # As of version 2.1.10, client certificates can be
+ # validated via an external command. This allows
+ # dynamic CRLs or OCSP to be used.
+ #
+ # This configuration is commented out in the
+ # default configuration. Uncomment it, and configure
+ # the correct paths below to enable it.
+ #
+ verify {
+ # A temporary directory where the client
+ # certificates are stored. This directory
+ # MUST be owned by the UID of the server,
+ # and MUST not be accessible by any other
+ # users. When the server starts, it will do
+ # "chmod go-rwx" on the directory, for
+ # security reasons. The directory MUST
+ # exist when the server starts.
+ #
+ # You should also delete all of the files
+ # in the directory when the server starts.
+ # tmpdir = /tmp/radiusd
+
+ # The command used to verify the client cert.
+ # We recommend using the OpenSSL command-line
+ # tool.
+ #
+ # The ${..CA_path} text is a reference to
+ # the CA_path variable defined above.
+ #
+ # The %{TLS-Client-Cert-Filename} is the name
+ # of the temporary file containing the cert
+ # in PEM format. This file is automatically
+ # deleted by the server when the command
+ # returns.
+ # client = "/path/to/openssl verify -CApath ${..CA_path} %{TLS-Client-Cert-Filename}"
+ }
}
# The TTLS module implements the EAP-TTLS protocol,
{ NULL, -1, 0, NULL, NULL } /* end the list */
};
+static CONF_PARSER verify_config[] = {
+ { "tmpdir", PW_TYPE_STRING_PTR,
+ offsetof(EAP_TLS_CONF, verify_tmp_dir), NULL, NULL},
+ { "client", PW_TYPE_STRING_PTR,
+ offsetof(EAP_TLS_CONF, verify_client_cert_cmd), NULL, NULL},
+ { NULL, -1, 0, NULL, NULL } /* end the list */
+};
+
static CONF_PARSER module_config[] = {
{ "rsa_key_exchange", PW_TYPE_BOOLEAN,
offsetof(EAP_TLS_CONF, rsa_key), NULL, "no" },
{ "cache", PW_TYPE_SUBSECTION, 0, NULL, (const void *) cache_config },
+ { "verify", PW_TYPE_SUBSECTION, 0, NULL, (const void *) verify_config },
+
{ NULL, -1, 0, NULL, NULL } /* end the list */
};
}
}
} /* check_cert_cn */
+
+ while (conf->verify_client_cert_cmd) {
+ char filename[256];
+ FILE *fp;
+
+ snprintf(filename, sizeof(filename), "%s/%s.client.XXXXXXXX",
+ conf->verify_tmp_dir, progname);
+ if (mkstemp(filename) < 0) {
+ RDEBUG("Failed creating file in %s: %s",
+ conf->verify_tmp_dir, strerror(errno));
+ break;
+ }
+
+ fp = fopen(filename, "w");
+ if (!fp) {
+ RDEBUG("Failed opening file %s: %s",
+ filename, strerror(errno));
+ break;
+ }
+
+ if (!PEM_write_X509(fp, client_cert)) {
+ fclose(fp);
+ RDEBUG("Failed writing certificate to file");
+ goto do_unlink;
+ }
+ fclose(fp);
+
+ if (!radius_pairmake(request, &request->packet->vps,
+ "TLS-Client-Cert-Filename",
+ filename, T_OP_SET)) {
+ RDEBUG("Failed creating TLS-Client-Cert-Filename");
+
+ goto do_unlink;
+ }
+
+ RDEBUG("Verifying client certificate: %s",
+ conf->verify_client_cert_cmd);
+ if (radius_exec_program(conf->verify_client_cert_cmd,
+ request, 1, NULL, 0,
+ request->packet->vps,
+ NULL, 1) != 0) {
+ radlog(L_AUTH, "rlm_eap_tls: Certificate CN (%s) fails external verification!", common_name);
+ my_ok = 0;
+ } else {
+ RDEBUG("Client certificate CN %s passed external validation", common_name);
+ }
+
+ do_unlink:
+ unlink(filename);
+ break;
+ }
+
+
} /* depth == 0 */
if (debug_flag > 0) {
}
if (generate_eph_rsa_key(inst->ctx) < 0) {
+ eaptls_detach(inst);
return -1;
}
+ if (conf->verify_tmp_dir) {
+ char filename[256];
+
+ if (chmod(conf->verify_tmp_dir, S_IRWXU) < 0) {
+ radlog(L_ERR, "rlm_eap_tls: Failed changing permissions on %s: %s", conf->verify_tmp_dir, strerror(errno));
+ eaptls_detach(inst);
+ return -1;
+ }
+ }
+
+ if (conf->verify_client_cert_cmd && !conf->verify_tmp_dir) {
+ radlog(L_ERR, "rlm_eap_tls: You MUST set the verify directory in order to use verify_client_cmd");
+ eaptls_detach(inst);
+ return -1;
+ }
+
*instance = inst;
return 0;