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 */