@@ -155,6 +155,7 @@ static void mag_store_deleg_creds(request_rec *req,
155155static int mag_auth (request_rec * req )
156156{
157157 const char * type ;
158+ const char * auth_type ;
158159 struct mag_config * cfg ;
159160 const char * auth_header ;
160161 char * auth_header_type ;
@@ -166,6 +167,7 @@ static int mag_auth(request_rec *req)
166167 gss_buffer_desc output = GSS_C_EMPTY_BUFFER ;
167168 gss_buffer_desc name = GSS_C_EMPTY_BUFFER ;
168169 gss_name_t client = GSS_C_NO_NAME ;
170+ gss_cred_id_t user_cred = GSS_C_NO_CREDENTIAL ;
169171 gss_cred_id_t acquired_cred = GSS_C_NO_CREDENTIAL ;
170172 gss_cred_id_t delegated_cred = GSS_C_NO_CREDENTIAL ;
171173 gss_cred_usage_t cred_usage = GSS_C_ACCEPT ;
@@ -178,6 +180,9 @@ static int mag_auth(request_rec *req)
178180 gss_OID mech_type = GSS_C_NO_OID ;
179181 gss_buffer_desc lname = GSS_C_EMPTY_BUFFER ;
180182 struct mag_conn * mc = NULL ;
183+ bool is_basic = false;
184+ gss_ctx_id_t user_ctx = GSS_C_NO_CONTEXT ;
185+ gss_name_t server = GSS_C_NO_NAME ;
181186
182187 type = ap_auth_type (req );
183188 if ((type == NULL ) || (strcasecmp (type , "GSSAPI" ) != 0 )) {
@@ -225,7 +230,7 @@ static int mag_auth(request_rec *req)
225230 ap_log_rerror (APLOG_MARK , APLOG_DEBUG |APLOG_NOERRNO , 0 , req ,
226231 "Already established context found!" );
227232 apr_table_set (req -> subprocess_env , "GSS_NAME" , mc -> gss_name );
228- req -> ap_auth_type = apr_pstrdup (req -> pool , "Negotiate" );
233+ req -> ap_auth_type = apr_pstrdup (req -> pool , mc -> auth_type );
229234 req -> user = apr_pstrdup (req -> pool , mc -> user_name );
230235 ret = OK ;
231236 goto done ;
@@ -241,21 +246,81 @@ static int mag_auth(request_rec *req)
241246 auth_header_type = ap_getword_white (req -> pool , & auth_header );
242247 if (!auth_header_type ) goto done ;
243248
244- if (strcasecmp (auth_header_type , "Negotiate" ) != 0 ) goto done ;
249+ if (strcasecmp (auth_header_type , "Negotiate" ) == 0 ) {
250+ auth_type = "Negotiate" ;
251+
252+ auth_header_value = ap_getword_white (req -> pool , & auth_header );
253+ if (!auth_header_value ) goto done ;
254+ input .length = apr_base64_decode_len (auth_header_value ) + 1 ;
255+ input .value = apr_pcalloc (req -> pool , input .length );
256+ if (!input .value ) goto done ;
257+ input .length = apr_base64_decode (input .value , auth_header_value );
258+ } else if (strcasecmp (auth_header_type , "Basic" ) == 0 ) {
259+ auth_type = "Basic" ;
260+ is_basic = true;
261+
262+ gss_buffer_desc ba_user ;
263+ gss_buffer_desc ba_pwd ;
264+
265+ switch (cfg -> basic_auth ) {
266+ case BA_ON :
267+ /* handle directly */
268+ break ;
269+ case BA_FORWARD :
270+ /* decline to handle ourselves, let other modules do it */
271+ ret = DECLINED ;
272+ goto done ;
273+ case BA_OFF :
274+ goto done ;
275+ default :
276+ goto done ;
277+ }
278+ ba_pwd .value = ap_pbase64decode (req -> pool , auth_header );
279+ if (!ba_pwd .value ) goto done ;
280+ ba_user .value = ap_getword_nulls_nc (req -> pool ,
281+ (char * * )& ba_pwd .value , ':' );
282+ if (!ba_user .value ) goto done ;
283+ if (((char * )ba_user .value )[0 ] == '\0' ||
284+ ((char * )ba_pwd .value )[0 ] == '\0' ) {
285+ ap_log_rerror (APLOG_MARK , APLOG_ERR |APLOG_NOERRNO , 0 , req ,
286+ "Invalid empty user or password for Basic Auth" );
287+ goto done ;
288+ }
289+ ba_user .length = strlen (ba_user .value );
290+ ba_pwd .length = strlen (ba_pwd .value );
291+ maj = gss_import_name (& min , & ba_user , GSS_C_NT_USER_NAME , & client );
292+ if (GSS_ERROR (maj )) {
293+ ap_log_rerror (APLOG_MARK , APLOG_ERR |APLOG_NOERRNO , 0 , req ,
294+ "In Basic Auth, %s" ,
295+ mag_error (req , "gss_import_name() failed" ,
296+ maj , min ));
297+ goto done ;
298+ }
299+ maj = gss_acquire_cred_with_password (& min , client , & ba_pwd ,
300+ GSS_C_INDEFINITE ,
301+ GSS_C_NO_OID_SET ,
302+ GSS_C_INITIATE ,
303+ & user_cred , NULL , NULL );
304+ if (GSS_ERROR (maj )) {
305+ ap_log_rerror (APLOG_MARK , APLOG_ERR |APLOG_NOERRNO , 0 , req ,
306+ "In Basic Auth, %s" ,
307+ mag_error (req , "gss_acquire_cred_with_password() "
308+ "failed" , maj , min ));
309+ goto done ;
310+ }
311+ gss_release_name (& min , & client );
312+ } else {
313+ goto done ;
314+ }
245315
246- auth_header_value = ap_getword_white (req -> pool , & auth_header );
247- if (!auth_header_value ) goto done ;
248- input .length = apr_base64_decode_len (auth_header_value ) + 1 ;
249- input .value = apr_pcalloc (req -> pool , input .length );
250- if (!input .value ) goto done ;
251- input .length = apr_base64_decode (input .value , auth_header_value );
316+ req -> ap_auth_type = apr_pstrdup (req -> pool , auth_type );
252317
253318#ifdef HAVE_GSS_ACQUIRE_CRED_FROM
254319 if (cfg -> use_s4u2proxy ) {
255320 cred_usage = GSS_C_BOTH ;
256321 }
257322 if (cfg -> cred_store ) {
258- maj = gss_acquire_cred_from (& min , GSS_C_NO_NAME , 0 ,
323+ maj = gss_acquire_cred_from (& min , GSS_C_NO_NAME , GSS_C_INDEFINITE ,
259324 GSS_C_NO_OID_SET , cred_usage ,
260325 cfg -> cred_store , & acquired_cred ,
261326 NULL , NULL );
@@ -268,6 +333,40 @@ static int mag_auth(request_rec *req)
268333 }
269334#endif
270335
336+ if (is_basic ) {
337+ if (!acquired_cred ) {
338+ /* Try to acquire default creds */
339+ maj = gss_acquire_cred (& min , GSS_C_NO_NAME , GSS_C_INDEFINITE ,
340+ GSS_C_NO_OID_SET , cred_usage ,
341+ & acquired_cred , NULL , NULL );
342+ if (GSS_ERROR (maj )) {
343+ ap_log_rerror (APLOG_MARK , APLOG_ERR |APLOG_NOERRNO , 0 , req ,
344+ "%s" , mag_error (req , "gss_acquire_cred_from()"
345+ " failed" , maj , min ));
346+ goto done ;
347+ }
348+ }
349+ maj = gss_inquire_cred (& min , acquired_cred , & server ,
350+ NULL , NULL , NULL );
351+ if (GSS_ERROR (maj )) {
352+ ap_log_rerror (APLOG_MARK , APLOG_ERR |APLOG_NOERRNO , 0 , req ,
353+ "%s" , mag_error (req , "gss_inquired_cred_() "
354+ "failed" , maj , min ));
355+ goto done ;
356+ }
357+ /* output and input are inverted here, this is intentional */
358+ maj = gss_init_sec_context (& min , user_cred , & user_ctx , server ,
359+ GSS_C_NO_OID , 0 , 300 ,
360+ GSS_C_NO_CHANNEL_BINDINGS , & output ,
361+ NULL , & input , NULL , NULL );
362+ if (GSS_ERROR (maj )) {
363+ ap_log_rerror (APLOG_MARK , APLOG_ERR |APLOG_NOERRNO , 0 , req ,
364+ "%s" , mag_error (req , "gss_init_sec_context() "
365+ "failed" , maj , min ));
366+ goto done ;
367+ }
368+ }
369+
271370 maj = gss_accept_sec_context (& min , pctx , acquired_cred ,
272371 & input , GSS_C_NO_CHANNEL_BINDINGS ,
273372 & client , & mech_type , & output , & flags , & vtime ,
@@ -278,8 +377,33 @@ static int mag_auth(request_rec *req)
278377 maj , min ));
279378 goto done ;
280379 }
281-
282- if (maj == GSS_S_CONTINUE_NEEDED ) {
380+ if (is_basic ) {
381+ while (maj == GSS_S_CONTINUE_NEEDED ) {
382+ gss_release_buffer (& min , & input );
383+ /* output and input are inverted here, this is intentional */
384+ maj = gss_init_sec_context (& min , user_cred , & user_ctx , server ,
385+ GSS_C_NO_OID , 0 , 300 ,
386+ GSS_C_NO_CHANNEL_BINDINGS , & output ,
387+ NULL , & input , NULL , NULL );
388+ if (GSS_ERROR (maj )) {
389+ ap_log_rerror (APLOG_MARK , APLOG_ERR |APLOG_NOERRNO , 0 , req ,
390+ "%s" , mag_error (req , "gss_init_sec_context() "
391+ "failed" , maj , min ));
392+ goto done ;
393+ }
394+ gss_release_buffer (& min , & output );
395+ maj = gss_accept_sec_context (& min , pctx , acquired_cred ,
396+ & input , GSS_C_NO_CHANNEL_BINDINGS ,
397+ & client , & mech_type , & output , & flags ,
398+ & vtime , & delegated_cred );
399+ if (GSS_ERROR (maj )) {
400+ ap_log_rerror (APLOG_MARK , APLOG_ERR |APLOG_NOERRNO , 0 , req ,
401+ "%s" , mag_error (req , "gss_accept_sec_context()"
402+ " failed" , maj , min ));
403+ goto done ;
404+ }
405+ }
406+ } else if (maj == GSS_S_CONTINUE_NEEDED ) {
283407 if (!mc ) {
284408 ap_log_rerror (APLOG_MARK , APLOG_ERR |APLOG_NOERRNO , 0 , req ,
285409 "Mechanism needs continuation but neither "
@@ -293,8 +417,6 @@ static int mag_auth(request_rec *req)
293417 goto done ;
294418 }
295419
296- req -> ap_auth_type = apr_pstrdup (req -> pool , "Negotiate" );
297-
298420 /* Always set the GSS name in an env var */
299421 maj = gss_display_name (& min , client , & name , NULL );
300422 if (GSS_ERROR (maj )) {
@@ -342,6 +464,7 @@ static int mag_auth(request_rec *req)
342464 if (cfg -> use_sessions ) {
343465 mag_attempt_session (req , cfg , mc );
344466 }
467+ mc -> auth_type = auth_type ;
345468 }
346469
347470 ret = OK ;
@@ -360,12 +483,21 @@ static int mag_auth(request_rec *req)
360483 } else {
361484 apr_table_add (req -> err_headers_out ,
362485 "WWW-Authenticate" , "Negotiate" );
486+ if (cfg -> basic_auth != BA_OFF ) {
487+ apr_table_add (req -> err_headers_out ,
488+ "WWW-Authenticate" ,
489+ apr_psprintf (req -> pool , "Basic realm=\"%s\"" ,
490+ ap_auth_name (req )));
491+ }
363492 }
364493 }
494+ gss_delete_sec_context (& min , & user_ctx , & output );
495+ gss_release_cred (& min , & user_cred );
365496 gss_release_cred (& min , & acquired_cred );
366497 gss_release_cred (& min , & delegated_cred );
367498 gss_release_buffer (& min , & output );
368499 gss_release_name (& min , & client );
500+ gss_release_name (& min , & server );
369501 gss_release_buffer (& min , & name );
370502 gss_release_buffer (& min , & lname );
371503 return ret ;
@@ -542,6 +674,22 @@ static const char *mag_deleg_ccache_dir(cmd_parms *parms, void *mconfig,
542674 return NULL ;
543675}
544676
677+ static const char * mag_use_basic_auth (cmd_parms * parms , void * mconfig ,
678+ const char * value )
679+ {
680+ struct mag_config * cfg = (struct mag_config * )mconfig ;
681+
682+ if (strcasecmp (value , "on" ) == 0 ) {
683+ cfg -> basic_auth = BA_ON ;
684+ } else if (strcasecmp (value , "forward" ) == 0 ) {
685+ cfg -> basic_auth = BA_FORWARD ;
686+ } else {
687+ cfg -> basic_auth = BA_OFF ;
688+ }
689+
690+ return NULL ;
691+ }
692+
545693static const command_rec mag_commands [] = {
546694 AP_INIT_FLAG ("GssapiSSLonly" , mag_ssl_only , NULL , OR_AUTHCFG ,
547695 "Work only if connection is SSL Secured" ),
@@ -562,6 +710,10 @@ static const command_rec mag_commands[] = {
562710 "Credential Store" ),
563711 AP_INIT_RAW_ARGS ("GssapiDelegCcacheDir" , mag_deleg_ccache_dir , NULL ,
564712 OR_AUTHCFG , "Directory to store delegated credentials" ),
713+ #endif
714+ #ifdef HAVE_GSS_ACQUIRE_CRED_WITH_PASSWORD
715+ AP_INIT_TAKE1 ("GssapiBasicAuth" , mag_use_basic_auth , NULL , OR_AUTHCFG ,
716+ "Allows use of Basic Auth for authentication" ),
565717#endif
566718 { NULL }
567719};
0 commit comments