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

Commit 45f2122

Browse files
committed
Merge pull request #2149 from davidsh/winhttphandler
Initial open source WinHttpHandler
2 parents 24bfd4f + bbe092e commit 45f2122

File tree

107 files changed

+11188
-100
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

107 files changed

+11188
-100
lines changed
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
// Copyright (c) Microsoft. All rights reserved.
2+
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
3+
4+
using System;
5+
using System.Runtime.InteropServices;
6+
using System.Security.Cryptography.X509Certificates;
7+
8+
using Microsoft.Win32.SafeHandles;
9+
10+
internal static partial class Interop
11+
{
12+
internal static partial class Crypt32
13+
{
14+
[DllImport(Interop.Libraries.Crypt32, CharSet = CharSet.Unicode, SetLastError = true)]
15+
[return: MarshalAs(UnmanagedType.Bool)]
16+
internal static extern bool CertFreeCertificateContext(IntPtr pCertContext);
17+
18+
[DllImport(Interop.Libraries.Crypt32, CharSet = CharSet.Unicode, SetLastError = true)]
19+
[return: MarshalAs(UnmanagedType.Bool)]
20+
internal static extern bool CertVerifyCertificateChainPolicy(
21+
IntPtr pszPolicyOID,
22+
SafeX509ChainHandle pChainContext,
23+
[In] ref CERT_CHAIN_POLICY_PARA pPolicyPara,
24+
[In, Out] ref CERT_CHAIN_POLICY_STATUS pPolicyStatus);
25+
}
26+
}
Lines changed: 129 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,129 @@
1+
// Copyright (c) Microsoft. All rights reserved.
2+
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
3+
4+
using System;
5+
using System.Runtime.InteropServices;
6+
using System.Security.Cryptography.X509Certificates;
7+
8+
using Microsoft.Win32.SafeHandles;
9+
10+
internal static partial class Interop
11+
{
12+
internal static partial class Crypt32
13+
{
14+
internal static partial class AuthType
15+
{
16+
internal const uint AUTHTYPE_CLIENT = 1;
17+
internal const uint AUTHTYPE_SERVER = 2;
18+
}
19+
20+
internal static partial class CertChainPolicyIgnoreFlags
21+
{
22+
internal const uint CERT_CHAIN_POLICY_IGNORE_NOT_TIME_VALID_FLAG = 0x00000001;
23+
internal const uint CERT_CHAIN_POLICY_IGNORE_CTL_NOT_TIME_VALID_FLAG = 0x00000002;
24+
internal const uint CERT_CHAIN_POLICY_IGNORE_NOT_TIME_NESTED_FLAG = 0x00000004;
25+
internal const uint CERT_CHAIN_POLICY_IGNORE_INVALID_BASIC_CONSTRAINTS_FLAG = 0x00000008;
26+
internal const uint CERT_CHAIN_POLICY_ALLOW_UNKNOWN_CA_FLAG = 0x00000010;
27+
internal const uint CERT_CHAIN_POLICY_IGNORE_WRONG_USAGE_FLAG = 0x00000020;
28+
internal const uint CERT_CHAIN_POLICY_IGNORE_INVALID_NAME_FLAG = 0x00000040;
29+
internal const uint CERT_CHAIN_POLICY_IGNORE_INVALID_POLICY_FLAG = 0x00000080;
30+
internal const uint CERT_CHAIN_POLICY_IGNORE_END_REV_UNKNOWN_FLAG = 0x00000100;
31+
internal const uint CERT_CHAIN_POLICY_IGNORE_CTL_SIGNER_REV_UNKNOWN_FLAG = 0x00000200;
32+
internal const uint CERT_CHAIN_POLICY_IGNORE_CA_REV_UNKNOWN_FLAG = 0x00000400;
33+
internal const uint CERT_CHAIN_POLICY_IGNORE_ROOT_REV_UNKNOWN_FLAG = 0x00000800;
34+
35+
internal const uint CERT_CHAIN_POLICY_IGNORE_ALL =
36+
CERT_CHAIN_POLICY_IGNORE_NOT_TIME_VALID_FLAG |
37+
CERT_CHAIN_POLICY_IGNORE_CTL_NOT_TIME_VALID_FLAG |
38+
CERT_CHAIN_POLICY_IGNORE_NOT_TIME_NESTED_FLAG |
39+
CERT_CHAIN_POLICY_IGNORE_INVALID_BASIC_CONSTRAINTS_FLAG |
40+
CERT_CHAIN_POLICY_ALLOW_UNKNOWN_CA_FLAG |
41+
CERT_CHAIN_POLICY_IGNORE_WRONG_USAGE_FLAG |
42+
CERT_CHAIN_POLICY_IGNORE_INVALID_NAME_FLAG |
43+
CERT_CHAIN_POLICY_IGNORE_INVALID_POLICY_FLAG |
44+
CERT_CHAIN_POLICY_IGNORE_END_REV_UNKNOWN_FLAG |
45+
CERT_CHAIN_POLICY_IGNORE_CTL_SIGNER_REV_UNKNOWN_FLAG |
46+
CERT_CHAIN_POLICY_IGNORE_CA_REV_UNKNOWN_FLAG |
47+
CERT_CHAIN_POLICY_IGNORE_ROOT_REV_UNKNOWN_FLAG;
48+
}
49+
50+
internal static partial class CertChainPolicy
51+
{
52+
internal const int CERT_CHAIN_POLICY_BASE = 1;
53+
internal const int CERT_CHAIN_POLICY_AUTHENTICODE = 2;
54+
internal const int CERT_CHAIN_POLICY_AUTHENTICODE_TS = 3;
55+
internal const int CERT_CHAIN_POLICY_SSL = 4;
56+
internal const int CERT_CHAIN_POLICY_BASIC_CONSTRAINTS = 5;
57+
internal const int CERT_CHAIN_POLICY_NT_AUTH = 6;
58+
internal const int CERT_CHAIN_POLICY_MICROSOFT_ROOT = 7;
59+
internal const int CERT_CHAIN_POLICY_EV = 8;
60+
}
61+
62+
internal static partial class CertChainPolicyErrors
63+
{
64+
// Base Policy errors (CERT_CHAIN_POLICY_BASE).
65+
internal const uint TRUST_E_CERT_SIGNATURE = 0x80096004;
66+
internal const uint CRYPT_E_REVOKED = 0x80092010;
67+
internal const uint CERT_E_UNTRUSTEDROOT = 0x800B0109;
68+
internal const uint CERT_E_UNTRUSTEDTESTROOT = 0x800B010D;
69+
internal const uint CERT_E_CHAINING = 0x800B010A;
70+
internal const uint CERT_E_WRONG_USAGE = 0x800B0110;
71+
internal const uint CERT_E_EXPIRE = 0x800B0101;
72+
internal const uint CERT_E_INVALID_NAME = 0x800B0114;
73+
internal const uint CERT_E_INVALID_POLICY = 0x800B0113;
74+
75+
// Basic Constraints Policy errors (CERT_CHAIN_POLICY_BASIC_CONSTRAINTS).
76+
internal const uint TRUST_E_BASIC_CONSTRAINTS = 0x80096019;
77+
78+
// Authenticode Policy errors (CERT_CHAIN_POLICY_AUTHENTICODE and CERT_CHAIN_POLICY_AUTHENTICODE_TS).
79+
internal const uint CERT_E_CRITICAL = 0x800B0105;
80+
internal const uint CERT_E_VALIDITYPERIODNESTING = 0x800B0102;
81+
internal const uint CRYPT_E_NO_REVOCATION_CHECK = 0x80092012;
82+
internal const uint CRYPT_E_REVOCATION_OFFLINE = 0x80092013;
83+
internal const uint CERT_E_PURPOSE = 0x800B0106;
84+
internal const uint CERT_E_REVOKED = 0x800B010C;
85+
internal const uint CERT_E_REVOCATION_FAILURE = 0x800B010E;
86+
87+
// SSL Policy errors (CERT_CHAIN_POLICY_SSL).
88+
internal const uint CERT_E_CN_NO_MATCH = 0x800B010F;
89+
internal const uint CERT_E_ROLE = 0x800B0103;
90+
}
91+
92+
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
93+
internal struct CERT_CONTEXT
94+
{
95+
internal uint dwCertEncodingType;
96+
internal IntPtr pbCertEncoded;
97+
internal uint cbCertEncoded;
98+
internal IntPtr pCertInfo;
99+
internal IntPtr hCertStore;
100+
}
101+
102+
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
103+
internal unsafe struct SSL_EXTRA_CERT_CHAIN_POLICY_PARA
104+
{
105+
internal uint cbSize;
106+
internal uint dwAuthType;
107+
internal uint fdwChecks;
108+
internal char* pwszServerName;
109+
}
110+
111+
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
112+
internal unsafe struct CERT_CHAIN_POLICY_PARA
113+
{
114+
public uint cbSize;
115+
public uint dwFlags;
116+
public SSL_EXTRA_CERT_CHAIN_POLICY_PARA* pvExtraPolicyPara;
117+
}
118+
119+
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
120+
internal unsafe struct CERT_CHAIN_POLICY_STATUS
121+
{
122+
public uint cbSize;
123+
public uint dwError;
124+
public int lChainIndex;
125+
public int lElementIndex;
126+
public void* pvExtraPolicyStatus;
127+
}
128+
}
129+
}

