source: server/common/oursrc/httpdmods/mod_auth_sslcert.c @ 389

Last change on this file since 389 was 236, checked in by andersk, 17 years ago
Fix version number comments.
File size: 4.3 KB
Line 
1/* mod_auth_sslcert
2 * version 1.0, released 2007-01-04
3 * Anders Kaseorg <anders@kaseorg.com>
4 *
5 * This module does authentication based on SSL client certificates:
6 *   AuthType SSLCert
7 *   AuthSSLCertVar SSL_CLIENT_S_DN_Email
8 *   AuthSSLCertStripSuffix "@MIT.EDU"
9 */
10
11#include "apr_strings.h"
12#define APR_WANT_STRFUNC        /* for strcasecmp */
13#include "apr_want.h"
14
15#include "ap_config.h"
16#include "httpd.h"
17#include "http_config.h"
18#include "http_core.h"
19#include "http_log.h"
20
21#include "mod_auth.h"
22#include "mod_ssl.h"
23
24static APR_OPTIONAL_FN_TYPE(ssl_var_lookup) *ssl_var_lookup;
25
26typedef struct {
27    char *dir;
28    int authoritative;
29    char *var;
30    char *strip_suffix;
31} auth_sslcert_config_rec;
32
33static void *create_auth_sslcert_dir_config(apr_pool_t *p, char *d)
34{
35    auth_sslcert_config_rec *conf = apr_pcalloc(p, sizeof(*conf));
36
37    conf->dir = d;
38    /* Any failures are fatal. */
39    conf->authoritative = 1;
40    conf->var = NULL;
41    conf->strip_suffix = NULL;
42
43    return conf;
44}
45
46static const command_rec auth_sslcert_cmds[] =
47{
48    AP_INIT_FLAG("AuthSSLCertAuthoritative", ap_set_flag_slot,
49                 (void *)APR_OFFSETOF(auth_sslcert_config_rec, authoritative),
50                 OR_AUTHCFG,
51                 "Set to 'Off' to allow access control to be passed along to "
52                 "lower modules if the UserID is not known to this module"),
53    AP_INIT_TAKE1("AuthSSLCertVar", ap_set_string_slot,
54                  (void*)APR_OFFSETOF(auth_sslcert_config_rec, var),
55                  OR_AUTHCFG,
56                  "SSL variable to use as the username"),
57    AP_INIT_TAKE1("AuthSSLCertStripSuffix", ap_set_string_slot,
58                  (void*)APR_OFFSETOF(auth_sslcert_config_rec, strip_suffix),
59                  OR_AUTHCFG,
60                  "An optional suffix to strip from the username"),
61    {NULL}
62};
63
64module AP_MODULE_DECLARE_DATA auth_sslcert_module;
65
66static int authenticate_sslcert_user(request_rec *r)
67{
68    auth_sslcert_config_rec *conf = ap_get_module_config(r->per_dir_config,
69                                                         &auth_sslcert_module);
70    const char *current_auth;
71
72    /* Are we configured to be SSLCert auth? */
73    current_auth = ap_auth_type(r);
74    if (!current_auth || strcasecmp(current_auth, "SSLCert") != 0) {
75        return DECLINED;
76    }
77
78    r->ap_auth_type = "SSLCert";
79
80    if (strcasecmp((char *)ssl_var_lookup(r->pool, r->server, r->connection, r,
81                                          "SSL_CLIENT_VERIFY"),
82                   "SUCCESS") == 0) {
83        if (conf->var == NULL) {
84            ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
85                          "AuthSSLCertVar is not set: \"%s\"", r->uri);
86            return HTTP_INTERNAL_SERVER_ERROR;
87        }
88        char *user = (char *)ssl_var_lookup(r->pool, r->server, r->connection, r,
89                                            conf->var);
90        if (user != NULL && user[0] != '\0') {
91            if (conf->strip_suffix != NULL) {
92                int i = strlen(user) - strlen(conf->strip_suffix);
93                if (i >= 0 && strcasecmp(user + i, conf->strip_suffix) == 0) {
94                    r->user = apr_pstrmemdup(r->pool, user, i);
95                    return OK;
96                } else {
97                    ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
98                                  "SSL username for \"%s\" has wrong suffix: \"%s\"",
99                                  r->uri, r->user);
100                }
101            } else {
102                r->user = user;
103                return OK;
104            }
105        } else {
106            ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
107                          "no SSL username for \"%s\"", r->uri);
108        }
109    } else {
110        ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
111                      "SSL client not verified for \"%s\"", r->uri);
112    }
113
114    /* If we're not authoritative, then any error is ignored. */
115    if (!conf->authoritative) {
116        return DECLINED;
117    }
118
119    ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
120                  "SSLCert authentication failure for \"%s\"",
121                  r->uri);
122    return HTTP_UNAUTHORIZED;
123}
124
125static void import_ssl_var_lookup()
126{
127    ssl_var_lookup = APR_RETRIEVE_OPTIONAL_FN(ssl_var_lookup);
128}
129
130static void register_hooks(apr_pool_t *p)
131{
132    ap_hook_check_user_id(authenticate_sslcert_user,NULL,NULL,APR_HOOK_MIDDLE);
133    ap_hook_optional_fn_retrieve(import_ssl_var_lookup,NULL,NULL,APR_HOOK_MIDDLE);
134}
135
136module AP_MODULE_DECLARE_DATA auth_sslcert_module =
137{
138    STANDARD20_MODULE_STUFF,
139    create_auth_sslcert_dir_config,  /* dir config creater */
140    NULL,                            /* dir merger --- default is to override */
141    NULL,                            /* server config */
142    NULL,                            /* merge server config */
143    auth_sslcert_cmds,               /* command apr_table_t */
144    register_hooks                   /* register hooks */
145};
Note: See TracBrowser for help on using the repository browser.