bed98ff9 |
1 | #include "httpd.h" |
2 | #include "http_config.h" |
7193eb01 |
3 | #include "http_conf_globals.h" |
bed98ff9 |
4 | #include "http_log.h" |
7193eb01 |
5 | #include "http_protocol.h" |
6 | #include "http_request.h" |
7 | #include "http_core.h" |
bed98ff9 |
8 | #include "ap_config.h" |
4e1ae1cd |
9 | #include <krb5.h> |
bed98ff9 |
10 | |
7193eb01 |
11 | #if defined(sun) |
bed98ff9 |
12 | #include <sys/ioccom.h> |
7193eb01 |
13 | #endif /* sun */ |
bed98ff9 |
14 | #include <stropts.h> |
15 | #include <kerberosIV/krb.h> |
16 | #include <kerberosIV/des.h> |
17 | #include <afs/venus.h> |
7193eb01 |
18 | #include <afs/auth.h> |
19 | #include <rx/rxkad.h> |
20 | |
21 | #include <asm/bitops.h> |
22 | #include <sys/shm.h> |
bed98ff9 |
23 | |
7193eb01 |
24 | #define KEYTAB_PATH "/home/drh/keytab.umweb.drhtest" |
25 | #define PRINCIPAL "umweb/drhtest" |
26 | #define AFS "afs" |
4e1ae1cd |
27 | #define IN_TKT_SERVICE "krbtgt/UMICH.EDU" |
28 | |
7193eb01 |
29 | #define K5PATH "FILE:/tmp/waklog.creds.k5" |
30 | #define K4PATH "/tmp/waklog.creds.k4" |
31 | |
313dde40 |
32 | module waklog_module; |
bed98ff9 |
33 | |
34 | struct ClearToken { |
35 | long AuthHandle; |
36 | char HandShakeKey[ 8 ]; |
37 | long ViceId; |
38 | long BeginTimestamp; |
39 | long EndTimestamp; |
40 | }; |
41 | |
313dde40 |
42 | typedef struct { |
4e1ae1cd |
43 | int configured; |
44 | int protect; |
45 | char *keytab; |
7193eb01 |
46 | char *keytab_principal; |
47 | char *afs_instance; |
313dde40 |
48 | } waklog_host_config; |
49 | |
7193eb01 |
50 | typedef struct { |
51 | krb5_timestamp endtime; /* time krbtgt expires */ |
52 | int getting_tgt; /* TAS flag, protecting above */ |
53 | } waklog_mod_config; |
54 | waklog_mod_config *mod = NULL; |
55 | |
56 | int shmid = -1; |
57 | |
58 | typedef struct { |
59 | struct ktc_token token; |
60 | } waklog_child_config; |
61 | waklog_child_config *child = NULL; |
313dde40 |
62 | |
63 | static void * |
64 | waklog_create_dir_config( pool *p, char *path ) |
65 | { |
66 | waklog_host_config *cfg; |
67 | |
68 | cfg = (waklog_host_config *)ap_pcalloc( p, sizeof( waklog_host_config )); |
69 | cfg->configured = 0; |
70 | cfg->protect = 0; |
7193eb01 |
71 | cfg->keytab = 0; |
72 | cfg->keytab_principal = 0; |
73 | cfg->afs_instance = 0; |
313dde40 |
74 | |
75 | return( cfg ); |
76 | } |
77 | |
78 | |
79 | static void * |
80 | waklog_create_server_config( pool *p, server_rec *s ) |
81 | { |
82 | waklog_host_config *cfg; |
83 | |
84 | cfg = (waklog_host_config *)ap_pcalloc( p, sizeof( waklog_host_config )); |
85 | cfg->configured = 0; |
86 | cfg->protect = 0; |
7193eb01 |
87 | cfg->keytab = 0; |
88 | cfg->keytab_principal = 0; |
89 | cfg->afs_instance = 0; |
313dde40 |
90 | |
91 | return( cfg ); |
92 | } |
93 | |
94 | |
b429ae96 |
95 | static void |
313dde40 |
96 | waklog_init( server_rec *s, pool *p ) |
b429ae96 |
97 | { |
7193eb01 |
98 | extern char *version; |
99 | static key_t shmkey = IPC_PRIVATE; |
100 | struct shmid_ds shmbuf; |
b429ae96 |
101 | |
102 | ap_log_error( APLOG_MARK, APLOG_INFO|APLOG_NOERRNO, s, |
313dde40 |
103 | "mod_waklog: version %s initialized.", version ); |
7193eb01 |
104 | |
105 | if ( mod == NULL ) { |
106 | if (( shmid = shmget( shmkey, sizeof( waklog_mod_config ), |
107 | IPC_CREAT | SHM_R | SHM_W )) == -1 ) { |
108 | ap_log_error( APLOG_MARK, APLOG_ERR, s, |
109 | "mod_waklog: shmget failed" ); |
110 | exit ( -1 ); |
111 | } |
112 | |
113 | ap_log_error( APLOG_MARK, APLOG_INFO|APLOG_NOERRNO, s, |
114 | "mod_waklog: waklog_init: created shared memory segment %d", shmid ); |
115 | |
116 | if (( mod = (waklog_mod_config *) shmat( shmid, 0, 0 ) ) == |
117 | (waklog_mod_config *) -1 ) { |
118 | ap_log_error( APLOG_MARK, APLOG_ERR, s, |
119 | "mod_waklog: shmat failed" ); |
120 | /* we'll exit after removing the segment */ |
121 | |
122 | } else { |
123 | if ( shmctl( shmid, IPC_STAT, &shmbuf ) != 0 ) { |
124 | ap_log_error( APLOG_MARK, APLOG_ERR, s, |
125 | "mod_waklog: shmctl failed to stat" ); |
126 | |
127 | } else { |
128 | shmbuf.shm_perm.uid = ap_user_id; |
129 | shmbuf.shm_perm.gid = ap_group_id; |
130 | |
131 | if ( shmctl( shmid, IPC_SET, &shmbuf ) != 0 ) { |
132 | ap_log_error( APLOG_MARK, APLOG_ERR, s, |
133 | "mod_waklog: shmctl failed to set" ); |
134 | } |
135 | } |
136 | |
137 | } |
138 | |
139 | if ( shmctl( shmid, IPC_RMID, NULL ) != 0 ) { |
140 | ap_log_error( APLOG_MARK, APLOG_ERR, s, |
141 | "mod_waklog: shmctl failed to remove" ); |
142 | } |
143 | |
144 | if ( mod == (waklog_mod_config *) -1 ) { |
145 | exit ( -1 ); |
146 | } |
147 | } |
148 | |
149 | mod->endtime = 0; |
150 | mod->getting_tgt = 0; |
151 | |
b429ae96 |
152 | return; |
153 | } |
154 | |
bed98ff9 |
155 | |
313dde40 |
156 | static const char * |
157 | set_waklog_protect( cmd_parms *params, void *mconfig, int flag ) |
158 | { |
159 | waklog_host_config *cfg; |
160 | |
161 | if ( params->path == NULL ) { |
162 | cfg = (waklog_host_config *) ap_get_module_config( |
163 | params->server->module_config, &waklog_module ); |
164 | } else { |
165 | cfg = (waklog_host_config *)mconfig; |
166 | } |
167 | |
168 | cfg->protect = flag; |
169 | cfg->configured = 1; |
170 | return( NULL ); |
171 | } |
172 | |
173 | |
4e1ae1cd |
174 | static const char * |
175 | set_waklog_use_keytab( cmd_parms *params, void *mconfig, char *file ) |
176 | { |
177 | waklog_host_config *cfg; |
178 | |
179 | if ( params->path == NULL ) { |
180 | cfg = (waklog_host_config *) ap_get_module_config( |
181 | params->server->module_config, &waklog_module ); |
182 | } else { |
183 | cfg = (waklog_host_config *)mconfig; |
184 | } |
185 | |
3ed1e28a |
186 | ap_log_error( APLOG_MARK, APLOG_INFO|APLOG_NOERRNO, params->server, |
187 | "mod_waklog: using keytab: %s", file ); |
188 | |
4e1ae1cd |
189 | cfg->keytab = file; |
190 | cfg->configured = 1; |
191 | return( NULL ); |
192 | } |
193 | |
194 | |
b74fad73 |
195 | static void |
313dde40 |
196 | waklog_child_init( server_rec *s, pool *p ) |
b74fad73 |
197 | { |
7193eb01 |
198 | |
199 | if ( child == NULL ) { |
200 | child = (waklog_child_config *) ap_palloc( p, sizeof( waklog_child_config ) ); |
201 | } |
202 | |
203 | memset( &child->token, 0, sizeof( struct ktc_token ) ); |
204 | |
b74fad73 |
205 | setpag(); |
7193eb01 |
206 | |
207 | ap_log_error( APLOG_MARK, APLOG_INFO|APLOG_NOERRNO, s, |
208 | "mod_waklog: waklog_child_init: child: 0x%08x", child ); |
209 | |
b74fad73 |
210 | return; |
211 | } |
212 | |
213 | |
313dde40 |
214 | command_rec waklog_cmds[ ] = |
215 | { |
216 | { "WaklogProtected", set_waklog_protect, |
217 | NULL, RSRC_CONF | ACCESS_CONF, FLAG, |
218 | "enable waklog on a location or directory basis" }, |
219 | |
4e1ae1cd |
220 | { "WaklogUseKeytab", set_waklog_use_keytab, |
221 | NULL, RSRC_CONF, TAKE1, |
222 | "Use the supplied keytab file rather than the user's TGT" }, |
223 | |
313dde40 |
224 | { NULL } |
225 | }; |
226 | |
227 | |
bed98ff9 |
228 | static void |
229 | pioctl_cleanup( void *data ) |
230 | { |
231 | request_rec *r = (request_rec *)data; |
bed98ff9 |
232 | |
7193eb01 |
233 | if ( child->token.ticketLen ) { |
234 | memset( &child->token, 0, sizeof( struct ktc_token ) ); |
bed98ff9 |
235 | |
7193eb01 |
236 | ktc_ForgetAllTokens(); |
bed98ff9 |
237 | |
7193eb01 |
238 | ap_log_error( APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r->server, |
239 | "mod_waklog: ktc_ForgetAllTokens succeeded" ); |
240 | } |
b74fad73 |
241 | return; |
bed98ff9 |
242 | } |
243 | |
244 | |
4e1ae1cd |
245 | static int |
7193eb01 |
246 | waklog_ktinit( request_rec *r, char *keytab_path ) |
4e1ae1cd |
247 | { |
248 | krb5_error_code kerror; |
249 | krb5_context kcontext; |
250 | krb5_principal kprinc; |
4e1ae1cd |
251 | krb5_get_init_creds_opt kopts; |
7193eb01 |
252 | krb5_creds v5creds; |
253 | CREDENTIALS v4creds; |
4e1ae1cd |
254 | krb5_ccache kccache; |
255 | krb5_keytab keytab = 0; |
256 | char ktbuf[ MAX_KEYTAB_NAME_LEN + 1 ]; |
7193eb01 |
257 | krb5_timestamp now; |
4e1ae1cd |
258 | |
7193eb01 |
259 | ap_log_error( APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r->server, |
260 | "mod_waklog: waklog_ktinit called" ); |
4e1ae1cd |
261 | |
7193eb01 |
262 | /* set our environment variables */ |
263 | ap_table_set( r->subprocess_env, "KRB5CCNAME", K5PATH ); |
264 | ap_table_set( r->subprocess_env, "KRBTKFILE", K4PATH ); |
4e1ae1cd |
265 | |
7193eb01 |
266 | ap_log_error( APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r->server, |
267 | "mod_waklog: KRB5CCNAME: %s, KRBTKFILE: %s", K5PATH, K4PATH ); |
4e1ae1cd |
268 | |
7193eb01 |
269 | #define SOON 300 |
4e1ae1cd |
270 | |
7193eb01 |
271 | /* will we need another tgt soon? */ |
272 | now = time( NULL ); |
273 | if ( !mod->getting_tgt && mod->endtime < now + SOON ) { |
4e1ae1cd |
274 | |
7193eb01 |
275 | ap_log_error( APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r->server, |
276 | "mod_waklog: mod->endtime: %u, now: %u", mod->endtime, now ); |
277 | |
278 | /* |
279 | ** Only one process will get into the critical region below and |
280 | ** replace the soon-to-be-expired credential; the rest will just |
281 | ** use the still-good credential until the new one shows up. |
282 | ** |
283 | ** The TAS flag will stop other processes from entering the |
284 | ** first half of the conditional above, and the critical region |
285 | ** below will not exit until mod->endtime has been updated to |
286 | ** reflect that of the new credentials (or fail). |
287 | ** |
288 | ** (While it is possible for all child processes to get past the |
289 | ** first half of the conditional above, and then for one |
290 | ** process to get into the critical region below and run to the |
291 | ** end (clearing the TAS flag), a fair scheduler would not |
292 | ** do this; but even so, it really wouldn't kill us if ALL of |
293 | ** the child processes got credentials, anyway. |
294 | */ |
295 | if ( !test_and_set_bit( 0, &mod->getting_tgt ) ) { |
296 | |
297 | if (( kerror = krb5_init_context( &kcontext ))) { |
298 | ap_log_error( APLOG_MARK, APLOG_ERR, r->server, |
299 | (char *)error_message( kerror )); |
300 | |
301 | goto cleanup1; |
302 | } |
303 | |
304 | /* use the path */ |
305 | if (( kerror = krb5_cc_resolve( kcontext, K5PATH, &kccache )) != 0 ) { |
306 | ap_log_error( APLOG_MARK, APLOG_ERR, r->server, |
307 | (char *)error_message( kerror )); |
4e1ae1cd |
308 | |
7193eb01 |
309 | goto cleanup2; |
310 | } |
4e1ae1cd |
311 | |
7193eb01 |
312 | if (( kerror = krb5_parse_name( kcontext, PRINCIPAL, &kprinc ))) { |
313 | ap_log_error( APLOG_MARK, APLOG_ERR, r->server, |
4e1ae1cd |
314 | (char *)error_message( kerror )); |
315 | |
7193eb01 |
316 | goto cleanup3; |
317 | } |
318 | |
319 | krb5_get_init_creds_opt_init( &kopts ); |
320 | krb5_get_init_creds_opt_set_tkt_life( &kopts, 10*60*60 ); |
321 | krb5_get_init_creds_opt_set_renew_life( &kopts, 0 ); |
322 | krb5_get_init_creds_opt_set_forwardable( &kopts, 1 ); |
323 | krb5_get_init_creds_opt_set_proxiable( &kopts, 0 ); |
324 | |
325 | /* which keytab should we use? */ |
326 | strcpy( ktbuf, keytab_path ? keytab_path : KEYTAB_PATH ); |
327 | |
328 | if ( strlen( ktbuf ) > MAX_KEYTAB_NAME_LEN ) { |
329 | ap_log_error( APLOG_MARK, APLOG_ERR, r->server, |
4e1ae1cd |
330 | "server configuration error" ); |
331 | |
7193eb01 |
332 | goto cleanup4; |
333 | } |
334 | |
335 | ap_log_error( APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r->server, |
336 | "mod_waklog: waklog_ktinit using: %s", ktbuf ); |
337 | |
338 | if (( kerror = krb5_kt_resolve( kcontext, ktbuf, &keytab )) != 0 ) { |
339 | ap_log_error( APLOG_MARK, APLOG_ERR, r->server, |
340 | (char *)error_message( kerror )); |
341 | |
342 | goto cleanup4; |
343 | } |
344 | |
345 | /* get the krbtgt */ |
346 | if (( kerror = krb5_get_init_creds_keytab( kcontext, &v5creds, |
347 | kprinc, keytab, 0, IN_TKT_SERVICE, &kopts ))) { |
348 | |
349 | ap_log_error( APLOG_MARK, APLOG_ERR, r->server, |
350 | (char *)error_message( kerror )); |
351 | |
352 | goto cleanup5; |
353 | } |
354 | |
355 | if (( kerror = krb5_verify_init_creds( kcontext, &v5creds, |
356 | kprinc, keytab, NULL, NULL )) != 0 ) { |
357 | |
358 | ap_log_error( APLOG_MARK, APLOG_ERR, r->server, |
359 | (char *)error_message( kerror )); |
360 | |
361 | goto cleanup6; |
362 | } |
363 | |
364 | if (( kerror = krb5_cc_initialize( kcontext, kccache, kprinc )) != 0 ) { |
365 | ap_log_error( APLOG_MARK, APLOG_ERR, r->server, |
366 | (char *)error_message( kerror )); |
367 | |
368 | goto cleanup6; |
369 | } |
370 | |
371 | if (( kerror = krb5_cc_store_cred( kcontext, kccache, &v5creds )) != 0 ) { |
372 | ap_log_error( APLOG_MARK, APLOG_ERR, r->server, |
373 | (char *)error_message( kerror )); |
374 | |
375 | goto cleanup6; |
376 | } |
377 | |
378 | /* convert K5 => K4 */ |
379 | ap_log_error( APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r->server, |
380 | "mod_waklog: before krb524_convert_creds" ); |
381 | |
382 | if (( kerror = krb524_convert_creds_kdc( kcontext, |
383 | &v5creds, &v4creds )) != 0 ) { |
384 | |
385 | ap_log_error( APLOG_MARK, APLOG_ERR, r->server, |
386 | (char *)error_message( kerror )); |
387 | |
388 | goto cleanup6; |
389 | } |
390 | |
391 | /* use the path */ |
392 | krb_set_tkt_string( (char *)K4PATH ); |
393 | |
394 | /* initialize ticket cache */ |
395 | ap_log_error( APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r->server, |
396 | "mod_waklog: before in_tkt" ); |
397 | |
398 | if (( kerror = in_tkt( v4creds.pname, v4creds.pinst )) != KSUCCESS ) { |
399 | ap_log_error( APLOG_MARK, APLOG_ERR, r->server, |
400 | (char *)error_message( kerror )); |
401 | |
402 | goto cleanup6; |
403 | } |
404 | |
405 | /* stash, ticket, session key, etc for future use */ |
406 | ap_log_error( APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r->server, |
407 | "mod_waklog: before krb_save_credentials" ); |
408 | |
409 | if (( kerror = krb_save_credentials( v4creds.service, |
410 | v4creds.instance, |
411 | v4creds.realm, |
412 | v4creds.session, |
413 | v4creds.lifetime, |
414 | v4creds.kvno, |
415 | &(v4creds.ticket_st), |
416 | v4creds.issue_date )) != 0 ) { |
417 | |
418 | ap_log_error( APLOG_MARK, APLOG_ERR, r->server, |
419 | (char *)error_message( kerror )); |
420 | |
421 | goto cleanup6; |
422 | } |
423 | |
424 | /* save this */ |
425 | mod->endtime = v5creds.times.endtime; |
426 | ap_log_error( APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r->server, |
427 | "mod_waklog: mod->endtime: %u, mod->getting_tgt: %d", |
428 | mod->endtime, mod->getting_tgt ); |
429 | |
430 | cleanup6: krb5_free_cred_contents( kcontext, &v5creds ); |
431 | cleanup5: (void)krb5_kt_close( kcontext, keytab ); |
432 | cleanup4: krb5_free_principal( kcontext, kprinc ); |
433 | cleanup3: krb5_cc_close( kcontext, kccache ); |
434 | cleanup2: krb5_free_context( kcontext ); |
435 | |
436 | /* exit the critical region */ |
437 | cleanup1: mod->getting_tgt = 0; |
4e1ae1cd |
438 | } |
7193eb01 |
439 | |
4e1ae1cd |
440 | } |
441 | |
7193eb01 |
442 | ap_log_error( APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r->server, |
443 | "mod_waklog: waklog_ktinit: exiting" ); |
444 | |
445 | return( 0 ); |
446 | } |
447 | |
448 | |
449 | static void |
450 | waklog_aklog( request_rec *r ) |
451 | { |
452 | int rc; |
453 | char buf[ 1024 ]; |
454 | const char *k4path = NULL; |
455 | const char *k5path = NULL; |
456 | krb5_error_code kerror; |
457 | krb5_context kcontext; |
458 | krb5_creds increds; |
459 | krb5_creds *v5credsp = NULL; |
460 | CREDENTIALS v4creds; |
461 | krb5_ccache kccache; |
462 | struct ktc_principal server = { "afs", "", "umich.edu" }; |
463 | struct ktc_principal client; |
464 | struct ktc_token token; |
465 | |
466 | k5path = ap_table_get( r->subprocess_env, "KRB5CCNAME" ); |
467 | k4path = ap_table_get( r->subprocess_env, "KRBTKFILE" ); |
468 | |
469 | ap_log_error( APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r->server, |
470 | "mod_waklog: waklog_aklog called: k5path: %s, k4path: %s", k5path, k4path ); |
471 | |
472 | if ( !k5path || !k4path ) { |
473 | ap_log_error( APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r->server, |
474 | "mod_waklog: waklog_aklog giving up" ); |
4e1ae1cd |
475 | return; |
476 | } |
477 | |
7193eb01 |
478 | /* |
479 | ** Get/build creds from file/tgs, then see if we need to SetToken |
480 | */ |
481 | |
482 | if (( kerror = krb5_init_context( &kcontext ))) { |
483 | /* Authentication Required ( kerberos error ) */ |
4e1ae1cd |
484 | ap_log_error( APLOG_MARK, APLOG_ERR, r->server, |
485 | (char *)error_message( kerror )); |
7193eb01 |
486 | |
4e1ae1cd |
487 | return; |
488 | } |
489 | |
7193eb01 |
490 | memset( (char *)&increds, 0, sizeof(increds)); |
4e1ae1cd |
491 | |
7193eb01 |
492 | /* set server part */ |
493 | if (( kerror = krb5_parse_name( kcontext, AFS, &increds.server ))) { |
4e1ae1cd |
494 | ap_log_error( APLOG_MARK, APLOG_ERR, r->server, |
495 | (char *)error_message( kerror )); |
496 | |
497 | return; |
498 | } |
499 | |
7193eb01 |
500 | if (( kerror = krb5_cc_resolve( kcontext, k5path, &kccache )) != 0 ) { |
501 | ap_log_error( APLOG_MARK, APLOG_ERR, r->server, |
502 | (char *)error_message( kerror )); |
503 | |
504 | return; |
505 | } |
4e1ae1cd |
506 | |
7193eb01 |
507 | /* set client part */ |
508 | krb5_cc_get_principal( kcontext, kccache, &increds.client ); |
4e1ae1cd |
509 | |
7193eb01 |
510 | increds.times.endtime = 0; |
511 | /* Ask for DES since that is what V4 understands */ |
512 | increds.keyblock.enctype = ENCTYPE_DES_CBC_CRC; |
513 | |
514 | /* get the V5 credentials */ |
515 | if (( kerror = krb5_get_credentials( kcontext, 0, kccache, |
516 | &increds, &v5credsp ) ) ) { |
517 | ap_log_error( APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r->server, |
518 | "mod_waklog: krb5_get_credentials: %s", krb_err_txt[ kerror ] ); |
4e1ae1cd |
519 | return; |
520 | } |
521 | |
7193eb01 |
522 | /* get the V4 credentials */ |
523 | if (( kerror = krb524_convert_creds_kdc( kcontext, v5credsp, &v4creds ) ) ) { |
524 | ap_log_error( APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r->server, |
525 | "mod_waklog: krb524_convert_creds_kdc: %s", krb_err_txt[ kerror ] ); |
4e1ae1cd |
526 | return; |
527 | } |
528 | |
7193eb01 |
529 | /* assemble the token */ |
530 | token.kvno = v4creds.kvno; |
531 | token.startTime = v4creds.issue_date; |
532 | token.endTime = v5credsp->times.endtime; |
533 | memmove( &token.sessionKey, v4creds.session, 8 ); |
534 | token.ticketLen = v4creds.ticket_st.length ; |
535 | memmove( token.ticket, v4creds.ticket_st.dat, token.ticketLen ); |
536 | |
537 | /* make sure we have to do this */ |
538 | if ( child->token.kvno != token.kvno || |
539 | child->token.ticketLen != token.ticketLen || |
540 | memcmp( &child->token.sessionKey, &token.sessionKey, |
541 | sizeof( token.sessionKey ) ) || |
542 | memcmp( child->token.ticket, token.ticket, token.ticketLen ) ) { |
543 | |
544 | ap_log_error( APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r->server, |
545 | "mod_waklog: %s.%s@%s", v4creds.service, v4creds.instance, |
546 | v4creds.realm ); |
547 | ap_log_error( APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r->server, |
548 | "mod_waklog: %d %d %d", v4creds.lifetime, v4creds.kvno, |
549 | v4creds.issue_date ); |
550 | ap_log_error( APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r->server, |
551 | "mod_waklog: %s %s", v4creds.pname, v4creds.pinst ); |
552 | ap_log_error( APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r->server, |
553 | "mod_waklog: %d", v4creds.ticket_st.length ); |
554 | |
555 | /* build the name */ |
556 | strcpy( buf, v4creds.pname ); |
557 | if ( v4creds.pinst[ 0 ] ) { |
558 | strcat( buf, "." ); |
559 | strcat( buf, v4creds.pinst ); |
560 | } |
561 | |
562 | /* assemble the client */ |
563 | strncpy( client.name, buf, MAXKTCNAMELEN - 1 ); |
564 | strcpy( client.instance, "" ); |
565 | strncpy( client.cell, v4creds.realm, MAXKTCNAMELEN - 1 ); |
566 | |
567 | ap_log_error( APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r->server, |
568 | "mod_waklog: server: name=%s, instance=%s, cell=%s", |
569 | server.name, server.instance, server.cell ); |
570 | |
571 | ap_log_error( APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r->server, |
572 | "mod_waklog: client: name=%s, instance=%s, cell=%s", |
573 | client.name, client.instance, client.cell ); |
574 | |
575 | /* use the path */ |
576 | krb_set_tkt_string( (char *)k4path ); |
577 | |
578 | /* rumor: we have to do this for AIX 4.1.4 with AFS 3.4+ */ |
579 | write( 2, "", 0 ); |
580 | |
581 | if ( ( rc = ktc_SetToken( &server, &token, &client, 0 ) ) ) { |
582 | ap_log_error( APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r->server, |
583 | "mod_waklog: settoken returned %d", rc ); |
584 | } |
585 | |
586 | /* save this */ |
587 | memmove( &child->token, &token, sizeof( struct ktc_token ) ); |
588 | |
589 | /* we'll need to unlog when this connection is done. */ |
590 | ap_register_cleanup( r->pool, (void *)r, pioctl_cleanup, ap_null_cleanup ); |
591 | } |
592 | |
593 | krb5_free_cred_contents( kcontext, v5credsp ); |
594 | krb5_free_principal( kcontext, increds.client ); |
4e1ae1cd |
595 | krb5_cc_close( kcontext, kccache ); |
596 | krb5_free_context( kcontext ); |
3ed1e28a |
597 | |
7193eb01 |
598 | ap_log_error( APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r->server, |
599 | "mod_waklog: finished with waklog_aklog" ); |
600 | |
4e1ae1cd |
601 | } |
602 | |
603 | |
bed98ff9 |
604 | static int |
7193eb01 |
605 | waklog_phase0( request_rec *r ) |
bed98ff9 |
606 | { |
313dde40 |
607 | waklog_host_config *cfg; |
608 | |
7193eb01 |
609 | ap_log_error( APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r->server, |
610 | "mod_waklog: phase0 called" ); |
611 | |
313dde40 |
612 | /* directory config? */ |
613 | cfg = (waklog_host_config *)ap_get_module_config( |
614 | r->per_dir_config, &waklog_module); |
bed98ff9 |
615 | |
313dde40 |
616 | /* server config? */ |
617 | if ( !cfg->configured ) { |
7193eb01 |
618 | cfg = (waklog_host_config *)ap_get_module_config( |
619 | r->server->module_config, &waklog_module); |
313dde40 |
620 | } |
621 | |
7193eb01 |
622 | if ( !cfg->protect ) { |
4e1ae1cd |
623 | ap_log_error( APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r->server, |
7193eb01 |
624 | "mod_waklog: phase0 declining" ); |
625 | return( DECLINED ); |
626 | } |
4e1ae1cd |
627 | |
7193eb01 |
628 | /* do this only if we are still unauthenticated */ |
629 | if ( !child->token.ticketLen ) { |
4e1ae1cd |
630 | |
7193eb01 |
631 | /* authenticate using keytab file */ |
632 | waklog_ktinit( r , cfg->keytab ); |
3ed1e28a |
633 | |
7193eb01 |
634 | /* stuff the credentials into the kernel */ |
635 | waklog_aklog( r ); |
4e1ae1cd |
636 | } |
7193eb01 |
637 | |
638 | ap_log_error( APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r->server, |
639 | "mod_waklog: phase0 returning" ); |
640 | return DECLINED; |
641 | } |
4e1ae1cd |
642 | |
1e18ef7d |
643 | |
7193eb01 |
644 | static int |
645 | waklog_phase7( request_rec *r ) |
646 | { |
647 | waklog_host_config *cfg; |
1e18ef7d |
648 | |
7193eb01 |
649 | ap_log_error( APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r->server, |
650 | "mod_waklog: phase7 called" ); |
1e18ef7d |
651 | |
7193eb01 |
652 | /* directory config? */ |
653 | cfg = (waklog_host_config *)ap_get_module_config( |
654 | r->per_dir_config, &waklog_module); |
1e18ef7d |
655 | |
7193eb01 |
656 | /* server config? */ |
657 | if ( !cfg->configured ) { |
658 | cfg = (waklog_host_config *)ap_get_module_config( |
659 | r->server->module_config, &waklog_module); |
bed98ff9 |
660 | } |
661 | |
7193eb01 |
662 | if ( !cfg->protect ) { |
663 | return( DECLINED ); |
bed98ff9 |
664 | } |
665 | |
7193eb01 |
666 | /* stuff the credentials into the kernel */ |
667 | waklog_aklog( r ); |
bed98ff9 |
668 | |
7193eb01 |
669 | ap_log_error( APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r->server, |
670 | "mod_waklog: phase7 returning" ); |
bed98ff9 |
671 | |
7193eb01 |
672 | return DECLINED; |
bed98ff9 |
673 | } |
674 | |
7193eb01 |
675 | static void |
676 | waklog_new_connection( conn_rec *c ) { |
677 | ap_log_error( APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, c->server, |
678 | "mod_waklog: new_connection called: conn_rec: 0x%08x pid: %d", c, getpid() ); |
679 | return; |
680 | } |
bed98ff9 |
681 | |
313dde40 |
682 | module MODULE_VAR_EXPORT waklog_module = { |
bed98ff9 |
683 | STANDARD_MODULE_STUFF, |
313dde40 |
684 | waklog_init, /* module initializer */ |
685 | waklog_create_dir_config, /* create per-dir config structures */ |
bed98ff9 |
686 | NULL, /* merge per-dir config structures */ |
313dde40 |
687 | waklog_create_server_config, /* create per-server config structures */ |
bed98ff9 |
688 | NULL, /* merge per-server config structures */ |
313dde40 |
689 | waklog_cmds, /* table of config file commands */ |
bed98ff9 |
690 | NULL, /* [#8] MIME-typed-dispatched handlers */ |
691 | NULL, /* [#1] URI to filename translation */ |
692 | NULL, /* [#4] validate user id from request */ |
693 | NULL, /* [#5] check if the user is ok _here_ */ |
694 | NULL, /* [#3] check access by host address */ |
695 | NULL, /* [#6] determine MIME type */ |
7193eb01 |
696 | waklog_phase7, /* [#7] pre-run fixups */ |
bed98ff9 |
697 | NULL, /* [#9] log a transaction */ |
313dde40 |
698 | NULL, /* [#2] header parser */ |
699 | waklog_child_init, /* child_init */ |
bed98ff9 |
700 | NULL, /* child_exit */ |
7193eb01 |
701 | waklog_phase0 /* [#0] post read-request */ |
bed98ff9 |
702 | #ifdef EAPI |
703 | ,NULL, /* EAPI: add_module */ |
704 | NULL, /* EAPI: remove_module */ |
705 | NULL, /* EAPI: rewrite_command */ |
7193eb01 |
706 | waklog_new_connection /* EAPI: new_connection */ |
bed98ff9 |
707 | #endif |
708 | }; |