src/Common/src/Interop/Windows/Interop.Libraries.cs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33

44
internal static partial class Interop
55
{
6-
private static class Libraries
6+
internal static class Libraries
77
{
88
internal const string BCrypt = "BCrypt.dll";
99
internal const string Console_L1 = "api-ms-win-core-console-l1-1-0.dll";
@@ -19,6 +19,7 @@ private static class Libraries
1919
internal const string Kernel32 = "kernel32.dll";
2020
internal const string Kernel32_L1 = "api-ms-win-core-kernel32-legacy-l1-1-1.dll";
2121
internal const string Kernel32_L2 = "api-ms-win-core-kernel32-legacy-l1-1-0.dll";
22+
internal const string LibraryLoader = "api-ms-win-core-libraryloader-l1-1-0.dll";
2223
internal const string Localization = "api-ms-win-core-localization-l1-2-0.dll";
2324
internal const string Memory_L1_0 = "api-ms-win-core-memory-l1-1-0.dll";
2425
internal const string Memory_L1_1 = "api-ms-win-core-memory-l1-1-1.dll";
@@ -50,6 +51,7 @@ private static class Libraries
5051
internal const string SystemInfo = "api-ms-win-core-sysinfo-l1-1-0.dll";
5152
internal const string User32 = "user32.dll";
5253
internal const string Version = "api-ms-win-core-version-l1-1-0.dll";
54+
internal const string WinHttp = "winhttp.dll";
5355
internal const string Wow64 = "api-ms-win-core-wow64-l1-1-0.dll";
5456
internal const string Zlib = "clrcompression.dll";
5557
}

src/Common/src/Interop/Windows/mincore/Interop.FormatMessage.cs

Lines changed: 21 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -10,15 +10,17 @@ internal partial class Interop
1010
internal partial class mincore
1111
{
1212
private const int FORMAT_MESSAGE_IGNORE_INSERTS = 0x00000200;
13+
private const int FORMAT_MESSAGE_FROM_HMODULE = 0x00000800;
1314
private const int FORMAT_MESSAGE_FROM_SYSTEM = 0x00001000;
1415
private const int FORMAT_MESSAGE_ARGUMENT_ARRAY = 0x00002000;
1516

17+
1618
private const int ERROR_INSUFFICIENT_BUFFER = 0x7A;
1719

1820
[DllImport(Libraries.Localization, CharSet = CharSet.Unicode, EntryPoint = "FormatMessageW", SetLastError = true, BestFitMapping = true)]
1921
private static extern int FormatMessage(
2022
int dwFlags,
21-
IntPtr lpSource_mustBeNull,
23+
IntPtr lpSource,
2224
uint dwMessageId,
2325
int dwLanguageId,
2426
StringBuilder lpBuffer,
@@ -29,12 +31,17 @@ private static extern int FormatMessage(
2931
/// Returns a string message for the specified Win32 error code.
3032
/// </summary>
3133
internal static string GetMessage(int errorCode)
34+
{
35+
return GetMessage(IntPtr.Zero, errorCode);
36+
}
37+
38+
internal static string GetMessage(IntPtr moduleHandle, int errorCode)
3239
{
3340
var sb = new StringBuilder(InitialBufferSize);
3441
do
3542
{
3643
string errorMsg;
37-
if (TryGetErrorMessage(errorCode, sb, out errorMsg))
44+
if (TryGetErrorMessage(moduleHandle, errorCode, sb, out errorMsg))
3845
{
3946
return errorMsg;
4047
}
@@ -50,15 +57,17 @@ internal static string GetMessage(int errorCode)
5057
return string.Format("Unknown error (0x{0:x})", errorCode);
5158
}
5259

53-
private static bool TryGetErrorMessage(int errorCode, StringBuilder sb, out string errorMsg)
60+
private static bool TryGetErrorMessage(IntPtr moduleHandle, int errorCode, StringBuilder sb, out string errorMsg)
5461
{
5562
errorMsg = "";
5663

57-
int result = FormatMessage(FORMAT_MESSAGE_IGNORE_INSERTS |
58-
FORMAT_MESSAGE_FROM_SYSTEM |
59-
FORMAT_MESSAGE_ARGUMENT_ARRAY,
60-
IntPtr.Zero, (uint)errorCode, 0, sb, sb.Capacity,
61-
null);
64+
int flags = FORMAT_MESSAGE_IGNORE_INSERTS | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_ARGUMENT_ARRAY;
65+
if (moduleHandle != IntPtr.Zero)
66+
{
67+
flags |= FORMAT_MESSAGE_FROM_HMODULE;
68+
}
69+
70+
int result = FormatMessage(flags, moduleHandle, (uint)errorCode, 0, sb, sb.Capacity, null);
6271
if (result != 0)
6372
{
6473
int i = sb.Length;
@@ -82,19 +91,19 @@ private static bool TryGetErrorMessage(int errorCode, StringBuilder sb, out stri
8291
return true;
8392
}
8493

85-
// Windows API FormatMessage lets you format a message string given an errocode.
94+
// Windows API FormatMessage lets you format a message string given an errorcode.
8695
// Unlike other APIs this API does not support a way to query it for the total message size.
8796
//
8897
// So the API can only be used in one of these two ways.
8998
// a. You pass a buffer of appropriate size and get the resource.
90-
// b. Windows creates a buffer and passes the address back and the onus of releasing the bugffer lies on the caller.
99+
// b. Windows creates a buffer and passes the address back and the onus of releasing the buffer lies on the caller.
91100
//
92101
// Since the error code is coming from the user, it is not possible to know the size in advance.
93102
// Unfortunately we can't use option b. since the buffer can only be freed using LocalFree and it is a private API on onecore.
94-
// Also, using option b is ugly for the manged code and could cause memory leak in situations where freeing is unsuccessful.
103+
// Also, using option b is ugly for the managed code and could cause memory leak in situations where freeing is unsuccessful.
95104
//
96105
// As a result we use the following approach.
97-
// We initially call the API with a buffer size of 256 and then gradually increase the size in case of failure until we reach the maxiumum allowed limit of 65K.
106+
// We initially call the API with a buffer size of 256 and then gradually increase the size in case of failure until we reach the maximum allowed limit of 65K.
98107
private const int InitialBufferSize = 256;
99108
private const int BufferSizeIncreaseFactor = 4;
100109
private const int MaxAllowedBufferSize = 65 * 1024;
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
// Copyright (c) Microsoft. All rights reserved.
2+
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
3+
4+
using Microsoft.Win32.SafeHandles;
5+
using System;
6+
using System.Runtime.InteropServices;
7+
using System.Text;
8+
9+
internal partial class Interop
10+
{
11+
internal partial class mincore
12+
{
13+
[DllImport(Libraries.LibraryLoader, EntryPoint = "GetModuleHandleW", CharSet = CharSet.Unicode, SetLastError = true)]
14+
internal static extern IntPtr GetModuleHandle(string moduleName);
15+
}
16+
}
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
// Copyright (c) Microsoft. All rights reserved.
2+
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
3+
4+
using System;
5+
using System.Runtime.InteropServices;
6+
7+
internal partial class Interop
8+
{
9+
internal partial class WinHttp
10+
{
11+
// TODO: Move SafeHandleZeroOrMinusOneIsInvalid class to Common
12+
internal abstract class SafeHandleZeroOrMinusOneIsInvalid : SafeHandle
13+
{
14+
protected SafeHandleZeroOrMinusOneIsInvalid(bool ownsHandle)
15+
: base(IntPtr.Zero, ownsHandle)
16+
{
17+
}
18+
19+
public override bool IsInvalid
20+
{
21+
get { return this.handle == IntPtr.Zero || this.handle == (IntPtr)(-1); }
22+
}
23+
}
24+
25+
internal class SafeWinHttpHandle : SafeHandleZeroOrMinusOneIsInvalid
26+
{
27+
public SafeWinHttpHandle() : base(true)
28+
{
29+
}
30+
31+
public static void DisposeAndClearHandle(ref SafeWinHttpHandle handle)
32+
{
33+
if (handle != null)
34+
{
35+
handle.Dispose();
36+
handle = null;
37+
}
38+
}
39+
40+
protected override bool ReleaseHandle()
41+
{
42+
// TODO: Add logging so we know when the handle gets closed.
43+
return Interop.WinHttp.WinHttpCloseHandle(this.handle);
44+
}
45+
}
46+
}
47+
}

0 commit comments

Comments
 (0)