Skip to content

Commit

Permalink
Add support for client cert auth when validating.
Browse files Browse the repository at this point in the history
The following directives were added:
    - CASClientCert - the client cert in PEM or DER format
    - CASClientKey - the client key in PEM or DER format
    - CASClientCertType - PEM or DER - the cert/key type

Configuration:
    CASClientCertType "PEM"
    CASClientCert /path/to/client/cert.pem
    CASClientKey /path/to/client/key.pem

The paths must point to valid files on startup. No checking is currently done to
ensure they exist when validating. This check could probably be added at some
point.

A key password directive could be added, but it seems kind of silly to me. Up
for debate.
  • Loading branch information
dhawes committed Nov 4, 2014
1 parent b68a2aa commit ae4b4f7
Show file tree
Hide file tree
Showing 2 changed files with 43 additions and 1 deletion.
35 changes: 35 additions & 0 deletions src/mod_auth_cas.c
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,9 @@ void *cas_create_server_config(apr_pool_t *pool, server_rec *svr)
c->CASDebug = CAS_DEFAULT_DEBUG;
c->CASValidateDepth = CAS_DEFAULT_VALIDATE_DEPTH;
c->CASCertificatePath = CAS_DEFAULT_CA_PATH;
c->CASClientCert = CAS_DEFAULT_CLIENT_CERT;
c->CASClientKey= CAS_DEFAULT_CLIENT_KEY;
c->CASClientCertType= CAS_DEFAULT_CLIENT_CERT_TYPE;
c->CASCookiePath = CAS_DEFAULT_COOKIE_PATH;
c->CASCookieEntropy = CAS_DEFAULT_COOKIE_ENTROPY;
c->CASTimeout = CAS_DEFAULT_COOKIE_TIMEOUT;
Expand Down Expand Up @@ -138,6 +141,9 @@ void *cas_merge_server_config(apr_pool_t *pool, void *BASE, void *ADD)
c->CASDebug = (add->CASDebug != CAS_DEFAULT_DEBUG ? add->CASDebug : base->CASDebug);
c->CASValidateDepth = (add->CASValidateDepth != CAS_DEFAULT_VALIDATE_DEPTH ? add->CASValidateDepth : base->CASValidateDepth);
c->CASCertificatePath = (apr_strnatcasecmp(add->CASCertificatePath,CAS_DEFAULT_CA_PATH) != 0 ? add->CASCertificatePath : base->CASCertificatePath);
c->CASClientCert = (add->CASClientCert != CAS_DEFAULT_CLIENT_CERT ? add->CASClientCert : base->CASClientCert);
c->CASClientKey = (add->CASClientKey != CAS_DEFAULT_CLIENT_KEY ? add->CASClientKey : base->CASClientKey);
c->CASClientCertType = (apr_strnatcasecmp(add->CASClientCertType,CAS_DEFAULT_CLIENT_CERT_TYPE) != 0 ? add->CASClientCertType: base->CASClientCertType);
c->CASCookiePath = (apr_strnatcasecmp(add->CASCookiePath, CAS_DEFAULT_COOKIE_PATH) != 0 ? add->CASCookiePath : base->CASCookiePath);
c->CASCookieEntropy = (add->CASCookieEntropy != CAS_DEFAULT_COOKIE_ENTROPY ? add->CASCookieEntropy : base->CASCookieEntropy);
c->CASTimeout = (add->CASTimeout != CAS_DEFAULT_COOKIE_TIMEOUT ? add->CASTimeout : base->CASTimeout);
Expand Down Expand Up @@ -281,6 +287,29 @@ const char *cfg_readCASParameter(cmd_parms *cmd, void *cfg, const char *value)
return(apr_psprintf(cmd->pool, "MOD_AUTH_CAS: Certificate Authority file '%s' is not a regular file or directory", value));
c->CASCertificatePath = apr_pstrdup(cmd->pool, value);
break;
case cmd_client_cert:
if(apr_stat(&f, value, APR_FINFO_TYPE, cmd->temp_pool) == APR_INCOMPLETE)
return(apr_psprintf(cmd->pool, "MOD_AUTH_CAS: Could not find Client Certificate file '%s'", value));

if(f.filetype != APR_REG)
return(apr_psprintf(cmd->pool, "MOD_AUTH_CAS: Client Certificate file '%s' is not a regular file", value));
c->CASClientCert = apr_pstrdup(cmd->pool, value);
break;
case cmd_client_key:
if(apr_stat(&f, value, APR_FINFO_TYPE, cmd->temp_pool) == APR_INCOMPLETE)
return(apr_psprintf(cmd->pool, "MOD_AUTH_CAS: Could not find Client Key file '%s'", value));

