@@ -346,71 +346,82 @@ static int on_header_value(http_parser *parser, const char *str, size_t len)
346346 return 0 ;
347347}
348348
349+ static int on_auth_required (http_parser * parser , int allowed_types )
350+ {
351+ parser_context * ctx = (parser_context * ) parser -> data ;
352+ http_subtransport * t = ctx -> t ;
353+ int ret ;
354+
355+ if (!allowed_types ) {
356+ giterr_set (GITERR_NET , "remote did not prompt for authentication mechanisms" );
357+ t -> parse_error = PARSE_ERROR_GENERIC ;
358+ return t -> parse_error ;
359+ }
360+
361+ if (t -> owner -> cred_acquire_cb ) {
362+ if (t -> cred ) {
363+ t -> cred -> free (t -> cred );
364+ t -> cred = NULL ;
365+ }
366+
367+ ret = t -> owner -> cred_acquire_cb (& t -> cred ,
368+ t -> owner -> url ,
369+ t -> gitserver_data .user ,
370+ allowed_types ,
371+ t -> owner -> cred_acquire_payload );
372+
373+ if (ret == GIT_PASSTHROUGH ) {
374+ /* treat GIT_PASSTHROUGH as if callback isn't set */
375+ } else if (ret < 0 ) {
376+ t -> error = ret ;
377+ t -> parse_error = PARSE_ERROR_EXT ;
378+ return t -> parse_error ;
379+ } else {
380+ assert (t -> cred );
381+
382+ if (!(t -> cred -> credtype & allowed_types )) {
383+ giterr_set (GITERR_NET , "credential provider returned an invalid cred type" );
384+ t -> parse_error = PARSE_ERROR_GENERIC ;
385+ return t -> parse_error ;
386+ }
387+
388+ /* Successfully acquired a credential. */
389+ t -> parse_error = PARSE_ERROR_REPLAY ;
390+ return 0 ;
391+ }
392+ }
393+
394+ giterr_set (GITERR_NET , "authentication required but no callback set" );
395+ t -> parse_error = PARSE_ERROR_GENERIC ;
396+ return t -> parse_error ;
397+ }
398+
349399static int on_headers_complete (http_parser * parser )
350400{
351401 parser_context * ctx = (parser_context * ) parser -> data ;
352402 http_subtransport * t = ctx -> t ;
353403 http_stream * s = ctx -> s ;
354404 git_buf buf = GIT_BUF_INIT ;
355- int error = 0 , no_callback = 0 , allowed_auth_types = 0 ;
405+ int allowed_www_auth_types = 0 ;
356406
357407 /* Both parse_header_name and parse_header_value are populated
358408 * and ready for consumption. */
359409 if (VALUE == t -> last_cb )
360410 if (on_header_ready (t ) < 0 )
361411 return t -> parse_error = PARSE_ERROR_GENERIC ;
362412
363- /* Capture authentication headers which may be a 401 (authentication
364- * is not complete) or a 200 (simply informing us that auth *is*
365- * complete.)
413+ /*
414+ * Capture authentication headers for the proxy or final endpoint,
415+ * these may be 407/401 (authentication is not complete) or a 200
416+ * (informing us that auth has completed).
366417 */
367418 if (parse_authenticate_response (& t -> www_authenticate , t ,
368- & allowed_auth_types ) < 0 )
419+ & allowed_www_auth_types ) < 0 )
369420 return t -> parse_error = PARSE_ERROR_GENERIC ;
370421
371422 /* Check for an authentication failure. */
372- if (parser -> status_code == 401 && get_verb == s -> verb ) {
373- if (!t -> owner -> cred_acquire_cb ) {
374- no_callback = 1 ;
375- } else {
376- if (allowed_auth_types ) {
377- if (t -> cred ) {
378- t -> cred -> free (t -> cred );
379- t -> cred = NULL ;
380- }
381-
382- error = t -> owner -> cred_acquire_cb (& t -> cred ,
383- t -> owner -> url ,
384- t -> gitserver_data .user ,
385- allowed_auth_types ,
386- t -> owner -> cred_acquire_payload );
387-
388- /* treat GIT_PASSTHROUGH as if callback isn't set */
389- if (error == GIT_PASSTHROUGH ) {
390- no_callback = 1 ;
391- } else if (error < 0 ) {
392- t -> error = error ;
393- return t -> parse_error = PARSE_ERROR_EXT ;
394- } else {
395- assert (t -> cred );
396-
397- if (!(t -> cred -> credtype & allowed_auth_types )) {
398- giterr_set (GITERR_NET , "credentials callback returned an invalid cred type" );
399- return t -> parse_error = PARSE_ERROR_GENERIC ;
400- }
401-
402- /* Successfully acquired a credential. */
403- t -> parse_error = PARSE_ERROR_REPLAY ;
404- return 0 ;
405- }
406- }
407- }
408-
409- if (no_callback ) {
410- giterr_set (GITERR_NET , "authentication required but no callback set" );
411- return t -> parse_error = PARSE_ERROR_GENERIC ;
412- }
413- }
423+ if (parser -> status_code == 401 && get_verb == s -> verb )
424+ return on_auth_required (parser , allowed_www_auth_types );
414425
415426 /* Check for a redirect.
416427 * Right now we only permit a redirect to the same hostname. */
0 commit comments