Skip to content
This repository was archived by the owner on Jan 23, 2023. It is now read-only.

Commit 4c99b29

Browse files
committed
Improve security of AutomaticRedirection options for HttpClientHandler/WinHttpHandler
As per the latest security review, this issue captures the following tasks in order to remove insecure automatic redirection of HTTPS -> HTTP in HttpClientHandler/WinHttpHandler. This will also match the current NETCore/NETNative behavior as well. In general, the security guidance is to remove insecure patterns from new code/platforms. This helps the entire ecosystem become more secure while balancing the needs of app-compat. 1. Change the WinHttpHandler API surface to remove the AutomaticRedirectionPolicy enum 3-state value. 2. Change the name/type of the 'AutomaticRedirectionPolicy' property to 'bool AutomaticRedirection'. This matches the current Framework Design guidelines of fully spelling out words and the word pattern of the 'AutomaticDecompression' property. 3. The default for the AutomaticRedirection property will be true. This value means that all redirects will be followed automatically EXCEPT for https:// to http://. This behavior is different from .NET desktop where https:// to http:// redirects are also followed. [tfs-changeset: 1498199]
1 parent 1b1ab18 commit 4c99b29

File tree

3 files changed

+27
-49
lines changed

3 files changed

+27
-49
lines changed

src/System.Net.Http.WinHttpHandler/src/System/Net/Http/WinHttpHandler.cs

Lines changed: 8 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -34,17 +34,6 @@ public enum WindowsProxyUsePolicy
3434
UseCustomProxy = 3 // Use the custom proxy specified in the Proxy property.
3535
}
3636

37-
#if HTTP_DLL
38-
internal enum AutomaticRedirectionPolicy
39-
#else
40-
public enum AutomaticRedirectionPolicy
41-
#endif
42-
{
43-
Never = 0,
44-
DisallowHttpsToHttp = 1,
45-
Always = 2
46-
}
47-
4837
#if HTTP_DLL
4938
internal enum CookieUsePolicy
5039
#else
@@ -118,7 +107,7 @@ public class WinHttpHandler : HttpMessageHandler
118107
private object _lockObject = new object();
119108
private bool _doManualDecompressionCheck = false;
120109
private WinInetProxyHelper _proxyHelper = null;
121-
private AutomaticRedirectionPolicy _automaticRedirectionPolicy = AutomaticRedirectionPolicy.DisallowHttpsToHttp;
110+
private bool _automaticRedirection = true;
122111
private int _maxAutomaticRedirections = 50;
123112
private DecompressionMethods _automaticDecompression = DecompressionMethods.Deflate | DecompressionMethods.GZip;
124113
private CookieUsePolicy _cookieUsePolicy = CookieUsePolicy.UseInternalCookieStoreOnly;
@@ -162,24 +151,17 @@ public WinHttpHandler()
162151
}
163152

164153
#region Properties
165-
public AutomaticRedirectionPolicy AutomaticRedirectionPolicy
154+
public bool AutomaticRedirection
166155
{
167156
get
168157
{
169-
return _automaticRedirectionPolicy;
158+
return _automaticRedirection;
170159
}
171160

172161
set
173162
{
174-
if (value != AutomaticRedirectionPolicy.Never
175-
&& value != AutomaticRedirectionPolicy.DisallowHttpsToHttp
176-
&& value != AutomaticRedirectionPolicy.Always)
177-
{
178-
throw new ArgumentOutOfRangeException("value");
179-
}
180-
181163
CheckDisposedOrStarted();
182-
_automaticRedirectionPolicy = value;
164+
_automaticRedirection = value;
183165
}
184166
}
185167

@@ -1604,7 +1586,7 @@ private void SetRequestHandleRedirectionOptions(SafeWinHttpHandle requestHandle)
16041586
{
16051587
uint optionData = 0;
16061588

1607-
if (_automaticRedirectionPolicy != AutomaticRedirectionPolicy.Never)
1589+
if (_automaticRedirection)
16081590
{
16091591
optionData = (uint)_maxAutomaticRedirections;
16101592
SetWinHttpOption(
@@ -1613,7 +1595,9 @@ private void SetRequestHandleRedirectionOptions(SafeWinHttpHandle requestHandle)
16131595
ref optionData);
16141596
}
16151597

1616-
optionData = (uint)_automaticRedirectionPolicy;
1598+
optionData = _automaticRedirection ?
1599+
Interop.WinHttp.WINHTTP_OPTION_REDIRECT_POLICY_DISALLOW_HTTPS_TO_HTTP :
1600+
Interop.WinHttp.WINHTTP_OPTION_REDIRECT_POLICY_NEVER;
16171601
SetWinHttpOption(requestHandle, Interop.WinHttp.WINHTTP_OPTION_REDIRECT_POLICY, ref optionData);
16181602
}
16191603