if(f.filetype != APR_REG)
return(apr_psprintf(cmd->pool, "MOD_AUTH_CAS: Client Key file '%s' is not a regular file", value));
c->CASClientKey = apr_pstrdup(cmd->pool, value);
break;
case cmd_client_cert_type:
if(apr_strnatcmp(value, "PEM") != 0 &&
apr_strnatcmp(value, "DER") != 0) {
return(apr_psprintf(cmd->pool, "MOD_AUTH_CAS: Client Cert Type '%s' is not 'PEM' or 'DER'", value));
}
c->CASClientCertType = apr_pstrdup(cmd->pool, value);
break;
case cmd_validate_depth:
i = atoi(value);
if(i > 0)
Expand Down Expand Up @@ -1770,6 +1799,9 @@ char *getResponseFromServer (request_rec *r, cas_cfg *c, char *ticket)
}

curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 2L);
curl_easy_setopt(curl, CURLOPT_SSLCERTTYPE, c->CASClientCertType);
curl_easy_setopt(curl, CURLOPT_SSLCERT, c->CASClientCert);
curl_easy_setopt(curl, CURLOPT_SSLKEY, c->CASClientKey);
curl_easy_setopt(curl, CURLOPT_USERAGENT, "mod_auth_cas 1.0.10");

if(c->CASValidateSAML == TRUE) {
Expand Down Expand Up @@ -2674,6 +2706,9 @@ const command_rec cas_cmds [] = {
/* ssl related options */
AP_INIT_TAKE1("CASValidateDepth", cfg_readCASParameter, (void *) cmd_validate_depth, RSRC_CONF, "Define the number of chained certificates required for a successful validation"),
AP_INIT_TAKE1("CASCertificatePath", cfg_readCASParameter, (void *) cmd_ca_path, RSRC_CONF, "Path to the X509 certificate for the CASServer Certificate Authority"),
AP_INIT_TAKE1("CASClientCert", cfg_readCASParameter, (void *) cmd_client_cert, RSRC_CONF, "Path to the X509 certificate for Client Authentication"),
AP_INIT_TAKE1("CASClientKey", cfg_readCASParameter, (void *) cmd_client_key, RSRC_CONF, "Path to the X509 key for Client Authentication"),
AP_INIT_TAKE1("CASClientCertType", cfg_readCASParameter, (void *) cmd_client_cert_type, RSRC_CONF, "The type of client SSL cert/key for Client Authentication"),

/* pertinent CAS urls */
AP_INIT_TAKE1("CASLoginURL", cfg_readCASParameter, (void *) cmd_loginurl, RSRC_CONF, "Define the CAS Login URL (ex: https://login.example.com/cas/login)"),
Expand Down
9 changes: 8 additions & 1 deletion src/mod_auth_cas.h
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,9 @@
#define CAS_DEFAULT_ATTRIBUTE_PREFIX "CAS_"
#define CAS_DEFAULT_VALIDATE_DEPTH 9
#define CAS_DEFAULT_CA_PATH "/etc/ssl/certs/"
#define CAS_DEFAULT_CLIENT_CERT NULL
#define CAS_DEFAULT_CLIENT_KEY NULL
#define CAS_DEFAULT_CLIENT_CERT_TYPE "PEM"
#define CAS_DEFAULT_COOKIE_PATH "/dev/null"
#define CAS_DEFAULT_LOGIN_URL NULL
#define CAS_DEFAULT_VALIDATE_V1_URL NULL
Expand Down Expand Up @@ -121,6 +124,9 @@ typedef struct cas_cfg {
unsigned int CASAuthoritative;
unsigned int CASValidateSAML;
char *CASCertificatePath;
char *CASClientCert;
char *CASClientKey;
char *CASClientCertType;
char *CASCookiePath;
char *CASCookieDomain;
char *CASAttributeDelimiter;
Expand Down Expand Up @@ -163,7 +169,8 @@ typedef enum {
cmd_loginurl, cmd_validateurl, cmd_proxyurl, cmd_cookie_entropy, cmd_session_timeout,
cmd_idle_timeout, cmd_cache_interval, cmd_cookie_domain, cmd_cookie_httponly,
cmd_sso, cmd_validate_saml, cmd_attribute_delimiter, cmd_attribute_prefix,
cmd_root_proxied_as, cmd_authoritative
cmd_root_proxied_as, cmd_authoritative, cmd_client_cert, cmd_client_key,
cmd_client_cert_type
} valid_cmds;

module AP_MODULE_DECLARE_DATA auth_cas_module;
Expand Down

0 comments on commit ae4b4f7

Please sign in to comment.