non-functional version of the keytab version.
[hcoop/debian/libapache-mod-waklog.git] / mod_waklog.c
CommitLineData
bed98ff9 1#include "httpd.h"
2#include "http_config.h"
3#include "http_protocol.h"
4#include "http_log.h"
5#include "ap_config.h"
4e1ae1cd 6#include <krb5.h>
bed98ff9 7
8#include <sys/ioccom.h>
9#include <stropts.h>
10#include <kerberosIV/krb.h>
11#include <kerberosIV/des.h>
12#include <afs/venus.h>
13
3ed1e28a 14#define KEYTAB_PATH "/usr/local/users/clunis/keytab.umweb.mysql"
15#define PRINCIPAL "umweb/mysql"
4e1ae1cd 16#define IN_TKT_SERVICE "krbtgt/UMICH.EDU"
17
313dde40 18module waklog_module;
bed98ff9 19
20struct ClearToken {
21 long AuthHandle;
22 char HandShakeKey[ 8 ];
23 long ViceId;
24 long BeginTimestamp;
25 long EndTimestamp;
26};
27
313dde40 28typedef struct {
4e1ae1cd 29 int configured;
30 int protect;
31 char *keytab;
313dde40 32} waklog_host_config;
33
34
35 static void *
36waklog_create_dir_config( pool *p, char *path )
37{
38 waklog_host_config *cfg;
39
40 cfg = (waklog_host_config *)ap_pcalloc( p, sizeof( waklog_host_config ));
41 cfg->configured = 0;
42 cfg->protect = 0;
43
44 return( cfg );
45}
46
47
48 static void *
49waklog_create_server_config( pool *p, server_rec *s )
50{
51 waklog_host_config *cfg;
52
53 cfg = (waklog_host_config *)ap_pcalloc( p, sizeof( waklog_host_config ));
54 cfg->configured = 0;
55 cfg->protect = 0;
56
57 return( cfg );
58}
59
60
b429ae96 61 static void
313dde40 62waklog_init( server_rec *s, pool *p )
b429ae96 63{
64 extern char *version;
65
66 ap_log_error( APLOG_MARK, APLOG_INFO|APLOG_NOERRNO, s,
313dde40 67 "mod_waklog: version %s initialized.", version );
b429ae96 68 return;
69}
70
bed98ff9 71
313dde40 72 static const char *
73set_waklog_protect( cmd_parms *params, void *mconfig, int flag )
74{
75 waklog_host_config *cfg;
76
77 if ( params->path == NULL ) {
78 cfg = (waklog_host_config *) ap_get_module_config(
79 params->server->module_config, &waklog_module );
80 } else {
81 cfg = (waklog_host_config *)mconfig;
82 }
83
84 cfg->protect = flag;
85 cfg->configured = 1;
86 return( NULL );
87}
88
89
4e1ae1cd 90 static const char *
91set_waklog_use_keytab( cmd_parms *params, void *mconfig, char *file )
92{
93 waklog_host_config *cfg;
94
95 if ( params->path == NULL ) {
96 cfg = (waklog_host_config *) ap_get_module_config(
97 params->server->module_config, &waklog_module );
98 } else {
99 cfg = (waklog_host_config *)mconfig;
100 }
101
3ed1e28a 102 ap_log_error( APLOG_MARK, APLOG_INFO|APLOG_NOERRNO, params->server,
103 "mod_waklog: using keytab: %s", file );
104
4e1ae1cd 105 cfg->keytab = file;
106 cfg->configured = 1;
107 return( NULL );
108}
109
110
b74fad73 111 static void
313dde40 112waklog_child_init( server_rec *s, pool *p )
b74fad73 113{
114 setpag();
b74fad73 115 return;
116}
117
118
313dde40 119command_rec waklog_cmds[ ] =
120{
121 { "WaklogProtected", set_waklog_protect,
122 NULL, RSRC_CONF | ACCESS_CONF, FLAG,
123 "enable waklog on a location or directory basis" },
124
4e1ae1cd 125 { "WaklogUseKeytab", set_waklog_use_keytab,
126 NULL, RSRC_CONF, TAKE1,
127 "Use the supplied keytab file rather than the user's TGT" },
128
313dde40 129 { NULL }
130};
131
132
bed98ff9 133 static void
134pioctl_cleanup( void *data )
135{
136 request_rec *r = (request_rec *)data;
137 struct ViceIoctl vi;
138
139 vi.in = NULL;
140 vi.in_size = 0;
141 vi.out = NULL;
142 vi.out_size = 0;
143
144 if ( pioctl( 0, VIOCUNPAG, &vi, 0 ) < 0 ) {
145 ap_log_error( APLOG_MARK, APLOG_ERR, r->server,
313dde40 146 "mod_waklog: unlog pioctl failed" );
bed98ff9 147 }
148
1e18ef7d 149 ap_log_error( APLOG_MARK, APLOG_DEBUG, r->server,
313dde40 150 "mod_waklog: unlog pioctl succeeded" );
b74fad73 151 return;
bed98ff9 152}
153
154
4e1ae1cd 155 static int
156waklog_ktinit( request_rec *r )
157{
158 krb5_error_code kerror;
159 krb5_context kcontext;
160 krb5_principal kprinc;
161 krb5_principal sprinc;
162 krb5_get_init_creds_opt kopts;
163 krb5_creds kcreds;
164 krb5_ccache kccache;
165 krb5_keytab keytab = 0;
166 char ktbuf[ MAX_KEYTAB_NAME_LEN + 1 ];
167 char krbpath [ 24 ];
168
169 if (( kerror = krb5_init_context( &kcontext ))) {
170 /* Authentication Required ( kerberos error ) */
171 ap_log_error( APLOG_MARK, APLOG_ERR, r->server,
172 (char *)error_message( kerror ));
173
174 return;
175 }
176
3ed1e28a 177 if (( kerror = krb5_parse_name( kcontext, "PRINCIPAL", &kprinc ))) {
4e1ae1cd 178 ap_log_error( APLOG_MARK, APLOG_ERR, r->server,
179 (char *)error_message( kerror ));
180
181 return;
182 }
183
184 snprintf( krbpath, sizeof( krbpath ), "/ticket/waklog" );
185
186 if (( kerror = krb5_cc_resolve( kcontext, krbpath, &kccache )) != 0 ) {
187 ap_log_error( APLOG_MARK, APLOG_ERR, r->server,
188 (char *)error_message( kerror ));
189
190 return;
191 }
192
193 krb5_get_init_creds_opt_init( &kopts );
194 krb5_get_init_creds_opt_set_tkt_life( &kopts, 10*60*60 );
195 krb5_get_init_creds_opt_set_renew_life( &kopts, 0 );
196 krb5_get_init_creds_opt_set_forwardable( &kopts, 1 );
197 krb5_get_init_creds_opt_set_proxiable( &kopts, 0 );
198
199 if ( KEYTAB_PATH == '\0' ) {
200 if (( kerror = krb5_kt_default_name(
201 kcontext, ktbuf, MAX_KEYTAB_NAME_LEN )) != 0 ) {
202 ap_log_error( APLOG_MARK, APLOG_ERR, r->server,
203 (char *)error_message( kerror ));
204
205 return;
206 }
207 } else {
208 if ( strlen( KEYTAB_PATH ) > MAX_KEYTAB_NAME_LEN ) {
209 ap_log_error( APLOG_MARK, APLOG_ERR, r->server,
210 "server configuration error" );
211
212 return;
213 }
214 strcpy( ktbuf, KEYTAB_PATH );
215 }
216
217 if (( kerror = krb5_kt_resolve( kcontext, ktbuf, &keytab )) != 0 ) {
218 ap_log_error( APLOG_MARK, APLOG_ERR, r->server,
219 (char *)error_message( kerror ));
220
221 return;
222 }
223
224 if (( kerror = krb5_sname_to_principal( kcontext, NULL, "cosign",
225 KRB5_NT_SRV_HST, &sprinc )) != 0 ) {
226 ap_log_error( APLOG_MARK, APLOG_ERR, r->server,
227 (char *)error_message( kerror ));
228
229 return;
230 }
231
232 if (( kerror = krb5_get_init_creds_keytab( kcontext, &kcreds,
233 kprinc, keytab, NULL, IN_TKT_SERVICE, &kopts ))) {
234
235 ap_log_error( APLOG_MARK, APLOG_ERR, r->server,
236 (char *)error_message( kerror ));
237
238 return;
239 }
240
241
242 (void)krb5_kt_close( kcontext, keytab );
243 krb5_free_principal( kcontext, sprinc );
244
245 if (( kerror = krb5_cc_initialize( kcontext, kccache, kprinc )) != 0 ) {
246 ap_log_error( APLOG_MARK, APLOG_ERR, r->server,
247 (char *)error_message( kerror ));
248
249 return;
250 }
251
252 if (( kerror = krb5_cc_store_cred( kcontext, kccache, &kcreds )) != 0 ) {
253 ap_log_error( APLOG_MARK, APLOG_ERR, r->server,
254 (char *)error_message( kerror ));
255
256 return;
257 }
258
259 krb5_free_cred_contents( kcontext, &kcreds );
260 krb5_free_principal( kcontext, kprinc );
261 krb5_cc_close( kcontext, kccache );
262 krb5_free_context( kcontext );
3ed1e28a 263
264 return( 0 );
4e1ae1cd 265}
266
267
bed98ff9 268 static int
313dde40 269waklog_get_tokens( request_rec *r )
bed98ff9 270{
271 CREDENTIALS cr;
272 struct ViceIoctl vi;
273 struct ClearToken ct;
274 int i, rc;
275 char buf[ 1024 ], *s;
276 char *urealm = "UMICH.EDU";
277 char *lrealm = "umich.edu";
313dde40 278 waklog_host_config *cfg;
279
280 /* directory config? */
281 cfg = (waklog_host_config *)ap_get_module_config(
282 r->per_dir_config, &waklog_module);
bed98ff9 283
313dde40 284 /* server config? */
285 if ( !cfg->configured ) {
286 cfg = (waklog_host_config *)ap_get_module_config(
287 r->server->module_config, &waklog_module);
288 }
289
3ed1e28a 290 if ( cfg->keytab != NULL ) {
4e1ae1cd 291 ap_log_error( APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r->server,
292 "mod_waklog: keytab is configured: %s", cfg->keytab );
293
4e1ae1cd 294 /* authenticate using keytab file */
3ed1e28a 295 waklog_ktinit( r );
4e1ae1cd 296
297 return OK;
3ed1e28a 298 } else {
299 ap_log_error( APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r->server,
300 "mod_waklog: keytab is not configured" );
301 }
302
303 if ( !cfg->protect ) {
304 return( DECLINED );
4e1ae1cd 305 }
306
bed98ff9 307 if (( rc = krb_get_cred( "afs", "", urealm, &cr )) != KSUCCESS ) {
308 ap_log_error( APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r->server,
313dde40 309 "mod_waklog: krb_get_cred: %s", krb_err_txt[ rc ] );
1e18ef7d 310
311 if (( rc = get_ad_tkt( "afs", "", urealm, 255 )) != KSUCCESS ) {
312 ap_log_error( APLOG_MARK, APLOG_NOERRNO|APLOG_DEBUG, r->server,
313 "mod_waklog: get_ad_tkt: %s", krb_err_txt[ rc ] );
314
4e1ae1cd 315 /* fail here or just let AFS deny permission? */
1e18ef7d 316
317 return OK;
318 }
319
320 if (( rc = krb_get_cred( "afs", "", urealm, &cr )) != KSUCCESS ) {
321 ap_log_error( APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r->server,
322 "mod_waklog: krb_get_cred: %s", krb_err_txt[ rc ] );
323 return OK;
324 }
bed98ff9 325 }
326
b429ae96 327 ap_log_error( APLOG_MARK, APLOG_NOERRNO|APLOG_DEBUG, r->server,
313dde40 328 "mod_waklog: %s.%s@%s", cr.service, cr.instance, cr.realm );
b429ae96 329 ap_log_error( APLOG_MARK, APLOG_NOERRNO|APLOG_DEBUG, r->server,
313dde40 330 "mod_waklog: %d %d %d", cr.lifetime, cr.kvno, cr.issue_date );
b429ae96 331 ap_log_error( APLOG_MARK, APLOG_NOERRNO|APLOG_DEBUG, r->server,
313dde40 332 "mod_waklog: %s %s", cr.pname, cr.pinst );
b429ae96 333 ap_log_error( APLOG_MARK, APLOG_NOERRNO|APLOG_DEBUG, r->server,
313dde40 334 "mod_waklog: %d", cr.ticket_st.length );
bed98ff9 335
336 s = buf;
337 memmove( s, &cr.ticket_st.length, sizeof( int ));
338 s += sizeof( int );
339 memmove( s, cr.ticket_st.dat, cr.ticket_st.length );
340 s += cr.ticket_st.length;
341
342 ct.AuthHandle = cr.kvno;
343 memmove( ct.HandShakeKey, cr.session, sizeof( cr.session ));
344 ct.ViceId = 0;
345 ct.BeginTimestamp = cr.issue_date;
346 ct.EndTimestamp = krb_life_to_time( cr.issue_date, cr.lifetime );
347
348 i = sizeof( struct ClearToken );
349 memmove( s, &i, sizeof( int ));
350 s += sizeof( int );
351 memmove( s, &ct, sizeof( struct ClearToken ));
352 s += sizeof( struct ClearToken );
353
354 i = 0;
355 memmove( s, &i, sizeof( int ));
356 s += sizeof( int );
357
358 strcpy( s, lrealm );
359 s += strlen( lrealm ) + 1;
360
361 vi.in = buf;
362 vi.in_size = s - buf;
363 vi.out = buf;
364 vi.out_size = sizeof( buf );
365
366 if ( pioctl( 0, VIOCSETTOK, &vi, 0 ) < 0 ) {
367 ap_log_error( APLOG_MARK, APLOG_ERR, r->server,
313dde40 368 "mod_waklog: pioctl failed" );
bed98ff9 369 }
370
371 /* we'll need to unlog when this connection is done. */
372 ap_register_cleanup( r->pool, (void *)r, pioctl_cleanup, ap_null_cleanup );
373
1e18ef7d 374 ap_log_error( APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, r->server,
375 "mod_waklog: finished with get_token" );
bed98ff9 376
377 return OK;
378}
379
380
313dde40 381module MODULE_VAR_EXPORT waklog_module = {
bed98ff9 382 STANDARD_MODULE_STUFF,
313dde40 383 waklog_init, /* module initializer */
384 waklog_create_dir_config, /* create per-dir config structures */
bed98ff9 385 NULL, /* merge per-dir config structures */
313dde40 386 waklog_create_server_config, /* create per-server config structures */
bed98ff9 387 NULL, /* merge per-server config structures */
313dde40 388 waklog_cmds, /* table of config file commands */
bed98ff9 389 NULL, /* [#8] MIME-typed-dispatched handlers */
390 NULL, /* [#1] URI to filename translation */
391 NULL, /* [#4] validate user id from request */
392 NULL, /* [#5] check if the user is ok _here_ */
393 NULL, /* [#3] check access by host address */
394 NULL, /* [#6] determine MIME type */
313dde40 395 waklog_get_tokens, /* [#7] pre-run fixups */
bed98ff9 396 NULL, /* [#9] log a transaction */
313dde40 397 NULL, /* [#2] header parser */
398 waklog_child_init, /* child_init */
bed98ff9 399 NULL, /* child_exit */
400 NULL /* [#0] post read-request */
401#ifdef EAPI
402 ,NULL, /* EAPI: add_module */
403 NULL, /* EAPI: remove_module */
404 NULL, /* EAPI: rewrite_command */
405 NULL /* EAPI: new_connection */
406#endif
407};