1 /***************************************************************************
2 Included Headers And Module Declaration
3 ***************************************************************************/
8 #include "http_config.h"
11 #include "http_protocol.h"
12 #include "http_request.h"
14 module kerb_auth_module;
17 #include "apr_strings.h"
19 #include "ap_config.h"
21 #include "http_config.h"
22 #include "http_core.h"
24 #include "http_protocol.h"
25 #include "http_request.h"
27 module AP_MODULE_DECLARE_DATA kerb_auth_module;
46 /***************************************************************************
47 Macros To Ease Compatibility
48 ***************************************************************************/
51 #define MK_TABLE_GET ap_table_get
52 #define MK_TABLE_SET ap_table_set
53 #define MK_TABLE_TYPE table
54 #define MK_PSTRDUP ap_pstrdup
55 #define MK_PROXY STD_PROXY
56 #define MK_USER r->connection->user
57 #define MK_AUTH_TYPE r->connection->ap_auth_type
58 #define MK_ARRAY_HEADER array_header
61 #define MK_POOL apr_pool_t
62 #define MK_TABLE_GET apr_table_get
63 #define MK_TABLE_SET apr_table_set
64 #define MK_TABLE_TYPE apr_table_t
65 #define MK_PSTRDUP apr_pstrdup
66 #define MK_PROXY PROXYREQ_PROXY
67 #define MK_USER r->user
68 #define MK_AUTH_TYPE r->ap_auth_type
69 #define MK_ARRAY_HEADER apr_array_header_t
76 /***************************************************************************
77 Auth Configuration Structure
78 ***************************************************************************/
87 char *krb_auth_realms;
88 int krb_authoritative;
90 char *krb_force_instance;
96 int krb_method_gssapi;
99 int krb_method_k4pass;
102 int krb_method_k5pass;
105 int krb_save_credentials;
113 /***************************************************************************
114 GSSAPI Support Initialization
115 ***************************************************************************/
118 gss_ctx_id_t context;
119 gss_cred_id_t server_creds;
122 static gss_connection_t *gss_connection = NULL;
125 cleanup_gss_connection(void *data)
127 OM_uint32 minor_status;
128 gss_connection_t *gss_conn = (gss_connection_t *)data;
132 if (gss_conn->context != GSS_C_NO_CONTEXT)
133 gss_delete_sec_context(&minor_status, &gss_conn->context,
135 if (gss_conn->server_creds != GSS_C_NO_CREDENTIAL)
136 gss_release_cred(&minor_status, &gss_conn->server_creds);
143 /***************************************************************************
144 Auth Configuration Initialization
145 ***************************************************************************/
146 static void *kerb_dir_config(MK_POOL *p, char *d)
149 rec = (void *) ap_pcalloc(p, sizeof(kerb_auth_config));
150 ((kerb_auth_config *)rec)->krb_fail_status = HTTP_UNAUTHORIZED;
151 ((kerb_auth_config *)rec)->krb_authoritative = 0;
153 ((kerb_auth_config *)rec)->krb_method_gssapi = 0;
156 ((kerb_auth_config *)rec)->krb_method_k4pass = 1;
159 ((kerb_auth_config *)rec)->krb_method_k5pass = 1;
161 ((kerb_auth_config *)rec)->krb_method_k4pass = 0;
164 ((kerb_auth_config *)rec)->krb_auth_realms = "";
171 /***************************************************************************
172 Auth Configuration Parsers
173 ***************************************************************************/
174 static const char *kerb_set_fail_slot(cmd_parms *cmd, void *struct_ptr,
177 int offset = (int) (long) cmd->info;
178 if (!strncasecmp(arg, "unauthorized", 12))
179 *(int *) ((char *)struct_ptr + offset) = HTTP_UNAUTHORIZED;
180 else if (!strncasecmp(arg, "forbidden", 9))
181 *(int *) ((char *)struct_ptr + offset) = HTTP_FORBIDDEN;
182 else if (!strncasecmp(arg, "declined", 8))
183 *(int *) ((char *)struct_ptr + offset) = DECLINED;
185 return "KrbAuthFailStatus must be Forbidden, Unauthorized, or Declined.";
192 /***************************************************************************
193 Auth Configuration Commands
194 ***************************************************************************/
196 command_rec kerb_auth_cmds[] = {
200 (void*)XtOffsetOf(kerb_auth_config, krb_auth_enable),
203 "Permit Kerberos auth without AuthType requirement."
210 (void*)XtOffsetOf(kerb_auth_config, krb_4_srvtab),
211 RSRC_CONF & ACCESS_CONF,
213 "Location of Kerberos V4 srvtab file."
221 (void*)XtOffsetOf(kerb_auth_config, krb_5_keytab),
222 RSRC_CONF & ACCESS_CONF,
224 "Location of Kerberos V5 keytab file."
231 (void*)XtOffsetOf(kerb_auth_config, krb_authoritative),
234 "Refuse to pass request down to lower modules."
240 (void*)XtOffsetOf(kerb_auth_config, krb_auth_realms),
243 "Realms to attempt authentication against (can be multiple)."
249 (void*)XtOffsetOf(kerb_auth_config, krb_fail_status),
252 "If auth fails, return status set here."
258 (void*)XtOffsetOf(kerb_auth_config, krb_force_instance),
261 "Force authentication against an instance specified here."
268 (void*)XtOffsetOf(kerb_auth_config, krb_forwardable),
271 "Credentials retrieved will be flagged as forwardable."
278 (void*)XtOffsetOf(kerb_auth_config, krb_lifetime),
281 "Lifetime of tickets retrieved."
288 (void*)XtOffsetOf(kerb_auth_config, krb_method_gssapi),
291 "Enable GSSAPI authentication."
299 (void*)XtOffsetOf(kerb_auth_config, krb_method_k4pass),
302 "Enable Kerberos V4 password authentication."
310 (void*)XtOffsetOf(kerb_auth_config, krb_method_k5pass),
313 "Enable Kerberos V5 password authentication."
319 (void*)XtOffsetOf(kerb_auth_config, krb_renewable),
322 "Credentials retrieved will be renewable for this length."
327 "KrbSaveCredentials",
329 (void*)XtOffsetOf(kerb_auth_config, krb_save_credentials),
332 "Save and store credentials/tickets retrieved during auth."
338 (void*)XtOffsetOf(kerb_auth_config, krb_save_credentials),
341 "Alias for KrbSaveCredentials."
347 (void*)XtOffsetOf(kerb_auth_config, krb_tmp_dir),
348 RSRC_CONF & ACCESS_CONF,
350 "Path to store ticket files and such in."
357 static const command_rec kerb_auth_cmds[] = {
361 (void*)APR_XtOffsetOf(kerb_auth_config, krb_auth_enable),
363 "Permit Kerberos auth without AuthType requirement."
370 (void*)APR_XtOffsetOf(kerb_auth_config, krb_4_srvtab),
371 RSRC_CONF & ACCESS_CONF,
372 "Location of Kerberos V4 srvtab file."
380 (void*)APR_XtOffsetOf(kerb_auth_config, krb_5_keytab),
381 RSRC_CONF & ACCESS_CONF,
382 "Location of Kerberos V5 keytab file."
389 (void*)APR_XtOffsetOf(kerb_auth_config, krb_authoritative),
391 "Refuse to pass request down to lower modules."
397 (void*)APR_XtOffsetOf(kerb_auth_config, krb_auth_realms),
399 "Realm to attempt authentication against (can be multiple)."
405 (void*)APR_XtOffsetOf(kerb_auth_config, krb_fail_status),
407 "If auth fails, return status set here."
413 (void*)APR_XtOffsetOf(kerb_auth_config, krb_force_instance),
415 "Force authentication against an instance specified here."
422 (void*)APR_XtOffsetOf(kerb_auth_config, krb_forwardable),
424 "Credentials retrieved will be flagged as forwardable."
431 (void*)APR_XtOffsetOf(kerb_auth_config, krb_lifetime),
433 "Lifetime of tickets retrieved."
440 (void*)APR_XtOffsetOf(kerb_auth_config, krb_method_gssapi),
442 "Enable GSSAPI authentication."
450 (void*)APR_XtOffsetOf(kerb_auth_config, krb_method_k4pass),
452 "Enable Kerberos V4 password authentication."
460 (void*)APR_XtOffsetOf(kerb_auth_config, krb_method_k5pass),
462 "Enable Kerberos V5 password authentication."
468 (void*)APR_XtOffsetOf(kerb_auth_config, krb_renewable),
470 "Credentials retrieved will be renewable for this length."
475 "KrbSaveCredentials",
477 (void*)APR_XtOffsetOf(kerb_auth_config, krb_save_credentials),
479 "Save and store credentials/tickets retrieved during auth."
485 (void*)APR_XtOffsetOf(kerb_auth_config, krb_save_credentials),
487 "Alias for KrbSaveCredentials."
493 (void*)APR_XtOffsetOf(kerb_auth_config, krb_tmp_dir),
494 RSRC_CONF & ACCESS_CONF,
495 "Path to store ticket files and such in."
506 krb5_verify_user(krb5_context context, krb5_principal principal,
507 krb5_ccache ccache, const char *password, krb5_boolean secure,
511 krb5_context kcontext;
512 krb5_principal server, client;
515 krb5_flags options = 0;
516 krb5_principal me = NULL;
517 krb5_data tgtname = {
523 memset((char *)&my_creds, 0, sizeof(my_creds));
524 my_creds.client = principal;
526 if (krb5_build_principal_ext(kcontext, &server,
527 krb5_princ_realm(kcontext, me)->length,
528 krb5_princ_realm(kcontext, me)->data,
529 tgtname.length, tgtname.data,
530 krb5_princ_realm(kcontext, me)->length,
531 krb5_princ_realm(kcontext, me)->data,
536 my_creds.server = server;
537 if (krb5_timeofday(kcontext, &now))
540 my_creds.times.starttime = 0;
542 my_creds.times.endtime = now + lifetime;
543 my_creds.times.renew_till = now + renewal;
546 ret = krb5_get_in_tkt_with_password(kcontext, options, 0, NULL, 0,
547 password, ccache, &my_creds, 0);
557 /***************************************************************************
558 Username/Password Validation
559 ***************************************************************************/
562 krb5_cache_cleanup(void *data)
564 krb5_context context;
566 krb5_error_code problem;
567 char *cache_name = (char *) data;
569 problem = krb5_init_context(&context);
571 ap_log_error(APLOG_MARK, APLOG_ERR, NULL, "krb5_init_context() failed");
575 problem = krb5_cc_resolve(context, cache_name, &cache);
577 ap_log_error(APLOG_MARK, APLOG_ERR, NULL,
578 "krb5_cc_resolve() failed (%s: %s)",
579 cache_name, krb5_get_err_text(context, problem));
583 krb5_cc_destroy(context, cache);
584 krb5_free_context(context);
588 store_krb5_creds(krb5_context kcontext,
590 kerb_auth_config *conf,
591 krb5_ccache delegated_cred)
593 char *c, ccname[MAX_STRING_LEN];
594 krb5_error_code problem;
597 krb5_ccache ccache = NULL;
598 krb5_principal me = NULL;
600 sprintf(ccname, "FILE:%s/k5cc_ap_%s",
601 conf->krb_tmp_dir ? conf->krb_tmp_dir : "/tmp",
604 for (c = ccname + strlen(conf->krb_tmp_dir ? conf->krb_tmp_dir :
605 "/tmp") + 1; *c; c++) {
610 problem = krb5_cc_set_default_name(kcontext, ccname);
612 snprintf(errstr, sizeof(errstr),
613 "krb5_cc_set_default_name() failed: %s",
614 krb5_get_err_text(kcontext, problem));
615 ap_log_reason (errstr, r->uri, r);
620 /* XXX Dan: Why is this done? Cleanup? But the file would not be
621 * accessible from another processes (CGI) */
622 unlink(ccname+strlen("FILE:"));
625 problem = krb5_cc_resolve(kcontext, ccname, &ccache);
627 snprintf(errstr, sizeof(errstr),
628 "krb5_cc_resolve() failed: %s",
629 krb5_get_err_text(kcontext, problem));
630 ap_log_reason (errstr, r->uri, r);
635 problem = krb5_cc_get_principal(kcontext, delegated_cred, &me);
637 snprintf(errstr, sizeof(errstr),
638 "krb5_cc_get_principal() failed: %s",
639 krb5_get_err_text(kcontext, problem));
640 ap_log_reason (errstr, r->uri, r);
645 problem = krb5_cc_initialize(kcontext, ccache, me);
647 snprintf(errstr, sizeof(errstr),
648 "krb5_cc_initialize() failed: %s",
649 krb5_get_err_text(kcontext, problem));
650 ap_log_reason (errstr, r->uri, r);
655 problem = krb5_cc_copy_cache(kcontext, delegated_cred, ccache);
657 snprintf(errstr, sizeof(errstr),
658 "krb5_cc_copy_cache failed: %s",
659 krb5_get_err_text(kcontext, problem));
660 ap_log_reason (errstr, r->uri, r);
664 ap_table_setn(r->subprocess_env, "KRB5CCNAME", ccname);
665 ap_register_cleanup(r->pool, ccname,
666 krb5_cache_cleanup, ap_null_cleanup);
668 krb5_cc_close(kcontext, ccache);
674 return ret; /* XXX */
677 int kerb5_password_validate(request_rec *r, const char *user, const char *pass)
680 kerb_auth_config *conf =
681 (kerb_auth_config *)ap_get_module_config(r->per_dir_config,
684 krb5_context kcontext;
685 krb5_principal server, client;
686 krb5_ccache ccache = NULL;
687 krb5_deltat lifetime = 300; /* 5 minutes */
688 krb5_deltat renewal = 0;
689 krb5_flags options = 0;
691 krb5_error_code code;
694 if (krb5_init_context(&kcontext)) {
695 snprintf(errstr, sizeof(errstr),
696 "Cannot initialize Kerberos5 context");
697 ap_log_reason (errstr, r->uri, r);
702 if (conf->krb_forwardable) {
703 options |= KDC_OPT_FORWARDABLE;
706 if (conf->krb_renewable) {
707 options |= KDC_OPT_RENEWABLE;
708 renewal = 86400; /* 24 hours */
711 if (conf->krb_lifetime) {
712 lifetime = atoi(conf->krb_lifetime);
716 code = krb5_cc_gen_new(kcontext, &krb5_mcc_ops, &ccache);
718 snprintf(errstr, sizeof(errstr), "krb5_cc_gen_new(): %.100s",
719 krb5_get_err_text(kcontext, code));
720 ap_log_reason (errstr, r->uri, r);
726 realms = conf->krb_auth_realms;
730 code = krb5_set_default_realm(kcontext,
731 ap_getword_white(r->pool, &realms));
736 code = krb5_parse_name(kcontext, r->connection->user, &client);
740 code = krb5_verify_user(kcontext, client, ccache, pass,
742 krb5_free_principal(kcontext, client);
746 /* ap_getword_white() used above shifts the parameter, so it's not
747 needed to touch the realms variable */
748 } while (realms && *realms);
750 memset((char *)pass, 0, strlen(pass));
753 snprintf(errstr, sizeof(errstr), "Verifying krb5 password failed: %s",
754 krb5_get_err_text(kcontext, code));
755 ap_log_reason (errstr, r->uri, r);
756 ret = HTTP_UNAUTHORIZED;
760 if (conf->krb_save_credentials) {
761 ret = store_krb5_creds(kcontext, r, conf, ccache);
766 ret = 1; /* XXX should be OK ? */
770 krb5_cc_destroy(kcontext, ccache);
771 krb5_free_context(kcontext);
773 return (ret != 1) ? 0 : 1; /* XXX */
778 int kerb4_password_validate(request_rec *r, const char *user, const char *pass)
780 kerb_auth_config *conf =
781 (kerb_auth_config *)ap_get_module_config(r->per_dir_config,
784 int lifetime = DEFAULT_TKT_LIFE;
786 char *username = NULL;
787 char *instance = NULL;
790 username = (char *)ap_pstrdup(r->pool, user);
795 instance = strchr(username, '.');
803 realm = strchr(username, '@');
811 if (conf->krb_lifetime) {
812 lifetime = atoi(conf->krb_lifetime);
815 if (conf->krb_force_instance) {
816 instance = conf->krb_force_instance;
819 if (conf->krb_save_credentials) {
820 tfname = (char *)malloc(sizeof(char) * MAX_STRING_LEN);
821 sprintf(tfname, "%s/k5cc_ap_%s",
822 conf->krb_tmp_dir ? conf->krb_tmp_dir : "/tmp",
825 if (!strcmp(instance, "")) {
826 tfname = strcat(tfname, ".");
827 tfname = strcat(tfname, instance);
830 if (!strcmp(realm, "")) {
831 tfname = strcat(tfname, ".");
832 tfname = strcat(tfname, realm);
835 for (c = tfname + strlen(conf->krb_tmp_dir ? conf->krb_tmp_dir :
836 "/tmp") + 1; *c; c++) {
841 krb_set_tkt_string(tfname);
844 if (!strcmp(realm, "")) {
845 realm = (char *)malloc(sizeof(char) * (REALM_SZ + 1));
846 ret = krb_get_lrealm(realm, 1);
851 ret = krb_get_pw_in_tkt((char *)user, instance, realm, "krbtgt", realm,
852 lifetime, (char *)pass);
869 /***************************************************************************
871 ***************************************************************************/
874 get_gss_creds(request_rec *r,
875 kerb_auth_config *conf,
876 gss_cred_id_t *server_creds)
879 gss_buffer_desc input_token = GSS_C_EMPTY_BUFFER;
880 OM_uint32 major_status, minor_status;
881 gss_name_t server_name = GSS_C_NO_NAME;
883 if (conf->service_name) {
884 input_token.value = conf->service_name;
885 input_token.length = strlen(conf->service_name) + 1;
888 input_token.value = "khttp";
889 input_token.length = 6;
891 major_status = gss_import_name(&minor_status, &input_token,
892 (conf->service_name) ?
893 GSS_C_NT_USER_NAME : GSS_C_NT_HOSTBASED_SERVICE,
895 if (GSS_ERROR(major_status)) {
896 ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_NOTICE, r,
897 "%s", get_gss_error(r->pool, minor_status,
898 "gss_import_name() failed"));
904 if (conf->krb_5_keytab)
905 setenv("KRB5_KTNAME", conf->krb_5_keytab, 1);
908 major_status = gss_acquire_cred(&minor_status, server_name, GSS_C_INDEFINITE,
909 GSS_C_NO_OID_SET, GSS_C_ACCEPT,
910 server_creds, NULL, NULL);
912 if (conf->krb_5_keytab)
913 unsetenv("KRB5_KTNAME");
915 if (GSS_ERROR(major_status)) {
916 ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_NOTICE, r,
917 "%s", get_gss_error(r->pool, minor_status,
918 "gss_acquire_cred() failed"));
932 negotiate_authenticate_user(request_rec *r,
933 kerb_auth_config *conf,
934 const char *auth_line)
936 OM_uint32 major_status, minor_status, minor_status2;
937 gss_buffer_desc input_token = GSS_C_EMPTY_BUFFER;
938 gss_buffer_desc output_token = GSS_C_EMPTY_BUFFER;
939 const char *auth_param = NULL;
940 krb5_context krb_ctx = NULL;
942 gss_name_t client_name = GSS_C_NO_NAME;
943 gss_cred_id_t delegated_cred = GSS_C_NO_CREDENTIAL;
946 if (gss_connection == NULL) {
947 gss_connection = ap_pcalloc(r->connection->pool, sizeof(*gss_connection));
948 if (gss_connection == NULL) {
949 ap_log_rerror(APLOG_MARK, APLOG_ERR, r,
950 "ap_pcalloc() failed (not enough memory)");
954 memset(gss_connection, 0, sizeof(*gss_connection));
955 ap_register_cleanup(r->connection->pool, gss_connection, cleanup_gss_connection, ap_null_cleanup);
958 if (gss_connection->server_creds == GSS_C_NO_CREDENTIAL) {
959 ret = get_gss_creds(r, conf, &gss_connection->server_creds);
964 /* ap_getword() shifts parameter */
965 auth_param = ap_getword_white(r->pool, &auth_line);
966 if (auth_param == NULL) {
967 ap_log_rerror(APLOG_MARK, APLOG_ERR, r,
968 "No Authorization parameter in request from client");
969 ret = HTTP_UNAUTHORIZED;
973 input_token.length = ap_base64decode_len(auth_param);
974 input_token.value = ap_pcalloc(r->connection->pool, input_token.length);
975 if (input_token.value == NULL) {
976 ap_log_rerror(APLOG_MARK, APLOG_ERR, r,
977 "ap_pcalloc() failed (not enough memory)");
981 input_token.length = ap_base64decode(input_token.value, auth_param);
983 major_status = gss_accept_sec_context(&minor_status,
984 &gss_connection->context,
985 gss_connection->server_creds,
987 GSS_C_NO_CHANNEL_BINDINGS,
994 if (output_token.length) {
998 len = ap_base64encode_len(output_token.length);
999 token = ap_pcalloc(r->connection->pool, len + 1);
1000 if (token == NULL) {
1001 ap_log_rerror(APLOG_MARK, APLOG_ERR, r,
1002 "ap_pcalloc() failed (not enough memory)");
1004 gss_release_buffer(&minor_status2, &output_token);
1007 ap_base64encode(token, output_token.value, output_token.length);
1009 ap_table_set(r->err_headers_out, "WWW-Authenticate",
1010 ap_pstrcat(r->pool, "GSS-Negotiate ", token, NULL));
1011 gss_release_buffer(&minor_status2, &output_token);
1014 if (GSS_ERROR(major_status)) {
1015 ap_log_rerror(APLOG_MARK, APLOG_ERR, r,
1016 "%s", get_gss_error(r->pool, minor_status,
1017 "gss_accept_sec_context() failed"));
1018 ret = HTTP_UNAUTHORIZED;
1022 if (major_status & GSS_S_CONTINUE_NEEDED) {
1023 /* Some GSSAPI mechanism (eg GSI from Globus) may require multiple
1024 * iterations to establish authentication */
1025 ret = HTTP_UNAUTHORIZED;
1029 major_status = gss_export_name(&minor_status, client_name, &output_token);
1030 gss_release_name(&minor_status, &client_name);
1031 if (GSS_ERROR(major_status)) {
1032 ap_log_rerror(APLOG_MARK, APLOG_ERR, r,
1033 "%s", get_gss_error(r->pool, minor_status,
1034 "gss_export_name() failed"));
1039 r->connection->ap_auth_type = "Negotiate";
1040 r->connection->user = ap_pstrdup(r->pool, output_token.value);
1042 /* If the user comes from a realm specified by configuration don't include
1043 its realm name in the username so that the authorization routine could
1044 work for both Password-based and Ticket-based authentication. It's
1045 administrators responsibility to include only such realm that have
1046 unified principal instances, i.e. if the same principal name occures in
1047 multiple realms, it must be always assigned to a single user.
1049 p = strchr(r->connection->user, '@');
1051 const char *realms = conf->gss_krb5_realms;
1053 while (realms && *realms) {
1054 if (strcmp(p+1, ap_getword_white(r->pool, &realms)) == 0) {
1062 gss_release_buffer(&minor_status, &output_token);
1065 /* This should be only done if afs token are requested or gss_save creds is
1067 /* gss_export_cred() from the GGF GSS Extensions could be used */
1068 if (delegated_cred != GSS_C_NO_CREDENTIAL &&
1069 (conf->gss_save_creds || (conf->gss_krb5_cells && k_hasafs()))) {
1070 krb5_init_context(&krb_ctx);
1071 do_afs_log(krb_ctx, r, delegated_cred->ccache, conf->gss_krb5_cells);
1072 ret = store_krb5_creds(krb_ctx, r, conf, delegated_cred->ccache);
1073 krb5_free_context(krb_ctx);
1082 gss_release_cred(&minor_status, &delegated_cred);
1084 if (output_token.length)
1085 gss_release_buffer(&minor_status, &output_token);
1087 if (client_name != GSS_C_NO_NAME)
1088 gss_release_name(&minor_status, &client_name);
1097 /***************************************************************************
1099 ***************************************************************************/
1100 int kerb_authenticate_user(request_rec *r)
1102 const char *name; /* AuthName specified */
1103 const char *type; /* AuthType specified */
1104 const char *sent_pw; /* Password sent by browser */
1105 int res; /* Response holder */
1106 int retcode; /* Return code holder */
1107 const char *t; /* Decoded auth_line */
1108 const char *authtype; /* AuthType to send back to browser */
1109 const char *auth_line = MK_TABLE_GET(r->headers_in,
1110 (r->proxyreq == MK_PROXY)
1111 ? "Proxy-Authorization"
1113 kerb_auth_config *conf =
1114 (kerb_auth_config *)ap_get_module_config(r->per_dir_config,
1117 type = ap_auth_type(r);
1119 if (!conf->krb_auth_enable &&
1120 (type == NULL || (strncasecmp(type, "Kerberos", 8) != 0))) {
1121 if (conf->krb_authoritative) {
1122 return HTTP_UNAUTHORIZED;
1129 name = ap_auth_name(r);
1131 return HTTP_INTERNAL_SERVER_ERROR;
1135 MK_TABLE_SET(r->err_headers_out, "WWW-Authenticate",
1136 (char *)ap_pstrcat(r->pool,
1137 "Basic realm=\"", name, "\"", NULL));
1138 return HTTP_UNAUTHORIZED;
1141 type = ap_getword_white(r->pool, &auth_line);
1142 t = ap_pbase64decode(r->pool, auth_line);
1143 MK_USER = ap_getword_nulls(r->pool, &t, ':');
1144 MK_AUTH_TYPE = "Kerberos";
1145 sent_pw = ap_getword_white(r->pool, &t);
1150 if (conf->krb_method_gssapi && retcode != OK) {
1152 Whatever you need to do here =)
1153 MK_AUTH_TYPE = "GSSAPI";
1154 if (kerb5_password_validate(r, MK_USER, sent_pw)) {
1158 retcode = conf->krb_fail_status;
1165 if (conf->krb_method_k5pass && retcode != OK) {
1166 MK_AUTH_TYPE = "KerberosV5";
1167 if (kerb5_password_validate(r, MK_USER, sent_pw)) {
1171 retcode = conf->krb_fail_status;
1172 /* XXX should SERVER_ERROR be overriden too? */
1178 if (conf->krb_method_k4pass && retcode != OK) {
1179 MK_AUTH_TYPE = "KerberosV4";
1180 if (kerb4_password_validate(r, MK_USER, sent_pw)) {
1184 retcode = conf->krb_fail_status;
1189 if (conf->krb_authoritative && retcode == DECLINED) {
1190 return HTTP_UNAUTHORIZED;
1200 /***************************************************************************
1202 ***************************************************************************/
1203 int kerb_check_user_access(request_rec *r)
1207 const MK_ARRAY_HEADER *reqs_arr = ap_requires(r);
1209 kerb_auth_config *conf =
1210 (kerb_auth_config *)ap_get_module_config(r->per_dir_config,
1213 if (reqs_arr == NULL) {
1216 reqs = (require_line *)reqs_arr->elts;
1218 for (x = 0; x < reqs_arr->nelts; x++) {
1219 t = reqs[x].requirement;
1220 w = ap_getword_white(r->pool, &t);
1221 if (strcmp(w, "realm") == 0) {
1222 while (t[0] != '\0') {
1223 w = ap_getword_conf(r->pool, &t);
1224 if (strcmp(MK_USER, w) == 0) {
1237 /***************************************************************************
1238 Module Setup/Configuration
1239 ***************************************************************************/
1241 module MODULE_VAR_EXPORT kerb_auth_module = {
1242 STANDARD_MODULE_STUFF,
1243 NULL, /* module initializer */
1244 kerb_dir_config, /* per-directory config creator */
1245 NULL, /* per-directory config merger */
1246 NULL, /* per-server config creator */
1247 NULL, /* per-server config merger */
1248 kerb_auth_cmds, /* command table */
1249 NULL, /* [ 9] content handlers */
1250 NULL, /* [ 2] URI-to-filename translation */
1251 kerb_authenticate_user, /* [ 5] check/validate user_id */
1252 kerb_check_user_access, /* [ 6] check user_id is valid *here* */
1253 NULL, /* [ 4] check access by host address */
1254 NULL, /* [ 7] MIME type checker/setter */
1255 NULL, /* [ 8] fixups */
1256 NULL, /* [10] logger */
1257 NULL, /* [ 3] header parser */
1258 NULL, /* process initialization */
1259 NULL, /* process exit/cleanup */
1260 NULL /* [ 1] post read_request handling */
1262 , /* EAPI Additions */
1263 NULL, /* EAPI add module */
1264 NULL, /* EAPI remove module */
1265 NULL, /* EAPI rewrite command */
1266 NULL /* EAPI new connection */
1271 void kerb_register_hooks(apr_pool_t *p)
1273 ap_hook_check_user_id(kerb_authenticate_user, NULL, NULL, APR_HOOK_MIDDLE);
1274 ap_hook_access_checker(kerb_check_user_access, NULL, NULL, APR_HOOK_MIDDLE);
1277 module AP_MODULE_DECLARE_DATA kerb_auth_module =
1279 STANDARD20_MODULE_STUFF,
1280 kerb_dir_config, /* create per-dir conf structures */
1281 NULL, /* merge per-dir conf structures */
1282 NULL, /* create per-server conf structures */
1283 NULL, /* merge per-server conf structures */
1284 kerb_auth_cmds, /* table of configuration directives */
1285 kerb_register_hooks /* register hooks */