src/System.Net.Http.WinHttpHandler/tests/WinHttpHandlerTest.cs

Lines changed: 17 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -34,49 +34,47 @@ public void Dispose()
3434
}
3535

3636
[Fact]
37-
public void AutomaticRedirectionPolicy_SetUsingInvalidEnum_ThrowsArgumentOutOfRangeException()
37+
public void AutomaticRedirection_CtorAndGet_DefaultValueIsTrue()
3838
{
3939
var handler = new WinHttpHandler();
40-
41-
Assert.Throws<ArgumentOutOfRangeException>(
42-
() => { handler.AutomaticRedirectionPolicy = (AutomaticRedirectionPolicy)100; });
40+
41+
Assert.True(handler.AutomaticRedirection);
4342
}
4443

4544
[Fact]
46-
public void AutomaticRedirectionPolicy_SetAlways_NoExceptionThrown()
45+
public void AutomaticRedirection_SetFalseAndGet_ValueIsFalse()
4746
{
4847
var handler = new WinHttpHandler();
49-
50-
handler.AutomaticRedirectionPolicy = AutomaticRedirectionPolicy.Always;
48+
handler.AutomaticRedirection = false;
49+
50+
Assert.False(handler.AutomaticRedirection);
5151
}
5252

5353
[Fact]
54-
public void AutomaticRedirectionPolicy_SetDisallowHttpsToHttp_NoExceptionThrown()
54+
public void AutomaticRedirection_SetTrue_ExpectedWinHttpHandleSettings()
5555
{
5656
var handler = new WinHttpHandler();
5757

58-
handler.AutomaticRedirectionPolicy = AutomaticRedirectionPolicy.DisallowHttpsToHttp;
59-
}
60-
61-
[Fact]
62-
public void AutomaticRedirectionPolicy_SetNever_NoExceptionThrown()
63-
{
64-
var handler = new WinHttpHandler();
58+
SendRequestHelper(
59+
handler,
60+
delegate { handler.AutomaticRedirection = true; });
6561

66-
handler.AutomaticRedirectionPolicy = AutomaticRedirectionPolicy.Never;
62+
Assert.Equal(
63+
Interop.WinHttp.WINHTTP_OPTION_REDIRECT_POLICY_DISALLOW_HTTPS_TO_HTTP,
64+
APICallHistory.WinHttpOptionRedirectPolicy);
6765
}
6866

6967
[Fact]
70-
public void AutomaticRedirectionPolicy_SetDisallowHttpsToHttp_ExpectedWinHttpHandleSettings()
68+
public void AutomaticRedirection_SetFalse_ExpectedWinHttpHandleSettings()
7169
{
7270
var handler = new WinHttpHandler();
7371

7472
SendRequestHelper(
7573
handler,
76-
delegate { handler.AutomaticRedirectionPolicy = AutomaticRedirectionPolicy.DisallowHttpsToHttp; });
74+
delegate { handler.AutomaticRedirection = false; });
7775

7876
Assert.Equal(
79-
Interop.WinHttp.WINHTTP_OPTION_REDIRECT_POLICY_DISALLOW_HTTPS_TO_HTTP,
77+
Interop.WinHttp.WINHTTP_OPTION_REDIRECT_POLICY_NEVER,
8078
APICallHistory.WinHttpOptionRedirectPolicy);
8179
}
8280

src/System.Net.Http/src/System/Net/Http/HttpClientHandler.Windows.cs

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -103,15 +103,11 @@ public bool AllowAutoRedirect
103103
{
104104
get
105105
{
106-
return (_winHttpHandler.AutomaticRedirectionPolicy != AutomaticRedirectionPolicy.Never);
106+
return _winHttpHandler.AutomaticRedirection;
107107
}
108108
set
109109
{
110-
// The existing .NET Desktop HttpClientHandler based on the HWR stack allows HTTPS -> HTTP redirection by default.
111-
// But, we're changing behavior to be more secure for ProjectK.
112-
_winHttpHandler.AutomaticRedirectionPolicy = value ?
113-
AutomaticRedirectionPolicy.DisallowHttpsToHttp :
114-
AutomaticRedirectionPolicy.Never;
110+
_winHttpHandler.AutomaticRedirection = value;
115111
}
116112
}
117113

0 commit comments

Comments
 (0)