Added a fair amount of functionality that was present in 4.*.
[mod_auth_kerb.git] / src / mod_auth_kerb.c
1 /*************************************************************************** 
2  Included Headers And Module Declaration
3  ***************************************************************************/
4 #ifdef APXS1
5 #include "httpd.h"
6 #include "http_config.h"
7 #include "http_core.h"
8 #include "http_log.h"
9 #include "http_protocol.h"
10 #include "http_request.h"
11
12 module kerb_auth_module;
13 #else
14 #ifdef APXS2
15 #include "apr_strings.h"
16 #include "apr_lib.h"
17 #include "ap_config.h"
18 #include "httpd.h"
19 #include "http_config.h"
20 #include "http_core.h"
21 #include "http_log.h"
22 #include "http_protocol.h"
23 #include "http_request.h"
24
25 module AP_MODULE_DECLARE_DATA kerb_auth_module;
26 #endif /* APXS2 */
27 #endif /* APXS1 */
28
29 #ifdef KRB5
30 #include <krb5.h>
31 #endif /* KRB5 */
32
33 #ifdef KRB4
34 #include <krb.h>
35 #endif /* KRB4 */
36
37
38
39
40 /*************************************************************************** 
41  Macros To Ease Compatibility
42  ***************************************************************************/
43 #ifdef APXS1
44 #define MK_POOL pool
45 #define MK_TABLE_GET ap_table_get
46 #define MK_TABLE_SET ap_table_set
47 #define MK_TABLE_TYPE table
48 #define MK_PSTRDUP ap_pstrdup
49 #define MK_PROXY STD_PROXY
50 #define MK_USER r->connection->user
51 #define MK_AUTH_TYPE r->connection->ap_auth_type
52 #define MK_ARRAY_HEADER array_header
53 #else
54 #ifdef APXS2
55 #define MK_POOL apr_pool_t
56 #define MK_TABLE_GET apr_table_get
57 #define MK_TABLE_SET apr_table_set
58 #define MK_TABLE_TYPE apr_table_t
59 #define MK_PSTRDUP apr_pstrdup
60 #define MK_PROXY PROXYREQ_PROXY
61 #define MK_USER r->user
62 #define MK_AUTH_TYPE r->ap_auth_type
63 #define MK_ARRAY_HEADER apr_array_header_t
64 #endif /* APXS2 */
65 #endif /* APXS1 */
66
67
68
69
70 /*************************************************************************** 
71  Auth Configuration Structure
72  ***************************************************************************/
73 typedef struct {
74         char *krb_auth_type;
75 #ifdef KRB4
76         char *krb_4_srvtab;
77 #endif /* KRB4 */
78 #ifdef KRB5
79         char *krb_5_keytab;
80 #endif /* KRB5 */
81         int krb_authoritative;
82         char *krb_default_realm;
83         int krb_fail_status;
84         char *krb_force_instance;
85 #ifdef KRB5
86         int krb_forwardable;
87 #endif /* KRB5 */
88         char *krb_lifetime;
89 #ifdef KRB5
90         char *krb_renewable;
91 #endif /* KRB5 */
92         int krb_save_credentials;
93         char *krb_tmp_dir;
94 } kerb_auth_config;
95
96
97
98
99 /*************************************************************************** 
100  Auth Configuration Initialization
101  ***************************************************************************/
102 static void *kerb_dir_config(MK_POOL *p, char *d)
103 {
104         static void *rec;
105         rec = (void *) ap_pcalloc(p, sizeof(kerb_auth_config));
106         ((kerb_auth_config *)rec)->krb_fail_status = HTTP_UNAUTHORIZED;
107         ((kerb_auth_config *)rec)->krb_authoritative = 0;
108         ((kerb_auth_config *)rec)->krb_auth_type = MK_PSTRDUP(p, "None");
109         return rec;
110 }
111
112
113
114
115 /*************************************************************************** 
116  Auth Configuration Parsers
117  ***************************************************************************/
118 static const char *kerb_set_fail_slot(cmd_parms *cmd, void *struct_ptr,
119                                         const char *arg)
120 {
121         int offset = (int) (long) cmd->info;
122         if (!strncasecmp(arg, "unauthorized", 12))
123                 *(int *) ((char *)struct_ptr + offset) = HTTP_UNAUTHORIZED;
124         else if (!strncasecmp(arg, "forbidden", 9))
125                 *(int *) ((char *)struct_ptr + offset) = HTTP_FORBIDDEN;
126         else if (!strncasecmp(arg, "declined", 8))
127                 *(int *) ((char *)struct_ptr + offset) = DECLINED;
128         else
129                 return "KrbAuthFailStatus must be Forbidden, Unauthorized, or Declined.";
130         return NULL;
131 }
132
133 /* these are either char *struct_ptr, char *arg or void *struct_ptr, const char *arg */
134 static const char *kerb_set_type_slot(cmd_parms *cmd, void *struct_ptr,
135                                         const char *arg)
136 {
137         int offset = (int) (long) cmd->info;
138         if
139 #ifdef KRB5
140            (!strncasecmp(arg, "v5", 2))
141                 *(char **) ((char *)struct_ptr + offset) = MK_PSTRDUP(cmd->pool, "KerberosV5");
142         else if
143 #endif /* KRB5 */
144 #ifdef KRB4
145            (!strncasecmp(arg, "v4", 2))
146                 *(char **) ((char *)struct_ptr + offset) = MK_PSTRDUP(cmd->pool, "KerberosV4");
147 #endif /* KRB4 */
148         else if
149            (!strncasecmp(arg, "dualv5v4", 8))
150                 *(char **) ((char *)struct_ptr + offset) = MK_PSTRDUP(cmd->pool, "KerberosDualV5V4");
151         else if
152            (!strncasecmp(arg, "dualv4v5", 8))
153                 *(char **) ((char *)struct_ptr + offset) = MK_PSTRDUP(cmd->pool, "KerberosDualV4V5");
154 #if defined(KRB4) && defined(KRB5)
155 #endif /* KRB4 && KRB5 */
156         else
157                 return "AuthKerberos must be V5, V4, DualV4V5, or DualV5V4.";
158         return NULL;
159 }
160
161
162
163
164 /*************************************************************************** 
165  Auth Configuration Commands
166  ***************************************************************************/
167 #ifdef APXS1
168 command_rec kerb_auth_cmds[] = {
169         {
170                 "AuthKerberos",
171                 kerb_set_type_slot,
172                 (void*)XtOffsetOf(kerb_auth_config, krb_auth_type),
173                 OR_AUTHCFG,
174                 TAKE1,
175                 "Permit Kerberos auth without AuthType requirement."
176         },
177
178 #ifdef KRB4
179         {
180                 "Krb4Srvtab",
181                 ap_set_file_slot,
182                 (void*)XtOffsetOf(kerb_auth_config, krb_4_srvtab),
183                 RSRC_CONF & ACCESS_CONF,
184                 TAKE1,
185                 "Location of Kerberos V4 srvtab file."
186         },
187 #endif /* KRB4 */
188
189 #ifdef KRB5
190         {
191                 "Krb5Keytab",
192                 ap_set_file_slot,
193                 (void*)XtOffsetOf(kerb_auth_config, krb_5_keytab),
194                 RSRC_CONF & ACCESS_CONF,
195                 TAKE1,
196                 "Location of Kerberos V5 keytab file."
197         },
198 #endif /* KRB5 */
199
200         {
201                 "KrbAuthoritative",
202                 ap_set_flag_slot,
203                 (void*)XtOffsetOf(kerb_auth_config, krb_authoritative),
204                 OR_AUTHCFG,
205                 FLAG,
206                 "Refuse to pass request down to lower modules."
207         },
208
209         {
210                 "KrbDefaultRealm",
211                 ap_set_string_slot,
212                 (void*)XtOffsetOf(kerb_auth_config, krb_default_realm),
213                 OR_AUTHCFG,
214                 TAKE1,
215                 "Default realm to authenticate users against."
216         },
217
218         {
219                 "KrbFailStatus",
220                 kerb_set_fail_slot,
221                 (void*)XtOffsetOf(kerb_auth_config, krb_fail_status),
222                 OR_AUTHCFG,
223                 TAKE1,
224                 "If auth fails, return status set here."
225         },
226
227         {
228                 "KrbForceInstance",
229                 ap_set_string_slot,
230                 (void*)XtOffsetOf(kerb_auth_config, krb_force_instance),
231                 OR_AUTHCFG,
232                 TAKE1,
233                 "Force authentication against an instance specified here."
234         },
235
236 #ifdef KRB5
237         {
238                 "KrbForwardable",
239                 ap_set_flag_slot,
240                 (void*)XtOffsetOf(kerb_auth_config, krb_forwardable),
241                 OR_AUTHCFG,
242                 FLAG,
243                 "Credentials retrieved will be flagged as forwardable."
244         },
245 #endif /* KRB5 */
246
247         {
248                 "KrbLifetime",
249                 ap_set_string_slot,
250                 (void*)XtOffsetOf(kerb_auth_config, krb_lifetime),
251                 OR_AUTHCFG,
252                 TAKE1,
253                 "Lifetime of tickets retrieved."
254         },
255
256 #ifdef KRB5
257         {
258                 "KrbRenewable",
259                 ap_set_string_slot,
260                 (void*)XtOffsetOf(kerb_auth_config, krb_renewable),
261                 OR_AUTHCFG,
262                 TAKE1,
263                 "Credentials retrieved will be renewable for this length."
264         },
265 #endif /* KRB5 */
266
267         {
268                 "KrbSaveCredentials",
269                 ap_set_flag_slot,
270                 (void*)XtOffsetOf(kerb_auth_config, krb_save_credentials),
271                 OR_AUTHCFG,
272                 FLAG,
273                 "Save and store credentials/tickets retrieved during auth."
274         },
275
276         {
277                 "KrbSaveTickets",
278                 ap_set_flag_slot,
279                 (void*)XtOffsetOf(kerb_auth_config, krb_save_credentials),
280                 OR_AUTHCFG,
281                 FLAG,
282                 "Alias for KrbSaveCredentials."
283         },
284
285         {
286                 "KrbTmpdir",
287                 ap_set_string_slot,
288                 (void*)XtOffsetOf(kerb_auth_config, krb_tmp_dir),
289                 RSRC_CONF & ACCESS_CONF,
290                 TAKE1,
291                 "Path to store ticket files and such in."
292         },
293
294         { NULL }
295 };
296 #else
297 #ifdef APXS2
298 static const command_rec kerb_auth_cmds[] = {
299         AP_INIT_TAKE1(
300                 "AuthKerberos",
301                 kerb_set_type_slot,
302                 (void*)APR_XtOffsetOf(kerb_auth_config, krb_auth_type),
303                 OR_AUTHCFG,
304                 "Permit Kerberos auth without AuthType requirement."
305         ),
306
307 #ifdef KRB4
308         AP_INIT_TAKE1(
309                 "Krb4Srvtab",
310                 ap_set_file_slot,
311                 (void*)APR_XtOffsetOf(kerb_auth_config, krb_4_srvtab),
312                 RSRC_CONF & ACCESS_CONF,
313                 "Location of Kerberos V4 srvtab file."
314         ),
315 #endif /* KRB4 */
316
317 #ifdef KRB5
318         AP_INIT_TAKE1(
319                 "Krb5Keytab",
320                 ap_set_file_slot,
321                 (void*)APR_XtOffsetOf(kerb_auth_config, krb_5_keytab),
322                 RSRC_CONF & ACCESS_CONF,
323                 "Location of Kerberos V5 keytab file."
324         ),
325 #endif /* KRB5 */
326
327         AP_INIT_FLAG(
328                 "KrbAuthoritative",
329                 ap_set_flag_slot,
330                 (void*)APR_XtOffsetOf(kerb_auth_config, krb_authoritative),
331                 OR_AUTHCFG,
332                 "Refuse to pass request down to lower modules."
333         ),
334
335         AP_INIT_TAKE1(
336                 "KrbDefaultRealm",
337                 ap_set_string_slot,
338                 (void*)APR_XtOffsetOf(kerb_auth_config, krb_default_realm),
339                 OR_AUTHCFG,
340                 "Default realm to authenticate users against."
341         ),
342
343         AP_INIT_TAKE1(
344                 "KrbFailStatus",
345                 kerb_set_fail_slot,
346                 (void*)APR_XtOffsetOf(kerb_auth_config, krb_fail_status),
347                 OR_AUTHCFG,
348                 "If auth fails, return status set here."
349         ),
350
351         AP_INIT_TAKE1(
352                 "KrbForceInstance",
353                 ap_set_string_slot,
354                 (void*)APR_XtOffsetOf(kerb_auth_config, krb_force_instance),
355                 OR_AUTHCFG,
356                 "Force authentication against an instance specified here."
357         ),
358
359 #ifdef KRB5
360         AP_INIT_FLAG(
361                 "KrbForwardable",
362                 ap_set_flag_slot,
363                 (void*)APR_XtOffsetOf(kerb_auth_config, krb_forwardable),
364                 OR_AUTHCFG,
365                 "Credentials retrieved will be flagged as forwardable."
366         ),
367 #endif /* KRB5 */
368
369         AP_INIT_TAKE1(
370                 "KrbLifetime",
371                 ap_set_string_slot,
372                 (void*)APR_XtOffsetOf(kerb_auth_config, krb_lifetime),
373                 OR_AUTHCFG,
374                 "Lifetime of tickets retrieved."
375         ),
376
377 #ifdef KRB5
378         AP_INIT_TAKE1(
379                 "KrbRenewable",
380                 ap_set_string_slot,
381                 (void*)APR_XtOffsetOf(kerb_auth_config, krb_renewable),
382                 OR_AUTHCFG,
383                 "Credentials retrieved will be renewable for this length."
384         ),
385 #endif /* KRB5 */
386
387         AP_INIT_FLAG(
388                 "KrbSaveCredentials",
389                 ap_set_flag_slot,
390                 (void*)APR_XtOffsetOf(kerb_auth_config, krb_save_credentials),
391                 OR_AUTHCFG,
392                 "Save and store credentials/tickets retrieved during auth."
393         ),
394
395         AP_INIT_FLAG(
396                 "KrbSaveTickets",
397                 ap_set_flag_slot,
398                 (void*)APR_XtOffsetOf(kerb_auth_config, krb_save_credentials),
399                 OR_AUTHCFG,
400                 "Alias for KrbSaveCredentials."
401         ),
402
403         AP_INIT_TAKE1(
404                 "KrbTmpdir",
405                 ap_set_string_slot,
406                 (void*)APR_XtOffsetOf(kerb_auth_config, krb_tmp_dir),
407                 RSRC_CONF & ACCESS_CONF,
408                 "Path to store ticket files and such in."
409         ),
410
411         { NULL }
412 };
413 #endif /* APXS2 */
414 #endif /* APXS1 */
415
416
417
418
419 /*************************************************************************** 
420  Username/Password Validation
421  ***************************************************************************/
422 #ifdef KRB5
423 int kerb5_password_validate(request_rec *r, const char *user, const char *pass)
424 {
425         kerb_auth_config *conf =
426                 (kerb_auth_config *)ap_get_module_config(r->per_dir_config,
427                                         &kerb_auth_module);
428         int ret;
429         krb5_context kcontext;
430         krb5_principal server, me;
431         krb5_creds my_creds;
432         krb5_timestamp now;
433         krb5_ccache ccache = NULL;
434         krb5_deltat lifetime = 300;     /* 5 minutes */
435         krb5_deltat renewal = 0;
436         krb5_flags options = 0;
437         krb5_data tgtname = {
438                 0,
439                 KRB5_TGS_NAME_SIZE,
440                 KRB5_TGS_NAME
441         };
442         char *c, ccname[MAX_STRING_LEN];
443
444         if (krb5_init_context(&kcontext))
445                 return 0;
446
447         if (conf->krb_save_credentials) {
448                 lifetime = 1800;        /* 30 minutes */
449
450                 if (conf->krb_forwardable) {
451                         options |= KDC_OPT_FORWARDABLE;
452                 }
453
454                 if (conf->krb_renewable) {
455                         options |= KDC_OPT_RENEWABLE;
456                         renewal = 86400;        /* 24 hours */
457                 }
458
459                 sprintf(ccname, "FILE:%s/k5cc_ap_%s",
460                         conf->krb_tmp_dir ? conf->krb_tmp_dir : "/tmp",
461                         MK_USER);
462
463                 for (c = ccname + strlen(conf->krb_tmp_dir ? conf->krb_tmp_dir :
464                                 "/tmp") + 1; *c; c++) {
465                         if (*c == '/')
466                                 *c = '.';
467                 }
468
469                 ap_table_setn(r->subprocess_env, "KRB5CCNAME", ccname);
470                 if (krb5_cc_set_default_name(kcontext, ccname)) {
471                         return 0;
472                 }
473                 unlink(ccname+strlen("FILE:"));
474         }
475
476         if (conf->krb_lifetime) {
477                 lifetime = atoi(conf->krb_lifetime);
478         }
479
480         memset((char *)&my_creds, 0, sizeof(my_creds));
481         if(krb5_parse_name(kcontext, user, &me))
482                 return 0;
483         my_creds.client = me;
484
485         if (krb5_build_principal_ext(kcontext, &server,
486                                 krb5_princ_realm(kcontext, me)->length,
487                                 krb5_princ_realm(kcontext, me)->data,
488                                 tgtname.length, tgtname.data,
489                                 krb5_princ_realm(kcontext, me)->length,
490                                 krb5_princ_realm(kcontext, me)->data,
491                                 0)) {
492                 return 0;
493         }
494         my_creds.server = server;
495         if (krb5_timeofday(kcontext, &now))
496                 return 0;
497         my_creds.times.starttime = 0;
498         my_creds.times.endtime = now + lifetime;
499         my_creds.times.renew_till = now + renewal;
500
501         if (conf->krb_save_credentials) {
502                 if (krb5_cc_resolve(kcontext, ccname, &ccache))
503                         return 0;
504
505                 if (krb5_cc_initialize(kcontext, ccache, me))
506                         return 0;
507         }
508
509         ret = krb5_get_in_tkt_with_password(kcontext, options, 0, NULL, 0,
510                                 pass, ccache, &my_creds, 0);
511         if (ret) {
512                 return 0;
513         }
514
515         krb5_free_cred_contents(kcontext, &my_creds);
516
517         return 1;
518 }
519 #endif /* KRB5 */
520
521 #ifdef KRB4
522 int kerb4_password_validate(request_rec *r, const char *user, const char *pass)
523 {
524         kerb_auth_config *conf =
525                 (kerb_auth_config *)ap_get_module_config(r->per_dir_config,
526                                         &kerb_auth_module);
527         int ret;
528         int lifetime = DEFAULT_TKT_LIFE;
529         char *c, *tfname;
530         char *username = NULL;
531         char *instance = NULL;
532         char *realm = NULL;
533
534         username = (char *)ap_pstrdup(r->pool, user);
535         if (!username) {
536                 return 0;
537         }
538
539         instance = strchr(username, '.');
540         if (instance) {
541                 *instance++ = '\0';
542         }
543         else {
544                 instance = "";
545         }
546
547         realm = strchr(username, '@');
548         if (realm) {
549                 *realm++ = '\0';
550         }
551         else {
552                 realm = "";
553         }
554
555         if (conf->krb_lifetime) {
556                 lifetime = atoi(conf->krb_lifetime);
557         }
558
559         if (conf->krb_force_instance) {
560                 instance = conf->krb_force_instance;
561         }
562
563         if (conf->krb_save_credentials) {
564                 tfname = (char *)malloc(sizeof(char) * MAX_STRING_LEN);
565                 sprintf(tfname, "%s/k5cc_ap_%s",
566                         conf->krb_tmp_dir ? conf->krb_tmp_dir : "/tmp",
567                         MK_USER);
568
569                 if (!strcmp(instance, "")) {
570                         tfname = strcat(tfname, ".");
571                         tfname = strcat(tfname, instance);
572                 }
573
574                 if (!strcmp(realm, "")) {
575                         tfname = strcat(tfname, ".");
576                         tfname = strcat(tfname, realm);
577                 }
578
579                 for (c = tfname + strlen(conf->krb_tmp_dir ? conf->krb_tmp_dir :
580                                 "/tmp") + 1; *c; c++) {
581                         if (*c == '/')
582                                 *c = '.';
583                 }
584
585                 krb_set_tkt_string(tfname);
586         }
587
588         if (!strcmp(realm, "")) {
589                 realm = (char *)malloc(sizeof(char) * (REALM_SZ + 1));
590                 ret = krb_get_lrealm(realm, 1);
591                 if (ret != KSUCCESS)
592                         return 0;
593         }
594
595         ret = krb_get_pw_in_tkt((char *)user, instance, realm, "krbtgt", realm,
596                                         lifetime, (char *)pass);
597         switch (ret) {
598                 case INTK_OK:
599                 case INTK_W_NOTALL:
600                         return 1;
601                         break;
602
603                 default:
604                         return 0;
605                         break;
606         }
607 }
608 #endif /* KRB4 */
609
610
611
612
613 /*************************************************************************** 
614  User Authentication
615  ***************************************************************************/
616 int kerb_authenticate_user(request_rec *r)
617 {
618         const char *name;               /* AuthName specified */
619         const char *type;               /* AuthType specified */
620         int KerberosV5 = 0;             /* Kerberos V5 check enabled */
621         int KerberosV4 = 0;             /* Kerberos V4 check enabled */
622         int KerberosV4first = 0;        /* Kerberos V4 check first */
623         const char *sent_pw;            /* Password sent by browser */
624         int res;                        /* Response holder */
625         int retcode;                    /* Return code holder */
626         const char *t;                  /* Decoded auth_line */
627         const char *authtype;           /* AuthType to send back to browser */
628         const char *auth_line = MK_TABLE_GET(r->headers_in,
629                                         (r->proxyreq == MK_PROXY)
630                                                 ? "Proxy-Authorization"
631                                                 : "Authorization");
632         kerb_auth_config *conf =
633                 (kerb_auth_config *)ap_get_module_config(r->per_dir_config,
634                                         &kerb_auth_module);
635
636         type = ap_auth_type(r);
637
638         if (type != NULL) {
639 #ifdef KRB5
640                 if ((strncasecmp(type, "KerberosV5", 10) == 0) ||
641                     (strncasecmp(conf->krb_auth_type, "KerberosV5", 10) == 0)) {
642                         KerberosV5 = 1;
643                 }
644 #endif /* KRB5 */
645
646 #ifdef KRB4
647                 if ((strncasecmp(type, "KerberosV4", 10) == 0) ||
648                     (strncasecmp(conf->krb_auth_type, "KerberosV4", 10) == 0)) {
649                         KerberosV4 = 1;
650                 }
651 #endif /* KRB4 */
652
653 #if defined(KRB5) && defined(KRB4)
654                 if ((strncasecmp(type, "KerberosDualV5V4", 15) == 0) ||
655                     (strncasecmp(conf->krb_auth_type, "KerberosDualV5V4", 15) == 0)) {
656                         KerberosV5 = 1;
657                         KerberosV4 = 1;
658                 }
659
660                 if ((strncasecmp(type, "KerberosDualV4V5", 15) == 0) ||
661                     (strncasecmp(conf->krb_auth_type, "KerberosDualV4V5", 15) == 0)) {
662                         KerberosV5 = 1;
663                         KerberosV4 = 1;
664                         KerberosV4first = 1;
665                 }
666 #endif /* KRB5 && KRB4 */
667         }
668
669         if (!KerberosV4 && !KerberosV5) {
670                 if (conf->krb_authoritative) {
671                         return HTTP_UNAUTHORIZED;
672                 }
673                 else {
674                         return DECLINED;
675                 }
676         }
677
678         name = ap_auth_name(r);
679         if (!name) {
680                 return HTTP_INTERNAL_SERVER_ERROR;
681         }
682
683         if (!auth_line) {
684                 MK_TABLE_SET(r->err_headers_out, "WWW-Authenticate",
685                         (char *)ap_pstrcat(r->pool,
686                         "Basic realm=\"", name, "\"", NULL));
687                 return HTTP_UNAUTHORIZED;
688         }
689
690         type = ap_getword_white(r->pool, &auth_line);
691         t = ap_pbase64decode(r->pool, auth_line);
692         MK_USER = ap_getword_nulls(r->pool, &t, ':');
693         MK_AUTH_TYPE = "Kerberos";
694         sent_pw = ap_getword_white(r->pool, &t);
695
696         retcode = DECLINED;
697
698 #ifdef KRB5
699         if (KerberosV5 && !KerberosV4first && retcode != OK) {
700                 MK_AUTH_TYPE = "KerberosV5";
701                 if (kerb5_password_validate(r, MK_USER, sent_pw)) {
702                         retcode = OK;
703                 }
704                 else {
705                         retcode = conf->krb_fail_status;
706                 }
707         }
708 #endif /* KRB5 */
709
710 #ifdef KRB4
711         if (KerberosV4 && retcode != OK) {
712                 MK_AUTH_TYPE = "KerberosV4";
713                 if (kerb4_password_validate(r, MK_USER, sent_pw)) {
714                         retcode = OK;
715                 }
716                 else {
717                         retcode = conf->krb_fail_status;
718                 }
719         }
720 #endif /* KRB4 */
721
722 #if defined(KRB5) && defined(KRB4)
723         if (KerberosV5 && KerberosV4first && retcode != OK) {
724                 MK_AUTH_TYPE = "KerberosV5";
725                 if (kerb5_password_validate(r, MK_USER, sent_pw)) {
726                         retcode = OK;
727                 }
728                 else {
729                         retcode = conf->krb_fail_status;
730                 }
731         }
732 #endif /* KRB5 && KRB4 */
733
734         if (conf->krb_authoritative && retcode == DECLINED) {
735                 return HTTP_UNAUTHORIZED;
736         }
737         else {
738                 return retcode;
739         }
740 }
741
742
743
744
745 /*************************************************************************** 
746  Access Verification
747  ***************************************************************************/
748 int kerb_check_user_access(request_rec *r)
749 {
750         register int x;
751         const char *t, *w;
752         const MK_ARRAY_HEADER *reqs_arr = ap_requires(r);
753         require_line *reqs;
754         kerb_auth_config *conf =
755                 (kerb_auth_config *)ap_get_module_config(r->per_dir_config,
756                                                 &kerb_auth_module);
757
758         if (reqs_arr == NULL) {
759                 return OK;
760         }
761         reqs = (require_line *)reqs_arr->elts;
762
763         for (x = 0; x < reqs_arr->nelts; x++) {
764                 t = reqs[x].requirement;
765                 w = ap_getword_white(r->pool, &t);
766                 if (strcmp(w, "realm") == 0) {
767                         while (t[0] != '\0') {
768                                 w = ap_getword_conf(r->pool, &t);
769                                 if (strcmp(MK_USER, w) == 0) {
770                                         return OK;
771                                 }
772                         }
773                 }
774         }
775
776         return DECLINED;
777 }
778
779
780
781
782 /*************************************************************************** 
783  Module Setup/Configuration
784  ***************************************************************************/
785 #ifdef APXS1
786 module MODULE_VAR_EXPORT kerb_auth_module = {
787         STANDARD_MODULE_STUFF,
788         NULL,                           /*      module initializer            */
789         kerb_dir_config,                /*      per-directory config creator  */
790         NULL,                           /*      per-directory config merger   */
791         NULL,                           /*      per-server    config creator  */
792         NULL,                           /*      per-server    config merger   */
793         kerb_auth_cmds,                 /*      command table                 */
794         NULL,                           /* [ 9] content handlers              */
795         NULL,                           /* [ 2] URI-to-filename translation   */
796         kerb_authenticate_user,         /* [ 5] check/validate user_id        */
797         kerb_check_user_access,         /* [ 6] check user_id is valid *here* */
798         NULL,                           /* [ 4] check access by host address  */
799         NULL,                           /* [ 7] MIME type checker/setter      */
800         NULL,                           /* [ 8] fixups                        */
801         NULL,                           /* [10] logger                        */
802         NULL,                           /* [ 3] header parser                 */
803         NULL,                           /*      process initialization        */
804         NULL,                           /*      process exit/cleanup          */
805         NULL                            /* [ 1] post read_request handling    */
806 #ifdef EAPI
807         ,                               /*            EAPI Additions          */
808         NULL,                           /* EAPI add module                    */
809         NULL,                           /* EAPI remove module                 */
810         NULL,                           /* EAPI rewrite command               */
811         NULL                            /* EAPI new connection                */
812 #endif /* EAPI */
813 };
814 #else
815 #ifdef APXS2
816 void kerb_register_hooks(apr_pool_t *p)
817 {
818         ap_hook_check_user_id(kerb_authenticate_user, NULL, NULL, APR_HOOK_MIDDLE);
819         ap_hook_access_checker(kerb_check_user_access, NULL, NULL, APR_HOOK_MIDDLE);
820 }
821
822 module AP_MODULE_DECLARE_DATA kerb_auth_module =
823 {
824         STANDARD20_MODULE_STUFF,
825         kerb_dir_config,                /* create per-dir    conf structures  */
826         NULL,                           /* merge  per-dir    conf structures  */
827         NULL,                           /* create per-server conf structures  */
828         NULL,                           /* merge  per-server conf structures  */
829         kerb_auth_cmds,                 /* table of configuration directives  */
830         kerb_register_hooks             /* register hooks                     */
831 };
832 #endif /* APXS2 */
833 #endif /* APXS1 */