4 #include "http_config.h"
7 #include "http_protocol.h"
8 #include "http_request.h"
20 module kerb_auth_module;
22 module AP_MODULE_DECLARE_DATA kerb_auth_module;
25 /***************************************************************************
26 Macros To Ease Compatibility
27 ***************************************************************************/
30 #define MK_TABLE_GET ap_table_get
31 #define MK_TABLE_SET ap_table_set
32 #define MK_TABLE_TYPE table
33 #define MK_PSTRDUP ap_pstrdup
34 #define MK_PROXY STD_PROXY
35 #define MK_USER r->connection->user
36 #define MK_AUTH_TYPE r->connection->ap_auth_type
37 #define MK_ARRAY_HEADER array_header
39 #define MK_POOL apr_pool_t
40 #define MK_TABLE_GET apr_table_get
41 #define MK_TABLE_SET apr_table_set
42 #define MK_TABLE_TYPE apr_table_t
43 #define MK_PSTRDUP apr_pstrdup
44 #define MK_PROXY PROXYREQ_PROXY
45 #define MK_USER r->user
46 #define MK_AUTH_TYPE r->ap_auth_type
47 #define MK_ARRAY_HEADER apr_array_header_t
53 /***************************************************************************
54 Auth Configuration Structure
55 ***************************************************************************/
58 char *krb_auth_realms;
60 char *krb_force_instance;
61 int krb_save_credentials;
68 int krb_method_gssapi;
69 int krb_method_k5pass;
73 int krb_method_k4pass;
78 #define command(name, func, var, type, usage) \
80 (void*)XtOffsetOf(kerb_auth_config, var), \
81 OR_AUTHCFG, type, usage }
83 #define command(name, func, var, type, usage) \
84 AP_INIT_ ## type (name, func, \
85 (void*)APR_XtOffsetOf(kerb_auth_config, var), \
89 static const command_rec kerb_auth_cmds[] = {
90 command("AuthKerberos", ap_set_flag_slot, krb_auth_enable,
91 FLAG, "Permit Kerberos auth without AuthType requirement."),
93 command("KrbAuthRealm", ap_set_string_slot, krb_auth_realms,
94 ITERATE, "Realms to attempt authentication against (can be multiple)."),
96 command("KrbAuthRealm", ap_set_string_slot, krb_auth_realms,
97 ITERATE, "Alias for KrbAuthRealm."),
100 command("KrbFailStatus", kerb_set_fail_slot, krb_fail_status,
101 TAKE1, "If auth fails, return status set here."),
104 command("KrbForceInstance", ap_set_string_slot, krb_force_instance,
105 TAKE1, "Force authentication against an instance specified here."),
107 command("KrbSaveCredentials", ap_set_flag_slot, krb_save_credentials,
108 FLAG, "Save and store credentials/tickets retrieved during auth."),
110 command("KrbSaveTickets", ap_set_flag_slot, krb_save_credentials,
111 FLAG, "Alias for KrbSaveCredentials."),
113 command("KrbTmpdir", ap_set_string_slot, krb_tmp_dir,
114 TAKE1, "Path to store ticket files and such in."),
116 command("KrbServiceName", ap_set_string_slot, service_name,
117 TAKE1, "Kerberos service name to be used by apache."),
120 command("KrbLifetime", ap_set_string_slot, krb_lifetime,
121 TAKE1, "Kerberos ticket lifetime."),
125 command("Krb5Keytab", ap_set_file_slot, krb_5_keytab,
126 TAKE1, "Location of Kerberos V5 keytab file."),
128 command("KrbForwardable", ap_set_flag_slot, krb_forwardable,
129 FLAG, "Credentials retrieved will be flagged as forwardable."),
131 command("KrbMethodGSSAPI", ap_set_flag_slot, krb_method_gssapi,
132 FLAG, "Enable GSSAPI authentication."),
134 command("KrbMethodK5Pass", ap_set_flag_slot, krb_method_k5pass,
135 FLAG, "Enable Kerberos V5 password authentication."),
139 command("Krb4Srvtab", ap_set_file_slot, krb_4_srvtab,
140 TAKE1, "Location of Kerberos V4 srvtab file."),
142 command("KrbMethodK4Pass", ap_set_flag_slot, krb_method_k4pass,
143 FLAG, "Enable Kerberos V4 password authentication."),
150 /***************************************************************************
151 GSSAPI Support Initialization
152 ***************************************************************************/
155 gss_ctx_id_t context;
156 gss_cred_id_t server_creds;
159 static gss_connection_t *gss_connection = NULL;
162 cleanup_gss_connection(void *data)
164 OM_uint32 minor_status;
165 gss_connection_t *gss_conn = (gss_connection_t *)data;
169 if (gss_conn->context != GSS_C_NO_CONTEXT)
170 gss_delete_sec_context(&minor_status, &gss_conn->context,
172 if (gss_conn->server_creds != GSS_C_NO_CREDENTIAL)
173 gss_release_cred(&minor_status, &gss_conn->server_creds);
180 /***************************************************************************
181 Auth Configuration Initialization
182 ***************************************************************************/
183 static void *kerb_dir_create_config(MK_POOL *p, char *d)
185 kerb_auth_config *rec;
187 rec = (kerb_auth_config *) ap_pcalloc(p, sizeof(kerb_auth_config));
188 ((kerb_auth_config *)rec)->krb_auth_enable = 1;
189 ((kerb_auth_config *)rec)->krb_fail_status = HTTP_UNAUTHORIZED;
191 ((kerb_auth_config *)rec)->krb_method_k5pass = 1;
192 ((kerb_auth_config *)rec)->krb_method_gssapi = 1;
195 ((kerb_auth_config *)rec)->krb_method_k4pass = 1;
202 static const char *kerb_set_fail_slot(cmd_parms *cmd, void *struct_ptr,
205 int offset = (int) (long) cmd->info;
206 if (!strncasecmp(arg, "unauthorized", 12))
207 *(int *) ((char *)struct_ptr + offset) = HTTP_UNAUTHORIZED;
208 else if (!strncasecmp(arg, "forbidden", 9))
209 *(int *) ((char *)struct_ptr + offset) = HTTP_FORBIDDEN;
210 else if (!strncasecmp(arg, "declined", 8))
211 *(int *) ((char *)struct_ptr + offset) = DECLINED;
213 return "KrbAuthFailStatus must be Forbidden, Unauthorized, or Declined.";
219 int kerb4_password_validate(request_rec *r, const char *user, const char *pass)
221 kerb_auth_config *conf =
222 (kerb_auth_config *)ap_get_module_config(r->per_dir_config,
225 int lifetime = DEFAULT_TKT_LIFE;
227 char *username = NULL;
228 char *instance = NULL;
231 username = (char *)ap_pstrdup(r->pool, user);
236 instance = strchr(username, '.');
244 realm = strchr(username, '@');
252 if (conf->krb_lifetime) {
253 lifetime = atoi(conf->krb_lifetime);
256 if (conf->krb_force_instance) {
257 instance = conf->krb_force_instance;
260 if (conf->krb_save_credentials) {
261 tfname = (char *)malloc(sizeof(char) * MAX_STRING_LEN);
262 sprintf(tfname, "%s/k5cc_ap_%s",
263 conf->krb_tmp_dir ? conf->krb_tmp_dir : "/tmp",
266 if (!strcmp(instance, "")) {
267 tfname = strcat(tfname, ".");
268 tfname = strcat(tfname, instance);
271 if (!strcmp(realm, "")) {
272 tfname = strcat(tfname, ".");
273 tfname = strcat(tfname, realm);
276 for (c = tfname + strlen(conf->krb_tmp_dir ? conf->krb_tmp_dir :
277 "/tmp") + 1; *c; c++) {
282 krb_set_tkt_string(tfname);
285 if (!strcmp(realm, "")) {
286 realm = (char *)malloc(sizeof(char) * (REALM_SZ + 1));
287 ret = krb_get_lrealm(realm, 1);
292 ret = krb_get_pw_in_tkt((char *)user, instance, realm, "krbtgt", realm,
293 lifetime, (char *)pass);
310 krb5_verify_user(krb5_context context, krb5_principal principal,
311 krb5_ccache ccache, const char *password, krb5_boolean secure,
315 krb5_context kcontext;
316 krb5_principal server, client;
319 krb5_flags options = 0;
320 krb5_principal me = NULL;
321 krb5_data tgtname = {
327 memset((char *)&my_creds, 0, sizeof(my_creds));
328 my_creds.client = principal;
330 if (krb5_build_principal_ext(kcontext, &server,
331 krb5_princ_realm(kcontext, me)->length,
332 krb5_princ_realm(kcontext, me)->data,
333 tgtname.length, tgtname.data,
334 krb5_princ_realm(kcontext, me)->length,
335 krb5_princ_realm(kcontext, me)->data,
340 my_creds.server = server;
341 if (krb5_timeofday(kcontext, &now))
344 my_creds.times.starttime = 0;
346 my_creds.times.endtime = now + lifetime;
347 my_creds.times.renew_till = now + renewal;
350 ret = krb5_get_in_tkt_with_password(kcontext, options, 0, NULL, 0,
351 password, ccache, &my_creds, 0);
361 /***************************************************************************
362 Username/Password Validation
363 ***************************************************************************/
365 krb5_cache_cleanup(void *data)
367 krb5_context context;
369 krb5_error_code problem;
370 char *cache_name = (char *) data;
372 problem = krb5_init_context(&context);
374 ap_log_error(APLOG_MARK, APLOG_ERR, NULL, "krb5_init_context() failed");
378 problem = krb5_cc_resolve(context, cache_name, &cache);
380 ap_log_error(APLOG_MARK, APLOG_ERR, NULL,
381 "krb5_cc_resolve() failed (%s: %s)",
382 cache_name, krb5_get_err_text(context, problem));
386 krb5_cc_destroy(context, cache);
387 krb5_free_context(context);
391 create_krb5_ccache(krb5_context kcontext,
393 kerb_auth_config *conf,
394 krb5_principal princ,
397 char *c, ccname[MAX_STRING_LEN];
398 krb5_error_code problem;
401 krb5_ccache tmp_ccache = NULL;
403 snprintf(ccname, sizeof(ccname), "FILE:%s/k5cc_ap_%s",
404 conf->krb_tmp_dir ? conf->krb_tmp_dir : "/tmp",
407 for (c = ccname + strlen(conf->krb_tmp_dir ? conf->krb_tmp_dir :
408 "/tmp") + 1; *c; c++) {
414 /* not sure what's the purpose of this call here */
415 problem = krb5_cc_set_default_name(kcontext, ccname);
417 snprintf(errstr, sizeof(errstr),
418 "krb5_cc_set_default_name() failed: %s",
419 krb5_get_err_text(kcontext, problem));
420 ap_log_reason (errstr, r->uri, r);
428 /* XXX Dan: Why is this done? Cleanup? But the file would not be
429 * accessible from another processes (CGI) */
430 unlink(ccname+strlen("FILE:"));
433 problem = krb5_cc_resolve(kcontext, ccname, &tmp_ccache);
435 snprintf(errstr, sizeof(errstr),
436 "krb5_cc_resolve() failed: %s",
437 krb5_get_err_text(kcontext, problem));
438 ap_log_reason (errstr, r->uri, r);
443 problem = krb5_cc_initialize(kcontext, tmp_ccache, princ);
445 snprintf(errstr, sizeof(errstr),
446 "krb5_cc_initialize() failed: %s",
447 krb5_get_err_text(kcontext, problem));
448 ap_log_reason (errstr, r->uri, r);
453 ap_table_setn(r->subprocess_env, "KRB5CCNAME", ccname);
454 ap_register_cleanup(r->pool, ccname,
455 krb5_cache_cleanup, ap_null_cleanup);
457 *ccache = tmp_ccache;
464 krb5_cc_destroy(kcontext, tmp_ccache);
466 return ret; /* XXX */
470 store_krb5_creds(krb5_context kcontext,
472 kerb_auth_config *conf,
473 krb5_ccache delegated_cred)
476 krb5_error_code problem;
477 krb5_principal princ;
481 problem = krb5_cc_get_principal(kcontext, delegated_cred, &princ);
483 snprintf(errstr, sizeof(errstr), "krb5_cc_get_principal() failed: %s",
484 krb5_get_err_text(kcontext, problem));
488 ret = create_krb5_ccache(kcontext, r, conf, princ, &ccache);
490 krb5_free_principal(kcontext, princ);
494 problem = krb5_cc_copy_cache(kcontext, delegated_cred, ccache);
495 krb5_free_principal(kcontext, princ);
497 snprintf(errstr, sizeof(errstr), "krb5_cc_copy_cache() failed: %s",
498 krb5_get_err_text(kcontext, problem));
499 krb5_cc_destroy(kcontext, ccache);
503 krb5_cc_close(kcontext, ccache);
508 int authenticate_user_krb5pwd(request_rec *r,
509 kerb_auth_config *conf,
510 const char *auth_line)
512 const char *sent_pw = NULL;
513 const char *realms = NULL;
514 krb5_context kcontext;
515 krb5_error_code code;
516 krb5_principal client = NULL;
517 krb5_ccache ccache = NULL;
520 code = krb5_init_context(&kcontext);
522 ap_log_rerror(APLOG_MARK, APLOG_NOERRNO, r,
523 "Cannot initialize Kerberos5 context (%d)", code);
527 sent_pw = ap_uudecode(r->pool, auth_line);
528 r->connection->user = ap_getword (r->pool, &sent_pw, ':');
529 r->connection->ap_auth_type = "Basic";
531 /* do not allow user to override realm setting of server */
532 if (strchr(r->connection->user,'@')) {
533 ap_log_rerror(APLOG_MARK, APLOG_NOERRNO, r,
534 "specifying realm in user name is prohibited");
535 ret = HTTP_UNAUTHORIZED;
540 code = krb5_cc_gen_new(kcontext, &krb5_mcc_ops, &ccache);
542 code = krb5_mcc_generate_new(kcontext, &ccache);
545 ap_log_rerror(APLOG_MARK, APLOG_NOERRNO, r,
546 "Cannot generate new ccache: %s",
547 krb5_get_err_text(kcontext, code));
552 realms = conf->krb_auth_realms;
554 if (realms && krb5_set_default_realm(kcontext,
555 ap_getword_white(r->pool, &realms)))
558 code = krb5_parse_name(kcontext, r->connection->user, &client);
562 code = krb5_verify_user(kcontext, client, ccache, sent_pw, 1, "khttp");
563 krb5_free_principal(kcontext, client);
567 /* ap_getword_white() used above shifts the parameter, so it's not
568 needed to touch the realms variable */
569 } while (realms && *realms);
571 memset((char *)sent_pw, 0, strlen(sent_pw));
574 ap_log_rerror(APLOG_MARK, APLOG_NOERRNO, r,
575 "Verifying krb5 password failed: %s",
576 krb5_get_err_text(kcontext, code));
577 ret = HTTP_UNAUTHORIZED;
581 if (conf->krb_save_credentials) {
582 ret = store_krb5_creds(kcontext, r, conf, ccache);
583 if (ret) /* Ignore error ?? */
591 krb5_free_principal(kcontext, client);
593 krb5_cc_destroy(kcontext, ccache);
594 krb5_free_context(kcontext);
601 get_gss_error(pool *p, OM_uint32 error_status, char *prefix)
603 OM_uint32 maj_stat, min_stat;
604 OM_uint32 msg_ctx = 0;
605 gss_buffer_desc status_string;
609 snprintf(buf, sizeof(buf), "%s: ", prefix);
612 maj_stat = gss_display_status (&min_stat,
618 if (sizeof(buf) > len + status_string.length + 1) {
619 sprintf(buf+len, "%s:", (char*) status_string.value);
620 len += status_string.length;
622 gss_release_buffer(&min_stat, &status_string);
623 } while (!GSS_ERROR(maj_stat) && msg_ctx != 0);
625 return (ap_pstrdup(p, buf));
630 store_gss_creds(request_rec *r, kerb_auth_config *conf, char *princ_name,
631 gss_cred_id_t delegated_cred)
633 OM_uint32 maj_stat, min_stat;
634 krb5_principal princ = NULL;
635 krb5_ccache ccache = NULL;
636 krb5_error_code problem;
637 krb5_context context;
638 int ret = SERVER_ERROR;
640 problem = krb5_init_context(&context);
642 ap_log_rerror(APLOG_MARK, APLOG_ERR, r,
643 "Cannot initialize krb5 context");
647 problem = krb5_parse_name(context, princ_name, &princ);
649 ap_log_rerror(APLOG_MARK, APLOG_ERR, r,
650 "Cannot parse delegated username (%s)", krb5_get_err_text(context, problem));
654 problem = create_krb5_ccache(context, r, conf, princ, &ccache);
656 ap_log_rerror(APLOG_MARK, APLOG_ERR, r,
657 "Cannot create krb5 ccache (%s)", krb5_get_err_text(context, problem));
661 maj_stat = gss_krb5_copy_ccache(&min_stat, delegated_cred, ccache);
662 if (GSS_ERROR(maj_stat)) {
663 ap_log_rerror(APLOG_MARK, APLOG_ERR, r,
664 "Cannot store delegated credential (%s)",
665 get_gss_error(r->pool, min_stat, "gss_krb5_copy_ccache"));
669 krb5_cc_close(context, ccache);
675 krb5_free_principal(context, princ);
677 krb5_cc_destroy(context, ccache);
678 krb5_free_context(context);
683 get_gss_creds(request_rec *r,
684 kerb_auth_config *conf,
685 gss_cred_id_t *server_creds)
687 gss_buffer_desc input_token = GSS_C_EMPTY_BUFFER;
688 OM_uint32 major_status, minor_status, minor_status2;
689 gss_name_t server_name = GSS_C_NO_NAME;
691 if (conf->service_name) {
692 input_token.value = conf->service_name;
693 input_token.length = strlen(conf->service_name) + 1;
696 input_token.value = "khttp";
697 input_token.length = 6;
699 major_status = gss_import_name(&minor_status, &input_token,
700 (conf->service_name) ?
701 GSS_C_NT_USER_NAME : GSS_C_NT_HOSTBASED_SERVICE,
703 if (GSS_ERROR(major_status)) {
704 ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_NOTICE, r,
705 "%s", get_gss_error(r->pool, minor_status,
706 "gss_import_name() failed"));
711 if (conf->krb_5_keytab)
712 setenv("KRB5_KTNAME", conf->krb_5_keytab, 1);
715 major_status = gss_acquire_cred(&minor_status, server_name, GSS_C_INDEFINITE,
716 GSS_C_NO_OID_SET, GSS_C_ACCEPT,
717 server_creds, NULL, NULL);
718 gss_release_name(&minor_status2, &server_name);
720 if (conf->krb_5_keytab)
721 unsetenv("KRB5_KTNAME");
723 if (GSS_ERROR(major_status)) {
724 ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_NOTICE, r,
725 "%s", get_gss_error(r->pool, minor_status,
726 "gss_acquire_cred() failed"));
734 authenticate_user_gss(request_rec *r,
735 kerb_auth_config *conf,
736 const char *auth_line)
738 OM_uint32 major_status, minor_status, minor_status2;
739 gss_buffer_desc input_token = GSS_C_EMPTY_BUFFER;
740 gss_buffer_desc output_token = GSS_C_EMPTY_BUFFER;
741 const char *auth_param = NULL;
743 gss_name_t client_name = GSS_C_NO_NAME;
744 gss_cred_id_t delegated_cred = GSS_C_NO_CREDENTIAL;
746 if (gss_connection == NULL) {
747 gss_connection = ap_pcalloc(r->connection->pool, sizeof(*gss_connection));
748 if (gss_connection == NULL) {
749 ap_log_rerror(APLOG_MARK, APLOG_ERR, r,
750 "ap_pcalloc() failed (not enough memory)");
754 memset(gss_connection, 0, sizeof(*gss_connection));
755 ap_register_cleanup(r->connection->pool, gss_connection, cleanup_gss_connection, ap_null_cleanup);
758 if (gss_connection->server_creds == GSS_C_NO_CREDENTIAL) {
759 ret = get_gss_creds(r, conf, &gss_connection->server_creds);
764 /* ap_getword() shifts parameter */
765 auth_param = ap_getword_white(r->pool, &auth_line);
766 if (auth_param == NULL) {
767 ap_log_rerror(APLOG_MARK, APLOG_ERR, r,
768 "No Authorization parameter in request from client");
769 ret = HTTP_UNAUTHORIZED;
773 input_token.length = ap_base64decode_len(auth_param);
774 input_token.value = ap_pcalloc(r->connection->pool, input_token.length);
775 if (input_token.value == NULL) {
776 ap_log_rerror(APLOG_MARK, APLOG_ERR, r,
777 "ap_pcalloc() failed (not enough memory)");
781 input_token.length = ap_base64decode(input_token.value, auth_param);
783 major_status = gss_accept_sec_context(&minor_status,
784 &gss_connection->context,
785 gss_connection->server_creds,
787 GSS_C_NO_CHANNEL_BINDINGS,
794 if (output_token.length) {
798 len = ap_base64encode_len(output_token.length);
799 token = ap_pcalloc(r->connection->pool, len + 1);
801 ap_log_rerror(APLOG_MARK, APLOG_ERR, r,
802 "ap_pcalloc() failed (not enough memory)");
804 gss_release_buffer(&minor_status2, &output_token);
807 ap_base64encode(token, output_token.value, output_token.length);
809 ap_table_set(r->err_headers_out, "WWW-Authenticate",
810 ap_pstrcat(r->pool, "GSS-Negotiate ", token, NULL));
811 gss_release_buffer(&minor_status2, &output_token);
814 if (GSS_ERROR(major_status)) {
815 ap_log_rerror(APLOG_MARK, APLOG_ERR, r,
816 "%s", get_gss_error(r->pool, minor_status,
817 "gss_accept_sec_context() failed"));
818 ret = HTTP_UNAUTHORIZED;
822 if (major_status & GSS_S_CONTINUE_NEEDED) {
823 /* Some GSSAPI mechanism (eg GSI from Globus) may require multiple
824 * iterations to establish authentication */
825 ret = HTTP_UNAUTHORIZED;
829 major_status = gss_export_name(&minor_status, client_name, &output_token);
830 gss_release_name(&minor_status, &client_name);
831 if (GSS_ERROR(major_status)) {
832 ap_log_rerror(APLOG_MARK, APLOG_ERR, r,
833 "%s", get_gss_error(r->pool, minor_status,
834 "gss_export_name() failed"));
839 r->connection->ap_auth_type = "Negotiate";
840 r->connection->user = ap_pstrdup(r->pool, output_token.value);
842 if (conf->krb_save_credentials && delegated_cred != GSS_C_NO_CREDENTIAL)
843 store_gss_creds(r, conf, (char *)output_token.value, delegated_cred);
845 gss_release_buffer(&minor_status, &output_token);
849 /* If the user comes from a realm specified by configuration don't include
850 its realm name in the username so that the authorization routine could
851 work for both Password-based and Ticket-based authentication. It's
852 administrators responsibility to include only such realm that have
853 unified principal instances, i.e. if the same principal name occures in
854 multiple realms, it must be always assigned to a single user.
856 p = strchr(r->connection->user, '@');
858 const char *realms = conf->gss_krb5_realms;
860 while (realms && *realms) {
861 if (strcmp(p+1, ap_getword_white(r->pool, &realms)) == 0) {
873 gss_release_cred(&minor_status, &delegated_cred);
875 if (output_token.length)
876 gss_release_buffer(&minor_status, &output_token);
878 if (client_name != GSS_C_NO_NAME)
879 gss_release_name(&minor_status, &client_name);
887 note_auth_failure(request_rec *r, const kerb_auth_config *conf)
889 const char *auth_name = NULL;
891 /* get the user realm specified in .htaccess */
892 auth_name = ap_auth_name(r);
894 /* XXX should the WWW-Authenticate header be cleared first? */
896 if (conf->krb_method_gssapi)
897 ap_table_add(r->err_headers_out, "WWW-Authenticate", "GSS-Negotiate ");
898 if (conf->krb_method_k5pass)
899 ap_table_add(r->err_headers_out, "WWW-Authenticate",
900 ap_pstrcat(r->pool, "Basic realm=\"", auth_name, "\"", NULL));
904 if (conf->krb_method_k4pass)
905 ap_table_add(r->err_headers_out, "WWW-Authenticate",
906 ap_pstrcat(r->pool, "Basic realm=\"", auth_name, "\"", NULL));
910 int kerb_authenticate_user(request_rec *r)
912 kerb_auth_config *conf =
913 (kerb_auth_config *) ap_get_module_config(r->per_dir_config,
915 const char *auth_type = NULL;
916 const char *auth_line = NULL;
917 const char *type = NULL;
920 /* get the type specified in .htaccess */
921 type = ap_auth_type(r);
924 if (type != NULL && strcasecmp(type, "KerberosV5") == 0) {
925 ap_log_rerror(APLOG_MARK, APLOG_WARNING, r,
926 "The use of KerberosV5 in AuthType is obsolete, please consider using the AuthKerberos option");
927 conf->krb_auth_enable = 1;
932 if (type != NULL && strcasecmp(type, "KerberosV4") == 0) {
933 ap_log_rerror(APLOG_MARK, APLOG_WARNING, r,
934 "The use of KerberosV4 in AuthType is obsolete, please consider using the AuthKerberos option");
935 conf->krb_auth_enable = 1;
939 if (!conf->krb_auth_enable)
942 /* get what the user sent us in the HTTP header */
943 auth_line = MK_TABLE_GET(r->headers_in, "Authorization");
945 note_auth_failure(r, conf);
946 return HTTP_UNAUTHORIZED;
948 auth_type = ap_getword_white(r->pool, &auth_line);
950 ret = HTTP_UNAUTHORIZED;
953 if (conf->krb_method_gssapi &&
954 strcasecmp(auth_type, "GSS-Negotiate") == 0) {
955 ret = authenticate_user_gss(r, conf, auth_line);
956 } else if (conf->krb_method_k5pass &&
957 strcasecmp(auth_type, "Basic") == 0) {
958 ret = authenticate_user_krb5pwd(r, conf, auth_line);
963 if (ret == HTTP_UNAUTHORIZED && conf->krb_method_k4pass &&
964 strcasecmp(auth_type, "Basic") == 0)
965 ret = authenticate_user_krb4pwd(r, conf, auth_line);
968 if (ret == HTTP_UNAUTHORIZED)
969 note_auth_failure(r, conf);
976 int kerb_check_user_access(request_rec *r)
980 const MK_ARRAY_HEADER *reqs_arr = ap_requires(r);
982 kerb_auth_config *conf =
983 (kerb_auth_config *)ap_get_module_config(r->per_dir_config,
986 if (reqs_arr == NULL) {
989 reqs = (require_line *)reqs_arr->elts;
991 for (x = 0; x < reqs_arr->nelts; x++) {
992 t = reqs[x].requirement;
993 w = ap_getword_white(r->pool, &t);
994 if (strcmp(w, "realm") == 0) {
995 while (t[0] != '\0') {
996 w = ap_getword_conf(r->pool, &t);
997 if (strcmp(MK_USER, w) == 0) {
1011 /***************************************************************************
1012 Module Setup/Configuration
1013 ***************************************************************************/
1015 module MODULE_VAR_EXPORT kerb_auth_module = {
1016 STANDARD_MODULE_STUFF,
1017 NULL, /* module initializer */
1018 kerb_dir_create_config, /* per-directory config creator */
1019 NULL, /* per-directory config merger */
1020 NULL, /* per-server config creator */
1021 NULL, /* per-server config merger */
1022 kerb_auth_cmds, /* command table */
1023 NULL, /* [ 9] content handlers */
1024 NULL, /* [ 2] URI-to-filename translation */
1025 kerb_authenticate_user, /* [ 5] check/validate user_id */
1026 NULL, /* [ 6] check user_id is valid *here* */
1027 NULL, /* [ 4] check access by host address */
1028 NULL, /* [ 7] MIME type checker/setter */
1029 NULL, /* [ 8] fixups */
1030 NULL, /* [10] logger */
1031 NULL, /* [ 3] header parser */
1032 NULL, /* process initialization */
1033 NULL, /* process exit/cleanup */
1034 NULL /* [ 1] post read_request handling */
1037 void kerb_register_hooks(apr_pool_t *p)
1039 ap_hook_check_user_id(kerb_authenticate_user, NULL, NULL, APR_HOOK_MIDDLE);
1042 module AP_MODULE_DECLARE_DATA kerb_auth_module =
1044 STANDARD20_MODULE_STUFF,
1045 kerb_dir_create_config, /* create per-dir conf structures */
1046 NULL, /* merge per-dir conf structures */
1047 NULL, /* create per-server conf structures */
1048 NULL, /* merge per-server conf structures */
1049 kerb_auth_cmds, /* table of configuration directives */
1050 kerb_register_hooks /* register hooks */