"Fossies" - the Fresh Open Source Software Archive 
As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style:
standard) with prefixed line numbers and
code folding option.
Alternatively you can here
view or
download the uninterpreted source code file.
1 /*
2 * DCE Authentication Module for Apache HTTP Server
3 *
4 * Paul B. Henson <henson@acm.org>
5 *
6 * Copyright (c) 1996-2003 Paul B. Henson -- see COPYRIGHT file for details
7 *
8 */
9
10 /* MODULE-DEFINITION-START
11 * Name: auth_dce
12 * ConfigStart
13
14 case "$PLAT" in
15
16 *-ibm-aix4.*)
17 echo " mod_auth_dce: Note - context caching not supported on this platform."
18 CC=xlC_r4
19 CFLAGS="$CFLAGS -DNO_CACHING"
20 LDFLAGS="$LDFLAGS -ldce -lm"
21 ;;
22
23 *-dec-osf*)
24 echo " mod_auth_dce: Note - context caching not supported on this platform."
25 CFLAGS="$CFLAGS -std -threads -DNO_CACHING"
26 LDFLAGS="$LDFLAGS -threads"
27 LIBS="$LIBS -ldce -lm"
28 ;;
29
30 *-solaris2*)
31 CFLAGS="$CFLAGS -D_REENTRANT"
32 case "$PLATOSVERS" in
33 2[012345]*)
34 LIBS="$LIBS -ldce -lthread -lsocket -lnsl -lm"
35 ;;
36 2[678]*)
37 LIBS="$LIBS -ldce -lpthread -lsocket -lnsl"
38 ;;
39 *)
40 echo " mod_auth_dce: This version of Solaris is not currently supported."
41 exit 1
42 ;;
43 esac
44 ;;
45
46 *)
47 echo " mod_auth_dce: I don't know how to compile DCE applications on this platform."
48 exit 1
49 ;;
50
51 esac
52
53 * ConfigEnd
54 * MODULE-DEFINITION-END
55 */
56
57 #if defined(HPUX) || defined(HPUX10) || defined(HPUX11) /* I guess HPSUX just had to be different */
58 #include <pthread.h>
59 #else
60 #include <dce/pthread.h>
61 #endif
62
63 #include <dce/dce_error.h>
64 #include <dce/sec_login.h>
65 #include <dce/binding.h>
66 #include <dce/pgo.h>
67 #include "httpd.h"
68 #include "http_config.h"
69 #include "http_core.h"
70 #include "http_log.h"
71 #include "http_main.h"
72 #include "http_protocol.h"
73 #include "util_script.h"
74 #include "mod_auth_dce.h"
75
76
77 #ifndef NO_CACHING
78 #ifdef SOLARIS2
79 static char krb5_env[] = "KRB5CCNAME=FILE:/opt/dcelocal/var/security/creds/dcecred_XXXXXXXX";
80 static char *krb5_env_pag = krb5_env+57;
81 #else
82 #error Credential cache directory not known for this platform.
83 #endif
84 static unsigned32 server_pag = 0;
85 #endif
86
87 #ifndef WITH_DFS
88 static unsigned long sec_login_inq_pag_no_dfs(void *dummy, error_status_t *dce_st)
89 {
90 char *krb5ccname = getenv("KRB5CCNAME");
91 *dce_st = 0;
92
93 if (krb5ccname)
94 {
95 int len = strlen(krb5ccname);
96 if (len >= 8)
97 return (unsigned long)strtol(krb5ccname + len - 8, (char **)NULL, 16);
98 }
99
100 return 0;
101 }
102 #define sec_login_inq_pag(X, Y) sec_login_inq_pag_no_dfs(X, Y)
103 #define installpag(X)
104 #define resetpag()
105 #endif
106
107 static sec_login_handle_t server_context = NULL;
108
109
110 server_config_rec auth_dce_server_config = {
111 NULL, /* default user */
112 NULL, /* default keytab */
113 0, /* default certify_identity */
114 #ifndef NO_CACHING
115 1000, /* default cache_buckets */
116 7200, /* default cache_graceperiod */
117 21600, /* default cache_lifetime */
118 14400, /* default cache_max_idle */
119 1800 /* default cache_sweep_interval */
120 #endif
121 };
122
123
124 static pthread_addr_t refresh_context(pthread_addr_t arg)
125 {
126 signed32 expiration_time;
127 time_t now;
128 struct timespec sleep_interval;
129 error_status_t dce_st;
130 dce_error_string_t dce_error;
131 int dce_error_st;
132 sec_login_auth_src_t auth_src;
133 unsigned32 kvno_worked;
134 boolean32 reset_passwd;
135 server_rec *s = (server_rec *)arg;
136
137 DEBUG_S("auth_dce.refresh_context: beginning context refresh loop");
138
139 while (1)
140 {
141 now = time(NULL);
142
143 sec_login_get_expiration(server_context, &expiration_time, &dce_st);
144 if (dce_st && (dce_st != sec_login_s_not_certified))
145 {
146 dce_error_inq_text(dce_st, dce_error, &dce_error_st);
147 ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, s,
148 "auth_dce.refresh_context: sec_login_get_expiration failed - %s (%d)", dce_error, dce_st);
149 expiration_time = now + 20 * 60;
150 }
151
152 DEBUG_S("auth_dce.refresh_context: context expires at time %d", expiration_time);
153
154 sleep_interval.tv_sec = expiration_time - now - 10 * 60;
155 sleep_interval.tv_nsec = 0;
156
157 DEBUG_S("auth_dce.refresh_context: sleeping %d seconds", sleep_interval.tv_sec);
158
159 pthread_delay_np(&sleep_interval);
160
161 DEBUG_S("auth_dce.refresh_context: calling sec_login_refresh_identity");
162
163 sec_login_refresh_identity(server_context, &dce_st);
164 if (dce_st)
165 {
166 dce_error_inq_text(dce_st, dce_error, &dce_error_st);
167 ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, s,
168 "auth_dce.refresh_context: sec_login_refresh_identity failed - %s (%d)", dce_error, dce_st);
169 }
170
171 DEBUG_S("auth_dce.refresh_context: calling sec_login_valid_from_keytable");
172
173 sec_login_valid_from_keytable(server_context, rpc_c_authn_dce_secret, auth_dce_server_config.keytab, (unsigned32) NULL, &kvno_worked,
174 &reset_passwd, &auth_src, &dce_st);
175 if (dce_st)
176 {
177 dce_error_inq_text(dce_st, dce_error, &dce_error_st);
178 ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, s,
179 "auth_dce.refresh_context: sec_login_valid_from_keytable failed - %s (%d)", dce_error, dce_st);
180 }
181
182 DEBUG_S("auth_dce.refresh_context: context refreshed");
183 }
184 return 0;
185 }
186
187 #ifndef NO_CACHING
188 void auth_dce_purge_context(server_rec *s, unsigned long pag)
189 {
190 sec_login_handle_t login_context;
191 error_status_t dce_st;
192 dce_error_string_t dce_error;
193 int dce_error_st;
194
195 DEBUG_S("auth_dce.purge_context called for pag %08x", pag);
196
197 sec_login_context_from_pag(pag, &login_context, &dce_st);
198 if (dce_st)
199 {
200 dce_error_inq_text(dce_st, dce_error, &dce_error_st);
201 ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, s,
202 "auth_dce.purge_context: sec_login_context_from_pag failed - %s (%d)", dce_error, dce_st);
203 return;
204 }
205
206 sec_login_purge_context(&login_context, &dce_st);
207 }
208 #endif
209
210 static void *create_server_config(pool *p, server_rec *s)
211 {
212 return ap_pcalloc (p, sizeof(server_config_rec));
213 }
214
215 static void *merge_server_configs(pool *p, void *basev, void *addv)
216 {
217 server_config_rec *new = (server_config_rec*)ap_pcalloc(p, sizeof(server_config_rec));
218 server_config_rec *base = (server_config_rec *)basev;
219 server_config_rec *add = (server_config_rec *)addv;
220
221 return new;
222 }
223
224 static const char *set_user(cmd_parms *cmd, void *dv, char *word1)
225 {
226 auth_dce_server_config.user = (word1) ? ap_pstrdup(cmd->pool, word1) : NULL;
227 return NULL;
228 }
229
230 static const char *set_keytab(cmd_parms *cmd, void *dv, char *word1)
231 {
232 auth_dce_server_config.keytab = ap_pstrcat(cmd->pool, "FILE:", word1, NULL);
233 return NULL;
234 }
235
236 static const char *set_certify_identity(cmd_parms *cmd, void *mconfig, int bool)
237 {
238 auth_dce_server_config.certify_identity = bool;
239 return NULL;
240 }
241
242 #ifndef NO_CACHING
243 static const char *set_cache_buckets(cmd_parms *cmd, void *dv, char *word1)
244 {
245 auth_dce_server_config.cache_buckets = atoi(word1);
246 if (auth_dce_server_config.cache_buckets < 1 || auth_dce_server_config.cache_buckets > 50000)
247 return "auth_dce: invalid cache_buckets value";
248
249 return NULL;
250 }
251
252 static const char *set_cache_graceperiod(cmd_parms *cmd, void *dv, char *word1)
253 {
254 auth_dce_server_config.cache_graceperiod = atoi(word1);
255 if (auth_dce_server_config.cache_graceperiod < 0)
256 return "auth_dce: invalid negative cache_graceperiod";
257
258 return NULL;
259 }
260
261 static const char *set_cache_lifetime(cmd_parms *cmd, void *dv, char *word1)
262 {
263 auth_dce_server_config.cache_lifetime = atoi(word1);
264 if (auth_dce_server_config.cache_lifetime < 3600)
265 return "auth_dce: invalid cache_buckets value < 3600 seconds";
266
267 return NULL;
268 }
269
270 static const char *set_cache_max_idle(cmd_parms *cmd, void *dv, char *word1)
271 {
272 auth_dce_server_config.cache_max_idle = atoi(word1);
273 if (auth_dce_server_config.cache_max_idle < 0)
274 return "auth_dce: invalid cache_max_idle < 0";
275
276 return NULL;
277 }
278
279 static const char *set_cache_sweep_interval(cmd_parms *cmd, void *dv, char *word1)
280 {
281 auth_dce_server_config.cache_sweep_interval = atoi(word1);
282 if (auth_dce_server_config.cache_sweep_interval < 300)
283 return "auth_dce: invalid cache_sweep_interval < 300 seconds";
284
285 return NULL;
286 }
287 #endif
288
289 static const char *set_indexes(cmd_parms *cmd, void *dv, const char *args)
290 {
291 dir_config_rec *dir_config = (dir_config_rec *)dv;
292 dir_config->index_names = ap_pstrcat(cmd->pool, args, NULL);
293 return NULL;
294 }
295
296 static void *create_dir_config(pool *p, char *d)
297 {
298 dir_config_rec *new = (dir_config_rec*)ap_pcalloc(p, sizeof(dir_config_rec));
299 new->impersonate_browser = 1;
300 new->authoritative = 1;
301
302 return new;
303 }
304
305 static void *merge_dir_configs(pool *p, void *basev, void *addv)
306 {
307 dir_config_rec *new = (dir_config_rec*)ap_pcalloc(p, sizeof(dir_config_rec));
308 dir_config_rec *base = (dir_config_rec *)basev;
309 dir_config_rec *add = (dir_config_rec *)addv;
310
311 new->active = add->active;
312 #ifdef WITH_DFS
313 new->dfs_authorization = add->dfs_authorization;
314 #endif
315 new->include_pw = add->include_pw;
316 new->impersonate_browser = add->impersonate_browser;
317 new->authoritative = add->authoritative;
318 new->index_names = (add->index_names) ? (add->index_names) : (base->index_names);
319
320 return new;
321 }
322
323
324 static command_rec cmds[] = {
325 { "AuthDCE", ap_set_flag_slot, (void *) XtOffsetOf(dir_config_rec, active), OR_AUTHCFG, FLAG,
326 "Perform DCE authentication in this directory?" },
327
328 #ifdef WITH_DFS
329 { "AuthDCEDFSAuthorization", ap_set_flag_slot, (void *) XtOffsetOf(dir_config_rec, dfs_authorization), OR_AUTHCFG, FLAG,
330 "Use DFS ACLs for authorization in this directory?" },
331 #endif
332
333 { "AuthDCEIncludePW", ap_set_flag_slot, (void *) XtOffsetOf(dir_config_rec, include_pw), OR_AUTHCFG, FLAG,
334 "Include DCE password for CGIs run in this directory?" },
335
336 { "AuthDCEImpersonateBrowser", ap_set_flag_slot, (void *) XtOffsetOf(dir_config_rec, impersonate_browser), OR_AUTHCFG, FLAG,
337 "Attach browser's credentials when accessing files or running CGIs?" },
338
339 { "AuthDCEUser", set_user, NULL, RSRC_CONF, TAKE1,
340 "DCE identity to run web server as" },
341
342 { "AuthDCEKeytab", set_keytab, NULL, RSRC_CONF, TAKE1,
343 "Keytab to use if different than default" },
344
345 { "AuthDCEAuthoritative", ap_set_flag_slot, (void *) XtOffsetOf(dir_config_rec, authoritative), OR_AUTHCFG, FLAG,
346 "Make DCE Authoritative" },
347
348 { "AuthDCEDirectoryIndex", set_indexes, NULL, OR_INDEXES, RAW_ARGS,
349 "Set this identical to DirectoryIndex if set" },
350
351 { "AuthDCECertifyIdentity", set_certify_identity, NULL, RSRC_CONF, FLAG,
352 "Certify DCE Identity" },
353
354 #ifndef NO_CACHING
355 { "AuthDCECacheBuckets", set_cache_buckets, NULL, RSRC_CONF, TAKE1,
356 "Number of buckets in credential hash table" },
357
358 { "AuthDCECacheGracePeriod", set_cache_graceperiod, NULL, RSRC_CONF, TAKE1,
359 "Time in seconds" },
360
361 { "AuthDCECacheLifetime", set_cache_lifetime, NULL, RSRC_CONF, TAKE1,
362 "Time in seconds after which credentials are removed" },
363
364 { "AuthDCECacheMaxIdle", set_cache_max_idle, NULL, RSRC_CONF, TAKE1,
365 "Time in seconds after which unused credentials are considered idle" },
366
367 { "AuthDCECacheSweepInterval", set_cache_sweep_interval, NULL, RSRC_CONF, TAKE1,
368 "Frequency in seconds to sweep cache for credential removal" },
369 #endif
370
371 { NULL }
372 };
373
374
375 module auth_dce_module;
376
377 static int authenticate(request_rec *r)
378 {
379 char *sent_pw;
380 sec_login_handle_t login_context;
381 error_status_t dce_st;
382 dce_error_string_t dce_error;
383 int dce_error_st;
384 sec_login_auth_src_t auth_src;
385 sec_passwd_rec_t pw_entry;
386 sec_passwd_str_t dce_pw;
387 boolean32 reset_passwd;
388 request_config_rec *request_config;
389
390 dir_config_rec *dir_config = (dir_config_rec *)ap_get_module_config(r->per_dir_config, &auth_dce_module);
391
392 DEBUG_R("auth_dce.authenticate: called for URI %s", r->uri);
393 DEBUG_R("auth_dce.authenticate: called for filename %s", r->filename);
394
395 if (!dir_config->active)
396 {
397 if (server_context)
398 ap_table_set(r->subprocess_env, "KRB5CCNAME", getenv("KRB5CCNAME"));
399
400 DEBUG_R("auth_dce.authenticate: active not set, returning DECLINED");
401
402 return DECLINED;
403 }
404
405 #ifdef WITH_DFS
406 if (dir_config->dfs_authorization)
407 {
408 struct stat statbuf;
409 int accessible = 1;
410
411 if(stat(r->filename, &statbuf))
412 accessible = (errno != EACCES);
413 else
414 {
415 int access_required = R_OK;
416
417 if (S_ISDIR(statbuf.st_mode))
418 if (r->uri[strlen(r->uri)-1] == '/')
419 {
420 const char *indexes = (dir_config->index_names) ? (dir_config->index_names) : (DEFAULT_INDEX);
421 char *slash = (r->filename[strlen(r->filename)-1] == '/') ? "" : "/";
422 access_required |= X_OK;
423
424 while (*indexes)
425 {
426 char *index = ap_getword_conf(r->pool, &indexes);
427 char *filename = ap_pstrcat(r->pool, r->filename, slash, index, NULL);
428
429 if (!stat(filename, &statbuf))
430 {
431 r->filename = filename;
432 access_required = R_OK;
433 break;
434 }
435 }
436 }
437 else
438 return OK; /* request for directory with no trailing slash, allow redirect without authentication */
439
440 if (access(r->filename, access_required))
441 accessible = (errno != EACCES);
442 }
443
444 if (accessible)
445 {
446 DEBUG_R("auth_dce.authenticate: file is accessible, returning OK");
447 ap_set_module_config(r->request_config, &auth_dce_module, NULL);
448
449 if (server_context)
450 ap_table_set(r->subprocess_env, "KRB5CCNAME", getenv("KRB5CCNAME"));
451
452 return OK;
453 }
454 }
455 #endif
456
457 if (!(ap_table_get(r->headers_in, r->proxyreq != STD_PROXY ? "Authorization" : "Proxy-Authorization")))
458 {
459 DEBUG_R("auth_dce.authenticate: authorization not provided, returning AUTH_REQUIRED");
460 ap_note_basic_auth_failure(r);
461
462 return AUTH_REQUIRED;
463 }
464
465 ap_set_module_config(r->request_config, &auth_dce_module, (void *)ap_pcalloc(r->pool, sizeof(request_config_rec)));
466 request_config = (request_config_rec *)ap_get_module_config(r->request_config, &auth_dce_module);
467
468 ap_get_basic_auth_pw(r, (const char **)&sent_pw);
469
470 DEBUG_R("auth_dce.authenticate: request made by user %s", r->connection->user);
471
472 #ifndef NO_CACHING
473 auth_dce_find_cached_context(r, request_config, r->connection->user, sent_pw);
474
475 if (!request_config->pag)
476 {
477 #endif
478
479 DEBUG_R("auth_dce.authenticate: calling sec_login_setup_identity");
480
481 if (!sec_login_setup_identity((unsigned_char_p_t)r->connection->user, sec_login_no_flags,
482 &login_context, &dce_st))
483 {
484 dce_error_inq_text(dce_st, dce_error, &dce_error_st);
485 ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r,
486 "auth_dce.authenticate: sec_login_setup_identity failed for %s - %s (%d)", r->connection->user, dce_error, dce_st);
487
488 if (dir_config->authoritative)
489 {
490 ap_note_basic_auth_failure(r);
491 DEBUG_R("auth_dce.authenticate: returning AUTH_REQUIRED");
492
493 return AUTH_REQUIRED;
494 }
495 else
496 {
497 DEBUG_R("auth_dce.authenticate: AuthDCEAuthoritative off, returning DECLINED");
498
499 return DECLINED;
500 }
501 }
502
503 pw_entry.version_number = sec_passwd_c_version_none;
504 pw_entry.pepper = NULL;
505 pw_entry.key.key_type = sec_passwd_plain;
506
507 strncpy( (char *)dce_pw, sent_pw, sec_passwd_str_max_len);
508 dce_pw[sec_passwd_str_max_len] = '\0';
509 pw_entry.key.tagged_union.plain = &(dce_pw[0]);
510
511 DEBUG_R("auth_dce.authenticate: calling sec_login_validate_identity");
512
513 if (!sec_login_validate_identity(login_context, &pw_entry, &reset_passwd,
514 &auth_src, &dce_st))
515 {
516 dce_error_inq_text(dce_st, dce_error, &dce_error_st);
517 ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r,
518 "auth_dce.authenticate: sec_login_validate_identity failed for %s - %s (%d)", r->connection->user, dce_error, dce_st);
519
520 sec_login_purge_context(&login_context, &dce_st);
521 ap_note_basic_auth_failure(r);
522 DEBUG_R("auth_dce.authenticate: returning AUTH_REQUIRED");
523
524 return AUTH_REQUIRED;
525 }
526
527 if (auth_dce_server_config.certify_identity)
528 {
529 DEBUG_R("auth_dce.authenticate: calling sec_login_certify_identity");
530
531 if (!sec_login_certify_identity(login_context, &dce_st))
532 {
533 dce_error_inq_text(dce_st, dce_error, &dce_error_st);
534 ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r,
535 "auth_dce.authenticate: sec_login_certify_identity failed for %s - %s (%d)", r->connection->user, dce_error, dce_st);
536
537 sec_login_purge_context(&login_context, &dce_st);
538 ap_note_basic_auth_failure(r);
539 DEBUG_R("auth_dce.authenticate: returning AUTH_REQUIRED");
540
541 return AUTH_REQUIRED;
542 }
543 }
544
545 if (auth_src != sec_login_auth_src_network)
546 {
547 ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r,
548 "auth_dce.authenticate: no network credentials for %s", r->connection->user);
549
550 sec_login_purge_context(&login_context, &dce_st);
551 ap_note_basic_auth_failure(r);
552 DEBUG_R("auth_dce.authenticate: returning AUTH_REQUIRED");
553
554 return AUTH_REQUIRED;
555 }
556
557
558 #ifndef NO_CACHING
559 DEBUG_R("auth_dce.authenticate: acquiring context pag");
560
561 if (server_pag)
562 krb5_env[0] = 'X';
563
564 sec_login_set_context(login_context, &dce_st);
565 if (dce_st)
566 {
567 dce_error_inq_text(dce_st, dce_error, &dce_error_st);
568 ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r,
569 "auth_dce.authenticate: sec_login_set_context failed for %s - %s (%d)", r->connection->user, dce_error, dce_st);
570
571 sec_login_purge_context(&login_context, &dce_st);
572
573 if (server_pag)
574 {
575 krb5_env[0] = 'K';
576 installpag(server_pag);
577 }
578
579 ap_note_basic_auth_failure(r);
580 DEBUG_R("auth_dce.authenticate: returning AUTH_REQUIRED");
581
582 return AUTH_REQUIRED;
583 }
584
585 request_config->pag = sec_login_inq_pag(login_context, &dce_st);
586 if (dce_st || !request_config->pag)
587 {
588 dce_error_inq_text(dce_st, dce_error, &dce_error_st);
589 ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r,
590 "auth_dce.authenticate: sec_login_inq_pag failed for %s - %s (%d)", r->connection->user, dce_error, dce_st);
591
592 sec_login_purge_context(&login_context, &dce_st);
593
594 if (server_pag)
595 {
596 krb5_env[0] = 'K';
597 installpag(server_pag);
598 }
599
600 ap_note_basic_auth_failure(r);
601 DEBUG_R("auth_dce.authenticate: returning AUTH_REQUIRED");
602
603 return AUTH_REQUIRED;
604 }
605
606 sec_login_release_context(&login_context, &dce_st);
607 if (server_pag)
608 {
609 krb5_env[0] = 'K';
610 installpag(server_pag);
611 }
612
613 auth_dce_add_cached_context(r, request_config);
614 }
615 #else
616 request_config->login_context = login_context;
617 #endif
618
619 if (dir_config->impersonate_browser)
620 {
621
622 DEBUG_R("auth_dce.authenticate: impersonating browser");
623
624 #ifndef NO_CACHING
625 krb5_env[0] = 'K';
626 sprintf(krb5_env_pag, "%08x", request_config->pag);
627 installpag(request_config->pag);
628 #else
629
630 if (server_context)
631 unlink(getenv("KRB5CCNAME")+5);
632
633 DEBUG_R("auth_dce.authenticate: calling sec_login_set_context");
634 sec_login_set_context(request_config->login_context, &dce_st);
635 if (dce_st)
636 {
637 dce_error_inq_text(dce_st, dce_error, &dce_error_st);
638 ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r,
639 "auth_dce.authenticate: sec_login_set_context failed for %s - %s (%d)", r->connection->user, dce_error, dce_st);
640
641 sec_login_purge_context(&request_config->login_context, &dce_st);
642
643 if (server_context)
644 sec_login_set_context(server_context, &dce_st);
645
646 ap_note_basic_auth_failure(r);
647 DEBUG_R("auth_dce.authenticate: returning AUTH_REQUIRED");
648
649 return AUTH_REQUIRED;
650 }
651 #endif
652 }
653
654
655 /* The server might have failed to fill in the request_rec
656 * structure due to permission errors. If the structure hasn't been
657 * filled in, call the function (from http_request.c) again.
658 */
659 if (r->finfo.st_mode == 0)
660 get_path_info(r);
661
662 DEBUG_R("auth_dce.authenticate: setting CGI environment variables");
663
664 ap_table_set(r->subprocess_env, "KRB5CCNAME", getenv("KRB5CCNAME"));
665
666 if (dir_config->include_pw)
667 ap_table_set(r->subprocess_env, "DCEPW", sent_pw);
668
669 /* requested feature to remove authorization header for requests where
670 include_pw not set, currently disabled pending debugging of strange
671 side effects
672
673 else
674 ap_table_set(r->headers_in, r->proxyreq != STD_PROXY ? "Authorization" : "Proxy-Authorization",
675 ap_pstrcat(r->pool, "Basic ",
676 ap_pbase64encode(r->pool, ap_pstrcat(r->pool, r->connection->user, ":<censored>", NULL)),
677 NULL));
678 */
679
680 DEBUG_R("auth_dce.authenticate: returning OK");
681
682 return OK;
683 }
684
685
686 static int authorize(request_rec *r)
687 {
688 dir_config_rec *dir_config = (dir_config_rec *)ap_get_module_config(r->per_dir_config, &auth_dce_module);
689
690 error_status_t dce_st;
691 dce_error_string_t dce_error;
692 int dce_error_st;
693
694 const char *require_list;
695 char *require_type, *entity;
696 const array_header *requires_array = ap_requires(r);
697 require_line *require_lines;
698
699 int index;
700
701 DEBUG_R("auth_dce.authorize: called for URI %s", r->uri);
702 DEBUG_R("auth_dce.authorize: called for filename %s", r->filename);
703
704 if (!dir_config->active)
705 {
706 DEBUG_R("auth_dce.authorize: active not set, returning DECLINED");
707
708 return DECLINED;
709 }
710
711 if (!ap_get_module_config(r->request_config, &auth_dce_module))
712 {
713 DEBUG_R("auth_dce.authorize: request_config not set, returning OK");
714
715 return OK;
716 }
717
718 DEBUG_R("auth_dce.authorize: called for user %s", r->connection->user);
719
720 if (!requires_array)
721 {
722 /* Assume no require information is the same as "require valid-user" and return OK. */
723 DEBUG_R("auth_dce.authorize: no requires line, returning OK");
724
725 return OK;
726 }
727
728 require_lines = (require_line *)requires_array->elts;
729 for(index = 0; index < requires_array->nelts; index++)
730 {
731 if (!(require_lines[index].method_mask & (1 << r->method_number)))
732 continue;
733
734 require_list = require_lines[index].requirement;
735 require_type = ap_getword_white(r->pool, &require_list);
736
737 if(!strcmp(require_type, "valid-user"))
738 {
739 DEBUG_R("auth_dce.authorize: matched valid-user, returning OK");
740
741 return OK;
742 }
743
744 if(!strcmp(require_type, "user"))
745 while(*require_list)
746 {
747 entity = ap_getword_conf(r->pool, &require_list);
748 if(!strcmp(entity, r->connection->user))
749 {
750 DEBUG_R("auth_dce.authorize: matched listed user, returning OK");
751
752 return OK;
753 }
754 }
755
756 if(!strcmp(require_type, "group"))
757 while(*require_list)
758 {
759 entity = ap_getword_conf(r->pool, &require_list);
760 if(sec_rgy_pgo_is_member(sec_rgy_default_handle, sec_rgy_domain_group, (unsigned_char_p_t)entity,
761 (unsigned_char_p_t)r->connection->user, &dce_st))
762 {
763 DEBUG_R("auth_dce.authorize: matched listed group %s, returning OK", entity);
764
765 return OK;
766 }
767 }
768 }
769
770 return ((dir_config->authoritative) ? FORBIDDEN : DECLINED);
771 }
772
773
774 static int request_cleanup(request_rec *orig)
775 {
776 sec_login_handle_t login_context;
777 error_status_t dce_st;
778 dce_error_string_t dce_error;
779 int dce_error_st;
780
781 request_rec *r = orig;
782 dir_config_rec *dir_config;
783 request_config_rec *request_config;
784
785 while (r)
786 {
787 DEBUG_R("auth_dce.request_cleanup: processing URI %s", r->uri);
788 DEBUG_R("auth_dce.request_cleanup: processing filename %s", r->filename);
789
790 dir_config = (dir_config_rec *)ap_get_module_config(r->per_dir_config, &auth_dce_module);
791
792 if (dir_config->active && dir_config->impersonate_browser &&
793 (request_config = (request_config_rec *)ap_get_module_config(r->request_config, &auth_dce_module)))
794 {
795
796 #ifndef NO_CACHING
797 if (memcmp(request_config->hash_key, "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 16))
798 {
799 if (request_config->pag)
800 {
801 DEBUG_R("auth_dce.request_cleanup: releasing cached context");
802 auth_dce_release_cached_context(r, request_config);
803 }
804 }
805 else
806 {
807 DEBUG_R("auth_dce.request_cleanup: no cache state in request, purging context");
808 sec_login_context_from_pag(request_config->pag, &login_context, &dce_st);
809 if (dce_st)
810 {
811 dce_error_inq_text(dce_st, dce_error, &dce_error_st);
812 ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r,
813 "auth_dce.request_cleanup: sec_login_context_from_pag failed - %s (%d)", dce_error, dce_st);
814 }
815 else
816 sec_login_purge_context(&login_context, &dce_st);
817 }
818
819 if (server_pag)
820 {
821 sprintf(krb5_env_pag, "%08x", server_pag);
822 installpag(server_pag);
823 }
824 else
825 {
826 krb5_env[0] = 'X';
827 resetpag();
828 }
829 #else
830 if (request_config->login_context)
831 {
832 DEBUG_R("auth_dce.request_cleanup: purging context");
833 sec_login_purge_context(&request_config->login_context, &dce_st);
834 }
835
836 if (server_context)
837 {
838 sec_login_set_context(server_context, &dce_st);
839 if (dce_st)
840 {
841 dce_error_inq_text(dce_st, dce_error, &dce_error_st);
842 ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r,
843 "auth_dce.request_cleanup: sec_login_set_context failed - %s (%d)", dce_error, dce_st);
844 }
845 }
846 #endif
847 }
848 r = r->next;
849 }
850
851 return OK;
852 }
853
854 static void initialize(server_rec *s, pool *p)
855 {
856
857 #ifndef NO_CACHING
858 DEBUG_S("auth_dce.initialize: cache_buckets = %d", auth_dce_server_config.cache_buckets);
859 DEBUG_S("auth_dce.initialize: cache_graceperiod = %d", auth_dce_server_config.cache_graceperiod);
860 DEBUG_S("auth_dce.initialize: cache_lifetime = %d", auth_dce_server_config.cache_lifetime);
861 DEBUG_S("auth_dce.initialize: cache_max_idle = %d", auth_dce_server_config.cache_max_idle);
862 DEBUG_S("auth_dce.initialize: cache_sweep_interval = %d", auth_dce_server_config.cache_sweep_interval);
863 DEBUG_S("auth_dce.initialize: calling cache initialization");
864
865 auth_dce_initialize_cache(s, p);
866 #endif
867 }
868
869
870 static void process_initialize(server_rec *s, pool *p)
871 {
872 error_status_t dce_st;
873 dce_error_string_t dce_error;
874 int dce_error_st;
875 sec_login_auth_src_t auth_src;
876 boolean32 reset_passwd;
877 unsigned32 kvno_worked;
878 pthread_t refresh_thread;
879
880 DEBUG_S("auth_dce.process_initialize: user = %s", (auth_dce_server_config.user ? auth_dce_server_config.user : "NULL"));
881 DEBUG_S("auth_dce.process_initialize: keytab = %s", (auth_dce_server_config.keytab ? auth_dce_server_config.keytab : "NULL"));
882 DEBUG_S("auth_dce.process_initialize: certify_identity = %d", auth_dce_server_config.certify_identity);
883
884 #ifndef NO_CACHING
885 putenv(krb5_env);
886 krb5_env[0] = 'X';
887 #endif
888
889 if (auth_dce_server_config.user)
890 {
891 DEBUG_S("auth_dce.initialize: calling sec_login_setup_identity");
892
893 if (!sec_login_setup_identity((unsigned_char_p_t)auth_dce_server_config.user,
894 sec_login_no_flags, &server_context, &dce_st))
895 {
896 dce_error_inq_text(dce_st, dce_error, &dce_error_st);
897 ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_EMERG, s,
898 "auth_dce.initialize: sec_login_setup_identity failed for %s - %s (%d)", auth_dce_server_config.user, dce_error, dce_st);
899 exit(1);
900 }
901
902 DEBUG_S("auth_dce.initialize: calling sec_login_valid_from_keytable");
903
904 sec_login_valid_from_keytable(server_context, rpc_c_authn_dce_secret, auth_dce_server_config.keytab, (unsigned32) NULL, &kvno_worked,
905 &reset_passwd, &auth_src, &dce_st);
906 if (dce_st)
907 {
908 dce_error_inq_text(dce_st, dce_error, &dce_error_st);
909 ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_EMERG, s,
910 "auth_dce.initialize: sec_login_valid_from_keytable failed for %s - %s (%d)", auth_dce_server_config.user, dce_error, dce_st);
911 sec_login_purge_context(&server_context, &dce_st);
912 exit(1);
913 }
914
915 if (auth_dce_server_config.certify_identity)
916 {
917 DEBUG_S("auth_dce.initialize: calling sec_login_certify_identity");
918
919 if (!sec_login_certify_identity(server_context, &dce_st))
920 {
921 dce_error_inq_text(dce_st, dce_error, &dce_error_st);
922 ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_EMERG, s,
923 "auth_dce.initialize: sec_login_certify_identity failed for %s - %s (%d)", auth_dce_server_config.user, dce_error, dce_st);
924 sec_login_purge_context(&server_context, &dce_st);
925 exit(1);
926 }
927 }
928
929 if (auth_src != sec_login_auth_src_network)
930 {
931 ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_EMERG, s,
932 "auth_dce.initialize: no network credentials for %s", auth_dce_server_config.user);
933 sec_login_purge_context(&server_context, &dce_st);
934 exit(1);
935 }
936
937
938 DEBUG_S("auth_dce.process_initialize: calling sec_login_set_context");
939
940 sec_login_set_context(server_context, &dce_st);
941 if (dce_st)
942 {
943 dce_error_inq_text(dce_st, dce_error, &dce_error_st);
944 ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_EMERG, s,
945 "auth_dce.process_initialize: sec_login_set_context failed - %s (%d)", dce_error, dce_st);
946
947 exit(1);
948 }
949
950 DEBUG_S("auth_dce.initialize: spawning server credential refresh thread");
951
952 if (pthread_create(&refresh_thread, pthread_attr_default, refresh_context, (pthread_addr_t) s))
953 {
954 ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_EMERG, s,
955 "auth_dce.initialize: pthread_create failed");
956 exit(1);
957 }
958
959 pthread_detach(&refresh_thread);
960
961 #ifndef NO_CACHING
962 server_pag = sec_login_inq_pag(server_context, &dce_st);
963 if (dce_st)
964 {
965 dce_error_inq_text(dce_st, dce_error, &dce_error_st);
966 ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_EMERG, s,
967 "auth_dce.process_initialize: sec_login_inq_pag failed - %s (%d)", dce_error, dce_st);
968
969 exit(1);
970 }
971
972 krb5_env[0] = 'K';
973 sprintf(krb5_env_pag, "%08x", server_pag);
974 installpag(server_pag);
975 #endif
976 }
977
978 #ifdef CACHE_TEST_LEVEL
979 srand48(getpid() ^ time(NULL));
980 #endif
981 }
982
983
984 module auth_dce_module = {
985 STANDARD_MODULE_STUFF,
986 initialize, /* initializer */
987 create_dir_config, /* dir config creater */
988 merge_dir_configs, /* dir merger --- default is to override */
989 create_server_config, /* server config */
990 merge_server_configs, /* merge server config */
991 cmds, /* command table */
992 NULL, /* handlers */
993 NULL, /* filename translation */
994 authenticate, /* check_user_id */
995 authorize, /* check auth */
996 NULL, /* check access */
997 NULL, /* type_checker */
998 NULL, /* fixups */
999 request_cleanup, /* logger */
1000 NULL, /* [3] header parser */
1001 process_initialize, /* process initializer */
1002 NULL, /* process exit/cleanup */
1003 NULL /* [1] post read_request handling */
1004 };