1 #include "mod_auth_gssapi.h"
3 module AP_MODULE_DECLARE_DATA auth_gssapi_module;
5 #define command(name, func, var, type, usage) \
6 AP_INIT_ ## type (name, (void*) func, \
7 (void*)APR_OFFSETOF(gss_auth_config, var), \
8 OR_AUTHCFG | RSRC_CONF, usage)
10 static const command_rec gss_config_cmds[] = {
11 command("GSSServiceName", ap_set_string_slot, service_name,
12 TAKE1, "Service name used for Apache authentication."),
14 command("GSSKrb5Keytab", ap_set_string_slot, krb5_keytab,
15 TAKE1, "Location of Kerberos V5 keytab file."),
21 gss_config_dir_create(apr_pool_t *p, char *d)
23 gss_auth_config *conf;
25 conf = (gss_auth_config *) apr_pcalloc(p, sizeof(*conf));
30 gss_log(const char *file, int line, int level, int status,
31 const request_rec *r, const char *fmt, ...)
37 vsnprintf(errstr, sizeof(errstr), fmt, ap);
40 ap_log_rerror(file, line, level | APLOG_NOERRNO, status, r, "%s", errstr);
44 set_http_headers(request_rec *r, const gss_auth_config *conf,
45 char *negotiate_ret_value)
48 const char *header_name = (r->proxyreq == PROXYREQ_PROXY) ?
49 "Proxy-Authenticate" : "WWW-Authenticate";
51 if (negotiate_ret_value == NULL)
54 negoauth_param = (*negotiate_ret_value == '\0') ? "GSSAPI" :
55 apr_pstrcat(r->pool, "GSSAPI ", negotiate_ret_value, NULL);
56 apr_table_add(r->err_headers_out, header_name, negoauth_param);
60 cleanup_conn_ctx(void *data)
62 gss_conn_ctx ctx = (gss_conn_ctx) data;
63 OM_uint32 minor_status;
65 if (ctx && ctx->context != GSS_C_NO_CONTEXT)
66 gss_delete_sec_context(&minor_status, &ctx->context, GSS_C_NO_BUFFER);
72 gss_get_conn_ctx(request_rec *r)
75 gss_conn_ctx ctx = NULL;
77 snprintf(key, sizeof(key), "mod_auth_gssapi:conn_ctx");
78 apr_pool_userdata_get((void **)&ctx, key, r->connection->pool);
81 ctx = (gss_conn_ctx) apr_palloc(r->connection->pool, sizeof(*ctx));
84 ctx->context = GSS_C_NO_CONTEXT;
85 ctx->state = GSS_CTX_EMPTY;
87 apr_pool_userdata_set(ctx, key, cleanup_conn_ctx, r->connection->pool);
93 gss_authenticate_user(request_rec *r)
95 gss_auth_config *conf =
96 (gss_auth_config *) ap_get_module_config(r->per_dir_config,
98 const char *auth_line = NULL;
99 const char *type = NULL;
100 char *auth_type = NULL;
101 char *negotiate_ret_value = NULL;
102 gss_conn_ctx conn_ctx = NULL;
105 gss_log(APLOG_MARK, APLOG_DEBUG, 0, r, "Entering GSSAPI authentication");
107 /* get the type specified in Apache configuration */
108 type = ap_auth_type(r);
109 if (type == NULL || strcmp(type, "GSSAPI") != 0) {
110 gss_log(APLOG_MARK, APLOG_DEBUG, 0, r,
111 "AuthType '%s' is not for us, bailing out",
112 (type) ? type : "(NULL)");
117 /* get what the user sent us in the HTTP header */
118 auth_line = apr_table_get(r->headers_in, (r->proxyreq == PROXYREQ_PROXY)
119 ? "Proxy-Authorization"
121 if (auth_line == NULL) {
122 gss_log(APLOG_MARK, APLOG_DEBUG, 0, r,
123 "Client hasn't sent any authentication data, giving up");
124 set_http_headers(r, conf, "\0");
125 return HTTP_UNAUTHORIZED;
128 auth_type = ap_getword_white(r->pool, &auth_line);
129 if (strcasecmp(auth_type, "GSSAPI") != 0) {
130 gss_log(APLOG_MARK, APLOG_DEBUG, 0, r,
131 "Unsupported authentication type (%s) requested by client",
132 (auth_type) ? auth_type : "(NULL)");
133 set_http_headers(r, conf, "\0");
134 return HTTP_UNAUTHORIZED;
137 conn_ctx = gss_get_conn_ctx(r);
138 if (conn_ctx == NULL) {
139 gss_log(APLOG_MARK, APLOG_ERR, 0, r,
140 "Failed to create internal context: probably not enough memory");
141 return HTTP_INTERNAL_SERVER_ERROR;
144 /* optimizing hack */
145 if (conn_ctx->state == GSS_CTX_ESTABLISHED && auth_line == NULL) {
146 r->user = apr_pstrdup(r->pool, conn_ctx->user);
147 r->ap_auth_type = "GSSAPI";
151 /* XXXX subrequests ignored, only successful accesses taken into account! */
152 if (!ap_is_initial_req(r) && conn_ctx->state == GSS_CTX_ESTABLISHED) {
153 r->user = apr_pstrdup(r->pool, conn_ctx->user);
154 r->ap_auth_type = "GSSAPI";
158 ret = gss_authenticate(r, conf, conn_ctx,
159 auth_line, &negotiate_ret_value);
160 if (ret == HTTP_UNAUTHORIZED || ret == OK) {
162 set_http_headers(r, conf, negotiate_ret_value);
166 r->user = apr_pstrdup(r->pool, conn_ctx->user);
167 r->ap_auth_type = "GSSAPI";
176 gss_register_hooks(apr_pool_t *p)
178 ap_hook_check_user_id(gss_authenticate_user, NULL, NULL, APR_HOOK_MIDDLE);
181 module AP_MODULE_DECLARE_DATA auth_gssapi_module = {
182 STANDARD20_MODULE_STUFF,
183 gss_config_dir_create,