2 * version 1.1.1, released 2007-10-01
3 * Anders Kaseorg <andersk@mit.edu>
5 * This module does authentication based on SSL client certificates:
7 * AuthSSLCertVar SSL_CLIENT_S_DN_Email
8 * AuthSSLCertStripSuffix "@MIT.EDU"
11 #include "apr_strings.h"
12 #define APR_WANT_STRFUNC /* for strcasecmp */
15 #include "ap_config.h"
17 #include "http_config.h"
18 #include "http_core.h"
20 #include "http_request.h"
25 static APR_OPTIONAL_FN_TYPE(ssl_var_lookup) *ssl_var_lookup;
31 int strip_suffix_required;
32 } auth_sslcert_config_rec;
34 static void *create_auth_sslcert_dir_config(apr_pool_t *p, char *dirspec)
36 auth_sslcert_config_rec *conf = apr_pcalloc(p, sizeof(*conf));
38 conf->authoritative = -1;
40 conf->strip_suffix = NULL;
41 conf->strip_suffix_required = -1;
46 static void *merge_auth_sslcert_dir_config(apr_pool_t *p, void *parent_conf, void *newloc_conf)
48 auth_sslcert_config_rec *pconf = parent_conf, *nconf = newloc_conf,
49 *conf = apr_pcalloc(p, sizeof(*conf));
51 conf->authoritative = (nconf->authoritative != -1) ?
52 nconf->authoritative : pconf->authoritative;
53 conf->var = (nconf->var != NULL) ?
54 nconf->var : pconf->var;
55 conf->strip_suffix = (nconf->var != NULL || nconf->strip_suffix != NULL) ?
56 nconf->strip_suffix : pconf->strip_suffix;
57 conf->strip_suffix_required = (nconf->var != NULL || nconf->strip_suffix_required != -1) ?
58 nconf->authoritative : pconf->authoritative;
63 static const command_rec auth_sslcert_cmds[] =
65 AP_INIT_FLAG("AuthSSLCertAuthoritative", ap_set_flag_slot,
66 (void *)APR_OFFSETOF(auth_sslcert_config_rec, authoritative),
68 "Set to 'Off' to allow access control to be passed along to "
69 "lower modules if the UserID is not known to this module"),
70 AP_INIT_TAKE1("AuthSSLCertVar", ap_set_string_slot,
71 (void*)APR_OFFSETOF(auth_sslcert_config_rec, var),
73 "SSL variable to use as the username"),
74 AP_INIT_TAKE1("AuthSSLCertStripSuffix", ap_set_string_slot,
75 (void*)APR_OFFSETOF(auth_sslcert_config_rec, strip_suffix),
77 "An optional suffix to strip from the username"),
78 AP_INIT_FLAG("AuthSSLCertStripSuffixRequired", ap_set_flag_slot,
79 (void *)APR_OFFSETOF(auth_sslcert_config_rec, strip_suffix_required),
81 "Set to 'Off' to allow certs that don't end with a recognized "
82 "suffix to still authenticate"),
86 module AP_MODULE_DECLARE_DATA auth_sslcert_module;
88 static int authenticate_sslcert_user(request_rec *r)
90 auth_sslcert_config_rec *conf = ap_get_module_config(r->per_dir_config,
91 &auth_sslcert_module);
92 const char *current_auth;
94 /* Are we configured to be SSLCert auth? */
95 current_auth = ap_auth_type(r);
96 if (!current_auth || strcasecmp(current_auth, "SSLCert") != 0) {
100 r->ap_auth_type = "SSLCert";
102 if (strcasecmp((char *)ssl_var_lookup(r->pool, r->server, r->connection, r,
103 "SSL_CLIENT_VERIFY"),
105 if (conf->var == NULL) {
106 ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
107 "AuthSSLCertVar is not set: \"%s\"", r->uri);
108 return HTTP_INTERNAL_SERVER_ERROR;
110 char *user = (char *)ssl_var_lookup(r->pool, r->server, r->connection, r,
112 if (user != NULL && user[0] != '\0') {
113 if (conf->strip_suffix != NULL) {
114 int i = strlen(user) - strlen(conf->strip_suffix);
115 if (i >= 0 && strcasecmp(user + i, conf->strip_suffix) == 0) {
116 r->user = apr_pstrmemdup(r->pool, user, i);
118 } else if (!conf->strip_suffix_required) {
122 ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
123 "SSL username for \"%s\" has wrong suffix: \"%s\"",
131 ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
132 "no SSL username for \"%s\"", r->uri);
134 } else if (conf->authoritative) {
135 ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
136 "SSL client not verified for \"%s\"", r->uri);
139 /* If we're not authoritative, then any error is ignored. */
140 if (!conf->authoritative) {
144 ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
145 "SSLCert authentication failure for \"%s\"",
147 return HTTP_UNAUTHORIZED;
150 static void import_ssl_var_lookup()
152 ssl_var_lookup = APR_RETRIEVE_OPTIONAL_FN(ssl_var_lookup);
155 static void register_hooks(apr_pool_t *p)
157 ap_hook_check_user_id(authenticate_sslcert_user, NULL, NULL, APR_HOOK_MIDDLE);
158 ap_hook_optional_fn_retrieve(import_ssl_var_lookup, NULL, NULL, APR_HOOK_MIDDLE);
161 module AP_MODULE_DECLARE_DATA auth_sslcert_module =
163 STANDARD20_MODULE_STUFF,
164 create_auth_sslcert_dir_config, /* dir config creater */
165 merge_auth_sslcert_dir_config, /* dir merger */
166 NULL, /* server config */
167 NULL, /* merge server config */
168 auth_sslcert_cmds, /* command apr_table_t */
169 register_hooks /* register hooks */