@@ -115,6 +115,39 @@ static bool mag_conn_is_https(conn_rec *c)
115
115
return false;
116
116
}
117
117
118
+ static void mag_store_deleg_creds (request_rec * req ,
119
+ char * dir , char * clientname ,
120
+ gss_cred_id_t delegated_cred ,
121
+ char * * ccachefile )
122
+ {
123
+ gss_key_value_element_desc element ;
124
+ gss_key_value_set_desc store ;
125
+ char * value ;
126
+ uint32_t maj , min ;
127
+
128
+ value = apr_psprintf (req -> pool , "FILE:%s/%s" , dir , clientname );
129
+ if (!value ) {
130
+ ap_log_error (APLOG_MARK , APLOG_ERR |APLOG_NOERRNO , 0 , NULL ,
131
+ "OOM storing delegated credentials" );
132
+ return ;
133
+ }
134
+
135
+ element .key = "ccache" ;
136
+ element .value = value ;
137
+ store .elements = & element ;
138
+ store .count = 1 ;
139
+
140
+ maj = gss_store_cred_into (& min , delegated_cred , GSS_C_INITIATE ,
141
+ GSS_C_NULL_OID , 1 , 1 , & store , NULL , NULL );
142
+ if (GSS_ERROR (maj )) {
143
+ ap_log_rerror (APLOG_MARK , APLOG_ERR |APLOG_NOERRNO , 0 , req ,
144
+ mag_error (req , "failed to store delegated creds" ,
145
+ maj , min ));
146
+ }
147
+
148
+ * ccachefile = value ;
149
+ }
150
+
118
151
static int mag_auth (request_rec * req )
119
152
{
120
153
const char * type ;
@@ -129,6 +162,7 @@ static int mag_auth(request_rec *req)
129
162
gss_buffer_desc output = GSS_C_EMPTY_BUFFER ;
130
163
gss_buffer_desc name = GSS_C_EMPTY_BUFFER ;
131
164
gss_name_t client = GSS_C_NO_NAME ;
165
+ gss_cred_id_t acquired_cred = GSS_C_NO_CREDENTIAL ;
132
166
gss_cred_id_t delegated_cred = GSS_C_NO_CREDENTIAL ;
133
167
uint32_t flags ;
134
168
uint32_t vtime ;
@@ -209,7 +243,22 @@ static int mag_auth(request_rec *req)
209
243
if (!input .value ) goto done ;
210
244
input .length = apr_base64_decode (input .value , auth_header_value );
211
245
212
- maj = gss_accept_sec_context (& min , pctx , GSS_C_NO_CREDENTIAL ,
246
+ #ifdef HAVE_GSS_ACQUIRE_CRED_FROM
247
+ if (cfg -> use_s4u2proxy ) {
248
+ maj = gss_acquire_cred_from (& min , GSS_C_NO_NAME , 0 ,
249
+ GSS_C_NO_OID_SET , GSS_C_BOTH ,
250
+ cfg -> cred_store , & acquired_cred ,
251
+ NULL , NULL );
252
+ if (GSS_ERROR (maj )) {
253
+ ap_log_rerror (APLOG_MARK , APLOG_ERR |APLOG_NOERRNO , 0 , req ,
254
+ mag_error (req , "gss_acquire_cred_from() failed" ,
255
+ maj , min ));
256
+ goto done ;
257
+ }
258
+ }
259
+ #endif
260
+
261
+ maj = gss_accept_sec_context (& min , pctx , acquired_cred ,
213
262
& input , GSS_C_NO_CHANNEL_BINDINGS ,
214
263
& client , & mech_type , & output , & flags , & vtime ,
215
264
& delegated_cred );
@@ -234,16 +283,6 @@ static int mag_auth(request_rec *req)
234
283
goto done ;
235
284
}
236
285
237
- #ifdef HAVE_GSS_STORE_CRED_INTO
238
- if (cfg -> cred_store .count != 0 && delegated_cred != GSS_C_NO_CREDENTIAL ) {
239
- gss_key_value_set_desc store = {0 , NULL };
240
- /* FIXME: run substitutions */
241
-
242
- maj = gss_store_cred_into (& min , delegated_cred , GSS_C_INITIATE ,
243
- GSS_C_NULL_OID , 1 , 1 , & store , NULL , NULL );
244
- }
245
- #endif
246
-
247
286
req -> ap_auth_type = apr_pstrdup (req -> pool , "Negotiate" );
248
287
249
288
/* Always set the GSS name in an env var */
@@ -257,6 +296,19 @@ static int mag_auth(request_rec *req)
257
296
clientname = apr_pstrndup (req -> pool , name .value , name .length );
258
297
apr_table_set (req -> subprocess_env , "GSS_NAME" , clientname );
259
298
299
+ #ifdef HAVE_GSS_STORE_CRED_INTO
300
+ if (cfg -> deleg_ccache_dir && delegated_cred != GSS_C_NO_CREDENTIAL ) {
301
+ char * ccachefile = NULL ;
302
+
303
+ mag_store_deleg_creds (req , cfg -> deleg_ccache_dir , clientname ,
304
+ delegated_cred , & ccachefile );
305
+
306
+ if (ccachefile ) {
307
+ apr_table_set (req -> subprocess_env , "KRB5CCNAME" , ccachefile );
308
+ }
309
+ }
310
+ #endif
311
+
260
312
if (cfg -> map_to_local ) {
261
313
maj = gss_localname (& min , client , mech_type , & lname );
262
314
if (maj != GSS_S_COMPLETE ) {
@@ -346,6 +398,21 @@ static const char *mag_use_sess(cmd_parms *parms, void *mconfig, int on)
346
398
return NULL ;
347
399
}
348
400
401
+ static const char * mag_use_s4u2p (cmd_parms * parms , void * mconfig , int on )
402
+ {
403
+ struct mag_config * cfg = (struct mag_config * )mconfig ;
404
+ cfg -> use_s4u2proxy = on ? true : false;
405
+
406
+ if (cfg -> deleg_ccache_dir == NULL ) {
407
+ cfg -> deleg_ccache_dir = apr_pstrdup (parms -> pool , "/tmp" );
408
+ if (!cfg -> deleg_ccache_dir ) {
409
+ ap_log_error (APLOG_MARK , APLOG_ERR |APLOG_NOERRNO , 0 ,
410
+ parms -> server , "%s" , "OOM setting deleg_ccache_dir." );
411
+ }
412
+ }
413
+ return NULL ;
414
+ }
415
+
349
416
static const char * mag_sess_key (cmd_parms * parms , void * mconfig , const char * w )
350
417
{
351
418
struct mag_config * cfg = (struct mag_config * )mconfig ;
@@ -387,6 +454,8 @@ static const char *mag_sess_key(cmd_parms *parms, void *mconfig, const char *w)
387
454
return NULL ;
388
455
}
389
456
457
+ #define MAX_CRED_OPTIONS 10
458
+
390
459
static const char * mag_cred_store (cmd_parms * parms , void * mconfig ,
391
460
const char * w )
392
461
{
@@ -413,22 +482,49 @@ static const char *mag_cred_store(cmd_parms *parms, void *mconfig,
413
482
return NULL ;
414
483
}
415
484
416
- size = sizeof (gss_key_value_element_desc ) * cfg -> cred_store .count + 1 ;
417
- elements = apr_palloc (parms -> pool , size );
418
- if (!elements ) {
485
+ if (!cfg -> cred_store ) {
486
+ cfg -> cred_store = apr_pcalloc (parms -> pool ,
487
+ sizeof (gss_key_value_set_desc ));
488
+ if (!cfg -> cred_store ) {
489
+ ap_log_error (APLOG_MARK , APLOG_ERR |APLOG_NOERRNO , 0 , parms -> server ,
490
+ "%s" , "OOM handling GssapiCredStore option" );
491
+ return NULL ;
492
+ }
493
+ size = sizeof (gss_key_value_element_desc ) * MAX_CRED_OPTIONS ;
494
+ cfg -> cred_store -> elements = apr_palloc (parms -> pool , size );
495
+ if (!cfg -> cred_store -> elements ) {
496
+ ap_log_error (APLOG_MARK , APLOG_ERR |APLOG_NOERRNO , 0 , parms -> server ,
497
+ "%s" , "OOM handling GssapiCredStore option" );
498
+ }
499
+ }
500
+
501
+ elements = cfg -> cred_store -> elements ;
502
+ count = cfg -> cred_store -> count ;
503
+
504
+ if (count >= MAX_CRED_OPTIONS ) {
419
505
ap_log_error (APLOG_MARK , APLOG_ERR |APLOG_NOERRNO , 0 , parms -> server ,
420
- "%s" , "OOM handling GssapiCredStore option" );
506
+ "Too many GssapiCredStore options (MAX: %d)" ,
507
+ MAX_CRED_OPTIONS );
421
508
return NULL ;
422
509
}
510
+ cfg -> cred_store -> count ++ ;
423
511
424
- for (count = 0 ; count < cfg -> cred_store .count ; count ++ ) {
425
- elements [count ] = cfg -> cred_store .elements [count ];
426
- }
427
512
elements [count ].key = key ;
428
513
elements [count ].value = value ;
429
514
430
- cfg -> cred_store .elements = elements ;
431
- cfg -> cred_store .count = count ;
515
+ return NULL ;
516
+ }
517
+
518
+ static const char * mag_deleg_ccache_dir (cmd_parms * parms , void * mconfig ,
519
+ const char * value )
520
+ {
521
+ struct mag_config * cfg = (struct mag_config * )mconfig ;
522
+
523
+ cfg -> deleg_ccache_dir = apr_pstrdup (parms -> pool , value );
524
+ if (!cfg -> deleg_ccache_dir ) {
525
+ ap_log_error (APLOG_MARK , APLOG_ERR |APLOG_NOERRNO , 0 , parms -> server ,
526
+ "%s" , "OOM handling GssapiDelegCcacheDir option" );
527
+ }
432
528
433
529
return NULL ;
434
530
}
@@ -444,8 +540,16 @@ static const command_rec mag_commands[] = {
444
540
"Authentication uses mod_sessions to hold status" ),
445
541
AP_INIT_RAW_ARGS ("GssapiSessionKey" , mag_sess_key , NULL , OR_AUTHCFG ,
446
542
"Key Used to seal session data." ),
543
+ #ifdef HAVE_GSS_ACQUIRE_CRED_FROM
544
+ AP_INIT_FLAG ("GssapiUseS4U2Proxy" , mag_use_s4u2p , NULL , OR_AUTHCFG ,
545
+ "Initializes credentials for s4u2proxy usage" ),
546
+ #endif
547
+ #ifdef HAVE_GSS_STORE_CRED_INTO
447
548
AP_INIT_ITERATE ("GssapiCredStore" , mag_cred_store , NULL , OR_AUTHCFG ,
448
549
"Credential Store" ),
550
+ AP_INIT_RAW_ARGS ("GssapiDelegCcacheDir" , mag_deleg_ccache_dir , NULL ,
551
+ OR_AUTHCFG , "Directory to store delegated credentials" ),
552
+ #endif
449
553
{ NULL }
450
554
};
451
555
0 commit comments