@@ -332,6 +332,158 @@ static void mag_set_req_data(request_rec *req,
332332 }
333333}
334334
335+ static bool mag_auth_basic (request_rec * req ,
336+ struct mag_config * cfg ,
337+ gss_buffer_desc ba_user ,
338+ gss_buffer_desc ba_pwd ,
339+ gss_cred_id_t acquired_cred ,
340+ gss_cred_usage_t cred_usage ,
341+ gss_name_t * client ,
342+ gss_OID * mech_type ,
343+ gss_cred_id_t * delegated_cred ,
344+ uint32_t * vtime )
345+ {
346+ #ifdef HAVE_GSS_KRB5_CCACHE_NAME
347+ const char * user_ccache = NULL ;
348+ const char * orig_ccache = NULL ;
349+ long long unsigned int rndname ;
350+ apr_status_t rs ;
351+ #endif
352+ gss_name_t user = GSS_C_NO_NAME ;
353+ gss_cred_id_t user_cred = GSS_C_NO_CREDENTIAL ;
354+ gss_ctx_id_t user_ctx = GSS_C_NO_CONTEXT ;
355+ gss_name_t server = GSS_C_NO_NAME ;
356+ gss_cred_id_t server_cred = GSS_C_NO_CREDENTIAL ;
357+ gss_ctx_id_t server_ctx = GSS_C_NO_CONTEXT ;
358+ gss_buffer_desc input = GSS_C_EMPTY_BUFFER ;
359+ gss_buffer_desc output = GSS_C_EMPTY_BUFFER ;
360+ uint32_t init_flags = 0 ;
361+ uint32_t maj , min ;
362+ bool ret = false;
363+
364+ #ifdef HAVE_GSS_KRB5_CCACHE_NAME
365+ rs = apr_generate_random_bytes ((unsigned char * )(& rndname ),
366+ sizeof (long long unsigned int ));
367+ if (rs != APR_SUCCESS ) {
368+ ap_log_rerror (APLOG_MARK , APLOG_ERR , 0 , req ,
369+ "Failed to generate random ccache name" );
370+ goto done ;
371+ }
372+ user_ccache = apr_psprintf (req -> pool , "MEMORY:user_%qu" , rndname );
373+ maj = gss_krb5_ccache_name (& min , user_ccache , & orig_ccache );
374+ if (GSS_ERROR (maj )) {
375+ ap_log_rerror (APLOG_MARK , APLOG_ERR , 0 , req ,
376+ "In Basic Auth, %s" ,
377+ mag_error (req , "gss_krb5_ccache_name() "
378+ "failed" , maj , min ));
379+ goto done ;
380+ }
381+ #endif
382+
383+ maj = gss_import_name (& min , & ba_user , GSS_C_NT_USER_NAME , & user );
384+ if (GSS_ERROR (maj )) {
385+ ap_log_rerror (APLOG_MARK , APLOG_ERR , 0 , req ,
386+ "In Basic Auth, %s" ,
387+ mag_error (req , "gss_import_name() failed" ,
388+ maj , min ));
389+ goto done ;
390+ }
391+
392+ maj = gss_acquire_cred_with_password (& min , user , & ba_pwd ,
393+ GSS_C_INDEFINITE ,
394+ cfg -> allowed_mechs ,
395+ GSS_C_INITIATE ,
396+ & user_cred , NULL , NULL );
397+ if (GSS_ERROR (maj )) {
398+ ap_log_rerror (APLOG_MARK , APLOG_ERR , 0 , req ,
399+ "In Basic Auth, %s" ,
400+ mag_error (req , "gss_acquire_cred_with_password() "
401+ "failed" , maj , min ));
402+ goto done ;
403+ }
404+
405+ if (cred_usage == GSS_C_BOTH ) {
406+ /* If GSS_C_BOTH is used then inquire_cred will return the client
407+ * name instead of the SPN of the server credentials. Therefore we
408+ * need to acquire a different set of credential setting
409+ * GSS_C_ACCEPT explicitly */
410+ if (!mag_acquire_creds (req , cfg , cfg -> allowed_mechs ,
411+ GSS_C_ACCEPT , & server_cred , NULL )) {
412+ goto done ;
413+ }
414+ } else {
415+ server_cred = acquired_cred ;
416+ }
417+ maj = gss_inquire_cred (& min , server_cred , & server ,
418+ NULL , NULL , NULL );
419+ if (GSS_ERROR (maj )) {
420+ ap_log_rerror (APLOG_MARK , APLOG_ERR , 0 , req ,
421+ "%s" , mag_error (req , "gss_inquired_cred_() "
422+ "failed" , maj , min ));
423+ goto done ;
424+ }
425+
426+ #ifdef HAVE_CRED_STORE
427+ if (cfg -> deleg_ccache_dir ) {
428+ /* delegate ourselves credentials so we store them as requested */
429+ init_flags |= GSS_C_DELEG_FLAG ;
430+ }
431+ #endif
432+
433+ do {
434+ /* output and input are inverted here, this is intentional */
435+ maj = gss_init_sec_context (& min , user_cred , & user_ctx , server ,
436+ GSS_C_NO_OID , init_flags , 300 ,
437+ GSS_C_NO_CHANNEL_BINDINGS , & output ,
438+ NULL , & input , NULL , NULL );
439+ if (GSS_ERROR (maj )) {
440+ ap_log_rerror (APLOG_MARK , APLOG_ERR , 0 , req ,
441+ "%s" , mag_error (req , "gss_init_sec_context() "
442+ "failed" , maj , min ));
443+ goto done ;
444+ }
445+ gss_release_buffer (& min , & output );
446+ maj = gss_accept_sec_context (& min , & server_ctx , acquired_cred ,
447+ & input , GSS_C_NO_CHANNEL_BINDINGS ,
448+ client , mech_type , & output , NULL ,
449+ vtime , delegated_cred );
450+ if (GSS_ERROR (maj )) {
451+ ap_log_rerror (APLOG_MARK , APLOG_ERR , 0 , req ,
452+ "%s" , mag_error (req , "gss_accept_sec_context()"
453+ " failed" , maj , min ));
454+ goto done ;
455+ }
456+ gss_release_buffer (& min , & input );
457+ } while (maj == GSS_S_CONTINUE_NEEDED );
458+
459+ ret = true;
460+
461+ done :
462+ gss_release_buffer (& min , & output );
463+ gss_release_buffer (& min , & input );
464+ gss_release_name (& min , & server );
465+ if (server_cred != acquired_cred ) {
466+ gss_release_cred (& min , & server_cred );
467+ }
468+ gss_delete_sec_context (& min , & server_ctx , GSS_C_NO_BUFFER );
469+ gss_release_name (& min , & user );
470+ gss_release_cred (& min , & user_cred );
471+ gss_delete_sec_context (& min , & user_ctx , GSS_C_NO_BUFFER );
472+ #ifdef HAVE_GSS_KRB5_CCACHE_NAME
473+ if (user_ccache != NULL ) {
474+ maj = gss_krb5_ccache_name (& min , orig_ccache , NULL );
475+ if (maj != GSS_S_COMPLETE ) {
476+ ap_log_rerror (APLOG_MARK , APLOG_ERR , 0 , req ,
477+ "Failed to restore per-thread ccache, %s" ,
478+ mag_error (req , "gss_krb5_ccache_name() "
479+ "failed" , maj , min ));
480+ }
481+ }
482+ #endif
483+ return ret ;
484+ }
485+
486+
335487static int mag_auth (request_rec * req )
336488{
337489 const char * type ;
@@ -348,12 +500,9 @@ static int mag_auth(request_rec *req)
348500 gss_buffer_desc ba_user ;
349501 gss_buffer_desc ba_pwd ;
350502 gss_name_t client = GSS_C_NO_NAME ;
351- gss_cred_id_t user_cred = GSS_C_NO_CREDENTIAL ;
352503 gss_cred_id_t acquired_cred = GSS_C_NO_CREDENTIAL ;
353- gss_cred_id_t server_cred = GSS_C_NO_CREDENTIAL ;
354504 gss_cred_id_t delegated_cred = GSS_C_NO_CREDENTIAL ;
355505 gss_cred_usage_t cred_usage = GSS_C_ACCEPT ;
356- uint32_t flags ;
357506 uint32_t vtime ;
358507 uint32_t maj , min ;
359508 char * reply ;
@@ -363,13 +512,6 @@ static int mag_auth(request_rec *req)
363512 gss_OID_set desired_mechs = GSS_C_NO_OID_SET ;
364513 gss_buffer_desc lname = GSS_C_EMPTY_BUFFER ;
365514 struct mag_conn * mc = NULL ;
366- gss_ctx_id_t user_ctx = GSS_C_NO_CONTEXT ;
367- gss_name_t server = GSS_C_NO_NAME ;
368- #ifdef HAVE_GSS_KRB5_CCACHE_NAME
369- const char * user_ccache = NULL ;
370- const char * orig_ccache = NULL ;
371- #endif
372- uint32_t init_flags = 0 ;
373515 time_t expiration ;
374516 int i ;
375517
@@ -382,6 +524,7 @@ static int mag_auth(request_rec *req)
382524
383525 if (!cfg -> allowed_mechs ) {
384526 /* Try to fetch the default set if not explicitly configured */
527+ gss_cred_id_t server_cred = GSS_C_NO_CREDENTIAL ;
385528 (void )mag_acquire_creds (req , cfg , GSS_C_NO_OID_SET , GSS_C_ACCEPT ,
386529 & server_cred , & cfg -> allowed_mechs );
387530 (void )gss_release_cred (& min , & server_cred );
@@ -543,108 +686,13 @@ static int mag_auth(request_rec *req)
543686 }
544687
545688 if (auth_type == AUTH_TYPE_BASIC ) {
546- maj = gss_import_name (& min , & ba_user , GSS_C_NT_USER_NAME , & client );
547- if (GSS_ERROR (maj )) {
548- ap_log_rerror (APLOG_MARK , APLOG_ERR , 0 , req ,
549- "In Basic Auth, %s" ,
550- mag_error (req , "gss_import_name() failed" ,
551- maj , min ));
552- goto done ;
553- }
554- #ifdef HAVE_GSS_KRB5_CCACHE_NAME
555- /* Set a per-thread ccache in case we are using kerberos,
556- * it is not elegant but avoids interference between threads */
557- long long unsigned int rndname ;
558- apr_status_t rs ;
559- rs = apr_generate_random_bytes ((unsigned char * )(& rndname ),
560- sizeof (long long unsigned int ));
561- if (rs != APR_SUCCESS ) {
562- ap_log_rerror (APLOG_MARK , APLOG_ERR , 0 , req ,
563- "Failed to generate random ccache name" );
564- goto done ;
565- }
566- user_ccache = apr_psprintf (req -> pool , "MEMORY:user_%qu" , rndname );
567- maj = gss_krb5_ccache_name (& min , user_ccache , & orig_ccache );
568- if (GSS_ERROR (maj )) {
569- ap_log_rerror (APLOG_MARK , APLOG_ERR , 0 , req ,
570- "In Basic Auth, %s" ,
571- mag_error (req , "gss_krb5_ccache_name() "
572- "failed" , maj , min ));
573- goto done ;
574- }
575- #endif
576- maj = gss_acquire_cred_with_password (& min , client , & ba_pwd ,
577- GSS_C_INDEFINITE ,
578- cfg -> allowed_mechs ,
579- GSS_C_INITIATE ,
580- & user_cred , NULL , NULL );
581- if (GSS_ERROR (maj )) {
582- ap_log_rerror (APLOG_MARK , APLOG_ERR , 0 , req ,
583- "In Basic Auth, %s" ,
584- mag_error (req , "gss_acquire_cred_with_password() "
585- "failed" , maj , min ));
586- goto done ;
689+ if (mag_auth_basic (req , cfg , ba_user , ba_pwd ,
690+ acquired_cred , cred_usage ,
691+ & client , & mech_type ,
692+ & delegated_cred , & vtime )) {
693+ goto complete ;
587694 }
588- gss_release_name (& min , & client );
589-
590- if (cred_usage == GSS_C_BOTH ) {
591- /* If GSS_C_BOTH is used then inquire_cred will return the client
592- * name instead of the SPN of the server credentials. Therefore we
593- * need to acquire a different set of credential setting
594- * GSS_C_ACCEPT explicitly */
595- if (!mag_acquire_creds (req , cfg , cfg -> allowed_mechs ,
596- GSS_C_ACCEPT , & server_cred , NULL )) {
597- goto done ;
598- }
599- } else {
600- server_cred = acquired_cred ;
601- }
602- maj = gss_inquire_cred (& min , server_cred , & server ,
603- NULL , NULL , NULL );
604- if (GSS_ERROR (maj )) {
605- ap_log_rerror (APLOG_MARK , APLOG_ERR , 0 , req ,
606- "%s" , mag_error (req , "gss_inquired_cred_() "
607- "failed" , maj , min ));
608- goto done ;
609- }
610- if (server_cred != acquired_cred ) {
611- gss_release_cred (& min , & server_cred );
612- }
613-
614- #ifdef HAVE_CRED_STORE
615- if (cfg -> deleg_ccache_dir ) {
616- /* delegate ourselves credentials so we store them as requested */
617- init_flags |= GSS_C_DELEG_FLAG ;
618- }
619- #endif
620-
621- do {
622- /* output and input are inverted here, this is intentional */
623- maj = gss_init_sec_context (& min , user_cred , & user_ctx , server ,
624- GSS_C_NO_OID , init_flags , 300 ,
625- GSS_C_NO_CHANNEL_BINDINGS , & output ,
626- NULL , & input , NULL , NULL );
627- if (GSS_ERROR (maj )) {
628- ap_log_rerror (APLOG_MARK , APLOG_ERR , 0 , req ,
629- "%s" , mag_error (req , "gss_init_sec_context() "
630- "failed" , maj , min ));
631- goto done ;
632- }
633- gss_release_buffer (& min , & output );
634- maj = gss_accept_sec_context (& min , pctx , acquired_cred ,
635- & input , GSS_C_NO_CHANNEL_BINDINGS ,
636- & client , & mech_type , & output , & flags ,
637- & vtime , & delegated_cred );
638- if (GSS_ERROR (maj )) {
639- ap_log_rerror (APLOG_MARK , APLOG_ERR , 0 , req ,
640- "%s" , mag_error (req , "gss_accept_sec_context()"
641- " failed" , maj , min ));
642- goto done ;
643- }
644- gss_release_buffer (& min , & input );
645- } while (maj == GSS_S_CONTINUE_NEEDED );
646- gss_release_buffer (& min , & output );
647- goto complete ;
695+ goto done ;
648696 }
649697
650698 if (auth_type == AUTH_TYPE_NEGOTIATE &&
@@ -660,7 +708,7 @@ static int mag_auth(request_rec *req)
660708
661709 maj = gss_accept_sec_context (& min , pctx , acquired_cred ,
662710 & input , GSS_C_NO_CHANNEL_BINDINGS ,
663- & client , & mech_type , & output , & flags , & vtime ,
711+ & client , & mech_type , & output , NULL , & vtime ,
664712 & delegated_cred );
665713 if (GSS_ERROR (maj )) {
666714 ap_log_rerror (APLOG_MARK , APLOG_ERR , 0 , req , "%s" ,
@@ -771,26 +819,12 @@ static int mag_auth(request_rec *req)
771819 ap_auth_name (req )));
772820 }
773821 }
774- #ifdef HAVE_GSS_KRB5_CCACHE_NAME
775- if (user_ccache != NULL ) {
776- maj = gss_krb5_ccache_name (& min , orig_ccache , NULL );
777- if (maj != GSS_S_COMPLETE ) {
778- ap_log_rerror (APLOG_MARK , APLOG_ERR , 0 , req ,
779- "Failed to restore per-thread ccache, %s" ,
780- mag_error (req , "gss_krb5_ccache_name() "
781- "failed" , maj , min ));
782- }
783- }
784- #endif
785822 if (ctx != GSS_C_NO_CONTEXT )
786823 gss_delete_sec_context (& min , & ctx , GSS_C_NO_BUFFER );
787- gss_delete_sec_context (& min , & user_ctx , GSS_C_NO_BUFFER );
788- gss_release_cred (& min , & user_cred );
789824 gss_release_cred (& min , & acquired_cred );
790825 gss_release_cred (& min , & delegated_cred );
791826 gss_release_buffer (& min , & output );
792827 gss_release_name (& min , & client );
793- gss_release_name (& min , & server );
794828 gss_release_buffer (& min , & name );
795829 gss_release_buffer (& min , & lname );
796830 return ret ;
0 commit comments