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