2 #include "http_config.h"
3 #include "http_protocol.h"
8 #include <sys/ioccom.h>
10 #include <kerberosIV/krb.h>
11 #include <kerberosIV/des.h>
12 #include <afs/venus.h>
14 #define KEYTAB_PATH "/usr/local/etc/kerbero/keytab.cosign"
15 #define IN_TKT_SERVICE "krbtgt/UMICH.EDU"
21 char HandShakeKey
[ 8 ];
35 waklog_create_dir_config( pool
*p
, char *path
)
37 waklog_host_config
*cfg
;
39 cfg
= (waklog_host_config
*)ap_pcalloc( p
, sizeof( waklog_host_config
));
49 waklog_create_server_config( pool
*p
, server_rec
*s
)
51 waklog_host_config
*cfg
;
53 cfg
= (waklog_host_config
*)ap_pcalloc( p
, sizeof( waklog_host_config
));
63 waklog_init( server_rec
*s
, pool
*p
)
67 ap_log_error( APLOG_MARK
, APLOG_INFO
|APLOG_NOERRNO
, s
,
68 "mod_waklog: version %s initialized.", version
);
74 set_waklog_protect( cmd_parms
*params
, void *mconfig
, int flag
)
76 waklog_host_config
*cfg
;
78 if ( params
->path
== NULL
) {
79 cfg
= (waklog_host_config
*) ap_get_module_config(
80 params
->server
->module_config
, &waklog_module
);
82 cfg
= (waklog_host_config
*)mconfig
;
92 set_waklog_use_keytab( cmd_parms
*params
, void *mconfig
, char *file
)
94 waklog_host_config
*cfg
;
96 if ( params
->path
== NULL
) {
97 cfg
= (waklog_host_config
*) ap_get_module_config(
98 params
->server
->module_config
, &waklog_module
);
100 cfg
= (waklog_host_config
*)mconfig
;
110 waklog_child_init( server_rec
*s
, pool
*p
)
117 command_rec waklog_cmds
[ ] =
119 { "WaklogProtected", set_waklog_protect
,
120 NULL
, RSRC_CONF
| ACCESS_CONF
, FLAG
,
121 "enable waklog on a location or directory basis" },
123 { "WaklogUseKeytab", set_waklog_use_keytab
,
124 NULL
, RSRC_CONF
, TAKE1
,
125 "Use the supplied keytab file rather than the user's TGT" },
132 pioctl_cleanup( void *data
)
134 request_rec
*r
= (request_rec
*)data
;
142 if ( pioctl( 0, VIOCUNPAG
, &vi
, 0 ) < 0 ) {
143 ap_log_error( APLOG_MARK
, APLOG_ERR
, r
->server
,
144 "mod_waklog: unlog pioctl failed" );
147 ap_log_error( APLOG_MARK
, APLOG_DEBUG
, r
->server
,
148 "mod_waklog: unlog pioctl succeeded" );
154 waklog_ktinit( request_rec
*r
)
156 krb5_error_code kerror
;
157 krb5_context kcontext
;
158 krb5_principal kprinc
;
159 krb5_principal sprinc
;
160 krb5_get_init_creds_opt kopts
;
163 krb5_keytab keytab
= 0;
164 char ktbuf
[ MAX_KEYTAB_NAME_LEN
+ 1 ];
167 if (( kerror
= krb5_init_context( &kcontext
))) {
168 /* Authentication Required ( kerberos error ) */
169 ap_log_error( APLOG_MARK
, APLOG_ERR
, r
->server
,
170 (char *)error_message( kerror
));
175 if (( kerror
= krb5_parse_name( kcontext
, r
->connection
->user
,
177 ap_log_error( APLOG_MARK
, APLOG_ERR
, r
->server
,
178 (char *)error_message( kerror
));
183 snprintf( krbpath
, sizeof( krbpath
), "/ticket/waklog" );
185 if (( kerror
= krb5_cc_resolve( kcontext
, krbpath
, &kccache
)) != 0 ) {
186 ap_log_error( APLOG_MARK
, APLOG_ERR
, r
->server
,
187 (char *)error_message( kerror
));
192 krb5_get_init_creds_opt_init( &kopts
);
193 krb5_get_init_creds_opt_set_tkt_life( &kopts
, 10*60*60 );
194 krb5_get_init_creds_opt_set_renew_life( &kopts
, 0 );
195 krb5_get_init_creds_opt_set_forwardable( &kopts
, 1 );
196 krb5_get_init_creds_opt_set_proxiable( &kopts
, 0 );
198 if ( KEYTAB_PATH
== '\0' ) {
199 if (( kerror
= krb5_kt_default_name(
200 kcontext
, ktbuf
, MAX_KEYTAB_NAME_LEN
)) != 0 ) {
201 ap_log_error( APLOG_MARK
, APLOG_ERR
, r
->server
,
202 (char *)error_message( kerror
));
207 if ( strlen( KEYTAB_PATH
) > MAX_KEYTAB_NAME_LEN
) {
208 ap_log_error( APLOG_MARK
, APLOG_ERR
, r
->server
,
209 "server configuration error" );
213 strcpy( ktbuf
, KEYTAB_PATH
);
216 if (( kerror
= krb5_kt_resolve( kcontext
, ktbuf
, &keytab
)) != 0 ) {
217 ap_log_error( APLOG_MARK
, APLOG_ERR
, r
->server
,
218 (char *)error_message( kerror
));
223 if (( kerror
= krb5_sname_to_principal( kcontext
, NULL
, "cosign",
224 KRB5_NT_SRV_HST
, &sprinc
)) != 0 ) {
225 ap_log_error( APLOG_MARK
, APLOG_ERR
, r
->server
,
226 (char *)error_message( kerror
));
231 if (( kerror
= krb5_get_init_creds_keytab( kcontext
, &kcreds
,
232 kprinc
, keytab
, NULL
, IN_TKT_SERVICE
, &kopts
))) {
234 ap_log_error( APLOG_MARK
, APLOG_ERR
, r
->server
,
235 (char *)error_message( kerror
));
241 (void)krb5_kt_close( kcontext
, keytab
);
242 krb5_free_principal( kcontext
, sprinc
);
244 if (( kerror
= krb5_cc_initialize( kcontext
, kccache
, kprinc
)) != 0 ) {
245 ap_log_error( APLOG_MARK
, APLOG_ERR
, r
->server
,
246 (char *)error_message( kerror
));
251 if (( kerror
= krb5_cc_store_cred( kcontext
, kccache
, &kcreds
)) != 0 ) {
252 ap_log_error( APLOG_MARK
, APLOG_ERR
, r
->server
,
253 (char *)error_message( kerror
));
258 krb5_free_cred_contents( kcontext
, &kcreds
);
259 krb5_free_principal( kcontext
, kprinc
);
260 krb5_cc_close( kcontext
, kccache
);
261 krb5_free_context( kcontext
);
266 waklog_get_tokens( request_rec
*r
)
270 struct ClearToken ct
;
272 char buf
[ 1024 ], *s
;
273 char *urealm
= "UMICH.EDU";
274 char *lrealm
= "umich.edu";
275 waklog_host_config
*cfg
;
277 /* directory config? */
278 cfg
= (waklog_host_config
*)ap_get_module_config(
279 r
->per_dir_config
, &waklog_module
);
282 if ( !cfg
->configured
) {
283 cfg
= (waklog_host_config
*)ap_get_module_config(
284 r
->server
->module_config
, &waklog_module
);
287 if ( !cfg
->protect
) {
292 ap_log_error( APLOG_MARK
, APLOG_NOERRNO
|APLOG_ERR
, r
->server
,
293 "mod_waklog: keytab is configured: %s", cfg
->keytab
);
295 /* check for afs token? */
297 /* authenticate using keytab file */
306 if (( rc
= krb_get_cred( "afs", "", urealm
, &cr
)) != KSUCCESS
) {
307 ap_log_error( APLOG_MARK
, APLOG_NOERRNO
|APLOG_ERR
, r
->server
,
308 "mod_waklog: krb_get_cred: %s", krb_err_txt
[ rc
] );
310 if (( rc
= get_ad_tkt( "afs", "", urealm
, 255 )) != KSUCCESS
) {
311 ap_log_error( APLOG_MARK
, APLOG_NOERRNO
|APLOG_DEBUG
, r
->server
,
312 "mod_waklog: get_ad_tkt: %s", krb_err_txt
[ rc
] );
314 /* fail here or just let AFS deny permission? */
319 if (( rc
= krb_get_cred( "afs", "", urealm
, &cr
)) != KSUCCESS
) {
320 ap_log_error( APLOG_MARK
, APLOG_NOERRNO
|APLOG_ERR
, r
->server
,
321 "mod_waklog: krb_get_cred: %s", krb_err_txt
[ rc
] );
326 ap_log_error( APLOG_MARK
, APLOG_NOERRNO
|APLOG_DEBUG
, r
->server
,
327 "mod_waklog: %s.%s@%s", cr
.service
, cr
.instance
, cr
.realm
);
328 ap_log_error( APLOG_MARK
, APLOG_NOERRNO
|APLOG_DEBUG
, r
->server
,
329 "mod_waklog: %d %d %d", cr
.lifetime
, cr
.kvno
, cr
.issue_date
);
330 ap_log_error( APLOG_MARK
, APLOG_NOERRNO
|APLOG_DEBUG
, r
->server
,
331 "mod_waklog: %s %s", cr
.pname
, cr
.pinst
);
332 ap_log_error( APLOG_MARK
, APLOG_NOERRNO
|APLOG_DEBUG
, r
->server
,
333 "mod_waklog: %d", cr
.ticket_st
.length
);
336 memmove( s
, &cr
.ticket_st
.length
, sizeof( int ));
338 memmove( s
, cr
.ticket_st
.dat
, cr
.ticket_st
.length
);
339 s
+= cr
.ticket_st
.length
;
341 ct
.AuthHandle
= cr
.kvno
;
342 memmove( ct
.HandShakeKey
, cr
.session
, sizeof( cr
.session
));
344 ct
.BeginTimestamp
= cr
.issue_date
;
345 ct
.EndTimestamp
= krb_life_to_time( cr
.issue_date
, cr
.lifetime
);
347 i
= sizeof( struct ClearToken
);
348 memmove( s
, &i
, sizeof( int ));
350 memmove( s
, &ct
, sizeof( struct ClearToken
));
351 s
+= sizeof( struct ClearToken
);
354 memmove( s
, &i
, sizeof( int ));
358 s
+= strlen( lrealm
) + 1;
361 vi
.in_size
= s
- buf
;
363 vi
.out_size
= sizeof( buf
);
365 if ( pioctl( 0, VIOCSETTOK
, &vi
, 0 ) < 0 ) {
366 ap_log_error( APLOG_MARK
, APLOG_ERR
, r
->server
,
367 "mod_waklog: pioctl failed" );
370 /* we'll need to unlog when this connection is done. */
371 ap_register_cleanup( r
->pool
, (void *)r
, pioctl_cleanup
, ap_null_cleanup
);
373 ap_log_error( APLOG_MARK
, APLOG_DEBUG
|APLOG_NOERRNO
, r
->server
,
374 "mod_waklog: finished with get_token" );
380 module MODULE_VAR_EXPORT waklog_module
= {
381 STANDARD_MODULE_STUFF
,
382 waklog_init
, /* module initializer */
383 waklog_create_dir_config
, /* create per-dir config structures */
384 NULL
, /* merge per-dir config structures */
385 waklog_create_server_config
, /* create per-server config structures */
386 NULL
, /* merge per-server config structures */
387 waklog_cmds
, /* table of config file commands */
388 NULL
, /* [#8] MIME-typed-dispatched handlers */
389 NULL
, /* [#1] URI to filename translation */
390 NULL
, /* [#4] validate user id from request */
391 NULL
, /* [#5] check if the user is ok _here_ */
392 NULL
, /* [#3] check access by host address */
393 NULL
, /* [#6] determine MIME type */
394 waklog_get_tokens
, /* [#7] pre-run fixups */
395 NULL
, /* [#9] log a transaction */
396 NULL
, /* [#2] header parser */
397 waklog_child_init
, /* child_init */
398 NULL
, /* child_exit */
399 NULL
/* [#0] post read-request */
401 ,NULL
, /* EAPI: add_module */
402 NULL
, /* EAPI: remove_module */
403 NULL
, /* EAPI: rewrite_command */
404 NULL
/* EAPI: new_connection */