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."),
151 gss_ctx_id_t context;
152 gss_cred_id_t server_creds;
155 static gss_connection_t *gss_connection = NULL;
159 /***************************************************************************
160 Auth Configuration Initialization
161 ***************************************************************************/
162 static void *kerb_dir_create_config(MK_POOL *p, char *d)
164 kerb_auth_config *rec;
166 rec = (kerb_auth_config *) ap_pcalloc(p, sizeof(kerb_auth_config));
167 ((kerb_auth_config *)rec)->krb_auth_enable = 1;
168 ((kerb_auth_config *)rec)->krb_fail_status = HTTP_UNAUTHORIZED;
170 ((kerb_auth_config *)rec)->krb_method_k5pass = 1;
171 ((kerb_auth_config *)rec)->krb_method_gssapi = 1;
174 ((kerb_auth_config *)rec)->krb_method_k4pass = 1;
181 static const char *kerb_set_fail_slot(cmd_parms *cmd, void *struct_ptr,
184 int offset = (int) (long) cmd->info;
185 if (!strncasecmp(arg, "unauthorized", 12))
186 *(int *) ((char *)struct_ptr + offset) = HTTP_UNAUTHORIZED;
187 else if (!strncasecmp(arg, "forbidden", 9))
188 *(int *) ((char *)struct_ptr + offset) = HTTP_FORBIDDEN;
189 else if (!strncasecmp(arg, "declined", 8))
190 *(int *) ((char *)struct_ptr + offset) = DECLINED;
192 return "KrbAuthFailStatus must be Forbidden, Unauthorized, or Declined.";
198 /***************************************************************************
199 Username/Password Validation for Krb4
200 ***************************************************************************/
201 int kerb4_password_validate(request_rec *r, const char *user, const char *pass)
203 kerb_auth_config *conf =
204 (kerb_auth_config *)ap_get_module_config(r->per_dir_config,
207 int lifetime = DEFAULT_TKT_LIFE;
209 char *username = NULL;
210 char *instance = NULL;
213 username = (char *)ap_pstrdup(r->pool, user);
218 instance = strchr(username, '.');
226 realm = strchr(username, '@');
234 if (conf->krb_lifetime) {
235 lifetime = atoi(conf->krb_lifetime);
238 if (conf->krb_force_instance) {
239 instance = conf->krb_force_instance;
242 if (conf->krb_save_credentials) {
243 tfname = (char *)malloc(sizeof(char) * MAX_STRING_LEN);
244 sprintf(tfname, "%s/k5cc_ap_%s",
245 conf->krb_tmp_dir ? conf->krb_tmp_dir : "/tmp",
248 if (!strcmp(instance, "")) {
249 tfname = strcat(tfname, ".");
250 tfname = strcat(tfname, instance);
253 if (!strcmp(realm, "")) {
254 tfname = strcat(tfname, ".");
255 tfname = strcat(tfname, realm);
258 for (c = tfname + strlen(conf->krb_tmp_dir ? conf->krb_tmp_dir :
259 "/tmp") + 1; *c; c++) {
264 krb_set_tkt_string(tfname);
267 if (!strcmp(realm, "")) {
268 realm = (char *)malloc(sizeof(char) * (REALM_SZ + 1));
269 ret = krb_get_lrealm(realm, 1);
274 ret = krb_get_pw_in_tkt((char *)user, instance, realm, "krbtgt", realm,
275 lifetime, (char *)pass);
290 /***************************************************************************
291 Username/Password Validation for Krb5
292 ***************************************************************************/
295 krb5_verify_user(krb5_context context, krb5_principal principal,
296 krb5_ccache ccache, const char *password, krb5_boolean secure,
300 krb5_context kcontext;
301 krb5_principal server, client;
304 krb5_flags options = 0;
305 krb5_principal me = NULL;
306 krb5_data tgtname = {
312 memset((char *)&my_creds, 0, sizeof(my_creds));
313 my_creds.client = principal;
315 if (krb5_build_principal_ext(kcontext, &server,
316 krb5_princ_realm(kcontext, me)->length,
317 krb5_princ_realm(kcontext, me)->data,
318 tgtname.length, tgtname.data,
319 krb5_princ_realm(kcontext, me)->length,
320 krb5_princ_realm(kcontext, me)->data,
325 my_creds.server = server;
326 if (krb5_timeofday(kcontext, &now))
329 my_creds.times.starttime = 0;
331 my_creds.times.endtime = now + lifetime;
332 my_creds.times.renew_till = now + renewal;
335 ret = krb5_get_in_tkt_with_password(kcontext, options, 0, NULL, 0,
336 password, ccache, &my_creds, 0);
347 krb5_cache_cleanup(void *data)
349 krb5_context context;
351 krb5_error_code problem;
352 char *cache_name = (char *) data;
354 problem = krb5_init_context(&context);
356 ap_log_error(APLOG_MARK, APLOG_ERR, NULL, "krb5_init_context() failed");
360 problem = krb5_cc_resolve(context, cache_name, &cache);
362 ap_log_error(APLOG_MARK, APLOG_ERR, NULL,
363 "krb5_cc_resolve() failed (%s: %s)",
364 cache_name, krb5_get_err_text(context, problem));
368 krb5_cc_destroy(context, cache);
369 krb5_free_context(context);
373 create_krb5_ccache(krb5_context kcontext,
375 kerb_auth_config *conf,
376 krb5_principal princ,
379 char *c, ccname[MAX_STRING_LEN];
380 krb5_error_code problem;
383 krb5_ccache tmp_ccache = NULL;
385 snprintf(ccname, sizeof(ccname), "FILE:%s/k5cc_ap_%s",
386 conf->krb_tmp_dir ? conf->krb_tmp_dir : "/tmp",
389 for (c = ccname + strlen(conf->krb_tmp_dir ? conf->krb_tmp_dir :
390 "/tmp") + 1; *c; c++) {
395 problem = krb5_cc_resolve(kcontext, ccname, &tmp_ccache);
397 snprintf(errstr, sizeof(errstr),
398 "krb5_cc_resolve() failed: %s",
399 krb5_get_err_text(kcontext, problem));
400 ap_log_reason (errstr, r->uri, r);
405 problem = krb5_cc_initialize(kcontext, tmp_ccache, princ);
407 snprintf(errstr, sizeof(errstr),
408 "krb5_cc_initialize() failed: %s",
409 krb5_get_err_text(kcontext, problem));
410 ap_log_reason (errstr, r->uri, r);
415 ap_table_setn(r->subprocess_env, "KRB5CCNAME", ccname);
416 ap_register_cleanup(r->pool, ccname,
417 krb5_cache_cleanup, ap_null_cleanup);
419 *ccache = tmp_ccache;
426 krb5_cc_destroy(kcontext, tmp_ccache);
432 store_krb5_creds(krb5_context kcontext,
434 kerb_auth_config *conf,
435 krb5_ccache delegated_cred)
438 krb5_error_code problem;
439 krb5_principal princ;
443 problem = krb5_cc_get_principal(kcontext, delegated_cred, &princ);
445 snprintf(errstr, sizeof(errstr), "krb5_cc_get_principal() failed: %s",
446 krb5_get_err_text(kcontext, problem));
450 ret = create_krb5_ccache(kcontext, r, conf, princ, &ccache);
452 krb5_free_principal(kcontext, princ);
456 problem = krb5_cc_copy_cache(kcontext, delegated_cred, ccache);
457 krb5_free_principal(kcontext, princ);
459 snprintf(errstr, sizeof(errstr), "krb5_cc_copy_cache() failed: %s",
460 krb5_get_err_text(kcontext, problem));
461 krb5_cc_destroy(kcontext, ccache);
465 krb5_cc_close(kcontext, ccache);
470 int authenticate_user_krb5pwd(request_rec *r,
471 kerb_auth_config *conf,
472 const char *auth_line)
474 const char *sent_pw = NULL;
475 const char *realms = NULL;
476 krb5_context kcontext;
477 krb5_error_code code;
478 krb5_principal client = NULL;
479 krb5_ccache ccache = NULL;
482 code = krb5_init_context(&kcontext);
484 ap_log_rerror(APLOG_MARK, APLOG_NOERRNO, r,
485 "Cannot initialize Kerberos5 context (%d)", code);
489 sent_pw = ap_uudecode(r->pool, auth_line);
490 r->connection->user = ap_getword (r->pool, &sent_pw, ':');
491 r->connection->ap_auth_type = "Basic";
493 /* do not allow user to override realm setting of server */
494 if (strchr(r->connection->user,'@')) {
495 ap_log_rerror(APLOG_MARK, APLOG_NOERRNO, r,
496 "specifying realm in user name is prohibited");
497 ret = HTTP_UNAUTHORIZED;
502 code = krb5_cc_gen_new(kcontext, &krb5_mcc_ops, &ccache);
504 code = krb5_mcc_generate_new(kcontext, &ccache);
507 ap_log_rerror(APLOG_MARK, APLOG_NOERRNO, r,
508 "Cannot generate new ccache: %s",
509 krb5_get_err_text(kcontext, code));
514 realms = conf->krb_auth_realms;
516 if (realms && krb5_set_default_realm(kcontext,
517 ap_getword_white(r->pool, &realms)))
520 code = krb5_parse_name(kcontext, r->connection->user, &client);
524 code = krb5_verify_user(kcontext, client, ccache, sent_pw, 1, "khttp");
525 krb5_free_principal(kcontext, client);
529 /* ap_getword_white() used above shifts the parameter, so it's not
530 needed to touch the realms variable */
531 } while (realms && *realms);
533 memset((char *)sent_pw, 0, strlen(sent_pw));
536 ap_log_rerror(APLOG_MARK, APLOG_NOERRNO, r,
537 "Verifying krb5 password failed: %s",
538 krb5_get_err_text(kcontext, code));
539 ret = HTTP_UNAUTHORIZED;
543 if (conf->krb_save_credentials) {
544 ret = store_krb5_creds(kcontext, r, conf, ccache);
545 if (ret) /* Ignore error ?? */
553 krb5_free_principal(kcontext, client);
555 krb5_cc_destroy(kcontext, ccache);
556 krb5_free_context(kcontext);
561 /*********************************************************************
562 * GSSAPI Authentication
563 ********************************************************************/
566 get_gss_error(pool *p, OM_uint32 error_status, char *prefix)
568 OM_uint32 maj_stat, min_stat;
569 OM_uint32 msg_ctx = 0;
570 gss_buffer_desc status_string;
574 snprintf(buf, sizeof(buf), "%s: ", prefix);
577 maj_stat = gss_display_status (&min_stat,
583 if (sizeof(buf) > len + status_string.length + 1) {
584 sprintf(buf+len, "%s:", (char*) status_string.value);
585 len += status_string.length;
587 gss_release_buffer(&min_stat, &status_string);
588 } while (!GSS_ERROR(maj_stat) && msg_ctx != 0);
590 return (ap_pstrdup(p, buf));
594 cleanup_gss_connection(void *data)
596 OM_uint32 minor_status;
597 gss_connection_t *gss_conn = (gss_connection_t *)data;
601 if (gss_conn->context != GSS_C_NO_CONTEXT)
602 gss_delete_sec_context(&minor_status, &gss_conn->context,
604 if (gss_conn->server_creds != GSS_C_NO_CREDENTIAL)
605 gss_release_cred(&minor_status, &gss_conn->server_creds);
609 store_gss_creds(request_rec *r, kerb_auth_config *conf, char *princ_name,
610 gss_cred_id_t delegated_cred)
612 OM_uint32 maj_stat, min_stat;
613 krb5_principal princ = NULL;
614 krb5_ccache ccache = NULL;
615 krb5_error_code problem;
616 krb5_context context;
617 int ret = SERVER_ERROR;
619 problem = krb5_init_context(&context);
621 ap_log_rerror(APLOG_MARK, APLOG_ERR, r,
622 "Cannot initialize krb5 context");
626 problem = krb5_parse_name(context, princ_name, &princ);
628 ap_log_rerror(APLOG_MARK, APLOG_ERR, r,
629 "Cannot parse delegated username (%s)", krb5_get_err_text(context, problem));
633 problem = create_krb5_ccache(context, r, conf, princ, &ccache);
635 ap_log_rerror(APLOG_MARK, APLOG_ERR, r,
636 "Cannot create krb5 ccache (%s)", krb5_get_err_text(context, problem));
640 maj_stat = gss_krb5_copy_ccache(&min_stat, delegated_cred, ccache);
641 if (GSS_ERROR(maj_stat)) {
642 ap_log_rerror(APLOG_MARK, APLOG_ERR, r,
643 "Cannot store delegated credential (%s)",
644 get_gss_error(r->pool, min_stat, "gss_krb5_copy_ccache"));
648 krb5_cc_close(context, ccache);
654 krb5_free_principal(context, princ);
656 krb5_cc_destroy(context, ccache);
657 krb5_free_context(context);
662 get_gss_creds(request_rec *r,
663 kerb_auth_config *conf,
664 gss_cred_id_t *server_creds)
666 gss_buffer_desc input_token = GSS_C_EMPTY_BUFFER;
667 OM_uint32 major_status, minor_status, minor_status2;
668 gss_name_t server_name = GSS_C_NO_NAME;
670 if (conf->service_name) {
671 input_token.value = conf->service_name;
672 input_token.length = strlen(conf->service_name) + 1;
675 input_token.value = "khttp";
676 input_token.length = 6;
678 major_status = gss_import_name(&minor_status, &input_token,
679 (conf->service_name) ?
680 GSS_C_NT_USER_NAME : GSS_C_NT_HOSTBASED_SERVICE,
682 if (GSS_ERROR(major_status)) {
683 ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_NOTICE, r,
684 "%s", get_gss_error(r->pool, minor_status,
685 "gss_import_name() failed"));
690 if (conf->krb_5_keytab)
691 setenv("KRB5_KTNAME", conf->krb_5_keytab, 1);
694 major_status = gss_acquire_cred(&minor_status, server_name, GSS_C_INDEFINITE,
695 GSS_C_NO_OID_SET, GSS_C_ACCEPT,
696 server_creds, NULL, NULL);
697 gss_release_name(&minor_status2, &server_name);
699 if (conf->krb_5_keytab)
700 unsetenv("KRB5_KTNAME");
702 if (GSS_ERROR(major_status)) {
703 ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_NOTICE, r,
704 "%s", get_gss_error(r->pool, minor_status,
705 "gss_acquire_cred() failed"));
713 authenticate_user_gss(request_rec *r,
714 kerb_auth_config *conf,
715 const char *auth_line)
717 OM_uint32 major_status, minor_status, minor_status2;
718 gss_buffer_desc input_token = GSS_C_EMPTY_BUFFER;
719 gss_buffer_desc output_token = GSS_C_EMPTY_BUFFER;
720 const char *auth_param = NULL;
722 gss_name_t client_name = GSS_C_NO_NAME;
723 gss_cred_id_t delegated_cred = GSS_C_NO_CREDENTIAL;
725 if (gss_connection == NULL) {
726 gss_connection = ap_pcalloc(r->connection->pool, sizeof(*gss_connection));
727 if (gss_connection == NULL) {
728 ap_log_rerror(APLOG_MARK, APLOG_ERR, r,
729 "ap_pcalloc() failed (not enough memory)");
733 memset(gss_connection, 0, sizeof(*gss_connection));
734 ap_register_cleanup(r->connection->pool, gss_connection, cleanup_gss_connection, ap_null_cleanup);
737 if (gss_connection->server_creds == GSS_C_NO_CREDENTIAL) {
738 ret = get_gss_creds(r, conf, &gss_connection->server_creds);
743 /* ap_getword() shifts parameter */
744 auth_param = ap_getword_white(r->pool, &auth_line);
745 if (auth_param == NULL) {
746 ap_log_rerror(APLOG_MARK, APLOG_ERR, r,
747 "No Authorization parameter in request from client");
748 ret = HTTP_UNAUTHORIZED;
752 input_token.length = ap_base64decode_len(auth_param);
753 input_token.value = ap_pcalloc(r->connection->pool, input_token.length);
754 if (input_token.value == NULL) {
755 ap_log_rerror(APLOG_MARK, APLOG_ERR, r,
756 "ap_pcalloc() failed (not enough memory)");
760 input_token.length = ap_base64decode(input_token.value, auth_param);
762 major_status = gss_accept_sec_context(&minor_status,
763 &gss_connection->context,
764 gss_connection->server_creds,
766 GSS_C_NO_CHANNEL_BINDINGS,
773 if (output_token.length) {
777 len = ap_base64encode_len(output_token.length);
778 token = ap_pcalloc(r->connection->pool, len + 1);
780 ap_log_rerror(APLOG_MARK, APLOG_ERR, r,
781 "ap_pcalloc() failed (not enough memory)");
783 gss_release_buffer(&minor_status2, &output_token);
786 ap_base64encode(token, output_token.value, output_token.length);
788 ap_table_set(r->err_headers_out, "WWW-Authenticate",
789 ap_pstrcat(r->pool, "GSS-Negotiate ", token, NULL));
790 gss_release_buffer(&minor_status2, &output_token);
793 if (GSS_ERROR(major_status)) {
794 ap_log_rerror(APLOG_MARK, APLOG_ERR, r,
795 "%s", get_gss_error(r->pool, minor_status,
796 "gss_accept_sec_context() failed"));
797 ret = HTTP_UNAUTHORIZED;
801 if (major_status & GSS_S_CONTINUE_NEEDED) {
802 /* Some GSSAPI mechanism (eg GSI from Globus) may require multiple
803 * iterations to establish authentication */
804 ret = HTTP_UNAUTHORIZED;
808 major_status = gss_export_name(&minor_status, client_name, &output_token);
809 gss_release_name(&minor_status, &client_name);
810 if (GSS_ERROR(major_status)) {
811 ap_log_rerror(APLOG_MARK, APLOG_ERR, r,
812 "%s", get_gss_error(r->pool, minor_status,
813 "gss_export_name() failed"));
818 r->connection->ap_auth_type = "Negotiate";
819 r->connection->user = ap_pstrdup(r->pool, output_token.value);
821 if (conf->krb_save_credentials && delegated_cred != GSS_C_NO_CREDENTIAL)
822 store_gss_creds(r, conf, (char *)output_token.value, delegated_cred);
824 gss_release_buffer(&minor_status, &output_token);
828 /* If the user comes from a realm specified by configuration don't include
829 its realm name in the username so that the authorization routine could
830 work for both Password-based and Ticket-based authentication. It's
831 administrators responsibility to include only such realm that have
832 unified principal instances, i.e. if the same principal name occures in
833 multiple realms, it must be always assigned to a single user.
835 p = strchr(r->connection->user, '@');
837 const char *realms = conf->gss_krb5_realms;
839 while (realms && *realms) {
840 if (strcmp(p+1, ap_getword_white(r->pool, &realms)) == 0) {
852 gss_release_cred(&minor_status, &delegated_cred);
854 if (output_token.length)
855 gss_release_buffer(&minor_status, &output_token);
857 if (client_name != GSS_C_NO_NAME)
858 gss_release_name(&minor_status, &client_name);
866 note_auth_failure(request_rec *r, const kerb_auth_config *conf)
868 const char *auth_name = NULL;
870 /* get the user realm specified in .htaccess */
871 auth_name = ap_auth_name(r);
873 /* XXX should the WWW-Authenticate header be cleared first? */
875 if (conf->krb_method_gssapi)
876 ap_table_add(r->err_headers_out, "WWW-Authenticate", "GSS-Negotiate ");
877 if (conf->krb_method_k5pass)
878 ap_table_add(r->err_headers_out, "WWW-Authenticate",
879 ap_pstrcat(r->pool, "Basic realm=\"", auth_name, "\"", NULL));
883 if (conf->krb_method_k4pass)
884 ap_table_add(r->err_headers_out, "WWW-Authenticate",
885 ap_pstrcat(r->pool, "Basic realm=\"", auth_name, "\"", NULL));
889 int kerb_authenticate_user(request_rec *r)
891 kerb_auth_config *conf =
892 (kerb_auth_config *) ap_get_module_config(r->per_dir_config,
894 const char *auth_type = NULL;
895 const char *auth_line = NULL;
896 const char *type = NULL;
899 /* get the type specified in .htaccess */
900 type = ap_auth_type(r);
903 if (type != NULL && strcasecmp(type, "KerberosV5") == 0) {
904 ap_log_rerror(APLOG_MARK, APLOG_WARNING, r,
905 "The use of KerberosV5 in AuthType is obsolete, please consider using the AuthKerberos option");
906 conf->krb_auth_enable = 1;
911 if (type != NULL && strcasecmp(type, "KerberosV4") == 0) {
912 ap_log_rerror(APLOG_MARK, APLOG_WARNING, r,
913 "The use of KerberosV4 in AuthType is obsolete, please consider using the AuthKerberos option");
914 conf->krb_auth_enable = 1;
918 if (!conf->krb_auth_enable)
921 /* get what the user sent us in the HTTP header */
922 auth_line = MK_TABLE_GET(r->headers_in, "Authorization");
924 note_auth_failure(r, conf);
925 return HTTP_UNAUTHORIZED;
927 auth_type = ap_getword_white(r->pool, &auth_line);
929 ret = HTTP_UNAUTHORIZED;
932 if (conf->krb_method_gssapi &&
933 strcasecmp(auth_type, "GSS-Negotiate") == 0) {
934 ret = authenticate_user_gss(r, conf, auth_line);
935 } else if (conf->krb_method_k5pass &&
936 strcasecmp(auth_type, "Basic") == 0) {
937 ret = authenticate_user_krb5pwd(r, conf, auth_line);
942 if (ret == HTTP_UNAUTHORIZED && conf->krb_method_k4pass &&
943 strcasecmp(auth_type, "Basic") == 0)
944 ret = authenticate_user_krb4pwd(r, conf, auth_line);
947 if (ret == HTTP_UNAUTHORIZED)
948 note_auth_failure(r, conf);
955 int kerb_check_user_access(request_rec *r)
959 const MK_ARRAY_HEADER *reqs_arr = ap_requires(r);
961 kerb_auth_config *conf =
962 (kerb_auth_config *)ap_get_module_config(r->per_dir_config,
965 if (reqs_arr == NULL) {
968 reqs = (require_line *)reqs_arr->elts;
970 for (x = 0; x < reqs_arr->nelts; x++) {
971 t = reqs[x].requirement;
972 w = ap_getword_white(r->pool, &t);
973 if (strcmp(w, "realm") == 0) {
974 while (t[0] != '\0') {
975 w = ap_getword_conf(r->pool, &t);
976 if (strcmp(MK_USER, w) == 0) {
990 /***************************************************************************
991 Module Setup/Configuration
992 ***************************************************************************/
994 module MODULE_VAR_EXPORT kerb_auth_module = {
995 STANDARD_MODULE_STUFF,
996 NULL, /* module initializer */
997 kerb_dir_create_config, /* per-directory config creator */
998 NULL, /* per-directory config merger */
999 NULL, /* per-server config creator */
1000 NULL, /* per-server config merger */
1001 kerb_auth_cmds, /* command table */
1002 NULL, /* [ 9] content handlers */
1003 NULL, /* [ 2] URI-to-filename translation */
1004 kerb_authenticate_user, /* [ 5] check/validate user_id */
1005 NULL, /* [ 6] check user_id is valid *here* */
1006 NULL, /* [ 4] check access by host address */
1007 NULL, /* [ 7] MIME type checker/setter */
1008 NULL, /* [ 8] fixups */
1009 NULL, /* [10] logger */
1010 NULL, /* [ 3] header parser */
1011 NULL, /* process initialization */
1012 NULL, /* process exit/cleanup */
1013 NULL /* [ 1] post read_request handling */
1016 void kerb_register_hooks(apr_pool_t *p)
1018 ap_hook_check_user_id(kerb_authenticate_user, NULL, NULL, APR_HOOK_MIDDLE);
1021 module AP_MODULE_DECLARE_DATA kerb_auth_module =
1023 STANDARD20_MODULE_STUFF,
1024 kerb_dir_create_config, /* create per-dir conf structures */
1025 NULL, /* merge per-dir conf structures */
1026 NULL, /* create per-server conf structures */
1027 NULL, /* merge per-server conf structures */
1028 kerb_auth_cmds, /* table of configuration directives */
1029 kerb_register_hooks /* register hooks */