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> |
bed98ff9 |
15 | #include <afs/venus.h> |
7193eb01 |
16 | #include <afs/auth.h> |
17 | #include <rx/rxkad.h> |
18 | |
b52ccbb1 |
19 | #define KEYTAB "/home/drh/keytab.itdwww" |
20 | #define KEYTAB_PRINCIPAL "itdwww" |
4e1ae1cd |
21 | |
58bbdc54 |
22 | #define TKT_LIFE 10*60*60 |
b52ccbb1 |
23 | #define SLEEP_TIME TKT_LIFE - 5*60 |
58bbdc54 |
24 | |
25 | #define AFS_CELL "umich.edu" /* NB: lower case */ |
26 | |
27 | #define K5PATH "FILE:/tmp/waklog.creds.k5" |
28 | #define K4PATH "/tmp/waklog.creds.k4" |
7193eb01 |
29 | |
313dde40 |
30 | module waklog_module; |
bed98ff9 |
31 | |
313dde40 |
32 | typedef struct { |
4e1ae1cd |
33 | int configured; |
34 | int protect; |
35 | char *keytab; |
7193eb01 |
36 | char *keytab_principal; |
403921ef |
37 | char *afs_cell; |
313dde40 |
38 | } waklog_host_config; |
39 | |
7193eb01 |
40 | typedef struct { |
41 | struct ktc_token token; |
42 | } waklog_child_config; |
58bbdc54 |
43 | waklog_child_config child; |
44 | |
b52ccbb1 |
45 | #if 0 |
4d47a8d9 |
46 | static void * |
47 | waklog_create_dir_config( pool *p, char *path ) |
48 | { |
49 | waklog_host_config *cfg; |
50 | |
51 | cfg = (waklog_host_config *)ap_pcalloc( p, sizeof( waklog_host_config )); |
52 | cfg->configured = 0; |
53 | cfg->protect = 0; |
54 | cfg->keytab = KEYTAB; |
55 | cfg->keytab_principal = KEYTAB_PRINCIPAL; |
56 | cfg->afs_cell = AFS_CELL; |
57 | |
58 | return( cfg ); |
59 | } |
b52ccbb1 |
60 | #endif /* 0 */ |
4d47a8d9 |
61 | |
62 | |
313dde40 |
63 | static void * |
64 | waklog_create_server_config( pool *p, server_rec *s ) |
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; |
58bbdc54 |
71 | cfg->keytab = KEYTAB; |
72 | cfg->keytab_principal = KEYTAB_PRINCIPAL; |
73 | cfg->afs_cell = AFS_CELL; |
313dde40 |
74 | |
4d47a8d9 |
75 | #if 0 |
76 | ap_set_module_config( s->module_config, &waklog_module, cfg); |
77 | #endif /* 0 */ |
78 | |
313dde40 |
79 | return( cfg ); |
80 | } |
81 | |
82 | |
313dde40 |
83 | static const char * |
84 | set_waklog_protect( cmd_parms *params, void *mconfig, int flag ) |
85 | { |
86 | waklog_host_config *cfg; |
87 | |
b52ccbb1 |
88 | #if 0 |
313dde40 |
89 | if ( params->path == NULL ) { |
b52ccbb1 |
90 | #endif /* 0 */ |
313dde40 |
91 | cfg = (waklog_host_config *) ap_get_module_config( |
92 | params->server->module_config, &waklog_module ); |
b52ccbb1 |
93 | #if 0 |
313dde40 |
94 | } else { |
95 | cfg = (waklog_host_config *)mconfig; |
96 | } |
b52ccbb1 |
97 | #endif /* 0 */ |
313dde40 |
98 | |
99 | cfg->protect = flag; |
100 | cfg->configured = 1; |
101 | return( NULL ); |
102 | } |
103 | |
104 | |
4e1ae1cd |
105 | static const char * |
106 | set_waklog_use_keytab( cmd_parms *params, void *mconfig, char *file ) |
107 | { |
108 | waklog_host_config *cfg; |
109 | |
b52ccbb1 |
110 | #if 0 |
4e1ae1cd |
111 | if ( params->path == NULL ) { |
b52ccbb1 |
112 | #endif /* 0 */ |
4e1ae1cd |
113 | cfg = (waklog_host_config *) ap_get_module_config( |
114 | params->server->module_config, &waklog_module ); |
b52ccbb1 |
115 | #if 0 |
4e1ae1cd |
116 | } else { |
117 | cfg = (waklog_host_config *)mconfig; |
118 | } |
b52ccbb1 |
119 | #endif /* 0 */ |
4e1ae1cd |
120 | |
3ed1e28a |
121 | ap_log_error( APLOG_MARK, APLOG_INFO|APLOG_NOERRNO, params->server, |
b52ccbb1 |
122 | "mod_waklog: will use keytab: %s", file ); |
3ed1e28a |
123 | |
b52ccbb1 |
124 | cfg->keytab = ap_pstrdup ( params->pool, file ); |
4e1ae1cd |
125 | cfg->configured = 1; |
126 | return( NULL ); |
127 | } |
128 | |
129 | |
58bbdc54 |
130 | static const char * |
131 | set_waklog_use_keytab_principal( cmd_parms *params, void *mconfig, char *file ) |
b74fad73 |
132 | { |
58bbdc54 |
133 | waklog_host_config *cfg; |
7193eb01 |
134 | |
b52ccbb1 |
135 | #if 0 |
58bbdc54 |
136 | if ( params->path == NULL ) { |
b52ccbb1 |
137 | #endif /* 0 */ |
58bbdc54 |
138 | cfg = (waklog_host_config *) ap_get_module_config( |
139 | params->server->module_config, &waklog_module ); |
b52ccbb1 |
140 | #if 0 |
58bbdc54 |
141 | } else { |
142 | cfg = (waklog_host_config *)mconfig; |
7193eb01 |
143 | } |
b52ccbb1 |
144 | #endif /* 0 */ |
7193eb01 |
145 | |
58bbdc54 |
146 | ap_log_error( APLOG_MARK, APLOG_INFO|APLOG_NOERRNO, params->server, |
b52ccbb1 |
147 | "mod_waklog: will use keytab_principal: %s", file ); |
58bbdc54 |
148 | |
b52ccbb1 |
149 | cfg->keytab_principal = ap_pstrdup ( params->pool, file ); |
58bbdc54 |
150 | cfg->configured = 1; |
151 | return( NULL ); |
152 | } |
153 | |
154 | |
155 | static const char * |
156 | set_waklog_use_afs_cell( cmd_parms *params, void *mconfig, char *file ) |
157 | { |
158 | waklog_host_config *cfg; |
159 | |
b52ccbb1 |
160 | #if 0 |
58bbdc54 |
161 | if ( params->path == NULL ) { |
b52ccbb1 |
162 | #endif /* 0 */ |
58bbdc54 |
163 | cfg = (waklog_host_config *) ap_get_module_config( |
164 | params->server->module_config, &waklog_module ); |
b52ccbb1 |
165 | #if 0 |
58bbdc54 |
166 | } else { |
167 | cfg = (waklog_host_config *)mconfig; |
168 | } |
b52ccbb1 |
169 | #endif /* 0 */ |
58bbdc54 |
170 | |
171 | ap_log_error( APLOG_MARK, APLOG_INFO|APLOG_NOERRNO, params->server, |
b52ccbb1 |
172 | "mod_waklog: will use afs_cell: %s", file ); |
58bbdc54 |
173 | |
b52ccbb1 |
174 | cfg->afs_cell = ap_pstrdup( params->pool, file ); |
58bbdc54 |
175 | cfg->configured = 1; |
176 | return( NULL ); |
177 | } |
178 | |
179 | |
180 | static void |
181 | waklog_child_init( server_rec *s, pool *p ) |
182 | { |
183 | |
184 | memset( &child.token, 0, sizeof( struct ktc_token ) ); |
7193eb01 |
185 | |
b74fad73 |
186 | setpag(); |
7193eb01 |
187 | |
b74fad73 |
188 | return; |
189 | } |
190 | |
191 | |
313dde40 |
192 | command_rec waklog_cmds[ ] = |
193 | { |
194 | { "WaklogProtected", set_waklog_protect, |
195 | NULL, RSRC_CONF | ACCESS_CONF, FLAG, |
196 | "enable waklog on a location or directory basis" }, |
197 | |
58bbdc54 |
198 | { "WaklogUseKeytabPath", set_waklog_use_keytab, |
b52ccbb1 |
199 | NULL, RSRC_CONF | ACCESS_CONF, TAKE1, |
58bbdc54 |
200 | "Use the supplied keytab rather than the default" }, |
201 | |
202 | { "WaklogUseKeytabPrincipal", set_waklog_use_keytab_principal, |
b52ccbb1 |
203 | NULL, RSRC_CONF | ACCESS_CONF, TAKE1, |
58bbdc54 |
204 | "Use the supplied keytab principal rather than the default" }, |
205 | |
206 | { "WaklogUseAFSCell", set_waklog_use_afs_cell, |
b52ccbb1 |
207 | NULL, RSRC_CONF | ACCESS_CONF, TAKE1, |
58bbdc54 |
208 | "Use the supplied AFS cell rather than the default" }, |
4e1ae1cd |
209 | |
313dde40 |
210 | { NULL } |
211 | }; |
212 | |
213 | |
bed98ff9 |
214 | static void |
e2df6441 |
215 | token_cleanup( void *data ) |
bed98ff9 |
216 | { |
217 | request_rec *r = (request_rec *)data; |
bed98ff9 |
218 | |
58bbdc54 |
219 | if ( child.token.ticketLen ) { |
220 | memset( &child.token, 0, sizeof( struct ktc_token ) ); |
bed98ff9 |
221 | |
7193eb01 |
222 | ktc_ForgetAllTokens(); |
bed98ff9 |
223 | |
7193eb01 |
224 | ap_log_error( APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r->server, |
58bbdc54 |
225 | "mod_waklog: ktc_ForgetAllTokens succeeded: pid: %d", getpid() ); |
7193eb01 |
226 | } |
b74fad73 |
227 | return; |
bed98ff9 |
228 | } |
229 | |
230 | |
4e1ae1cd |
231 | static int |
e2df6441 |
232 | waklog_kinit( server_rec *s ) |
4e1ae1cd |
233 | { |
234 | krb5_error_code kerror; |
e2df6441 |
235 | krb5_context kcontext = NULL; |
236 | krb5_principal kprinc = NULL; |
4e1ae1cd |
237 | krb5_get_init_creds_opt kopts; |
7193eb01 |
238 | krb5_creds v5creds; |
e2df6441 |
239 | krb5_ccache kccache = NULL; |
240 | krb5_keytab keytab = NULL; |
4e1ae1cd |
241 | char ktbuf[ MAX_KEYTAB_NAME_LEN + 1 ]; |
e21f34f0 |
242 | waklog_host_config *cfg; |
b52ccbb1 |
243 | int i; |
4e1ae1cd |
244 | |
e21f34f0 |
245 | ap_log_error( APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, s, |
b52ccbb1 |
246 | "mod_waklog: waklog_kinit called: pid: %d", getpid() ); |
4e1ae1cd |
247 | |
58bbdc54 |
248 | cfg = (waklog_host_config *) ap_get_module_config( s->module_config, |
249 | &waklog_module ); |
250 | |
e21f34f0 |
251 | if (( kerror = krb5_init_context( &kcontext ))) { |
252 | ap_log_error( APLOG_MARK, APLOG_ERR, s, |
253 | (char *)error_message( kerror )); |
4e1ae1cd |
254 | |
e2df6441 |
255 | goto cleanup; |
e21f34f0 |
256 | } |
4e1ae1cd |
257 | |
e21f34f0 |
258 | /* use the path */ |
259 | if (( kerror = krb5_cc_resolve( kcontext, K5PATH, &kccache )) != 0 ) { |
260 | ap_log_error( APLOG_MARK, APLOG_ERR, s, |
261 | (char *)error_message( kerror )); |
4e1ae1cd |
262 | |
e2df6441 |
263 | goto cleanup; |
e21f34f0 |
264 | } |
4e1ae1cd |
265 | |
b52ccbb1 |
266 | ap_log_error( APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, s, |
267 | "mod_waklog: keytab_principal: %s", cfg->keytab_principal ); |
268 | |
269 | if (( kerror = krb5_parse_name( kcontext, cfg->keytab_principal, &kprinc ))) { |
e21f34f0 |
270 | ap_log_error( APLOG_MARK, APLOG_ERR, s, |
271 | (char *)error_message( kerror )); |
7193eb01 |
272 | |
e2df6441 |
273 | goto cleanup; |
e21f34f0 |
274 | } |
7193eb01 |
275 | |
b52ccbb1 |
276 | #if 0 |
277 | ap_log_error( APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, s, |
278 | "mod_waklog: kprinc->realm: %.*s", kprinc->realm.length, kprinc->realm.data ); |
279 | |
280 | ap_log_error( APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, s, |
281 | "mod_waklog: kprinc->length: %d", kprinc->length ); |
282 | for ( i = 0; i < kprinc->length; i++ ) { |
283 | ap_log_error( APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, s, |
284 | "mod_waklog: kprinc->data[%d].data: %.*s", i, kprinc->data[i].length, kprinc->data[i].data ); |
285 | } |
286 | #endif /* 0 */ |
287 | |
e21f34f0 |
288 | krb5_get_init_creds_opt_init( &kopts ); |
58bbdc54 |
289 | krb5_get_init_creds_opt_set_tkt_life( &kopts, TKT_LIFE ); |
e21f34f0 |
290 | krb5_get_init_creds_opt_set_renew_life( &kopts, 0 ); |
291 | krb5_get_init_creds_opt_set_forwardable( &kopts, 1 ); |
292 | krb5_get_init_creds_opt_set_proxiable( &kopts, 0 ); |
7193eb01 |
293 | |
58bbdc54 |
294 | /* keytab from config */ |
295 | strncpy( ktbuf, cfg->keytab, sizeof( ktbuf ) - 1 ); |
7193eb01 |
296 | |
e21f34f0 |
297 | ap_log_error( APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, s, |
e2df6441 |
298 | "mod_waklog: waklog_kinit using: %s", ktbuf ); |
7193eb01 |
299 | |
e21f34f0 |
300 | if (( kerror = krb5_kt_resolve( kcontext, ktbuf, &keytab )) != 0 ) { |
301 | ap_log_error( APLOG_MARK, APLOG_ERR, s, |
302 | (char *)error_message( kerror )); |
7193eb01 |
303 | |
e2df6441 |
304 | goto cleanup; |
e21f34f0 |
305 | } |
7193eb01 |
306 | |
b52ccbb1 |
307 | memset( (char *)&v5creds, 0, sizeof(v5creds)); |
308 | |
e21f34f0 |
309 | /* get the krbtgt */ |
310 | if (( kerror = krb5_get_init_creds_keytab( kcontext, &v5creds, |
403921ef |
311 | kprinc, keytab, 0, NULL, &kopts ))) { |
7193eb01 |
312 | |
e21f34f0 |
313 | ap_log_error( APLOG_MARK, APLOG_ERR, s, |
314 | (char *)error_message( kerror )); |
7193eb01 |
315 | |
e2df6441 |
316 | goto cleanup; |
e21f34f0 |
317 | } |
7193eb01 |
318 | |
b52ccbb1 |
319 | #if 0 |
320 | ap_log_error( APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, s, |
321 | "mod_waklog: v5creds.client->realm: %.*s", v5creds.client->realm.length, v5creds.client->realm.data ); |
322 | |
323 | ap_log_error( APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, s, |
324 | "mod_waklog: v5creds.client->length: %d", v5creds.client->length ); |
325 | for ( i = 0; i < v5creds.client->length; i++ ) { |
326 | ap_log_error( APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, s, |
327 | "mod_waklog: v5creds.client->data[%d].data: %.*s", |
328 | i, v5creds.client->data[i].length, v5creds.client->data[i].data ); |
329 | } |
330 | |
331 | ap_log_error( APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, s, |
332 | "mod_waklog: v5creds.server->realm: %.*s", v5creds.server->realm.length, v5creds.server->realm.data ); |
333 | |
334 | ap_log_error( APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, s, |
335 | "mod_waklog: v5creds.server->length: %d", v5creds.server->length ); |
336 | for ( i = 0; i < v5creds.server->length; i++ ) { |
337 | ap_log_error( APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, s, |
338 | "mod_waklog: v5creds.server->data[%d].data: %.*s", |
339 | i, v5creds.server->data[i].length, v5creds.server->data[i].data ); |
340 | } |
341 | |
342 | ap_log_error( APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, s, |
343 | "mod_waklog: waklog_kinit #4" ); |
344 | |
345 | ap_log_error( APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, s, |
346 | "mod_waklog: waklog_kinit kprinc==v5creds.server: %s", |
347 | krb5_principal_compare( kcontext, kprinc, v5creds.server ) ? "true" : "false" ); |
348 | #endif /* 0 */ |
349 | |
350 | #if 0 |
351 | #error the proof of the pudding is in the eating |
352 | if (( kerror = krb5_verify_init_creds( kcontext, &v5creds, |
353 | v5creds.server, keytab, NULL, &vopts )) != 0 ) { |
7193eb01 |
354 | |
e21f34f0 |
355 | ap_log_error( APLOG_MARK, APLOG_ERR, s, |
356 | (char *)error_message( kerror )); |
7193eb01 |
357 | |
e2df6441 |
358 | goto cleanup; |
e21f34f0 |
359 | } |
b52ccbb1 |
360 | #endif /* 0 */ |
7193eb01 |
361 | |
e21f34f0 |
362 | if (( kerror = krb5_cc_initialize( kcontext, kccache, kprinc )) != 0 ) { |
363 | ap_log_error( APLOG_MARK, APLOG_ERR, s, |
364 | (char *)error_message( kerror )); |
7193eb01 |
365 | |
e2df6441 |
366 | goto cleanup; |
e21f34f0 |
367 | } |
7193eb01 |
368 | |
e2df6441 |
369 | kerror = krb5_cc_store_cred( kcontext, kccache, &v5creds ); |
370 | krb5_free_cred_contents( kcontext, &v5creds ); |
371 | if ( kerror != 0 ) { |
e21f34f0 |
372 | ap_log_error( APLOG_MARK, APLOG_ERR, s, |
373 | (char *)error_message( kerror )); |
7193eb01 |
374 | |
e2df6441 |
375 | goto cleanup; |
e21f34f0 |
376 | } |
7193eb01 |
377 | |
e21f34f0 |
378 | ap_log_error( APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, s, |
e2df6441 |
379 | "mod_waklog: waklog_kinit success" ); |
380 | |
381 | cleanup: |
382 | if ( keytab ) |
383 | (void)krb5_kt_close( kcontext, keytab ); |
384 | if ( kprinc ) |
385 | krb5_free_principal( kcontext, kprinc ); |
386 | if ( kccache ) |
387 | krb5_cc_close( kcontext, kccache ); |
388 | if ( kcontext ) |
389 | krb5_free_context( kcontext ); |
e21f34f0 |
390 | |
391 | ap_log_error( APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, s, |
e2df6441 |
392 | "mod_waklog: waklog_kinit: exiting" ); |
7193eb01 |
393 | |
394 | return( 0 ); |
395 | } |
396 | |
397 | |
398 | static void |
399 | waklog_aklog( request_rec *r ) |
400 | { |
401 | int rc; |
bd173fe7 |
402 | char buf[ MAXKTCTICKETLEN ]; |
7193eb01 |
403 | const char *k4path = NULL; |
404 | const char *k5path = NULL; |
405 | krb5_error_code kerror; |
e2df6441 |
406 | krb5_context kcontext = NULL; |
7193eb01 |
407 | krb5_creds increds; |
408 | krb5_creds *v5credsp = NULL; |
e2df6441 |
409 | krb5_ccache kccache = NULL; |
403921ef |
410 | struct ktc_principal server = { "afs", "", "" }; |
7193eb01 |
411 | struct ktc_principal client; |
412 | struct ktc_token token; |
403921ef |
413 | waklog_host_config *cfg; |
58bbdc54 |
414 | int buflen; |
7193eb01 |
415 | |
416 | k5path = ap_table_get( r->subprocess_env, "KRB5CCNAME" ); |
417 | k4path = ap_table_get( r->subprocess_env, "KRBTKFILE" ); |
418 | |
419 | ap_log_error( APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r->server, |
420 | "mod_waklog: waklog_aklog called: k5path: %s, k4path: %s", k5path, k4path ); |
421 | |
422 | if ( !k5path || !k4path ) { |
423 | ap_log_error( APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r->server, |
424 | "mod_waklog: waklog_aklog giving up" ); |
e2df6441 |
425 | goto cleanup; |
4e1ae1cd |
426 | } |
427 | |
7193eb01 |
428 | /* |
429 | ** Get/build creds from file/tgs, then see if we need to SetToken |
430 | */ |
431 | |
432 | if (( kerror = krb5_init_context( &kcontext ))) { |
433 | /* Authentication Required ( kerberos error ) */ |
4e1ae1cd |
434 | ap_log_error( APLOG_MARK, APLOG_ERR, r->server, |
435 | (char *)error_message( kerror )); |
7193eb01 |
436 | |
e2df6441 |
437 | goto cleanup; |
4e1ae1cd |
438 | } |
439 | |
7193eb01 |
440 | memset( (char *)&increds, 0, sizeof(increds)); |
4e1ae1cd |
441 | |
403921ef |
442 | cfg = (waklog_host_config *) ap_get_module_config( |
443 | r->server->module_config, &waklog_module ); |
444 | |
445 | /* afs/<cell> or afs */ |
446 | strncpy( buf, "afs", sizeof( buf ) - 1 ); |
58bbdc54 |
447 | if ( strcmp( cfg->afs_cell, AFS_CELL ) ) { |
403921ef |
448 | strncat( buf, "/" , sizeof( buf ) - strlen( buf ) - 1 ); |
449 | strncat( buf, cfg->afs_cell, sizeof( buf ) - strlen( buf ) - 1 ); |
450 | } |
451 | |
7193eb01 |
452 | /* set server part */ |
403921ef |
453 | if (( kerror = krb5_parse_name( kcontext, buf, &increds.server ))) { |
4e1ae1cd |
454 | ap_log_error( APLOG_MARK, APLOG_ERR, r->server, |
455 | (char *)error_message( kerror )); |
456 | |
e2df6441 |
457 | goto cleanup; |
4e1ae1cd |
458 | } |
459 | |
7193eb01 |
460 | if (( kerror = krb5_cc_resolve( kcontext, k5path, &kccache )) != 0 ) { |
461 | ap_log_error( APLOG_MARK, APLOG_ERR, r->server, |
462 | (char *)error_message( kerror )); |
463 | |
e2df6441 |
464 | goto cleanup; |
7193eb01 |
465 | } |
4e1ae1cd |
466 | |
7193eb01 |
467 | /* set client part */ |
468 | krb5_cc_get_principal( kcontext, kccache, &increds.client ); |
4e1ae1cd |
469 | |
7193eb01 |
470 | increds.times.endtime = 0; |
471 | /* Ask for DES since that is what V4 understands */ |
472 | increds.keyblock.enctype = ENCTYPE_DES_CBC_CRC; |
473 | |
474 | /* get the V5 credentials */ |
475 | if (( kerror = krb5_get_credentials( kcontext, 0, kccache, |
476 | &increds, &v5credsp ) ) ) { |
403921ef |
477 | ap_log_error( APLOG_MARK, APLOG_ERR, r->server, |
478 | "mod_waklog: krb5_get_credentials: %s", error_message( kerror )); |
e2df6441 |
479 | goto cleanup; |
4e1ae1cd |
480 | } |
481 | |
c4ad0387 |
482 | /* don't overflow */ |
483 | if ( v5credsp->ticket.length >= MAXKTCTICKETLEN ) { /* from krb524d.c */ |
403921ef |
484 | ap_log_error( APLOG_MARK, APLOG_ERR, r->server, |
c4ad0387 |
485 | "mod_waklog: ticket size (%d) too big to fake", v5credsp->ticket.length ); |
e2df6441 |
486 | goto cleanup; |
4e1ae1cd |
487 | } |
488 | |
7193eb01 |
489 | /* assemble the token */ |
58bbdc54 |
490 | memset( &token, 0, sizeof( struct ktc_token ) ); |
491 | |
492 | token.startTime = v5credsp->times.starttime ? v5credsp->times.starttime : v5credsp->times.authtime; |
7193eb01 |
493 | token.endTime = v5credsp->times.endtime; |
58bbdc54 |
494 | memmove( &token.sessionKey, v5credsp->keyblock.contents, v5credsp->keyblock.length ); |
495 | token.kvno = RXKAD_TKT_TYPE_KERBEROS_V5; |
496 | token.ticketLen = v5credsp->ticket.length; |
497 | memmove( token.ticket, v5credsp->ticket.data, token.ticketLen ); |
7193eb01 |
498 | |
58bbdc54 |
499 | /* make sure we have to do this */ |
500 | if ( child.token.kvno != token.kvno || |
501 | child.token.ticketLen != token.ticketLen || |
502 | (memcmp( &child.token.sessionKey, &token.sessionKey, |
503 | sizeof( token.sessionKey ) )) || |
504 | (memcmp( child.token.ticket, token.ticket, token.ticketLen )) ) { |
505 | |
8258901d |
506 | ap_log_error( APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r->server, |
507 | "mod_waklog: client: %s", buf ); |
7193eb01 |
508 | |
509 | /* build the name */ |
bd173fe7 |
510 | memmove( buf, v5credsp->client->data[0].data, |
511 | min( v5credsp->client->data[0].length, MAXKTCNAMELEN - 1 ) ); |
58bbdc54 |
512 | buf[ v5credsp->client->data[0].length ] = '\0'; |
513 | if ( v5credsp->client->length > 1 ) { |
8258901d |
514 | strncat( buf, ".", sizeof( buf ) - strlen( buf ) - 1 ); |
58bbdc54 |
515 | buflen = strlen( buf ); |
bd173fe7 |
516 | memmove( buf + buflen, v5credsp->client->data[1].data, |
517 | min( v5credsp->client->data[1].length, MAXKTCNAMELEN - strlen( buf ) - 1 ) ); |
58bbdc54 |
518 | buf[ buflen + v5credsp->client->data[1].length ] = '\0'; |
7193eb01 |
519 | } |
520 | |
521 | /* assemble the client */ |
403921ef |
522 | strncpy( client.name, buf, sizeof( client.name ) - 1 ); |
523 | strncpy( client.instance, "", sizeof( client.instance) - 1 ); |
bd173fe7 |
524 | memmove( buf, v5credsp->client->realm.data, |
525 | min( v5credsp->client->realm.length, MAXKTCNAMELEN - 1 ) ); |
58bbdc54 |
526 | buf[ v5credsp->client->realm.length ] = '\0'; |
527 | strncpy( client.cell, buf, sizeof( client.cell ) - 1 ); |
403921ef |
528 | |
58bbdc54 |
529 | /* assemble the server's cell */ |
403921ef |
530 | strncpy( server.cell, cfg->afs_cell , sizeof( server.cell ) - 1 ); |
7193eb01 |
531 | |
532 | ap_log_error( APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r->server, |
533 | "mod_waklog: server: name=%s, instance=%s, cell=%s", |
534 | server.name, server.instance, server.cell ); |
535 | |
536 | ap_log_error( APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r->server, |
537 | "mod_waklog: client: name=%s, instance=%s, cell=%s", |
538 | client.name, client.instance, client.cell ); |
539 | |
540 | /* use the path */ |
541 | krb_set_tkt_string( (char *)k4path ); |
542 | |
543 | /* rumor: we have to do this for AIX 4.1.4 with AFS 3.4+ */ |
544 | write( 2, "", 0 ); |
545 | |
546 | if ( ( rc = ktc_SetToken( &server, &token, &client, 0 ) ) ) { |
58bbdc54 |
547 | ap_log_error( APLOG_MARK, APLOG_ERR, r->server, |
7193eb01 |
548 | "mod_waklog: settoken returned %d", rc ); |
58bbdc54 |
549 | goto cleanup; |
7193eb01 |
550 | } |
551 | |
552 | /* save this */ |
58bbdc54 |
553 | memmove( &child.token, &token, sizeof( struct ktc_token ) ); |
7193eb01 |
554 | |
555 | /* we'll need to unlog when this connection is done. */ |
e2df6441 |
556 | ap_register_cleanup( r->pool, (void *)r, token_cleanup, ap_null_cleanup ); |
7193eb01 |
557 | } |
558 | |
e2df6441 |
559 | cleanup: |
560 | if ( v5credsp ) |
561 | krb5_free_cred_contents( kcontext, v5credsp ); |
562 | if ( increds.client ) |
563 | krb5_free_principal( kcontext, increds.client ); |
564 | if ( increds.server ) |
565 | krb5_free_principal( kcontext, increds.server ); |
566 | if ( kccache ) |
567 | krb5_cc_close( kcontext, kccache ); |
568 | if ( kcontext ) |
569 | krb5_free_context( kcontext ); |
3ed1e28a |
570 | |
7193eb01 |
571 | ap_log_error( APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r->server, |
572 | "mod_waklog: finished with waklog_aklog" ); |
573 | |
e2df6441 |
574 | return; |
575 | |
4e1ae1cd |
576 | } |
577 | |
e21f34f0 |
578 | static int |
579 | waklog_child_routine( void *s, child_info *pinfo ) |
580 | { |
e21f34f0 |
581 | if ( !getuid() ) { |
132ef613 |
582 | ap_log_error( APLOG_MARK, APLOG_ERR|APLOG_NOERRNO, s, |
e21f34f0 |
583 | "mod_waklog: waklog_child_routine called as root" ); |
584 | |
585 | /* this was causing the credential file to get owned by root */ |
586 | setgid(ap_group_id); |
587 | setuid(ap_user_id); |
588 | } |
589 | |
590 | while( 1 ) { |
e2df6441 |
591 | waklog_kinit( s ); |
58bbdc54 |
592 | sleep( SLEEP_TIME ); |
e21f34f0 |
593 | } |
594 | |
595 | } |
596 | |
597 | |
598 | static void |
599 | waklog_init( server_rec *s, pool *p ) |
600 | { |
601 | extern char *version; |
602 | int pid; |
603 | |
604 | ap_log_error( APLOG_MARK, APLOG_INFO|APLOG_NOERRNO, s, |
605 | "mod_waklog: version %s initialized.", version ); |
606 | |
607 | pid = ap_bspawn_child( p, waklog_child_routine, s, kill_always, |
608 | NULL, NULL, NULL ); |
609 | |
132ef613 |
610 | ap_log_error( APLOG_MARK, APLOG_ERR|APLOG_NOERRNO, s, |
e21f34f0 |
611 | "mod_waklog: ap_bspawn_child: %d.", pid ); |
612 | } |
613 | |
4e1ae1cd |
614 | |
bed98ff9 |
615 | static int |
7193eb01 |
616 | waklog_phase0( request_rec *r ) |
bed98ff9 |
617 | { |
313dde40 |
618 | waklog_host_config *cfg; |
619 | |
7193eb01 |
620 | ap_log_error( APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r->server, |
621 | "mod_waklog: phase0 called" ); |
622 | |
b52ccbb1 |
623 | #if 0 |
313dde40 |
624 | /* directory config? */ |
625 | cfg = (waklog_host_config *)ap_get_module_config( |
626 | r->per_dir_config, &waklog_module); |
bed98ff9 |
627 | |
b52ccbb1 |
628 | |
313dde40 |
629 | /* server config? */ |
630 | if ( !cfg->configured ) { |
b52ccbb1 |
631 | #endif /* 0 */ |
7193eb01 |
632 | cfg = (waklog_host_config *)ap_get_module_config( |
633 | r->server->module_config, &waklog_module); |
b52ccbb1 |
634 | #if 0 |
313dde40 |
635 | } |
b52ccbb1 |
636 | #endif /* 0 */ |
313dde40 |
637 | |
7193eb01 |
638 | if ( !cfg->protect ) { |
4e1ae1cd |
639 | ap_log_error( APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r->server, |
7193eb01 |
640 | "mod_waklog: phase0 declining" ); |
641 | return( DECLINED ); |
642 | } |
4e1ae1cd |
643 | |
b52ccbb1 |
644 | /* set our environment variables */ |
645 | ap_table_set( r->subprocess_env, "KRB5CCNAME", K5PATH ); |
646 | ap_table_set( r->subprocess_env, "KRBTKFILE", K4PATH ); |
647 | |
7193eb01 |
648 | /* do this only if we are still unauthenticated */ |
58bbdc54 |
649 | if ( !child.token.ticketLen ) { |
4e1ae1cd |
650 | |
7193eb01 |
651 | /* stuff the credentials into the kernel */ |
652 | waklog_aklog( r ); |
4e1ae1cd |
653 | } |
7193eb01 |
654 | |
655 | ap_log_error( APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r->server, |
656 | "mod_waklog: phase0 returning" ); |
657 | return DECLINED; |
658 | } |
4e1ae1cd |
659 | |
1e18ef7d |
660 | |
7193eb01 |
661 | static int |
662 | waklog_phase7( request_rec *r ) |
663 | { |
664 | waklog_host_config *cfg; |
1e18ef7d |
665 | |
7193eb01 |
666 | ap_log_error( APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r->server, |
667 | "mod_waklog: phase7 called" ); |
1e18ef7d |
668 | |
b52ccbb1 |
669 | #if 0 |
7193eb01 |
670 | /* directory config? */ |
671 | cfg = (waklog_host_config *)ap_get_module_config( |
672 | r->per_dir_config, &waklog_module); |
1e18ef7d |
673 | |
7193eb01 |
674 | /* server config? */ |
675 | if ( !cfg->configured ) { |
b52ccbb1 |
676 | #endif /* 0 */ |
7193eb01 |
677 | cfg = (waklog_host_config *)ap_get_module_config( |
678 | r->server->module_config, &waklog_module); |
b52ccbb1 |
679 | #if 0 |
bed98ff9 |
680 | } |
b52ccbb1 |
681 | #endif /* 0 */ |
bed98ff9 |
682 | |
7193eb01 |
683 | if ( !cfg->protect ) { |
684 | return( DECLINED ); |
bed98ff9 |
685 | } |
686 | |
7193eb01 |
687 | /* stuff the credentials into the kernel */ |
688 | waklog_aklog( r ); |
bed98ff9 |
689 | |
7193eb01 |
690 | ap_log_error( APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r->server, |
691 | "mod_waklog: phase7 returning" ); |
bed98ff9 |
692 | |
7193eb01 |
693 | return DECLINED; |
bed98ff9 |
694 | } |
695 | |
7193eb01 |
696 | static void |
697 | waklog_new_connection( conn_rec *c ) { |
698 | ap_log_error( APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, c->server, |
58bbdc54 |
699 | "mod_waklog: new_connection called: pid: %d", getpid() ); |
7193eb01 |
700 | return; |
701 | } |
bed98ff9 |
702 | |
c4ad0387 |
703 | |
704 | static int waklog_phase2( request_rec *r ) |
705 | { |
706 | ap_log_error( APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r->server, "mod_waklog: phase2 called" ); |
707 | if ( child.token.ticketLen ) { |
708 | memset( &child.token, 0, sizeof( struct ktc_token ) ); |
709 | |
710 | ktc_ForgetAllTokens(); |
711 | |
712 | ap_log_error( APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r->server, |
713 | "mod_waklog: ktc_ForgetAllTokens succeeded: pid: %d", getpid() ); |
714 | } |
715 | ap_log_error( APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r->server, "mod_waklog: phase2 returning" ); |
716 | return DECLINED; |
717 | } |
718 | |
719 | #if 0 |
720 | static int waklog_phase1( request_rec *r ) |
721 | { |
722 | ap_log_error( APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r->server, "mod_waklog: phase1 returning" ); |
723 | return DECLINED; |
724 | } |
725 | static int waklog_phase3( request_rec *r ) |
726 | { |
727 | ap_log_error( APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r->server, "mod_waklog: phase3 returning" ); |
728 | return DECLINED; |
729 | } |
730 | static int waklog_phase4( request_rec *r ) |
731 | { |
732 | ap_log_error( APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r->server, "mod_waklog: phase4 returning" ); |
733 | return DECLINED; |
734 | } |
735 | static int waklog_phase5( request_rec *r ) |
736 | { |
737 | ap_log_error( APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r->server, "mod_waklog: phase5 returning" ); |
738 | return DECLINED; |
739 | } |
740 | static int waklog_phase6( request_rec *r ) |
741 | { |
742 | ap_log_error( APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r->server, "mod_waklog: phase6 returning" ); |
743 | return DECLINED; |
744 | } |
745 | static void waklog_phase8( request_rec *r ) |
746 | { |
747 | ap_log_error( APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r->server, "mod_waklog: phase8 returning" ); |
748 | return; |
749 | } |
750 | static int waklog_phase9( request_rec *r ) |
751 | { |
752 | ap_log_error( APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r->server, "mod_waklog: phase9 returning" ); |
753 | return DECLINED; |
754 | } |
755 | #endif /* 0 */ |
756 | |
313dde40 |
757 | module MODULE_VAR_EXPORT waklog_module = { |
bed98ff9 |
758 | STANDARD_MODULE_STUFF, |
003832b1 |
759 | waklog_init, /* module initializer */ |
b52ccbb1 |
760 | #if 0 |
4d47a8d9 |
761 | waklog_create_dir_config, /* create per-dir config structures */ |
b52ccbb1 |
762 | #else /* 0 */ |
763 | NULL, /* create per-dir config structures */ |
764 | #endif /* 0 */ |
bed98ff9 |
765 | NULL, /* merge per-dir config structures */ |
313dde40 |
766 | waklog_create_server_config, /* create per-server config structures */ |
bed98ff9 |
767 | NULL, /* merge per-server config structures */ |
313dde40 |
768 | waklog_cmds, /* table of config file commands */ |
bed98ff9 |
769 | NULL, /* [#8] MIME-typed-dispatched handlers */ |
770 | NULL, /* [#1] URI to filename translation */ |
771 | NULL, /* [#4] validate user id from request */ |
772 | NULL, /* [#5] check if the user is ok _here_ */ |
773 | NULL, /* [#3] check access by host address */ |
774 | NULL, /* [#6] determine MIME type */ |
7193eb01 |
775 | waklog_phase7, /* [#7] pre-run fixups */ |
bed98ff9 |
776 | NULL, /* [#9] log a transaction */ |
c4ad0387 |
777 | waklog_phase2, /* [#2] header parser */ |
313dde40 |
778 | waklog_child_init, /* child_init */ |
bed98ff9 |
779 | NULL, /* child_exit */ |
7193eb01 |
780 | waklog_phase0 /* [#0] post read-request */ |
bed98ff9 |
781 | #ifdef EAPI |
782 | ,NULL, /* EAPI: add_module */ |
783 | NULL, /* EAPI: remove_module */ |
784 | NULL, /* EAPI: rewrite_command */ |
7193eb01 |
785 | waklog_new_connection /* EAPI: new_connection */ |
bed98ff9 |
786 | #endif |
787 | }; |