@@ -12,11 +12,11 @@ namespace System.Net.Http
1212{
1313 internal partial class AuthenticationHelper
1414 {
15- private static Task < HttpResponseMessage > InnerSendAsync ( HttpRequestMessage request , bool isProxyAuth , HttpConnection connection , CancellationToken cancellationToken )
15+ private static Task < HttpResponseMessage > InnerSendAsync ( HttpRequestMessage request , bool isProxyAuth , HttpConnectionPool pool , HttpConnection connection , CancellationToken cancellationToken )
1616 {
1717 return isProxyAuth ?
1818 connection . SendAsyncCore ( request , cancellationToken ) :
19- connection . SendWithNtProxyAuthAsync ( request , cancellationToken ) ;
19+ pool . SendWithNtProxyAuthAsync ( connection , request , cancellationToken ) ;
2020 }
2121
2222 private static bool ProxySupportsConnectionAuth ( HttpResponseMessage response )
@@ -37,9 +37,9 @@ private static bool ProxySupportsConnectionAuth(HttpResponseMessage response)
3737 return false ;
3838 }
3939
40- private static async Task < HttpResponseMessage > SendWithNtAuthAsync ( HttpRequestMessage request , Uri authUri , ICredentials credentials , bool isProxyAuth , HttpConnection connection , CancellationToken cancellationToken )
40+ private static async Task < HttpResponseMessage > SendWithNtAuthAsync ( HttpRequestMessage request , Uri authUri , ICredentials credentials , bool isProxyAuth , HttpConnection connection , HttpConnectionPool connectionPool , CancellationToken cancellationToken )
4141 {
42- HttpResponseMessage response = await InnerSendAsync ( request , isProxyAuth , connection , cancellationToken ) . ConfigureAwait ( false ) ;
42+ HttpResponseMessage response = await InnerSendAsync ( request , isProxyAuth , connectionPool , connection , cancellationToken ) . ConfigureAwait ( false ) ;
4343 if ( ! isProxyAuth && connection . Kind == HttpConnectionKind . Proxy && ! ProxySupportsConnectionAuth ( response ) )
4444 {
4545 // Proxy didn't indicate that it supports connection-based auth, so we can't proceed.
@@ -55,51 +55,80 @@ private static async Task<HttpResponseMessage> SendWithNtAuthAsync(HttpRequestMe
5555 if ( challenge . AuthenticationType == AuthenticationType . Negotiate ||
5656 challenge . AuthenticationType == AuthenticationType . Ntlm )
5757 {
58- string challengeData = challenge . ChallengeData ;
59-
60- string spn = "HTTP/" + authUri . IdnHost ;
61- ChannelBinding channelBinding = connection . TransportContext ? . GetChannelBinding ( ChannelBindingKind . Endpoint ) ;
62- NTAuthentication authContext = new NTAuthentication ( isServer : false , challenge . SchemeName , challenge . Credential , spn , ContextFlagsPal . Connection , channelBinding ) ;
58+ bool isNewConnection = false ;
6359 try
6460 {
65- while ( true )
61+ if ( response . Headers . ConnectionClose . GetValueOrDefault ( ) )
6662 {
67- string challengeResponse = authContext . GetOutgoingBlob ( challengeData ) ;
68- if ( challengeResponse == null )
63+ // Server is closing the connection and asking us to authenticate on a new connection.
64+ ( connection , response ) = await connectionPool . CreateConnectionAsync ( request , cancellationToken ) . ConfigureAwait ( false ) ;
65+ if ( response != null )
6966 {
70- // Response indicated denial even after login, so stop processing and return current response.
71- break ;
67+ return response ;
7268 }
7369
70+ connectionPool . IncrementConnectionCount ( ) ;
71+ connection . Acquire ( ) ;
72+ isNewConnection = true ;
73+ }
74+ else
75+ {
7476 await connection . DrainResponseAsync ( response ) . ConfigureAwait ( false ) ;
77+ }
7578
76- SetRequestAuthenticationHeaderValue ( request , new AuthenticationHeaderValue ( challenge . SchemeName , challengeResponse ) , isProxyAuth ) ;
79+ string challengeData = challenge . ChallengeData ;
7780
78- response = await InnerSendAsync ( request , isProxyAuth , connection , cancellationToken ) . ConfigureAwait ( false ) ;
79- if ( authContext . IsCompleted || ! TryGetRepeatedChallenge ( response , challenge . SchemeName , isProxyAuth , out challengeData ) )
81+ string spn = "HTTP/" + authUri . IdnHost ;
82+ ChannelBinding channelBinding = connection . TransportContext ? . GetChannelBinding ( ChannelBindingKind . Endpoint ) ;
83+ NTAuthentication authContext = new NTAuthentication ( isServer : false , challenge . SchemeName , challenge . Credential , spn , ContextFlagsPal . Connection , channelBinding ) ;
84+ try
85+ {
86+ while ( true )
8087 {
81- break ;
88+ string challengeResponse = authContext . GetOutgoingBlob ( challengeData ) ;
89+ if ( challengeResponse == null )
90+ {
91+ // Response indicated denial even after login, so stop processing and return current response.
92+ break ;
93+ }
94+
95+ SetRequestAuthenticationHeaderValue ( request , new AuthenticationHeaderValue ( challenge . SchemeName , challengeResponse ) , isProxyAuth ) ;
96+
97+ response = await InnerSendAsync ( request , isProxyAuth , connectionPool , connection , cancellationToken ) . ConfigureAwait ( false ) ;
98+ if ( authContext . IsCompleted || ! TryGetRepeatedChallenge ( response , challenge . SchemeName , isProxyAuth , out challengeData ) )
99+ {
100+ break ;
101+ }
102+
103+ await connection . DrainResponseAsync ( response ) . ConfigureAwait ( false ) ;
82104 }
83105 }
106+ finally
107+ {
108+ authContext . CloseContext ( ) ;
109+ }
84110 }
85111 finally
86112 {
87- authContext . CloseContext ( ) ;
113+ if ( isNewConnection )
114+ {
115+ connection . Release ( ) ;
116+ }
88117 }
89118 }
90119 }
91120
92121 return response ;
93122 }
94123
95- public static Task < HttpResponseMessage > SendWithNtProxyAuthAsync ( HttpRequestMessage request , Uri proxyUri , ICredentials proxyCredentials , HttpConnection connection , CancellationToken cancellationToken )
124+ public static Task < HttpResponseMessage > SendWithNtProxyAuthAsync ( HttpRequestMessage request , Uri proxyUri , ICredentials proxyCredentials , HttpConnection connection , HttpConnectionPool connectionPool , CancellationToken cancellationToken )
96125 {
97- return SendWithNtAuthAsync ( request , proxyUri , proxyCredentials , isProxyAuth : true , connection , cancellationToken ) ;
126+ return SendWithNtAuthAsync ( request , proxyUri , proxyCredentials , isProxyAuth : true , connection , connectionPool , cancellationToken ) ;
98127 }
99128
100- public static Task < HttpResponseMessage > SendWithNtConnectionAuthAsync ( HttpRequestMessage request , ICredentials credentials , HttpConnection connection , CancellationToken cancellationToken )
129+ public static Task < HttpResponseMessage > SendWithNtConnectionAuthAsync ( HttpRequestMessage request , ICredentials credentials , HttpConnection connection , HttpConnectionPool connectionPool , CancellationToken cancellationToken )
101130 {
102- return SendWithNtAuthAsync ( request , request . RequestUri , credentials , isProxyAuth : false , connection , cancellationToken ) ;
131+ return SendWithNtAuthAsync ( request , request . RequestUri , credentials , isProxyAuth : false , connection , connectionPool , cancellationToken ) ;
103132 }
104133 }
105134}
0 commit comments