87822447 |
1 | #define _LARGEFILE64_SOURCE |
ff47641b |
2 | #define _GNU_SOURCE |
87822447 |
3 | |
bed98ff9 |
4 | #include "httpd.h" |
5 | #include "http_config.h" |
bed98ff9 |
6 | #include "http_log.h" |
7193eb01 |
7 | #include "http_protocol.h" |
8 | #include "http_request.h" |
9 | #include "http_core.h" |
87822447 |
10 | |
ff47641b |
11 | #ifdef sun |
12 | #include <synch.h> |
13 | #elif linux |
14 | #define use_pthreads |
15 | #include <features.h> |
16 | #include <sys/types.h> |
17 | #include <sys/mman.h> |
18 | #include <pthread.h> |
19 | #else |
20 | #error "make sure you include the right stuff here" |
21 | #endif |
22 | |
23 | #ifndef MAXNAMELEN |
24 | #define MAXNAMELEN 1024 |
25 | #endif |
26 | |
ebb1f61c |
27 | /********************* APACHE1 ******************************************************************************/ |
28 | #ifndef STANDARD20_MODULE_STUFF |
29 | #include "ap_config.h" |
30 | #if defined(sun) |
31 | #include <sys/ioccom.h> |
32 | #endif /* sun */ |
33 | #include <http_conf_globals.h> |
34 | #define MK_POOL pool |
35 | #define MK_TABLE_GET ap_table_get |
36 | #define MK_TABLE_SET ap_table_set |
37 | #define command(name, func, var, type, usage) \ |
38 | { name, func, \ |
39 | NULL , \ |
40 | RSRC_CONF | ACCESS_CONF , type, usage } |
41 | #define command(name, func, var, type, usage) \ |
42 | { name, func, \ |
43 | (void*)XtOffsetOf(waklog_commands, var), \ |
44 | OR_AUTHCFG | RSRC_CONF, type, usage } |
45 | |
46 | /********************* APACHE2 ******************************************************************************/ |
47 | #else |
87822447 |
48 | #include <apr_strings.h> |
49 | #include <apr_base64.h> |
ebb1f61c |
50 | //#include <ap_compat.h> |
51 | #define ap_pcalloc apr_pcalloc |
52 | #define ap_pdupstr apr_pdupstr |
53 | #define ap_pstrdup apr_pstrdup |
87822447 |
54 | |
55 | module AP_MODULE_DECLARE_DATA waklog_module; |
56 | |
57 | #define MK_POOL apr_pool_t |
58 | #define MK_TABLE_GET apr_table_get |
d06251b1 |
59 | #define MK_TABLE_SET apr_table_set |
87822447 |
60 | #include "unixd.h" |
61 | extern unixd_config_rec unixd_config; |
62 | #define ap_user_id unixd_config.user_id |
63 | #define ap_group_id unixd_config.group_id |
64 | #define ap_user_name unixd_config.user_name |
65 | #define command(name, func, var, type, usage) \ |
66 | AP_INIT_ ## type (name, (void*) func, \ |
ebb1f61c |
67 | NULL, \ |
68 | RSRC_CONF | ACCESS_CONF, usage) |
69 | typedef struct |
70 | { |
87822447 |
71 | int dummy; |
877d453f |
72 | } |
73 | child_info; |
87822447 |
74 | |
75 | const char *userdata_key = "waklog_init"; |
ebb1f61c |
76 | #endif /* STANDARD20_MODULE_STUFF */ |
77 | /**************************************************************************************************/ |
877d453f |
78 | |
79 | #include <krb5.h> |
877d453f |
80 | #include <stropts.h> |
81 | #include <afs/venus.h> |
82 | #include <afs/auth.h> |
83 | #include <afs/dirpath.h> |
84 | #include <afs/ptuser.h> |
85 | #include <rx/rxkad.h> |
86 | |
87 | #define TKT_LIFE ( 12 * 60 * 60 ) |
88 | #define SLEEP_TIME ( TKT_LIFE - 5*60 ) |
89 | |
90 | #define WAKLOG_ON 1 |
91 | #define WAKLOG_OFF 2 |
92 | #define WAKLOG_UNSET 0 |
93 | |
94 | #ifdef WAKLOG_DEBUG |
95 | #undef APLOG_DEBUG |
96 | #define APLOG_DEBUG APLOG_ERR |
97 | #endif |
98 | |
99 | #ifndef CELL_IN_PRINCIPAL |
100 | int cell_in_principal = 1; |
101 | #else |
102 | int cell_in_principal = 0; |
103 | #endif |
104 | |
105 | /* this is used to turn off pag generation for the backround worker child during startup */ |
106 | int pag_for_children = 1; |
107 | |
108 | typedef struct |
109 | { |
110 | int forked; |
111 | int configured; |
112 | int protect; |
113 | int usertokens; |
114 | char *keytab; |
115 | char *principal; |
116 | char *default_principal; |
117 | char *default_keytab; |
118 | char *afs_cell; |
119 | char *path; |
120 | MK_POOL *p; |
121 | } |
122 | waklog_config; |
123 | |
124 | typedef struct |
125 | { |
126 | struct ktc_token token; |
127 | char clientprincipal[MAXNAMELEN]; |
128 | krb5_context kcontext; |
129 | krb5_ccache ccache; |
130 | struct ktc_principal server; |
131 | struct ktc_principal client; |
132 | int pr_init; |
133 | } waklog_child_config; |
134 | |
135 | waklog_child_config child; |
136 | |
137 | struct tokencache_ent { |
138 | char clientprincipal[MAXNAMELEN]; |
139 | struct ktc_token token; |
140 | struct ktc_principal client; |
141 | struct ktc_principal server; |
142 | time_t lastused; |
143 | int persist; |
144 | }; |
145 | |
146 | #define SHARED_TABLE_SIZE 512 |
147 | |
148 | struct sharedspace_s { |
149 | int renewcount; |
150 | struct tokencache_ent sharedtokens[SHARED_TABLE_SIZE]; |
151 | }; |
152 | |
153 | struct sharedspace_s *sharedspace = NULL; |
154 | |
155 | struct renew_ent { |
156 | char *keytab; |
157 | char *principal; |
158 | int lastrenewed; |
159 | }; |
160 | |
161 | #ifdef use_pthreads |
162 | pthread_rwlock_t *sharedlock = NULL; |
163 | #else |
164 | rwlock_t *sharedlock = NULL; |
165 | #endif |
166 | |
167 | struct renew_ent renewtable[SHARED_TABLE_SIZE]; |
168 | |
169 | int renewcount = 0; |
170 | |
87822447 |
171 | module waklog_module; |
ebb1f61c |
172 | |
87822447 |
173 | |
c69d952f |
174 | #define getModConfig(P, X) P = (waklog_config *) ap_get_module_config( (X)->module_config, &waklog_module ); |
87822447 |
175 | |
4e1ae1cd |
176 | #include <krb5.h> |
bed98ff9 |
177 | |
7193eb01 |
178 | #if defined(sun) |
bed98ff9 |
179 | #include <sys/ioccom.h> |
7193eb01 |
180 | #endif /* sun */ |
bed98ff9 |
181 | #include <stropts.h> |
bed98ff9 |
182 | #include <afs/venus.h> |
7193eb01 |
183 | #include <afs/auth.h> |
d06251b1 |
184 | #include <afs/dirpath.h> |
185 | #include <afs/ptuser.h> |
7193eb01 |
186 | #include <rx/rxkad.h> |
187 | |
87822447 |
188 | #define KEYTAB "/etc/keytab.wwwserver" |
ad1d1967 |
189 | #define PRINCIPAL "someplacewwwserver" |
87822447 |
190 | #define AFS_CELL "someplace.edu" |
4e1ae1cd |
191 | |
87822447 |
192 | /* If there's an error, retry more aggressively */ |
193 | #define ERR_SLEEP_TIME 5*60 |
58bbdc54 |
194 | |
58bbdc54 |
195 | |
196 | #define K5PATH "FILE:/tmp/waklog.creds.k5" |
7193eb01 |
197 | |
87822447 |
198 | static void |
199 | log_error(const char *file, int line, int level, int status, |
200 | const server_rec *s, const char *fmt, ...) |
4d47a8d9 |
201 | { |
87822447 |
202 | char errstr[1024]; |
203 | va_list ap; |
4d47a8d9 |
204 | |
87822447 |
205 | va_start(ap, fmt); |
206 | vsnprintf(errstr, sizeof(errstr), fmt, ap); |
207 | va_end(ap); |
4d47a8d9 |
208 | |
87822447 |
209 | #ifdef STANDARD20_MODULE_STUFF |
210 | ap_log_error(file, line, level | APLOG_NOERRNO, status, s, "%s", errstr); |
211 | #else |
212 | ap_log_error(file, line, level | APLOG_NOERRNO, s, "%s", errstr); |
213 | #endif |
4d47a8d9 |
214 | |
87822447 |
215 | } |
4d47a8d9 |
216 | |
313dde40 |
217 | static void * |
87822447 |
218 | waklog_create_server_config( MK_POOL *p, server_rec *s ) |
313dde40 |
219 | { |
c69d952f |
220 | waklog_config *cfg; |
313dde40 |
221 | |
c69d952f |
222 | cfg = (waklog_config *)ap_pcalloc( p, sizeof( waklog_config )); |
87822447 |
223 | cfg->p = p; |
224 | cfg->forked = 0; |
313dde40 |
225 | cfg->configured = 0; |
226 | cfg->protect = 0; |
58bbdc54 |
227 | cfg->keytab = KEYTAB; |
ad1d1967 |
228 | cfg->principal = PRINCIPAL; |
58bbdc54 |
229 | cfg->afs_cell = AFS_CELL; |
313dde40 |
230 | |
87822447 |
231 | log_error( APLOG_MARK, APLOG_DEBUG, 0, s, "mod_waklog: server config created." ); |
232 | |
313dde40 |
233 | return( cfg ); |
234 | } |
235 | |
236 | |
313dde40 |
237 | static const char * |
238 | set_waklog_protect( cmd_parms *params, void *mconfig, int flag ) |
239 | { |
c69d952f |
240 | waklog_config *cfg; |
313dde40 |
241 | |
87822447 |
242 | getModConfig(cfg, params->server ); |
313dde40 |
243 | |
244 | cfg->protect = flag; |
245 | cfg->configured = 1; |
87822447 |
246 | log_error( APLOG_MARK, APLOG_DEBUG, 0, params->server, "mod_waklog: waklog_protect set" ); |
313dde40 |
247 | return( NULL ); |
248 | } |
249 | |
250 | |
4e1ae1cd |
251 | static const char * |
161ffd84 |
252 | set_waklog_keytab( cmd_parms *params, void *mconfig, char *file ) |
4e1ae1cd |
253 | { |
c69d952f |
254 | waklog_config *cfg; |
4e1ae1cd |
255 | |
87822447 |
256 | getModConfig(cfg, params->server ); |
4e1ae1cd |
257 | |
87822447 |
258 | log_error( APLOG_MARK, APLOG_INFO, 0, params->server, |
259 | "mod_waklog: will use keytab: %s", file ); |
3ed1e28a |
260 | |
b52ccbb1 |
261 | cfg->keytab = ap_pstrdup ( params->pool, file ); |
4e1ae1cd |
262 | cfg->configured = 1; |
263 | return( NULL ); |
264 | } |
265 | |
266 | |
58bbdc54 |
267 | static const char * |
ad1d1967 |
268 | set_waklog_use_principal( cmd_parms *params, void *mconfig, char *file ) |
b74fad73 |
269 | { |
c69d952f |
270 | waklog_config *cfg; |
7193eb01 |
271 | |
87822447 |
272 | getModConfig(cfg, params->server ); |
7193eb01 |
273 | |
87822447 |
274 | log_error( APLOG_MARK, APLOG_INFO, 0, params->server, |
ad1d1967 |
275 | "mod_waklog: will use principal: %s", file ); |
58bbdc54 |
276 | |
ad1d1967 |
277 | cfg->principal = ap_pstrdup ( params->pool, file ); |
58bbdc54 |
278 | cfg->configured = 1; |
279 | return( NULL ); |
280 | } |
281 | |
282 | |
283 | static const char * |
284 | set_waklog_use_afs_cell( cmd_parms *params, void *mconfig, char *file ) |
285 | { |
c69d952f |
286 | waklog_config *cfg; |
58bbdc54 |
287 | |
87822447 |
288 | getModConfig(cfg, params->server ); |
58bbdc54 |
289 | |
87822447 |
290 | log_error( APLOG_MARK, APLOG_INFO, 0, params->server, |
291 | "mod_waklog: will use afs_cell: %s", file ); |
58bbdc54 |
292 | |
b52ccbb1 |
293 | cfg->afs_cell = ap_pstrdup( params->pool, file ); |
58bbdc54 |
294 | cfg->configured = 1; |
295 | return( NULL ); |
296 | } |
297 | |
298 | |
299 | static void |
87822447 |
300 | #ifdef STANDARD20_MODULE_STUFF |
301 | waklog_child_init(MK_POOL *p, server_rec *s) |
302 | #else |
303 | waklog_child_init(server_rec *s, MK_POOL *p) |
304 | #endif |
58bbdc54 |
305 | { |
306 | |
87822447 |
307 | log_error( APLOG_MARK, APLOG_DEBUG, 0, s, |
308 | "mod_waklog: child_init called" ); |
309 | |
58bbdc54 |
310 | memset( &child.token, 0, sizeof( struct ktc_token ) ); |
7193eb01 |
311 | |
b74fad73 |
312 | setpag(); |
7193eb01 |
313 | |
87822447 |
314 | log_error( APLOG_MARK, APLOG_DEBUG, 0, s, |
315 | "mod_waklog: child_init returned" ); |
316 | |
b74fad73 |
317 | return; |
318 | } |
319 | |
87822447 |
320 | typedef struct { |
321 | int wak_protect; |
322 | char *wak_keytab; |
323 | char *wak_ktprinc; |
324 | char *wak_afscell; |
c69d952f |
325 | } waklog_commands; |
b74fad73 |
326 | |
313dde40 |
327 | command_rec waklog_cmds[ ] = |
328 | { |
87822447 |
329 | command("WaklogProtected", set_waklog_protect, wak_protect, FLAG, "enable waklog on a location or directory basis"), |
313dde40 |
330 | |
87822447 |
331 | command("WaklogKeytab", set_waklog_keytab, wak_keytab, TAKE1, "Use the supplied keytab rather than the default"), |
58bbdc54 |
332 | |
ad1d1967 |
333 | command("WaklogUseKeytabPrincipal", set_waklog_use_principal, wak_ktprinc, TAKE1, "Use the supplied keytab principal rather than the default"), |
58bbdc54 |
334 | |
87822447 |
335 | command("WaklogUseAFSCell", set_waklog_use_afs_cell, wak_afscell, TAKE1, "Use the supplied AFS cell rather than the default"), |
4e1ae1cd |
336 | |
313dde40 |
337 | { NULL } |
338 | }; |
339 | |
340 | |
87822447 |
341 | static int |
e2df6441 |
342 | token_cleanup( void *data ) |
bed98ff9 |
343 | { |
344 | request_rec *r = (request_rec *)data; |
bed98ff9 |
345 | |
58bbdc54 |
346 | if ( child.token.ticketLen ) { |
347 | memset( &child.token, 0, sizeof( struct ktc_token ) ); |
bed98ff9 |
348 | |
7193eb01 |
349 | ktc_ForgetAllTokens(); |
bed98ff9 |
350 | |
87822447 |
351 | log_error( APLOG_MARK, APLOG_DEBUG, 0, r->server, |
352 | "mod_waklog: ktc_ForgetAllTokens succeeded: pid: %d", getpid() ); |
7193eb01 |
353 | } |
87822447 |
354 | return 0; |
bed98ff9 |
355 | } |
356 | |
357 | |
4e1ae1cd |
358 | static int |
e2df6441 |
359 | waklog_kinit( server_rec *s ) |
4e1ae1cd |
360 | { |
87822447 |
361 | krb5_error_code kerror = 0; |
e2df6441 |
362 | krb5_context kcontext = NULL; |
363 | krb5_principal kprinc = NULL; |
4e1ae1cd |
364 | krb5_get_init_creds_opt kopts; |
7193eb01 |
365 | krb5_creds v5creds; |
e2df6441 |
366 | krb5_ccache kccache = NULL; |
367 | krb5_keytab keytab = NULL; |
4e1ae1cd |
368 | char ktbuf[ MAX_KEYTAB_NAME_LEN + 1 ]; |
b52ccbb1 |
369 | int i; |
c69d952f |
370 | waklog_config *cfg; |
4e1ae1cd |
371 | |
87822447 |
372 | log_error( APLOG_MARK, APLOG_DEBUG, 0, s, |
373 | "mod_waklog: waklog_kinit called: pid: %d", getpid() ); |
4e1ae1cd |
374 | |
87822447 |
375 | getModConfig(cfg, s); |
58bbdc54 |
376 | |
e21f34f0 |
377 | if (( kerror = krb5_init_context( &kcontext ))) { |
87822447 |
378 | log_error( APLOG_MARK, APLOG_ERR, 0, s, |
379 | "mod_waklog: %s", (char *)error_message( kerror )); |
4e1ae1cd |
380 | |
e2df6441 |
381 | goto cleanup; |
e21f34f0 |
382 | } |
4e1ae1cd |
383 | |
e21f34f0 |
384 | /* use the path */ |
385 | if (( kerror = krb5_cc_resolve( kcontext, K5PATH, &kccache )) != 0 ) { |
87822447 |
386 | log_error( APLOG_MARK, APLOG_ERR, 0, s, |
387 | "mod_waklog: %s", (char *)error_message( kerror )); |
4e1ae1cd |
388 | |
e2df6441 |
389 | goto cleanup; |
e21f34f0 |
390 | } |
4e1ae1cd |
391 | |
87822447 |
392 | log_error( APLOG_MARK, APLOG_DEBUG, 0, s, |
ad1d1967 |
393 | "mod_waklog: principal: %s", cfg->principal ); |
b52ccbb1 |
394 | |
ad1d1967 |
395 | if (( kerror = krb5_parse_name( kcontext, cfg->principal, &kprinc ))) { |
87822447 |
396 | log_error( APLOG_MARK, APLOG_ERR, 0, s, |
397 | "mod_waklog: %s", (char *)error_message( kerror )); |
7193eb01 |
398 | |
e2df6441 |
399 | goto cleanup; |
e21f34f0 |
400 | } |
7193eb01 |
401 | |
e21f34f0 |
402 | krb5_get_init_creds_opt_init( &kopts ); |
58bbdc54 |
403 | krb5_get_init_creds_opt_set_tkt_life( &kopts, TKT_LIFE ); |
e21f34f0 |
404 | krb5_get_init_creds_opt_set_renew_life( &kopts, 0 ); |
405 | krb5_get_init_creds_opt_set_forwardable( &kopts, 1 ); |
406 | krb5_get_init_creds_opt_set_proxiable( &kopts, 0 ); |
7193eb01 |
407 | |
58bbdc54 |
408 | /* keytab from config */ |
409 | strncpy( ktbuf, cfg->keytab, sizeof( ktbuf ) - 1 ); |
7193eb01 |
410 | |
87822447 |
411 | log_error( APLOG_MARK, APLOG_DEBUG, 0, s, |
412 | "mod_waklog: waklog_kinit using: %s", ktbuf ); |
7193eb01 |
413 | |
e21f34f0 |
414 | if (( kerror = krb5_kt_resolve( kcontext, ktbuf, &keytab )) != 0 ) { |
87822447 |
415 | log_error( APLOG_MARK, APLOG_ERR, 0, s, |
416 | "mod_waklog:krb5_kt_resolve %s", (char *)error_message( kerror )); |
7193eb01 |
417 | |
e2df6441 |
418 | goto cleanup; |
e21f34f0 |
419 | } |
7193eb01 |
420 | |
b52ccbb1 |
421 | memset( (char *)&v5creds, 0, sizeof(v5creds)); |
422 | |
e21f34f0 |
423 | /* get the krbtgt */ |
424 | if (( kerror = krb5_get_init_creds_keytab( kcontext, &v5creds, |
403921ef |
425 | kprinc, keytab, 0, NULL, &kopts ))) { |
7193eb01 |
426 | |
87822447 |
427 | log_error( APLOG_MARK, APLOG_ERR, 0, s, |
428 | "mod_waklog:krb5_get_init_creds_keytab %s", (char *)error_message( kerror )); |
7193eb01 |
429 | |
e2df6441 |
430 | goto cleanup; |
e21f34f0 |
431 | } |
7193eb01 |
432 | |
e21f34f0 |
433 | if (( kerror = krb5_cc_initialize( kcontext, kccache, kprinc )) != 0 ) { |
87822447 |
434 | log_error( APLOG_MARK, APLOG_ERR, 0, s, |
435 | "mod_waklog:krb5_cc_initialize %s", (char *)error_message( kerror )); |
7193eb01 |
436 | |
e2df6441 |
437 | goto cleanup; |
e21f34f0 |
438 | } |
7193eb01 |
439 | |
e2df6441 |
440 | kerror = krb5_cc_store_cred( kcontext, kccache, &v5creds ); |
441 | krb5_free_cred_contents( kcontext, &v5creds ); |
442 | if ( kerror != 0 ) { |
87822447 |
443 | log_error( APLOG_MARK, APLOG_ERR, 0, s, |
444 | "mod_waklog: %s", (char *)error_message( kerror )); |
7193eb01 |
445 | |
e2df6441 |
446 | goto cleanup; |
e21f34f0 |
447 | } |
7193eb01 |
448 | |
87822447 |
449 | log_error( APLOG_MARK, APLOG_DEBUG, 0, s, |
450 | "mod_waklog: waklog_kinit success" ); |
e2df6441 |
451 | |
452 | cleanup: |
453 | if ( keytab ) |
454 | (void)krb5_kt_close( kcontext, keytab ); |
455 | if ( kprinc ) |
456 | krb5_free_principal( kcontext, kprinc ); |
457 | if ( kccache ) |
458 | krb5_cc_close( kcontext, kccache ); |
459 | if ( kcontext ) |
460 | krb5_free_context( kcontext ); |
e21f34f0 |
461 | |
87822447 |
462 | log_error( APLOG_MARK, APLOG_DEBUG, 0, s, |
463 | "mod_waklog: waklog_kinit: exiting" ); |
7193eb01 |
464 | |
87822447 |
465 | return( kerror ); |
7193eb01 |
466 | } |
467 | |
468 | |
469 | static void |
470 | waklog_aklog( request_rec *r ) |
471 | { |
472 | int rc; |
bd173fe7 |
473 | char buf[ MAXKTCTICKETLEN ]; |
7193eb01 |
474 | const char *k5path = NULL; |
475 | krb5_error_code kerror; |
e2df6441 |
476 | krb5_context kcontext = NULL; |
7193eb01 |
477 | krb5_creds increds; |
478 | krb5_creds *v5credsp = NULL; |
e2df6441 |
479 | krb5_ccache kccache = NULL; |
403921ef |
480 | struct ktc_principal server = { "afs", "", "" }; |
7193eb01 |
481 | struct ktc_principal client; |
482 | struct ktc_token token; |
c69d952f |
483 | waklog_config *cfg; |
58bbdc54 |
484 | int buflen; |
7193eb01 |
485 | |
87822447 |
486 | k5path = MK_TABLE_GET( r->subprocess_env, "KRB5CCNAME" ); |
7193eb01 |
487 | |
87822447 |
488 | log_error( APLOG_MARK, APLOG_INFO, 0, r->server, |
489 | "mod_waklog: waklog_aklog called: k5path: %s", k5path ); |
7193eb01 |
490 | |
161ffd84 |
491 | if ( k5path == NULL ) { |
87822447 |
492 | log_error( APLOG_MARK, APLOG_DEBUG, 0, r->server, |
493 | "mod_waklog: waklog_aklog giving up" ); |
e2df6441 |
494 | goto cleanup; |
4e1ae1cd |
495 | } |
496 | |
7193eb01 |
497 | /* |
498 | ** Get/build creds from file/tgs, then see if we need to SetToken |
499 | */ |
500 | |
501 | if (( kerror = krb5_init_context( &kcontext ))) { |
502 | /* Authentication Required ( kerberos error ) */ |
87822447 |
503 | log_error( APLOG_MARK, APLOG_ERR, 0, r->server, |
504 | (char *)error_message( kerror )); |
505 | |
e2df6441 |
506 | goto cleanup; |
4e1ae1cd |
507 | } |
508 | |
7193eb01 |
509 | memset( (char *)&increds, 0, sizeof(increds)); |
4e1ae1cd |
510 | |
87822447 |
511 | getModConfig(cfg, r->server ); |
403921ef |
512 | |
513 | /* afs/<cell> or afs */ |
514 | strncpy( buf, "afs", sizeof( buf ) - 1 ); |
58bbdc54 |
515 | if ( strcmp( cfg->afs_cell, AFS_CELL ) ) { |
403921ef |
516 | strncat( buf, "/" , sizeof( buf ) - strlen( buf ) - 1 ); |
517 | strncat( buf, cfg->afs_cell, sizeof( buf ) - strlen( buf ) - 1 ); |
518 | } |
519 | |
7193eb01 |
520 | /* set server part */ |
403921ef |
521 | if (( kerror = krb5_parse_name( kcontext, buf, &increds.server ))) { |
87822447 |
522 | log_error( APLOG_MARK, APLOG_ERR, 0, r->server, |
523 | (char *)error_message( kerror )); |
4e1ae1cd |
524 | |
e2df6441 |
525 | goto cleanup; |
4e1ae1cd |
526 | } |
527 | |
7193eb01 |
528 | if (( kerror = krb5_cc_resolve( kcontext, k5path, &kccache )) != 0 ) { |
87822447 |
529 | log_error( APLOG_MARK, APLOG_ERR, 0, r->server, |
530 | (char *)error_message( kerror )); |
7193eb01 |
531 | |
e2df6441 |
532 | goto cleanup; |
7193eb01 |
533 | } |
4e1ae1cd |
534 | |
7193eb01 |
535 | /* set client part */ |
536 | krb5_cc_get_principal( kcontext, kccache, &increds.client ); |
4e1ae1cd |
537 | |
7193eb01 |
538 | increds.times.endtime = 0; |
539 | /* Ask for DES since that is what V4 understands */ |
540 | increds.keyblock.enctype = ENCTYPE_DES_CBC_CRC; |
541 | |
542 | /* get the V5 credentials */ |
543 | if (( kerror = krb5_get_credentials( kcontext, 0, kccache, |
544 | &increds, &v5credsp ) ) ) { |
87822447 |
545 | log_error( APLOG_MARK, APLOG_ERR, 0, r->server, |
546 | "mod_waklog: krb5_get_credentials: %s", error_message( kerror )); |
e2df6441 |
547 | goto cleanup; |
4e1ae1cd |
548 | } |
549 | |
c4ad0387 |
550 | /* don't overflow */ |
551 | if ( v5credsp->ticket.length >= MAXKTCTICKETLEN ) { /* from krb524d.c */ |
87822447 |
552 | log_error( APLOG_MARK, APLOG_ERR, 0, r->server, |
553 | "mod_waklog: ticket size (%d) too big to fake", v5credsp->ticket.length ); |
e2df6441 |
554 | goto cleanup; |
4e1ae1cd |
555 | } |
556 | |
7193eb01 |
557 | /* assemble the token */ |
58bbdc54 |
558 | memset( &token, 0, sizeof( struct ktc_token ) ); |
559 | |
560 | token.startTime = v5credsp->times.starttime ? v5credsp->times.starttime : v5credsp->times.authtime; |
7193eb01 |
561 | token.endTime = v5credsp->times.endtime; |
58bbdc54 |
562 | memmove( &token.sessionKey, v5credsp->keyblock.contents, v5credsp->keyblock.length ); |
563 | token.kvno = RXKAD_TKT_TYPE_KERBEROS_V5; |
564 | token.ticketLen = v5credsp->ticket.length; |
565 | memmove( token.ticket, v5credsp->ticket.data, token.ticketLen ); |
7193eb01 |
566 | |
58bbdc54 |
567 | /* make sure we have to do this */ |
568 | if ( child.token.kvno != token.kvno || |
569 | child.token.ticketLen != token.ticketLen || |
570 | (memcmp( &child.token.sessionKey, &token.sessionKey, |
571 | sizeof( token.sessionKey ) )) || |
572 | (memcmp( child.token.ticket, token.ticket, token.ticketLen )) ) { |
573 | |
87822447 |
574 | log_error( APLOG_MARK, APLOG_DEBUG, 0, r->server, |
575 | "mod_waklog: client: %s", buf ); |
7193eb01 |
576 | |
577 | /* build the name */ |
bd173fe7 |
578 | memmove( buf, v5credsp->client->data[0].data, |
579 | min( v5credsp->client->data[0].length, MAXKTCNAMELEN - 1 ) ); |
58bbdc54 |
580 | buf[ v5credsp->client->data[0].length ] = '\0'; |
581 | if ( v5credsp->client->length > 1 ) { |
8258901d |
582 | strncat( buf, ".", sizeof( buf ) - strlen( buf ) - 1 ); |
58bbdc54 |
583 | buflen = strlen( buf ); |
bd173fe7 |
584 | memmove( buf + buflen, v5credsp->client->data[1].data, |
585 | min( v5credsp->client->data[1].length, MAXKTCNAMELEN - strlen( buf ) - 1 ) ); |
58bbdc54 |
586 | buf[ buflen + v5credsp->client->data[1].length ] = '\0'; |
7193eb01 |
587 | } |
588 | |
589 | /* assemble the client */ |
403921ef |
590 | strncpy( client.name, buf, sizeof( client.name ) - 1 ); |
591 | strncpy( client.instance, "", sizeof( client.instance) - 1 ); |
bd173fe7 |
592 | memmove( buf, v5credsp->client->realm.data, |
593 | min( v5credsp->client->realm.length, MAXKTCNAMELEN - 1 ) ); |
58bbdc54 |
594 | buf[ v5credsp->client->realm.length ] = '\0'; |
595 | strncpy( client.cell, buf, sizeof( client.cell ) - 1 ); |
403921ef |
596 | |
58bbdc54 |
597 | /* assemble the server's cell */ |
403921ef |
598 | strncpy( server.cell, cfg->afs_cell , sizeof( server.cell ) - 1 ); |
7193eb01 |
599 | |
87822447 |
600 | log_error( APLOG_MARK, APLOG_DEBUG, 0, r->server, |
601 | "mod_waklog: server: name=%s, instance=%s, cell=%s", |
602 | server.name, server.instance, server.cell ); |
603 | |
604 | log_error( APLOG_MARK, APLOG_DEBUG, 0, r->server, |
605 | "mod_waklog: client: name=%s, instance=%s, cell=%s", |
606 | client.name, client.instance, client.cell ); |
7193eb01 |
607 | |
608 | /* use the path */ |
7193eb01 |
609 | |
610 | /* rumor: we have to do this for AIX 4.1.4 with AFS 3.4+ */ |
611 | write( 2, "", 0 ); |
612 | |
613 | if ( ( rc = ktc_SetToken( &server, &token, &client, 0 ) ) ) { |
87822447 |
614 | log_error( APLOG_MARK, APLOG_ERR, 0, r->server, |
615 | "mod_waklog: settoken returned %d", rc ); |
58bbdc54 |
616 | goto cleanup; |
7193eb01 |
617 | } |
618 | |
619 | /* save this */ |
58bbdc54 |
620 | memmove( &child.token, &token, sizeof( struct ktc_token ) ); |
7193eb01 |
621 | |
622 | /* we'll need to unlog when this connection is done. */ |
ebb1f61c |
623 | #ifndef STANDARD20_MODULE_STUFF |
e2df6441 |
624 | ap_register_cleanup( r->pool, (void *)r, token_cleanup, ap_null_cleanup ); |
ebb1f61c |
625 | #else |
626 | /* FIXME!!!! */ |
627 | #endif |
7193eb01 |
628 | } |
629 | |
e2df6441 |
630 | cleanup: |
631 | if ( v5credsp ) |
632 | krb5_free_cred_contents( kcontext, v5credsp ); |
633 | if ( increds.client ) |
634 | krb5_free_principal( kcontext, increds.client ); |
635 | if ( increds.server ) |
636 | krb5_free_principal( kcontext, increds.server ); |
637 | if ( kccache ) |
638 | krb5_cc_close( kcontext, kccache ); |
639 | if ( kcontext ) |
640 | krb5_free_context( kcontext ); |
3ed1e28a |
641 | |
87822447 |
642 | log_error( APLOG_MARK, APLOG_DEBUG, 0, r->server, |
643 | "mod_waklog: finished with waklog_aklog" ); |
7193eb01 |
644 | |
e2df6441 |
645 | return; |
646 | |
4e1ae1cd |
647 | } |
648 | |
e21f34f0 |
649 | static int |
650 | waklog_child_routine( void *s, child_info *pinfo ) |
651 | { |
e21f34f0 |
652 | if ( !getuid() ) { |
87822447 |
653 | log_error( APLOG_MARK, APLOG_DEBUG, 0, s, |
654 | "mod_waklog: waklog_child_routine called as root" ); |
e21f34f0 |
655 | |
656 | /* this was causing the credential file to get owned by root */ |
ea3e8708 |
657 | #ifdef STANDARD20_MODULE_STUFF |
e21f34f0 |
658 | setgid(ap_group_id); |
659 | setuid(ap_user_id); |
ea3e8708 |
660 | #endif |
e21f34f0 |
661 | } |
662 | |
663 | while( 1 ) { |
e2df6441 |
664 | waklog_kinit( s ); |
87822447 |
665 | log_error( APLOG_MARK, APLOG_DEBUG, 0, s, |
666 | "mod_waklog: child_routine sleeping" ); |
58bbdc54 |
667 | sleep( SLEEP_TIME ); |
87822447 |
668 | log_error( APLOG_MARK, APLOG_DEBUG, 0, s, |
669 | "mod_waklog: slept, calling waklog_kinit" ); |
e21f34f0 |
670 | } |
671 | |
672 | } |
673 | |
87822447 |
674 | #ifdef STANDARD20_MODULE_STUFF |
675 | static int |
676 | waklog_init_handler(apr_pool_t *p, apr_pool_t *plog, |
677 | apr_pool_t *ptemp, server_rec *s) |
678 | { |
679 | int rv; |
680 | extern char *version; |
681 | apr_proc_t *proc; |
c69d952f |
682 | waklog_config *cfg; |
87822447 |
683 | void *data; |
684 | |
685 | getModConfig(cfg, s); |
686 | |
687 | /* initialize_module() will be called twice, and if it's a DSO |
688 | * then all static data from the first call will be lost. Only |
689 | * set up our static data on the second call. |
690 | * see http://issues.apache.org/bugzilla/show_bug.cgi?id=37519 */ |
691 | apr_pool_userdata_get(&data, userdata_key, s->process->pool); |
692 | |
693 | if (!data) { |
694 | apr_pool_userdata_set((const void *)1, userdata_key, |
695 | apr_pool_cleanup_null, s->process->pool); |
696 | } else { |
697 | log_error( APLOG_MARK, APLOG_INFO, 0, s, |
698 | "mod_waklog: version %s initialized.", version ); |
699 | |
700 | proc = (apr_proc_t *)ap_pcalloc( s->process->pool, sizeof(apr_proc_t)); |
701 | |
702 | rv = apr_proc_fork(proc, s->process->pool); |
703 | |
704 | if (rv == APR_INCHILD) { |
705 | waklog_child_routine(s, NULL); |
706 | } else { |
707 | apr_pool_note_subprocess(s->process->pool, proc, APR_KILL_ALWAYS); |
708 | } |
709 | /* parent and child */ |
710 | cfg->forked = proc->pid; |
711 | } |
712 | return 0; |
713 | } |
714 | #else |
e21f34f0 |
715 | static void |
87822447 |
716 | waklog_init( server_rec *s, MK_POOL *p ) |
e21f34f0 |
717 | { |
718 | extern char *version; |
719 | int pid; |
720 | |
87822447 |
721 | log_error( APLOG_MARK, APLOG_INFO, 0, s, |
722 | "mod_waklog: version %s initialized.", version ); |
e21f34f0 |
723 | |
724 | pid = ap_bspawn_child( p, waklog_child_routine, s, kill_always, |
725 | NULL, NULL, NULL ); |
726 | |
87822447 |
727 | log_error( APLOG_MARK, APLOG_DEBUG, 0, s, |
728 | "mod_waklog: ap_bspawn_child: %d.", pid ); |
e21f34f0 |
729 | } |
87822447 |
730 | #endif |
4e1ae1cd |
731 | |
bed98ff9 |
732 | static int |
7193eb01 |
733 | waklog_phase0( request_rec *r ) |
bed98ff9 |
734 | { |
c69d952f |
735 | waklog_config *cfg; |
313dde40 |
736 | |
87822447 |
737 | log_error( APLOG_MARK, APLOG_DEBUG, 0, r->server, |
738 | "mod_waklog: phase0 called" ); |
7193eb01 |
739 | |
87822447 |
740 | getModConfig(cfg, r->server ); |
313dde40 |
741 | |
87822447 |
742 | log_error( APLOG_MARK, APLOG_DEBUG, 0, r->server, |
743 | "mod_waklog: phase0, checking cfg->protect" ); |
7193eb01 |
744 | if ( !cfg->protect ) { |
87822447 |
745 | log_error( APLOG_MARK, APLOG_DEBUG, 0, r->server, |
746 | "mod_waklog: phase0 declining" ); |
7193eb01 |
747 | return( DECLINED ); |
748 | } |
4e1ae1cd |
749 | |
87822447 |
750 | log_error( APLOG_MARK, APLOG_DEBUG, 0, r->server, |
751 | "mod_waklog: phase0, NOT setting environment variable" ); |
752 | /* set our environment variable */ |
753 | apr_table_set( r->subprocess_env, "KRB5CCNAME", K5PATH ); |
b52ccbb1 |
754 | |
87822447 |
755 | log_error( APLOG_MARK, APLOG_DEBUG, 0, r->server, |
756 | "mod_waklog: phase0, checking child.token.ticketLen" ); |
7193eb01 |
757 | /* do this only if we are still unauthenticated */ |
58bbdc54 |
758 | if ( !child.token.ticketLen ) { |
87822447 |
759 | |
760 | log_error( APLOG_MARK, APLOG_DEBUG, 0, r->server, |
761 | "mod_waklog: phase0, calling waklog_aklog" ); |
7193eb01 |
762 | /* stuff the credentials into the kernel */ |
763 | waklog_aklog( r ); |
4e1ae1cd |
764 | } |
7193eb01 |
765 | |
87822447 |
766 | log_error( APLOG_MARK, APLOG_DEBUG, 0, r->server, |
767 | "mod_waklog: phase0 returning" ); |
7193eb01 |
768 | return DECLINED; |
769 | } |
4e1ae1cd |
770 | |
1e18ef7d |
771 | |
7193eb01 |
772 | static int |
773 | waklog_phase7( request_rec *r ) |
774 | { |
c69d952f |
775 | waklog_config *cfg; |
1e18ef7d |
776 | |
87822447 |
777 | log_error( APLOG_MARK, APLOG_DEBUG, 0, r->server, |
778 | "mod_waklog: phase7 called" ); |
1e18ef7d |
779 | |
87822447 |
780 | getModConfig(cfg, r->server ); |
bed98ff9 |
781 | |
7193eb01 |
782 | if ( !cfg->protect ) { |
783 | return( DECLINED ); |
bed98ff9 |
784 | } |
785 | |
7193eb01 |
786 | /* stuff the credentials into the kernel */ |
87822447 |
787 | |
788 | log_error( APLOG_MARK, APLOG_DEBUG, 0, r->server, |
789 | "mod_waklog: phase7, calling waklog_aklog" ); |
7193eb01 |
790 | waklog_aklog( r ); |
bed98ff9 |
791 | |
87822447 |
792 | log_error( APLOG_MARK, APLOG_DEBUG, 0, r->server, |
793 | "mod_waklog: phase7 returning" ); |
bed98ff9 |
794 | |
7193eb01 |
795 | return DECLINED; |
bed98ff9 |
796 | } |
797 | |
ff47641b |
798 | |
87822447 |
799 | static |
800 | #ifdef STANDARD20_MODULE_STUFF |
ff47641b |
801 | int |
87822447 |
802 | #else |
ff47641b |
803 | void |
87822447 |
804 | #endif |
ff47641b |
805 | waklog_new_connection (conn_rec * c |
87822447 |
806 | #ifdef STANDARD20_MODULE_STUFF |
807 | , void *dummy |
808 | #endif |
ff47641b |
809 | ) |
810 | { |
811 | |
c69d952f |
812 | waklog_commands *cfg; |
ff47641b |
813 | |
814 | log_error (APLOG_MARK, APLOG_DEBUG, 0, c->base_server, |
815 | "mod_waklog: new_connection called: pid: %d", getpid ()); |
816 | /* |
817 | getModConfig(cfg, c->base_server); |
818 | |
819 | if ( cfg->default_principal ) { |
820 | log_error(APLOG_MARK, APLOG_DEBUG, 0, c->base_server, "mod_waklog: new conn setting default user %s", |
821 | cfg->default_principal); |
822 | set_auth( c->base_server, NULL, 0, cfg->default_principal, cfg->default_keytab, 0); |
823 | } |
824 | */ |
825 | |
87822447 |
826 | return |
827 | #ifdef STANDARD20_MODULE_STUFF |
828 | 0 |
829 | #endif |
830 | ; |
7193eb01 |
831 | } |
bed98ff9 |
832 | |
c4ad0387 |
833 | |
1196adfe |
834 | /* |
835 | ** Here's a quick explaination for phase0 and phase2: |
836 | ** Apache does a stat() on the path between phase0 and |
837 | ** phase2, and must by ACLed rl to succeed. So, at |
838 | ** phase0 we acquire credentials for umweb:servers from |
839 | ** a keytab, and at phase2 we must ensure we remove them. |
840 | ** |
841 | ** Failure to "unlog" would be a security risk. |
842 | */ |
ff47641b |
843 | static int |
844 | waklog_phase2 (request_rec * r) |
c4ad0387 |
845 | { |
161ffd84 |
846 | |
ff47641b |
847 | log_error (APLOG_MARK, APLOG_DEBUG, 0, r->server, |
848 | "mod_waklog: phase2 called"); |
1196adfe |
849 | |
ff47641b |
850 | if (child.token.ticketLen) |
851 | { |
852 | memset (&child.token, 0, sizeof (struct ktc_token)); |
c4ad0387 |
853 | |
ff47641b |
854 | ktc_ForgetAllTokens (); |
c4ad0387 |
855 | |
ff47641b |
856 | log_error (APLOG_MARK, APLOG_DEBUG, 0, r->server, |
857 | "mod_waklog: ktc_ForgetAllTokens succeeded: pid: %d", |
858 | getpid ()); |
c4ad0387 |
859 | } |
1196adfe |
860 | |
ff47641b |
861 | log_error (APLOG_MARK, APLOG_DEBUG, 0, r->server, |
862 | "mod_waklog: phase2 returning"); |
1196adfe |
863 | |
c4ad0387 |
864 | return DECLINED; |
865 | } |
866 | |
87822447 |
867 | #ifndef STANDARD20_MODULE_STUFF |
313dde40 |
868 | module MODULE_VAR_EXPORT waklog_module = { |
bed98ff9 |
869 | STANDARD_MODULE_STUFF, |
003832b1 |
870 | waklog_init, /* module initializer */ |
b52ccbb1 |
871 | #if 0 |
4d47a8d9 |
872 | waklog_create_dir_config, /* create per-dir config structures */ |
b52ccbb1 |
873 | #else /* 0 */ |
874 | NULL, /* create per-dir config structures */ |
875 | #endif /* 0 */ |
bed98ff9 |
876 | NULL, /* merge per-dir config structures */ |
313dde40 |
877 | waklog_create_server_config, /* create per-server config structures */ |
bed98ff9 |
878 | NULL, /* merge per-server config structures */ |
313dde40 |
879 | waklog_cmds, /* table of config file commands */ |
bed98ff9 |
880 | NULL, /* [#8] MIME-typed-dispatched handlers */ |
881 | NULL, /* [#1] URI to filename translation */ |
882 | NULL, /* [#4] validate user id from request */ |
883 | NULL, /* [#5] check if the user is ok _here_ */ |
884 | NULL, /* [#3] check access by host address */ |
885 | NULL, /* [#6] determine MIME type */ |
7193eb01 |
886 | waklog_phase7, /* [#7] pre-run fixups */ |
bed98ff9 |
887 | NULL, /* [#9] log a transaction */ |
c4ad0387 |
888 | waklog_phase2, /* [#2] header parser */ |
313dde40 |
889 | waklog_child_init, /* child_init */ |
bed98ff9 |
890 | NULL, /* child_exit */ |
7193eb01 |
891 | waklog_phase0 /* [#0] post read-request */ |
bed98ff9 |
892 | #ifdef EAPI |
893 | ,NULL, /* EAPI: add_module */ |
894 | NULL, /* EAPI: remove_module */ |
895 | NULL, /* EAPI: rewrite_command */ |
7193eb01 |
896 | waklog_new_connection /* EAPI: new_connection */ |
bed98ff9 |
897 | #endif |
898 | }; |
87822447 |
899 | #else |
900 | static void |
ff47641b |
901 | waklog_register_hooks (apr_pool_t * p) |
87822447 |
902 | { |
ff47641b |
903 | ap_hook_header_parser (waklog_phase2, NULL, NULL, APR_HOOK_FIRST); |
904 | ap_hook_fixups (waklog_phase7, NULL, NULL, APR_HOOK_FIRST); |
905 | ap_hook_child_init (waklog_child_init, NULL, NULL, APR_HOOK_FIRST); |
906 | ap_hook_post_read_request (waklog_phase0, NULL, NULL, APR_HOOK_FIRST); |
907 | ap_hook_pre_connection (waklog_new_connection, NULL, NULL, APR_HOOK_FIRST); |
908 | ap_hook_post_config (waklog_init_handler, NULL, NULL, APR_HOOK_MIDDLE); |
87822447 |
909 | } |
910 | |
911 | |
912 | module AP_MODULE_DECLARE_DATA waklog_module = |
913 | { |
914 | STANDARD20_MODULE_STUFF, |
915 | NULL, /* create per-dir conf structures */ |
916 | NULL, /* merge per-dir conf structures */ |
917 | waklog_create_server_config, /* create per-server conf structures */ |
918 | NULL, /* merge per-server conf structures */ |
919 | waklog_cmds, /* table of configuration directives */ |
920 | waklog_register_hooks /* register hooks */ |
921 | }; |
922 | #endif |
161ffd84 |
923 | |