@@ -115,6 +115,39 @@ static bool mag_conn_is_https(conn_rec *c)
115115 return false;
116116}
117117
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+
118151static int mag_auth (request_rec * req )
119152{
120153 const char * type ;
@@ -129,6 +162,7 @@ static int mag_auth(request_rec *req)
129162 gss_buffer_desc output = GSS_C_EMPTY_BUFFER ;
130163 gss_buffer_desc name = GSS_C_EMPTY_BUFFER ;
131164 gss_name_t client = GSS_C_NO_NAME ;
165+ gss_cred_id_t acquired_cred = GSS_C_NO_CREDENTIAL ;
132166 gss_cred_id_t delegated_cred = GSS_C_NO_CREDENTIAL ;
133167 uint32_t flags ;
134168 uint32_t vtime ;
@@ -209,7 +243,22 @@ static int mag_auth(request_rec *req)
209243 if (!input .value ) goto done ;
210244 input .length = apr_base64_decode (input .value , auth_header_value );
211245
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 ,
213262 & input , GSS_C_NO_CHANNEL_BINDINGS ,
214263 & client , & mech_type , & output , & flags , & vtime ,
215264 & delegated_cred );
@@ -234,16 +283,6 @@ static int mag_auth(request_rec *req)
234283 goto done ;
235284 }
236285
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-
247286 req -> ap_auth_type = apr_pstrdup (req -> pool , "Negotiate" );
248287
249288 /* Always set the GSS name in an env var */
@@ -257,6 +296,19 @@ static int mag_auth(request_rec *req)
257296 clientname = apr_pstrndup (req -> pool , name .value , name .length );
258297 apr_table_set (req -> subprocess_env , "GSS_NAME" , clientname );
259298
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+
260312 if (cfg -> map_to_local ) {
261313 maj = gss_localname (& min , client , mech_type , & lname );
262314 if (maj != GSS_S_COMPLETE ) {
@@ -346,6 +398,21 @@ static const char *mag_use_sess(cmd_parms *parms, void *mconfig, int on)
346398 return NULL ;
347399}
348400
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+
349416static const char * mag_sess_key (cmd_parms * parms , void * mconfig , const char * w )
350417{
351418 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)
387454 return NULL ;
388455}
389456
457+ #define MAX_CRED_OPTIONS 10
458+
390459static const char * mag_cred_store (cmd_parms * parms , void * mconfig ,
391460 const char * w )
392461{
@@ -413,22 +482,49 @@ static const char *mag_cred_store(cmd_parms *parms, void *mconfig,
413482 return NULL ;
414483 }
415484
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 ) {
419505 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 );
421508 return NULL ;
422509 }
510+ cfg -> cred_store -> count ++ ;
423511
424- for (count = 0 ; count < cfg -> cred_store .count ; count ++ ) {
425- elements [count ] = cfg -> cred_store .elements [count ];
426- }
427512 elements [count ].key = key ;
428513 elements [count ].value = value ;
429514
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+ }
432528
433529 return NULL ;
434530}
@@ -444,8 +540,16 @@ static const command_rec mag_commands[] = {
444540 "Authentication uses mod_sessions to hold status" ),
445541 AP_INIT_RAW_ARGS ("GssapiSessionKey" , mag_sess_key , NULL , OR_AUTHCFG ,
446542 "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
447548 AP_INIT_ITERATE ("GssapiCredStore" , mag_cred_store , NULL , OR_AUTHCFG ,
448549 "Credential Store" ),
550+ AP_INIT_RAW_ARGS ("GssapiDelegCcacheDir" , mag_deleg_ccache_dir , NULL ,
551+ OR_AUTHCFG , "Directory to store delegated credentials" ),
552+ #endif
449553 { NULL }
450554};
451555
0 commit comments