7 #include "http_config.h"
10 #include "http_protocol.h"
11 #include "http_request.h"
23 module kerb_auth_module;
25 module AP_MODULE_DECLARE_DATA kerb_auth_module;
28 /***************************************************************************
29 Macros To Ease Compatibility
30 ***************************************************************************/
33 #define MK_TABLE_GET ap_table_get
34 #define MK_TABLE_SET ap_table_set
35 #define MK_TABLE_TYPE table
36 #define MK_PSTRDUP ap_pstrdup
37 #define MK_USER r->connection->user
38 #define MK_AUTH_TYPE r->connection->ap_auth_type
39 #define MK_ARRAY_HEADER array_header
40 #define apr_status_t int
42 #define MK_POOL apr_pool_t
43 #define MK_TABLE_GET apr_table_get
44 #define MK_TABLE_SET apr_table_set
45 #define MK_TABLE_TYPE apr_table_t
46 #define MK_PSTRDUP apr_pstrdup
47 #define MK_USER r->user
48 #define MK_AUTH_TYPE r->ap_auth_type
49 #define MK_ARRAY_HEADER apr_array_header_t
55 /***************************************************************************
56 Auth Configuration Structure
57 ***************************************************************************/
60 char *krb_auth_realms;
62 char *krb_force_instance;
63 int krb_save_credentials;
70 int krb_method_gssapi;
71 int krb_method_k5pass;
75 int krb_method_k4pass;
80 #define command(name, func, var, type, usage) \
82 (void*)XtOffsetOf(kerb_auth_config, var), \
83 OR_AUTHCFG, type, usage }
85 #define command(name, func, var, type, usage) \
86 AP_INIT_ ## type (name, func, \
87 (void*)APR_XtOffsetOf(kerb_auth_config, var), \
91 static const command_rec kerb_auth_cmds[] = {
92 command("AuthKerberos", ap_set_flag_slot, krb_auth_enable,
93 FLAG, "Permit Kerberos auth without AuthType requirement."),
95 command("KrbAuthRealm", ap_set_string_slot, krb_auth_realms,
96 ITERATE, "Realms to attempt authentication against (can be multiple)."),
98 command("KrbAuthRealms", ap_set_string_slot, krb_auth_realms,
99 ITERATE, "Alias for KrbAuthRealm."),
102 command("KrbFailStatus", kerb_set_fail_slot, krb_fail_status,
103 TAKE1, "If auth fails, return status set here."),
106 command("KrbForceInstance", ap_set_string_slot, krb_force_instance,
107 TAKE1, "Force authentication against an instance specified here."),
109 command("KrbSaveCredentials", ap_set_flag_slot, krb_save_credentials,
110 FLAG, "Save and store credentials/tickets retrieved during auth."),
112 command("KrbSaveTickets", ap_set_flag_slot, krb_save_credentials,
113 FLAG, "Alias for KrbSaveCredentials."),
115 command("KrbTmpdir", ap_set_string_slot, krb_tmp_dir,
116 TAKE1, "Path to store ticket files and such in."),
118 command("KrbServiceName", ap_set_string_slot, service_name,
119 TAKE1, "Kerberos service name to be used by apache."),
122 command("KrbLifetime", ap_set_string_slot, krb_lifetime,
123 TAKE1, "Kerberos ticket lifetime."),
127 command("Krb5Keytab", ap_set_file_slot, krb_5_keytab,
128 TAKE1, "Location of Kerberos V5 keytab file."),
130 command("KrbForwardable", ap_set_flag_slot, krb_forwardable,
131 FLAG, "Credentials retrieved will be flagged as forwardable."),
133 command("KrbMethodGSSAPI", ap_set_flag_slot, krb_method_gssapi,
134 FLAG, "Enable GSSAPI authentication."),
136 command("KrbMethodK5Pass", ap_set_flag_slot, krb_method_k5pass,
137 FLAG, "Enable Kerberos V5 password authentication."),
141 command("Krb4Srvtab", ap_set_file_slot, krb_4_srvtab,
142 TAKE1, "Location of Kerberos V4 srvtab file."),
144 command("KrbMethodK4Pass", ap_set_flag_slot, krb_method_k4pass,
145 FLAG, "Enable Kerberos V4 password authentication."),
153 gss_ctx_id_t context;
154 gss_cred_id_t server_creds;
157 static gss_connection_t *gss_connection = NULL;
161 /***************************************************************************
162 Auth Configuration Initialization
163 ***************************************************************************/
164 static void *kerb_dir_create_config(MK_POOL *p, char *d)
166 kerb_auth_config *rec;
168 rec = (kerb_auth_config *) ap_pcalloc(p, sizeof(kerb_auth_config));
169 ((kerb_auth_config *)rec)->krb_auth_enable = 1;
170 ((kerb_auth_config *)rec)->krb_fail_status = HTTP_UNAUTHORIZED;
172 ((kerb_auth_config *)rec)->krb_method_k5pass = 1;
173 ((kerb_auth_config *)rec)->krb_method_gssapi = 1;
176 ((kerb_auth_config *)rec)->krb_method_k4pass = 1;
182 static const char *kerb_set_fail_slot(cmd_parms *cmd, void *struct_ptr,
185 int offset = (int) (long) cmd->info;
186 if (!strncasecmp(arg, "unauthorized", 12))
187 *(int *) ((char *)struct_ptr + offset) = HTTP_UNAUTHORIZED;
188 else if (!strncasecmp(arg, "forbidden", 9))
189 *(int *) ((char *)struct_ptr + offset) = HTTP_FORBIDDEN;
190 else if (!strncasecmp(arg, "declined", 8))
191 *(int *) ((char *)struct_ptr + offset) = DECLINED;
193 return "KrbAuthFailStatus must be Forbidden, Unauthorized, or Declined.";
199 /***************************************************************************
200 Username/Password Validation for Krb4
201 ***************************************************************************/
202 int kerb4_password_validate(request_rec *r, const char *user, const char *pass)
204 kerb_auth_config *conf =
205 (kerb_auth_config *)ap_get_module_config(r->per_dir_config,
208 int lifetime = DEFAULT_TKT_LIFE;
210 char *username = NULL;
211 char *instance = NULL;
214 username = (char *)ap_pstrdup(r->pool, user);
219 instance = strchr(username, '.');
227 realm = strchr(username, '@');
235 if (conf->krb_lifetime) {
236 lifetime = atoi(conf->krb_lifetime);
239 if (conf->krb_force_instance) {
240 instance = conf->krb_force_instance;
243 if (conf->krb_save_credentials) {
244 tfname = (char *)malloc(sizeof(char) * MAX_STRING_LEN);
245 sprintf(tfname, "%s/k5cc_ap_%s",
246 conf->krb_tmp_dir ? conf->krb_tmp_dir : "/tmp",
249 if (!strcmp(instance, "")) {
250 tfname = strcat(tfname, ".");
251 tfname = strcat(tfname, instance);
254 if (!strcmp(realm, "")) {
255 tfname = strcat(tfname, ".");
256 tfname = strcat(tfname, realm);
259 for (c = tfname + strlen(conf->krb_tmp_dir ? conf->krb_tmp_dir :
260 "/tmp") + 1; *c; c++) {
265 krb_set_tkt_string(tfname);
268 if (!strcmp(realm, "")) {
269 realm = (char *)malloc(sizeof(char) * (REALM_SZ + 1));
270 ret = krb_get_lrealm(realm, 1);
275 ret = krb_get_pw_in_tkt((char *)user, instance, realm, "krbtgt", realm,
276 lifetime, (char *)pass);
291 /***************************************************************************
292 Username/Password Validation for Krb5
293 ***************************************************************************/
296 krb5_verify_user(krb5_context context, krb5_principal principal,
297 krb5_ccache ccache, const char *password, krb5_boolean secure,
301 krb5_context kcontext;
302 krb5_principal server, client;
305 krb5_flags options = 0;
306 krb5_principal me = NULL;
307 krb5_data tgtname = {
313 memset((char *)&my_creds, 0, sizeof(my_creds));
314 my_creds.client = principal;
316 if (krb5_build_principal_ext(kcontext, &server,
317 krb5_princ_realm(kcontext, me)->length,
318 krb5_princ_realm(kcontext, me)->data,
319 tgtname.length, tgtname.data,
320 krb5_princ_realm(kcontext, me)->length,
321 krb5_princ_realm(kcontext, me)->data,
326 my_creds.server = server;
327 if (krb5_timeofday(kcontext, &now))
330 my_creds.times.starttime = 0;
332 my_creds.times.endtime = now + lifetime;
333 my_creds.times.renew_till = now + renewal;
336 ret = krb5_get_in_tkt_with_password(kcontext, options, 0, NULL, 0,
337 password, ccache, &my_creds, 0);
348 krb5_cache_cleanup(void *data)
350 krb5_context context;
352 krb5_error_code problem;
353 char *cache_name = (char *) data;
355 problem = krb5_init_context(&context);
357 ap_log_error(APLOG_MARK, APLOG_ERR, 0, NULL, "krb5_init_context() failed");
358 return HTTP_INTERNAL_SERVER_ERROR;
361 problem = krb5_cc_resolve(context, cache_name, &cache);
363 ap_log_error(APLOG_MARK, APLOG_ERR, 0, NULL,
364 "krb5_cc_resolve() failed (%s: %s)",
365 cache_name, krb5_get_err_text(context, problem));
366 return HTTP_INTERNAL_SERVER_ERROR;
369 krb5_cc_destroy(context, cache);
370 krb5_free_context(context);
375 create_krb5_ccache(krb5_context kcontext,
377 kerb_auth_config *conf,
378 krb5_principal princ,
381 char *c, ccname[MAX_STRING_LEN];
382 krb5_error_code problem;
384 krb5_ccache tmp_ccache = NULL;
386 snprintf(ccname, sizeof(ccname), "FILE:%s/k5cc_ap_%s",
387 conf->krb_tmp_dir ? conf->krb_tmp_dir : "/tmp",
390 for (c = ccname + strlen(conf->krb_tmp_dir ? conf->krb_tmp_dir :
391 "/tmp") + 1; *c; c++) {
396 problem = krb5_cc_resolve(kcontext, ccname, &tmp_ccache);
398 ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
399 "Cannot create krb5 ccache: krb5_cc_resolve() failed: %s",
400 krb5_get_err_text(kcontext, problem));
401 ret = HTTP_INTERNAL_SERVER_ERROR;
405 problem = krb5_cc_initialize(kcontext, tmp_ccache, princ);
407 ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
408 "Cannot create krb5 ccache: krb5_cc_initialize() failed: %s",
409 krb5_get_err_text(kcontext, problem));
410 ret = HTTP_INTERNAL_SERVER_ERROR;
414 ap_table_setn(r->subprocess_env, "KRB5CCNAME", ccname);
415 ap_register_cleanup(r->pool, ccname,
416 krb5_cache_cleanup, ap_null_cleanup);
418 *ccache = tmp_ccache;
425 krb5_cc_destroy(kcontext, tmp_ccache);
431 store_krb5_creds(krb5_context kcontext,
433 kerb_auth_config *conf,
434 krb5_ccache delegated_cred)
437 krb5_error_code problem;
438 krb5_principal princ;
442 problem = krb5_cc_get_principal(kcontext, delegated_cred, &princ);
444 snprintf(errstr, sizeof(errstr), "krb5_cc_get_principal() failed: %s",
445 krb5_get_err_text(kcontext, problem));
446 return HTTP_INTERNAL_SERVER_ERROR;
449 ret = create_krb5_ccache(kcontext, r, conf, princ, &ccache);
451 krb5_free_principal(kcontext, princ);
455 problem = krb5_cc_copy_cache(kcontext, delegated_cred, ccache);
456 krb5_free_principal(kcontext, princ);
458 snprintf(errstr, sizeof(errstr), "krb5_cc_copy_cache() failed: %s",
459 krb5_get_err_text(kcontext, problem));
460 krb5_cc_destroy(kcontext, ccache);
461 return HTTP_INTERNAL_SERVER_ERROR;
464 krb5_cc_close(kcontext, ccache);
469 int authenticate_user_krb5pwd(request_rec *r,
470 kerb_auth_config *conf,
471 const char *auth_line)
473 const char *sent_pw = NULL;
474 const char *realms = NULL;
475 krb5_context kcontext;
476 krb5_error_code code;
477 krb5_principal client = NULL;
478 krb5_ccache ccache = NULL;
481 code = krb5_init_context(&kcontext);
483 ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
484 "Cannot initialize Kerberos5 context (%d)", code);
485 return HTTP_INTERNAL_SERVER_ERROR;
488 sent_pw = ap_pbase64decode(r->pool, auth_line);
489 MK_USER = ap_getword (r->pool, &sent_pw, ':');
490 MK_AUTH_TYPE = "Basic";
492 /* do not allow user to override realm setting of server */
493 if (strchr(MK_USER, '@')) {
494 ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
495 "specifying realm in user name is prohibited");
496 ret = HTTP_UNAUTHORIZED;
501 code = krb5_cc_gen_new(kcontext, &krb5_mcc_ops, &ccache);
503 code = krb5_mcc_generate_new(kcontext, &ccache);
506 ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
507 "Cannot generate new ccache: %s",
508 krb5_get_err_text(kcontext, code));
509 ret = HTTP_INTERNAL_SERVER_ERROR;
513 if (conf->krb_5_keytab)
514 /* setenv("KRB5_KTNAME", conf->krb_5_keytab, 1); */
515 kcontext->default_keytab = conf->krb_5_keytab;
517 realms = conf->krb_auth_realms;
519 if (realms && (code = krb5_set_default_realm(kcontext,
520 ap_getword_white(r->pool, &realms))))
523 code = krb5_parse_name(kcontext, MK_USER, &client);
527 code = krb5_verify_user(kcontext, client, ccache, sent_pw, 1,
528 (conf->service_name) ? conf->service_name : "khttp");
529 krb5_free_principal(kcontext, client);
533 /* ap_getword_white() used above shifts the parameter, so it's not
534 needed to touch the realms variable */
535 } while (realms && *realms);
537 memset((char *)sent_pw, 0, strlen(sent_pw));
540 ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
541 "Verifying krb5 password failed: %s",
542 krb5_get_err_text(kcontext, code));
543 ret = HTTP_UNAUTHORIZED;
547 if (conf->krb_save_credentials) {
548 ret = store_krb5_creds(kcontext, r, conf, ccache);
549 if (ret) /* Ignore error ?? */
557 krb5_free_principal(kcontext, client);
559 krb5_cc_destroy(kcontext, ccache);
560 krb5_free_context(kcontext);
565 /*********************************************************************
566 * GSSAPI Authentication
567 ********************************************************************/
570 get_gss_error(MK_POOL *p, OM_uint32 error_status, char *prefix)
572 OM_uint32 maj_stat, min_stat;
573 OM_uint32 msg_ctx = 0;
574 gss_buffer_desc status_string;
578 snprintf(buf, sizeof(buf), "%s", prefix);
581 maj_stat = gss_display_status (&min_stat,
587 if (sizeof(buf) > len + status_string.length + 1) {
588 sprintf(buf+len, ": %s", (char*) status_string.value);
589 len += status_string.length;
591 gss_release_buffer(&min_stat, &status_string);
592 } while (!GSS_ERROR(maj_stat) && msg_ctx != 0);
594 return (ap_pstrdup(p, buf));
598 cleanup_gss_connection(void *data)
600 OM_uint32 minor_status;
601 gss_connection_t *gss_conn = (gss_connection_t *)data;
605 if (gss_conn->context != GSS_C_NO_CONTEXT)
606 gss_delete_sec_context(&minor_status, &gss_conn->context,
608 if (gss_conn->server_creds != GSS_C_NO_CREDENTIAL)
609 gss_release_cred(&minor_status, &gss_conn->server_creds);
615 store_gss_creds(request_rec *r, kerb_auth_config *conf, char *princ_name,
616 gss_cred_id_t delegated_cred)
618 OM_uint32 maj_stat, min_stat;
619 krb5_principal princ = NULL;
620 krb5_ccache ccache = NULL;
621 krb5_error_code problem;
622 krb5_context context;
623 int ret = HTTP_INTERNAL_SERVER_ERROR;
625 problem = krb5_init_context(&context);
627 ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
628 "Cannot initialize krb5 context");
629 return HTTP_INTERNAL_SERVER_ERROR;
632 problem = krb5_parse_name(context, princ_name, &princ);
634 ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
635 "Cannot parse delegated username (%s)", krb5_get_err_text(context, problem));
639 problem = create_krb5_ccache(context, r, conf, princ, &ccache);
641 ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
642 "Cannot create krb5 ccache (%s)", krb5_get_err_text(context, problem));
646 maj_stat = gss_krb5_copy_ccache(&min_stat, delegated_cred, ccache);
647 if (GSS_ERROR(maj_stat)) {
648 ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
649 "Cannot store delegated credential (%s)",
650 get_gss_error(r->pool, min_stat, "gss_krb5_copy_ccache"));
654 krb5_cc_close(context, ccache);
660 krb5_free_principal(context, princ);
662 krb5_cc_destroy(context, ccache);
663 krb5_free_context(context);
668 get_gss_creds(request_rec *r,
669 kerb_auth_config *conf,
670 gss_cred_id_t *server_creds)
672 gss_buffer_desc input_token = GSS_C_EMPTY_BUFFER;
673 OM_uint32 major_status, minor_status, minor_status2;
674 gss_name_t server_name = GSS_C_NO_NAME;
676 if (conf->service_name) {
677 input_token.value = conf->service_name;
678 input_token.length = strlen(conf->service_name) + 1;
681 input_token.value = "khttp";
682 input_token.length = 6;
684 major_status = gss_import_name(&minor_status, &input_token,
685 (conf->service_name) ?
686 GSS_C_NT_USER_NAME : GSS_C_NT_HOSTBASED_SERVICE,
688 if (GSS_ERROR(major_status)) {
689 ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
690 "%s", get_gss_error(r->pool, minor_status,
691 "gss_import_name() failed"));
692 return HTTP_INTERNAL_SERVER_ERROR;
695 major_status = gss_acquire_cred(&minor_status, server_name, GSS_C_INDEFINITE,
696 GSS_C_NO_OID_SET, GSS_C_ACCEPT,
697 server_creds, NULL, NULL);
698 gss_release_name(&minor_status2, &server_name);
699 if (GSS_ERROR(major_status)) {
700 ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
701 "%s", get_gss_error(r->pool, minor_status,
702 "gss_acquire_cred() failed"));
703 return HTTP_INTERNAL_SERVER_ERROR;
710 authenticate_user_gss(request_rec *r,
711 kerb_auth_config *conf,
712 const char *auth_line)
714 OM_uint32 major_status, minor_status, minor_status2;
715 gss_buffer_desc input_token = GSS_C_EMPTY_BUFFER;
716 gss_buffer_desc output_token = GSS_C_EMPTY_BUFFER;
717 const char *auth_param = NULL;
719 gss_name_t client_name = GSS_C_NO_NAME;
720 gss_cred_id_t delegated_cred = GSS_C_NO_CREDENTIAL;
722 if (gss_connection == NULL) {
723 gss_connection = ap_pcalloc(r->connection->pool, sizeof(*gss_connection));
724 if (gss_connection == NULL) {
725 ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
726 "ap_pcalloc() failed (not enough memory)");
727 ret = HTTP_INTERNAL_SERVER_ERROR;
730 memset(gss_connection, 0, sizeof(*gss_connection));
731 ap_register_cleanup(r->connection->pool, gss_connection, cleanup_gss_connection, ap_null_cleanup);
734 if (conf->krb_5_keytab)
735 setenv("KRB5_KTNAME", conf->krb_5_keytab, 1);
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, 0, r,
747 "No Authorization parameter in request from client");
748 ret = HTTP_UNAUTHORIZED;
752 input_token.length = ap_base64decode_len(auth_param) + 1;
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, 0, r,
756 "ap_pcalloc() failed (not enough memory)");
757 ret = HTTP_INTERNAL_SERVER_ERROR;
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) + 1;
778 token = ap_pcalloc(r->connection->pool, len + 1);
780 ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
781 "ap_pcalloc() failed (not enough memory)");
782 ret = HTTP_INTERNAL_SERVER_ERROR;
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, 0, 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, 0, r,
812 "%s", get_gss_error(r->pool, minor_status,
813 "gss_export_name() failed"));
814 ret = HTTP_INTERNAL_SERVER_ERROR;
818 MK_AUTH_TYPE = "Negotiate";
819 MK_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_kerb_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, 0, 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, 0, 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_kerb_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_kerb_auth_failure(r, conf);
954 /***************************************************************************
955 Module Setup/Configuration
956 ***************************************************************************/
958 module MODULE_VAR_EXPORT kerb_auth_module = {
959 STANDARD_MODULE_STUFF,
960 NULL, /* module initializer */
961 kerb_dir_create_config, /* per-directory config creator */
962 NULL, /* per-directory config merger */
963 NULL, /* per-server config creator */
964 NULL, /* per-server config merger */
965 kerb_auth_cmds, /* command table */
966 NULL, /* [ 9] content handlers */
967 NULL, /* [ 2] URI-to-filename translation */
968 kerb_authenticate_user, /* [ 5] check/validate user_id */
969 NULL, /* [ 6] check user_id is valid *here* */
970 NULL, /* [ 4] check access by host address */
971 NULL, /* [ 7] MIME type checker/setter */
972 NULL, /* [ 8] fixups */
973 NULL, /* [10] logger */
974 NULL, /* [ 3] header parser */
975 NULL, /* process initialization */
976 NULL, /* process exit/cleanup */
977 NULL /* [ 1] post read_request handling */
980 void kerb_register_hooks(apr_pool_t *p)
982 ap_hook_check_user_id(kerb_authenticate_user, NULL, NULL, APR_HOOK_MIDDLE);
985 module AP_MODULE_DECLARE_DATA kerb_auth_module =
987 STANDARD20_MODULE_STUFF,
988 kerb_dir_create_config, /* create per-dir conf structures */
989 NULL, /* merge per-dir conf structures */
990 NULL, /* create per-server conf structures */
991 NULL, /* merge per-server conf structures */
992 kerb_auth_cmds, /* table of configuration directives */
993 kerb_register_hooks /* register hooks */