4 Copyright (C) 2014 Simo Sorce <simo@redhat.com>
6 Permission is hereby granted, free of charge, to any person obtaining a
7 copy of this software and associated documentation files (the "Software"),
8 to deal in the Software without restriction, including without limitation
9 the rights to use, copy, modify, merge, publish, distribute, sublicense,
10 and/or sell copies of the Software, and to permit persons to whom the
11 Software is furnished to do so, subject to the following conditions:
13 The above copyright notice and this permission notice shall be included in
14 all copies or substantial portions of the Software.
16 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19 THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21 FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
22 DEALINGS IN THE SOFTWARE.
25 #include "mod_auth_gssapi.h"
27 #define MOD_AUTH_GSSAPI_VERSION PACKAGE_NAME "/" PACKAGE_VERSION
29 module AP_MODULE_DECLARE_DATA auth_gssapi_module;
31 APLOG_USE_MODULE(auth_gssapi);
33 static char *mag_status(request_rec *req, int type, uint32_t err)
35 uint32_t maj_ret, min_ret;
44 maj_ret = gss_display_status(&min_ret, err, type,
45 GSS_C_NO_OID, &msg_ctx, &text);
46 if (maj_ret != GSS_S_COMPLETE) {
52 msg_ret = apr_psprintf(req->pool, "%s, %*s",
53 msg_ret, len, (char *)text.value);
55 msg_ret = apr_psprintf(req->pool, "%*s", len, (char *)text.value);
57 gss_release_buffer(&min_ret, &text);
58 } while (msg_ctx != 0);
63 static char *mag_error(request_rec *req, const char *msg,
64 uint32_t maj, uint32_t min)
69 msg_maj = mag_status(req, GSS_C_GSS_CODE, maj);
70 msg_min = mag_status(req, GSS_C_MECH_CODE, min);
71 return apr_psprintf(req->pool, "%s: [%s (%s)]", msg, msg_maj, msg_min);
74 static APR_OPTIONAL_FN_TYPE(ssl_is_https) *mag_is_https = NULL;
76 static int mag_post_config(apr_pool_t *cfgpool, apr_pool_t *log,
77 apr_pool_t *temp, server_rec *s)
79 /* FIXME: create mutex to deal with connections and contexts ? */
80 mag_is_https = APR_RETRIEVE_OPTIONAL_FN(ssl_is_https);
81 mag_post_config_session();
82 ap_add_version_component(cfgpool, MOD_AUTH_GSSAPI_VERSION);
87 static int mag_pre_connection(conn_rec *c, void *csd)
91 mc = apr_pcalloc(c->pool, sizeof(struct mag_conn));
94 ap_set_module_config(c->conn_config, &auth_gssapi_module, (void*)mc);
98 static apr_status_t mag_conn_destroy(void *ptr)
100 struct mag_conn *mc = (struct mag_conn *)ptr;
104 (void)gss_delete_sec_context(&min, &mc->ctx, GSS_C_NO_BUFFER);
105 mc->established = false;
110 static bool mag_conn_is_https(conn_rec *c)
113 if (mag_is_https(c)) return true;
119 static char *escape(apr_pool_t *pool, const char *name,
120 char find, const char *replace)
122 char *escaped = NULL;
127 namecopy = apr_pstrdup(pool, name);
129 p = strchr(namecopy, find);
130 if (!p) return namecopy;
135 /* terminate previous segment */
138 escaped = apr_pstrcat(pool, escaped, n, replace, NULL);
140 escaped = apr_pstrcat(pool, n, replace, NULL);
142 /* move to next segment */
146 /* append last segment if any */
148 escaped = apr_pstrcat(pool, escaped, n, NULL);
154 static void mag_store_deleg_creds(request_rec *req,
155 char *dir, char *clientname,
156 gss_cred_id_t delegated_cred,
159 gss_key_value_element_desc element;
160 gss_key_value_set_desc store;
165 /* We need to escape away '/', we can't have path separators in
166 * a ccache file name */
167 /* first double escape the esacping char (~) if any */
168 escaped = escape(req->pool, clientname, '~', "~~");
169 if (!escaped) return;
170 /* then escape away the separator (/) if any */
171 escaped = escape(req->pool, escaped, '/', "~");
172 if (!escaped) return;
174 value = apr_psprintf(req->pool, "FILE:%s/%s", dir, escaped);
176 element.key = "ccache";
177 element.value = value;
178 store.elements = &element;
181 maj = gss_store_cred_into(&min, delegated_cred, GSS_C_INITIATE,
182 GSS_C_NULL_OID, 1, 1, &store, NULL, NULL);
183 if (GSS_ERROR(maj)) {
184 ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, req, "%s",
185 mag_error(req, "failed to store delegated creds",
192 static int mag_auth(request_rec *req)
195 const char *auth_type;
196 struct mag_config *cfg;
197 const char *auth_header;
198 char *auth_header_type;
199 char *auth_header_value;
200 int ret = HTTP_UNAUTHORIZED;
201 gss_ctx_id_t ctx = GSS_C_NO_CONTEXT;
203 gss_buffer_desc input = GSS_C_EMPTY_BUFFER;
204 gss_buffer_desc output = GSS_C_EMPTY_BUFFER;
205 gss_buffer_desc name = GSS_C_EMPTY_BUFFER;
206 gss_name_t client = GSS_C_NO_NAME;
207 gss_cred_id_t user_cred = GSS_C_NO_CREDENTIAL;
208 gss_cred_id_t acquired_cred = GSS_C_NO_CREDENTIAL;
209 gss_cred_id_t delegated_cred = GSS_C_NO_CREDENTIAL;
210 gss_cred_usage_t cred_usage = GSS_C_ACCEPT;
217 gss_OID mech_type = GSS_C_NO_OID;
218 gss_buffer_desc lname = GSS_C_EMPTY_BUFFER;
219 struct mag_conn *mc = NULL;
220 bool is_basic = false;
221 gss_ctx_id_t user_ctx = GSS_C_NO_CONTEXT;
222 gss_name_t server = GSS_C_NO_NAME;
223 #ifdef HAVE_GSS_KRB5_CCACHE_NAME
224 const char *user_ccache = NULL;
225 const char *orig_ccache = NULL;
227 uint32_t init_flags = 0;
230 type = ap_auth_type(req);
231 if ((type == NULL) || (strcasecmp(type, "GSSAPI") != 0)) {
235 cfg = ap_get_module_config(req->per_dir_config, &auth_gssapi_module);
237 /* implicit auth for subrequests if main auth already happened */
238 if (!ap_is_initial_req(req)) {
239 type = ap_auth_type(req->main);
240 if ((type != NULL) && (strcasecmp(type, "GSSAPI") == 0)) {
241 /* warn if the subrequest location and the main request
242 * location have different configs */
243 if (cfg != ap_get_module_config(req->main->per_dir_config,
244 &auth_gssapi_module)) {
245 ap_log_rerror(APLOG_MARK, APLOG_WARNING, 0,
246 req, "Subrequest authentication bypass on "
247 "location with different configuration!");
249 if (req->main->user) {
250 req->user = apr_pstrdup(req->pool, req->main->user);
253 ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, req,
254 "The main request is tasked to establish the "
255 "security context, can't proceed!");
256 return HTTP_UNAUTHORIZED;
259 ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, req,
260 "Subrequest GSSAPI auth with no auth on the main "
261 "request. This operation may fail if other "
262 "subrequests already established a context or the "
263 "mechanism requires multiple roundtrips.");
268 if (!mag_conn_is_https(req->connection)) {
269 ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, req,
270 "Not a TLS connection, refusing to authenticate!");
275 if (cfg->gss_conn_ctx) {
276 mc = (struct mag_conn *)ap_get_module_config(
277 req->connection->conn_config,
278 &auth_gssapi_module);
280 ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, req,
281 "Failed to retrieve connection context!");
286 /* if available, session always supersedes connection bound data */
287 if (cfg->use_sessions) {
288 mag_check_session(req, cfg, &mc);
292 /* register the context in the memory pool, so it can be freed
293 * when the connection/request is terminated */
294 apr_pool_userdata_set(mc, "mag_conn_ptr",
295 mag_conn_destroy, mc->parent);
297 if (mc->established) {
298 ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, req,
299 "Already established context found!");
300 apr_table_set(req->subprocess_env, "GSS_NAME", mc->gss_name);
301 apr_table_set(req->subprocess_env, "GSS_SESSION_EXPIRATION",
302 apr_psprintf(req->pool,
303 "%ld", (long)mc->expiration));
304 req->ap_auth_type = apr_pstrdup(req->pool, mc->auth_type);
305 req->user = apr_pstrdup(req->pool, mc->user_name);
314 auth_header = apr_table_get(req->headers_in, "Authorization");
315 if (!auth_header) goto done;
317 auth_header_type = ap_getword_white(req->pool, &auth_header);
318 if (!auth_header_type) goto done;
320 if (strcasecmp(auth_header_type, "Negotiate") == 0) {
321 auth_type = "Negotiate";
323 auth_header_value = ap_getword_white(req->pool, &auth_header);
324 if (!auth_header_value) goto done;
325 input.length = apr_base64_decode_len(auth_header_value) + 1;
326 input.value = apr_pcalloc(req->pool, input.length);
327 if (!input.value) goto done;
328 input.length = apr_base64_decode(input.value, auth_header_value);
329 } else if ((strcasecmp(auth_header_type, "Basic") == 0) &&
330 (cfg->use_basic_auth == true)) {
334 gss_buffer_desc ba_user;
335 gss_buffer_desc ba_pwd;
337 ba_pwd.value = ap_pbase64decode(req->pool, auth_header);
338 if (!ba_pwd.value) goto done;
339 ba_user.value = ap_getword_nulls_nc(req->pool,
340 (char **)&ba_pwd.value, ':');
341 if (!ba_user.value) goto done;
342 if (((char *)ba_user.value)[0] == '\0' ||
343 ((char *)ba_pwd.value)[0] == '\0') {
344 ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, req,
345 "Invalid empty user or password for Basic Auth");
348 ba_user.length = strlen(ba_user.value);
349 ba_pwd.length = strlen(ba_pwd.value);
350 maj = gss_import_name(&min, &ba_user, GSS_C_NT_USER_NAME, &client);
351 if (GSS_ERROR(maj)) {
352 ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, req,
354 mag_error(req, "gss_import_name() failed",
358 #ifdef HAVE_GSS_KRB5_CCACHE_NAME
359 /* Set a per-thread ccache in case we are using kerberos,
360 * it is not elegant but avoids interference between threads */
361 long long unsigned int rndname;
363 rs = apr_generate_random_bytes((unsigned char *)(&rndname),
364 sizeof(long long unsigned int));
365 if (rs != APR_SUCCESS) {
366 ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, req,
367 "Failed to generate random ccache name");
370 user_ccache = apr_psprintf(req->pool, "MEMORY:user_%qu", rndname);
371 maj = gss_krb5_ccache_name(&min, user_ccache, &orig_ccache);
372 if (GSS_ERROR(maj)) {
373 ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, req,
375 mag_error(req, "gss_krb5_ccache_name() "
376 "failed", maj, min));
380 maj = gss_acquire_cred_with_password(&min, client, &ba_pwd,
384 &user_cred, NULL, NULL);
385 if (GSS_ERROR(maj)) {
386 ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, req,
388 mag_error(req, "gss_acquire_cred_with_password() "
389 "failed", maj, min));
392 gss_release_name(&min, &client);
397 req->ap_auth_type = apr_pstrdup(req->pool, auth_type);
399 #ifdef HAVE_GSS_ACQUIRE_CRED_FROM
400 if (cfg->use_s4u2proxy) {
401 cred_usage = GSS_C_BOTH;
403 if (cfg->cred_store) {
404 maj = gss_acquire_cred_from(&min, GSS_C_NO_NAME, GSS_C_INDEFINITE,
405 GSS_C_NO_OID_SET, cred_usage,
406 cfg->cred_store, &acquired_cred,
408 if (GSS_ERROR(maj)) {
409 ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, req, "%s",
410 mag_error(req, "gss_acquire_cred_from() failed",
418 if (!acquired_cred) {
419 /* Try to acquire default creds */
420 maj = gss_acquire_cred(&min, GSS_C_NO_NAME, GSS_C_INDEFINITE,
421 GSS_C_NO_OID_SET, cred_usage,
422 &acquired_cred, NULL, NULL);
423 if (GSS_ERROR(maj)) {
424 ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, req,
425 "%s", mag_error(req, "gss_acquire_cred_from()"
426 " failed", maj, min));
430 maj = gss_inquire_cred(&min, acquired_cred, &server,
432 if (GSS_ERROR(maj)) {
433 ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, req,
434 "%s", mag_error(req, "gss_inquired_cred_() "
435 "failed", maj, min));
439 if (cfg->deleg_ccache_dir) {
440 /* delegate ourselves credentials so we store them as requested */
441 init_flags |= GSS_C_DELEG_FLAG;
444 /* output and input are inverted here, this is intentional */
445 maj = gss_init_sec_context(&min, user_cred, &user_ctx, server,
446 GSS_C_NO_OID, init_flags, 300,
447 GSS_C_NO_CHANNEL_BINDINGS, &output,
448 NULL, &input, NULL, NULL);
449 if (GSS_ERROR(maj)) {
450 ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, req,
451 "%s", mag_error(req, "gss_init_sec_context() "
452 "failed", maj, min));
457 maj = gss_accept_sec_context(&min, pctx, acquired_cred,
458 &input, GSS_C_NO_CHANNEL_BINDINGS,
459 &client, &mech_type, &output, &flags, &vtime,
461 if (GSS_ERROR(maj)) {
462 ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, req, "%s",
463 mag_error(req, "gss_accept_sec_context() failed",
468 while (maj == GSS_S_CONTINUE_NEEDED) {
469 gss_release_buffer(&min, &input);
470 /* output and input are inverted here, this is intentional */
471 maj = gss_init_sec_context(&min, user_cred, &user_ctx, server,
472 GSS_C_NO_OID, init_flags, 300,
473 GSS_C_NO_CHANNEL_BINDINGS, &output,
474 NULL, &input, NULL, NULL);
475 if (GSS_ERROR(maj)) {
476 ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, req,
477 "%s", mag_error(req, "gss_init_sec_context() "
478 "failed", maj, min));
481 gss_release_buffer(&min, &output);
482 maj = gss_accept_sec_context(&min, pctx, acquired_cred,
483 &input, GSS_C_NO_CHANNEL_BINDINGS,
484 &client, &mech_type, &output, &flags,
485 &vtime, &delegated_cred);
486 if (GSS_ERROR(maj)) {
487 ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, req,
488 "%s", mag_error(req, "gss_accept_sec_context()"
489 " failed", maj, min));
493 } else if (maj == GSS_S_CONTINUE_NEEDED) {
495 ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, req,
496 "Mechanism needs continuation but neither "
497 "GssapiConnectionBound nor "
498 "GssapiUseSessions are available");
499 gss_delete_sec_context(&min, pctx, GSS_C_NO_BUFFER);
500 gss_release_buffer(&min, &output);
503 /* auth not complete send token and wait next packet */
507 /* Always set the GSS name in an env var */
508 maj = gss_display_name(&min, client, &name, NULL);
509 if (GSS_ERROR(maj)) {
510 ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, req, "%s",
511 mag_error(req, "gss_display_name() failed",
515 clientname = apr_pstrndup(req->pool, name.value, name.length);
516 apr_table_set(req->subprocess_env, "GSS_NAME", clientname);
517 expiration = time(NULL) + vtime;
518 apr_table_set(req->subprocess_env, "GSS_SESSION_EXPIRATION",
519 apr_psprintf(req->pool, "%ld", (long)expiration));
521 #ifdef HAVE_GSS_STORE_CRED_INTO
522 if (cfg->deleg_ccache_dir && delegated_cred != GSS_C_NO_CREDENTIAL) {
523 char *ccachefile = NULL;
525 mag_store_deleg_creds(req, cfg->deleg_ccache_dir, clientname,
526 delegated_cred, &ccachefile);
529 apr_table_set(req->subprocess_env, "KRB5CCNAME", ccachefile);
534 if (cfg->map_to_local) {
535 maj = gss_localname(&min, client, mech_type, &lname);
536 if (maj != GSS_S_COMPLETE) {
537 ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, req, "%s",
538 mag_error(req, "gss_localname() failed", maj, min));
541 req->user = apr_pstrndup(req->pool, lname.value, lname.length);
543 req->user = clientname;
547 mc->user_name = apr_pstrdup(mc->parent, req->user);
548 mc->gss_name = apr_pstrdup(mc->parent, clientname);
549 mc->established = true;
550 if (vtime == GSS_C_INDEFINITE || vtime < MIN_SESS_EXP_TIME) {
551 vtime = MIN_SESS_EXP_TIME;
553 mc->expiration = expiration;
554 if (cfg->use_sessions) {
555 mag_attempt_session(req, cfg, mc);
557 mc->auth_type = auth_type;
560 if (cfg->send_persist)
561 apr_table_set(req->headers_out, "Persistent-Auth",
562 cfg->gss_conn_ctx ? "true" : "false");
567 if ((!is_basic) && (output.length != 0)) {
568 replen = apr_base64_encode_len(output.length) + 1;
569 reply = apr_pcalloc(req->pool, 10 + replen);
571 memcpy(reply, "Negotiate ", 10);
572 apr_base64_encode(&reply[10], output.value, output.length);
573 apr_table_add(req->err_headers_out,
574 "WWW-Authenticate", reply);
576 } else if (ret == HTTP_UNAUTHORIZED) {
577 apr_table_add(req->err_headers_out,
578 "WWW-Authenticate", "Negotiate");
579 if (cfg->use_basic_auth) {
580 apr_table_add(req->err_headers_out,
582 apr_psprintf(req->pool, "Basic realm=\"%s\"",
586 #ifdef HAVE_GSS_KRB5_CCACHE_NAME
587 if (user_ccache != NULL) {
588 maj = gss_krb5_ccache_name(&min, orig_ccache, NULL);
589 if (maj != GSS_S_COMPLETE) {
590 ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, req,
591 "Failed to restore per-thread ccache, %s",
592 mag_error(req, "gss_krb5_ccache_name() "
593 "failed", maj, min));
597 gss_delete_sec_context(&min, &user_ctx, &output);
598 gss_release_cred(&min, &user_cred);
599 gss_release_cred(&min, &acquired_cred);
600 gss_release_cred(&min, &delegated_cred);
601 gss_release_buffer(&min, &output);
602 gss_release_name(&min, &client);
603 gss_release_name(&min, &server);
604 gss_release_buffer(&min, &name);
605 gss_release_buffer(&min, &lname);
610 static void *mag_create_dir_config(apr_pool_t *p, char *dir)
612 struct mag_config *cfg;
614 cfg = (struct mag_config *)apr_pcalloc(p, sizeof(struct mag_config));
620 static const char *mag_ssl_only(cmd_parms *parms, void *mconfig, int on)
622 struct mag_config *cfg = (struct mag_config *)mconfig;
623 cfg->ssl_only = on ? true : false;
627 static const char *mag_map_to_local(cmd_parms *parms, void *mconfig, int on)
629 struct mag_config *cfg = (struct mag_config *)mconfig;
630 cfg->map_to_local = on ? true : false;
634 static const char *mag_conn_ctx(cmd_parms *parms, void *mconfig, int on)
636 struct mag_config *cfg = (struct mag_config *)mconfig;
637 cfg->gss_conn_ctx = on ? true : false;
641 static const char *mag_send_persist(cmd_parms *parms, void *mconfig, int on)
643 struct mag_config *cfg = (struct mag_config *)mconfig;
644 cfg->send_persist = on ? true : false;
648 static const char *mag_use_sess(cmd_parms *parms, void *mconfig, int on)
650 struct mag_config *cfg = (struct mag_config *)mconfig;
651 cfg->use_sessions = on ? true : false;
655 static const char *mag_use_s4u2p(cmd_parms *parms, void *mconfig, int on)
657 struct mag_config *cfg = (struct mag_config *)mconfig;
658 cfg->use_s4u2proxy = on ? true : false;
660 if (cfg->deleg_ccache_dir == NULL) {
661 cfg->deleg_ccache_dir = apr_pstrdup(parms->pool, "/tmp");
666 static const char *mag_sess_key(cmd_parms *parms, void *mconfig, const char *w)
668 struct mag_config *cfg = (struct mag_config *)mconfig;
675 if (strncmp(w, "key:", 4) != 0) {
676 ap_log_error(APLOG_MARK, APLOG_ERR, 0, parms->server,
677 "Invalid key format, expected prefix 'key:'");
682 l = apr_base64_decode_len(k);
683 val = apr_palloc(parms->temp_pool, l);
685 keys.length = (int)apr_base64_decode_binary(val, k);
686 keys.value = (unsigned char *)val;
688 if (keys.length != 32) {
689 ap_log_error(APLOG_MARK, APLOG_ERR, 0, parms->server,
690 "Invalid key length, expected 32 got %d", keys.length);
694 rc = SEAL_KEY_CREATE(cfg->pool, &cfg->mag_skey, &keys);
696 ap_log_error(APLOG_MARK, APLOG_ERR, 0, parms->server,
697 "Failed to import sealing key!");
702 #define MAX_CRED_OPTIONS 10
704 static const char *mag_cred_store(cmd_parms *parms, void *mconfig,
707 struct mag_config *cfg = (struct mag_config *)mconfig;
708 gss_key_value_element_desc *elements;
717 ap_log_error(APLOG_MARK, APLOG_ERR, 0, parms->server,
718 "%s [%s]", "Invalid syntax for GssapiCredStore option", w);
722 key = apr_pstrndup(parms->pool, w, (p-w));
723 value = apr_pstrdup(parms->pool, p + 1);
725 if (!cfg->cred_store) {
726 cfg->cred_store = apr_pcalloc(parms->pool,
727 sizeof(gss_key_value_set_desc));
728 size = sizeof(gss_key_value_element_desc) * MAX_CRED_OPTIONS;
729 cfg->cred_store->elements = apr_palloc(parms->pool, size);
732 elements = cfg->cred_store->elements;
733 count = cfg->cred_store->count;
735 if (count >= MAX_CRED_OPTIONS) {
736 ap_log_error(APLOG_MARK, APLOG_ERR, 0, parms->server,
737 "Too many GssapiCredStore options (MAX: %d)",
741 cfg->cred_store->count++;
743 elements[count].key = key;
744 elements[count].value = value;
749 static const char *mag_deleg_ccache_dir(cmd_parms *parms, void *mconfig,
752 struct mag_config *cfg = (struct mag_config *)mconfig;
754 cfg->deleg_ccache_dir = apr_pstrdup(parms->pool, value);
759 static const char *mag_use_basic_auth(cmd_parms *parms, void *mconfig, int on)
761 struct mag_config *cfg = (struct mag_config *)mconfig;
763 cfg->use_basic_auth = on ? true : false;
767 static const command_rec mag_commands[] = {
768 AP_INIT_FLAG("GssapiSSLonly", mag_ssl_only, NULL, OR_AUTHCFG,
769 "Work only if connection is SSL Secured"),
770 AP_INIT_FLAG("GssapiLocalName", mag_map_to_local, NULL, OR_AUTHCFG,
771 "Translate principals to local names"),
772 AP_INIT_FLAG("GssapiConnectionBound", mag_conn_ctx, NULL, OR_AUTHCFG,
773 "Authentication is bound to the TCP connection"),
774 AP_INIT_FLAG("GssapiSignalPersistentAuth", mag_send_persist, NULL, OR_AUTHCFG,
775 "Send Persitent-Auth header according to connection bound"),
776 AP_INIT_FLAG("GssapiUseSessions", mag_use_sess, NULL, OR_AUTHCFG,
777 "Authentication uses mod_sessions to hold status"),
778 AP_INIT_RAW_ARGS("GssapiSessionKey", mag_sess_key, NULL, OR_AUTHCFG,
779 "Key Used to seal session data."),
780 #ifdef HAVE_GSS_ACQUIRE_CRED_FROM
781 AP_INIT_FLAG("GssapiUseS4U2Proxy", mag_use_s4u2p, NULL, OR_AUTHCFG,
782 "Initializes credentials for s4u2proxy usage"),
784 #ifdef HAVE_GSS_STORE_CRED_INTO
785 AP_INIT_ITERATE("GssapiCredStore", mag_cred_store, NULL, OR_AUTHCFG,
787 AP_INIT_RAW_ARGS("GssapiDelegCcacheDir", mag_deleg_ccache_dir, NULL,
788 OR_AUTHCFG, "Directory to store delegated credentials"),
790 #ifdef HAVE_GSS_ACQUIRE_CRED_WITH_PASSWORD
791 AP_INIT_FLAG("GssapiBasicAuth", mag_use_basic_auth, NULL, OR_AUTHCFG,
792 "Allows use of Basic Auth for authentication"),
798 mag_register_hooks(apr_pool_t *p)
800 ap_hook_check_user_id(mag_auth, NULL, NULL, APR_HOOK_MIDDLE);
801 ap_hook_post_config(mag_post_config, NULL, NULL, APR_HOOK_MIDDLE);
802 ap_hook_pre_connection(mag_pre_connection, NULL, NULL, APR_HOOK_MIDDLE);
805 module AP_MODULE_DECLARE_DATA auth_gssapi_module =
807 STANDARD20_MODULE_STUFF,
808 mag_create_dir_config,