aboutsummaryrefslogtreecommitdiff
path: root/src/ext/Http/ca
diff options
context:
space:
mode:
authorBob Arnson <bob@firegiant.com>2025-02-17 22:30:31 -0500
committerBob Arnson <bob@firegiant.com>2025-02-25 17:17:56 -0500
commit085ba380e7991013c6bb6dce48dc89f02eca4808 (patch)
tree7b27ad1e329277c204dee8c5c72451d475727630 /src/ext/Http/ca
parent1be4e0930eb296f44b8cecd10fc9632a867149ce (diff)
downloadwix-bob/HttpNonSniSslCerts.tar.gz
wix-bob/HttpNonSniSslCerts.tar.bz2
wix-bob/HttpNonSniSslCerts.zip
Support non-SNI SSL certificates in Http extensionbob/HttpNonSniSslCerts
Implements https://github.com/wixtoolset/issues/issues/7622
Diffstat (limited to 'src/ext/Http/ca')
-rw-r--r--src/ext/Http/ca/httpca.vcxproj13
-rw-r--r--src/ext/Http/ca/httpca.vcxproj.filters3
-rw-r--r--src/ext/Http/ca/httpcerts.cpp (renamed from src/ext/Http/ca/snisslcert.cpp)656
-rw-r--r--src/ext/Http/ca/precomp.h6
-rw-r--r--src/ext/Http/ca/wixhttpca.def6
5 files changed, 457 insertions, 227 deletions
diff --git a/src/ext/Http/ca/httpca.vcxproj b/src/ext/Http/ca/httpca.vcxproj
index 42acd85d..73ded72e 100644
--- a/src/ext/Http/ca/httpca.vcxproj
+++ b/src/ext/Http/ca/httpca.vcxproj
@@ -1,6 +1,5 @@
1<?xml version="1.0" encoding="utf-8"?> 1<?xml version="1.0" encoding="utf-8"?>
2<!-- Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. --> 2<!-- Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. -->
3
4<Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> 3<Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
5 <ItemGroup Label="ProjectConfigurations"> 4 <ItemGroup Label="ProjectConfigurations">
6 <ProjectConfiguration Include="Debug|Win32"> 5 <ProjectConfiguration Include="Debug|Win32">
@@ -28,7 +27,6 @@
28 <Platform>ARM64</Platform> 27 <Platform>ARM64</Platform>
29 </ProjectConfiguration> 28 </ProjectConfiguration>
30 </ItemGroup> 29 </ItemGroup>
31
32 <PropertyGroup Label="Globals"> 30 <PropertyGroup Label="Globals">
33 <ProjectGuid>{90743805-C043-47C7-B5FF-8F5EE5C8A2DE}</ProjectGuid> 31 <ProjectGuid>{90743805-C043-47C7-B5FF-8F5EE5C8A2DE}</ProjectGuid>
34 <ConfigurationType>DynamicLibrary</ConfigurationType> 32 <ConfigurationType>DynamicLibrary</ConfigurationType>
@@ -37,35 +35,28 @@
37 <ProjectModuleDefinitionFile>wixhttpca.def</ProjectModuleDefinitionFile> 35 <ProjectModuleDefinitionFile>wixhttpca.def</ProjectModuleDefinitionFile>
38 <Description>WiX Toolset Http CustomAction</Description> 36 <Description>WiX Toolset Http CustomAction</Description>
39 </PropertyGroup> 37 </PropertyGroup>
40
41 <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" /> 38 <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
42 <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" /> 39 <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
43
44 <PropertyGroup> 40 <PropertyGroup>
45 <ProjectAdditionalLinkLibraries>crypt32.lib;httpapi.lib;msi.lib;rpcrt4.lib;ws2_32.lib</ProjectAdditionalLinkLibraries> 41 <ProjectAdditionalLinkLibraries>crypt32.lib;httpapi.lib;msi.lib;rpcrt4.lib;ws2_32.lib</ProjectAdditionalLinkLibraries>
46 </PropertyGroup> 42 </PropertyGroup>
47
48 <ItemGroup> 43 <ItemGroup>
49 <ClCompile Include="dllmain.cpp"> 44 <ClCompile Include="dllmain.cpp">
50 <PrecompiledHeader>Create</PrecompiledHeader> 45 <PrecompiledHeader>Create</PrecompiledHeader>
51 </ClCompile> 46 </ClCompile>
52 <ClCompile Include="snisslcert.cpp" /> 47 <ClCompile Include="httpcerts.cpp" />
53 <ClCompile Include="wixhttpca.cpp" /> 48 <ClCompile Include="wixhttpca.cpp" />
54 </ItemGroup> 49 </ItemGroup>
55
56 <ItemGroup> 50 <ItemGroup>
57 <ClInclude Include="cost.h" /> 51 <ClInclude Include="cost.h" />
58 <ClInclude Include="precomp.h" /> 52 <ClInclude Include="precomp.h" />
59 </ItemGroup> 53 </ItemGroup>
60
61 <ItemGroup> 54 <ItemGroup>
62 <None Include="wixhttpca.def" /> 55 <None Include="wixhttpca.def" />
63 </ItemGroup> 56 </ItemGroup>
64
65 <ItemGroup> 57 <ItemGroup>
66 <PackageReference Include="WixToolset.WcaUtil" /> 58 <PackageReference Include="WixToolset.WcaUtil" />
67 <PackageReference Include="Microsoft.SourceLink.GitHub" PrivateAssets="All" /> 59 <PackageReference Include="Microsoft.SourceLink.GitHub" PrivateAssets="All" />
68 </ItemGroup> 60 </ItemGroup>
69
70 <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" /> 61 <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
71</Project> 62</Project> \ No newline at end of file
diff --git a/src/ext/Http/ca/httpca.vcxproj.filters b/src/ext/Http/ca/httpca.vcxproj.filters
index 2ccd604d..4f91b946 100644
--- a/src/ext/Http/ca/httpca.vcxproj.filters
+++ b/src/ext/Http/ca/httpca.vcxproj.filters
@@ -21,7 +21,7 @@
21 <ClCompile Include="dllmain.cpp"> 21 <ClCompile Include="dllmain.cpp">
22 <Filter>Source Files</Filter> 22 <Filter>Source Files</Filter>
23 </ClCompile> 23 </ClCompile>
24 <ClCompile Include="snisslcert.cpp"> 24 <ClCompile Include="httpcerts.cpp">
25 <Filter>Source Files</Filter> 25 <Filter>Source Files</Filter>
26 </ClCompile> 26 </ClCompile>
27 </ItemGroup> 27 </ItemGroup>
@@ -37,6 +37,5 @@
37 <None Include="wixhttpca.def"> 37 <None Include="wixhttpca.def">
38 <Filter>Source Files</Filter> 38 <Filter>Source Files</Filter>
39 </None> 39 </None>
40 <None Include="packages.config" />
41 </ItemGroup> 40 </ItemGroup>
42</Project> \ No newline at end of file 41</Project> \ No newline at end of file
diff --git a/src/ext/Http/ca/snisslcert.cpp b/src/ext/Http/ca/httpcerts.cpp
index 81cd5298..c91dbbe1 100644
--- a/src/ext/Http/ca/snisslcert.cpp
+++ b/src/ext/Http/ca/httpcerts.cpp
@@ -27,10 +27,19 @@ typedef struct _HTTP_SERVICE_CONFIG_SSL_SNI_QUERY
27 27
28#endif 28#endif
29 29
30static UINT SchedHttpSniSslCerts( 30static UINT SchedHttpCertificates(
31 __in WCA_TODO todoSched 31 __in WCA_TODO todoSched
32); 32);
33static HRESULT WriteExistingSniSslCert( 33static HRESULT FindExistingSniSslCertificate(
34 __in_z LPWSTR wzHost,
35 __in int nPort,
36 __out HTTP_SERVICE_CONFIG_SSL_SNI_SET** ppSet
37);
38static HRESULT FindExistingIpSslCertificate(
39 __in int nPort,
40 __out HTTP_SERVICE_CONFIG_SSL_SET** ppSet
41);
42static HRESULT WriteSniSslCertCustomActionData(
34 __in WCA_TODO action, 43 __in WCA_TODO action,
35 __in_z LPCWSTR wzId, 44 __in_z LPCWSTR wzId,
36 __in_z LPCWSTR wzHost, 45 __in_z LPCWSTR wzHost,
@@ -39,25 +48,14 @@ static HRESULT WriteExistingSniSslCert(
39 __in HTTP_SERVICE_CONFIG_SSL_SNI_SET* pSniSslSet, 48 __in HTTP_SERVICE_CONFIG_SSL_SNI_SET* pSniSslSet,
40 __inout_z LPWSTR* psczCustomActionData 49 __inout_z LPWSTR* psczCustomActionData
41); 50);
42static HRESULT WriteSniSslCert( 51static HRESULT WriteIpSslCertCustomActionData(
43 __in WCA_TODO action, 52 __in WCA_TODO action,
44 __in_z LPCWSTR wzId, 53 __in_z LPCWSTR wzId,
45 __in_z LPCWSTR wzHost,
46 __in int iPort, 54 __in int iPort,
47 __in int iHandleExisting, 55 __in int iHandleExisting,
48 __in_z LPCWSTR wzCertificateThumbprint, 56 __in HTTP_SERVICE_CONFIG_SSL_SET* pSniSslSet,
49 __in_z LPCWSTR wzAppId,
50 __in_z_opt LPCWSTR wzCertificateStore,
51 __inout_z LPWSTR* psczCustomActionData 57 __inout_z LPWSTR* psczCustomActionData
52); 58);
53static HRESULT EnsureAppId(
54 __inout_z LPWSTR* psczAppId,
55 __in_opt HTTP_SERVICE_CONFIG_SSL_SNI_SET* pExistingSniSslSet
56);
57static HRESULT StringFromGuid(
58 __in REFGUID rguid,
59 __inout_z LPWSTR* psczGuid
60);
61static HRESULT AddSniSslCert( 59static HRESULT AddSniSslCert(
62 __in_z LPCWSTR wzId, 60 __in_z LPCWSTR wzId,
63 __in_z LPWSTR wzHost, 61 __in_z LPWSTR wzHost,
@@ -67,43 +65,75 @@ static HRESULT AddSniSslCert(
67 __in GUID* pAppId, 65 __in GUID* pAppId,
68 __in_z LPWSTR wzSslCertStore 66 __in_z LPWSTR wzSslCertStore
69); 67);
70static HRESULT GetSniSslCert( 68static HRESULT AddIpSslCert(
71 __in_z LPWSTR wzHost, 69 __in_z LPCWSTR wzId,
72 __in int nPort, 70 __in int iPort,
73 __out HTTP_SERVICE_CONFIG_SSL_SNI_SET** ppSet 71 __in BYTE rgbCertificateThumbprint[],
72 __in DWORD cbCertificateThumbprint,
73 __in GUID* pAppId,
74 __in_z LPWSTR wzSslCertStore
74); 75);
75static HRESULT RemoveSniSslCert( 76static HRESULT RemoveSniSslCert(
76 __in_z LPCWSTR wzId, 77 __in_z_opt LPCWSTR wzId,
77 __in_z LPWSTR wzHost, 78 __in_z LPWSTR wzHost,
78 __in int iPort 79 __in int iPort
79); 80);
80static void SetSniSslCertSetKey( 81static HRESULT RemoveIpSslCert(
82 __in_z_opt LPCWSTR wzId,
83 __in int iPort
84);
85static void SetSniSslCertificateKeyPort(
81 __in HTTP_SERVICE_CONFIG_SSL_SNI_KEY* pKey, 86 __in HTTP_SERVICE_CONFIG_SSL_SNI_KEY* pKey,
82 __in_z LPWSTR wzHost, 87 __in_z LPWSTR wzHost,
83 __in int iPort 88 __in int iPort
84); 89);
90static void SetIpSslCertificateKeyPort(
91 __in HTTP_SERVICE_CONFIG_SSL_KEY* pKey,
92 __in SOCKADDR_IN* pSin,
93 __in int iPort
94);
95static HRESULT EnsureAppId(
96 __inout_z LPWSTR* psczAppId,
97 __in_opt GUID* pGuid
98);
99static HRESULT StringFromGuid(
100 __in REFGUID rguid,
101 __inout_z LPWSTR* psczGuid
102);
103static HRESULT WriteCertificateCaData(
104 __in eCertificateType certType,
105 __in WCA_TODO action,
106 __in_z LPCWSTR wzId,
107 __in_z_opt LPCWSTR wzHost,
108 __in int iPort,
109 __in int iHandleExisting,
110 __in_z LPCWSTR wzCertificateThumbprint,
111 __in_z_opt LPCWSTR wzAppId,
112 __in_z_opt LPCWSTR wzCertificateStore,
113 __inout_z LPWSTR* psczCustomActionData
114);
85 115
86 116
87LPCWSTR vcsWixHttpSniSslCertQuery = 117LPCWSTR vcsHttpCertificatesQuery =
88L"SELECT `WixHttpSniSslCert`, `Host`, `Port`, `Thumbprint`, `AppId`, `Store`, `HandleExisting`, `Component_` " 118L"SELECT `HttpCertificate`, `Host`, `Port`, `Thumbprint`, `AppId`, `Store`, `HandleExisting`, `Type`, `Component_` "
89L"FROM `Wix4HttpSniSslCert`"; 119L"FROM `Wix6HttpCertificate`";
90enum eWixHttpSniSslCertQuery { hurqId = 1, hurqHost, hurqPort, hurqCertificateThumbprint, hurqAppId, hurqCertificateStore, hurqHandleExisting, hurqComponent }; 120enum eHttpCertificatesQuery { hcqId = 1, hcqHost, hcqPort, hcqCertificateThumbprint, hcqAppId, hcqCertificateStore, hcqHandleExisting, hcqType, hcqComponent };
91 121
92/****************************************************************** 122/******************************************************************
93 SchedWixHttpSniSslCertsInstall - immediate custom action entry 123 SchedHttpCertificatesInstall - immediate custom action entry
94 point to prepare adding URL reservations. 124 point to prepare adding certificates.
95 125
96********************************************************************/ 126********************************************************************/
97extern "C" UINT __stdcall SchedHttpSniSslCertsInstall( 127extern "C" UINT __stdcall SchedHttpCertificatesInstall(
98 __in MSIHANDLE hInstall 128 __in MSIHANDLE hInstall
99) 129)
100{ 130{
101 HRESULT hr = S_OK; 131 HRESULT hr = S_OK;
102 132
103 hr = WcaInitialize(hInstall, "SchedHttpSniSslCertsInstall"); 133 hr = WcaInitialize(hInstall, "SchedHttpCertificatesInstall");
104 ExitOnFailure(hr, "Failed to initialize"); 134 ExitOnFailure(hr, "Failed to initialize");
105 135
106 hr = SchedHttpSniSslCerts(WCA_TODO_INSTALL); 136 hr = SchedHttpCertificates(WCA_TODO_INSTALL);
107 137
108LExit: 138LExit:
109 return WcaFinalize(FAILED(hr) ? ERROR_INSTALL_FAILURE : ERROR_SUCCESS); 139 return WcaFinalize(FAILED(hr) ? ERROR_INSTALL_FAILURE : ERROR_SUCCESS);
@@ -111,30 +141,30 @@ LExit:
111 141
112/****************************************************************** 142/******************************************************************
113 SchedWixHttpSniSslCertsUninstall - immediate custom action entry 143 SchedWixHttpSniSslCertsUninstall - immediate custom action entry
114 point to prepare removing URL reservations. 144 point to prepare removing certificates.
115 145
116********************************************************************/ 146********************************************************************/
117extern "C" UINT __stdcall SchedHttpSniSslCertsUninstall( 147extern "C" UINT __stdcall SchedHttpCertificatesUninstall(
118 __in MSIHANDLE hInstall 148 __in MSIHANDLE hInstall
119) 149)
120{ 150{
121 HRESULT hr = S_OK; 151 HRESULT hr = S_OK;
122 152
123 hr = WcaInitialize(hInstall, "SchedHttpSniSslCertsUninstall"); 153 hr = WcaInitialize(hInstall, "SchedHttpCertificatesUninstall");
124 ExitOnFailure(hr, "Failed to initialize"); 154 ExitOnFailure(hr, "Failed to initialize");
125 155
126 hr = SchedHttpSniSslCerts(WCA_TODO_UNINSTALL); 156 hr = SchedHttpCertificates(WCA_TODO_UNINSTALL);
127 157
128LExit: 158LExit:
129 return WcaFinalize(FAILED(hr) ? ERROR_INSTALL_FAILURE : ERROR_SUCCESS); 159 return WcaFinalize(FAILED(hr) ? ERROR_INSTALL_FAILURE : ERROR_SUCCESS);
130} 160}
131 161
132/****************************************************************** 162/******************************************************************
133 ExecHttpSniSslCerts - deferred custom action entry point to 163 ExecHttpCertificates - deferred custom action entry point to
134 register and remove URL reservations. 164 bind/unbind certificates.
135 165
136********************************************************************/ 166********************************************************************/
137extern "C" UINT __stdcall ExecHttpSniSslCerts( 167extern "C" UINT __stdcall ExecHttpCertificates(
138 __in MSIHANDLE hInstall 168 __in MSIHANDLE hInstall
139) 169)
140{ 170{
@@ -147,6 +177,7 @@ extern "C" UINT __stdcall ExecHttpSniSslCerts(
147 LPWSTR sczHost = NULL; 177 LPWSTR sczHost = NULL;
148 int iPort = 0; 178 int iPort = 0;
149 eHandleExisting handleExisting = heIgnore; 179 eHandleExisting handleExisting = heIgnore;
180 eCertificateType certificateType = ctSniSsl;
150 LPWSTR sczCertificateThumbprint = NULL; 181 LPWSTR sczCertificateThumbprint = NULL;
151 LPWSTR sczAppId = NULL; 182 LPWSTR sczAppId = NULL;
152 LPWSTR sczCertificateStore = NULL; 183 LPWSTR sczCertificateStore = NULL;
@@ -161,7 +192,7 @@ extern "C" UINT __stdcall ExecHttpSniSslCerts(
161 DWORD cbCertificateThumbprint = 0; 192 DWORD cbCertificateThumbprint = 0;
162 193
163 // Initialize. 194 // Initialize.
164 hr = WcaInitialize(hInstall, "ExecHttpSniSslCerts"); 195 hr = WcaInitialize(hInstall, "ExecHttpCertificates");
165 ExitOnFailure(hr, "Failed to initialize"); 196 ExitOnFailure(hr, "Failed to initialize");
166 197
167 hr = HRESULT_FROM_WIN32(::HttpInitialize(HTTPAPI_VERSION_1, HTTP_INITIALIZE_CONFIG, NULL)); 198 hr = HRESULT_FROM_WIN32(::HttpInitialize(HTTPAPI_VERSION_1, HTTP_INITIALIZE_CONFIG, NULL));
@@ -177,6 +208,9 @@ extern "C" UINT __stdcall ExecHttpSniSslCerts(
177 while (wz && *wz) 208 while (wz && *wz)
178 { 209 {
179 // Extract the custom action data and if rolling back, swap INSTALL and UNINSTALL. 210 // Extract the custom action data and if rolling back, swap INSTALL and UNINSTALL.
211 hr = WcaReadIntegerFromCaData(&wz, reinterpret_cast<int*>(&certificateType));
212 ExitOnFailure(hr, "Failed to read Type from custom action data");
213
180 hr = WcaReadIntegerFromCaData(&wz, &iTodo); 214 hr = WcaReadIntegerFromCaData(&wz, &iTodo);
181 ExitOnFailure(hr, "Failed to read todo from custom action data"); 215 ExitOnFailure(hr, "Failed to read todo from custom action data");
182 216
@@ -219,35 +253,50 @@ extern "C" UINT __stdcall ExecHttpSniSslCerts(
219 253
220 if (fRemove) 254 if (fRemove)
221 { 255 {
222 hr = RemoveSniSslCert(sczId, sczHost, iPort); 256 if (ctSniSsl == certificateType)
257 {
258 hr = RemoveSniSslCert(sczId, sczHost, iPort);
259 }
260 else
261 {
262 hr = RemoveIpSslCert(sczId, iPort);
263 }
264
223 if (S_OK == hr) 265 if (S_OK == hr)
224 { 266 {
225 WcaLog(LOGMSG_STANDARD, "Removed SNI SSL certificate '%ls' for hostname: %ls:%d", sczId, sczHost, iPort); 267 WcaLog(LOGMSG_STANDARD, "Removed SSL certificate '%ls' for hostname: %ls:%d.", sczId, sczHost, iPort);
226 } 268 }
227 else if (FAILED(hr)) 269 else if (FAILED(hr))
228 { 270 {
229 if (fRollback) 271 if (fRollback)
230 { 272 {
231 WcaLogError(hr, "Failed to remove SNI SSL certificate to rollback '%ls' for hostname: %ls:%d", sczId, sczHost, iPort); 273 WcaLogError(hr, "Failed to remove SSL certificate to rollback '%ls' for hostname: %ls:%d.", sczId, sczHost, iPort);
232 } 274 }
233 else 275 else
234 { 276 {
235 ExitOnFailure(hr, "Failed to remove SNI SSL certificate '%ls' for hostname: %ls:%d", sczId, sczHost, iPort); 277 ExitOnFailure(hr, "Failed to remove SSL certificate '%ls' for hostname: %ls:%d.", sczId, sczHost, iPort);
236 } 278 }
237 } 279 }
238 } 280 }
239 281
240 if (fAdd) 282 if (fAdd)
241 { 283 {
242 WcaLog(LOGMSG_STANDARD, "Adding SNI SSL certificate '%ls' for hostname: %ls:%d", sczId, sczHost, iPort); 284 WcaLog(LOGMSG_STANDARD, "Adding SSL certificate '%ls' for hostname: %ls:%d.", sczId, sczHost, iPort);
243 285
244 hr = StrAllocHexDecode(sczCertificateThumbprint, &pbCertificateThumbprint, &cbCertificateThumbprint); 286 hr = StrAllocHexDecode(sczCertificateThumbprint, &pbCertificateThumbprint, &cbCertificateThumbprint);
245 ExitOnFailure(hr, "Failed to convert thumbprint to bytes for SNI SSL certificate '%ls' for hostname: %ls:%d", sczId, sczHost, iPort); 287 ExitOnFailure(hr, "Failed to convert thumbprint to bytes for SSL certificate '%ls' for hostname: %ls:%d", sczId, sczHost, iPort);
246 288
247 hr = ::IIDFromString(sczAppId, &guidAppId); 289 hr = ::IIDFromString(sczAppId, &guidAppId);
248 ExitOnFailure(hr, "Failed to convert AppId '%ls' back to GUID for SNI SSL certificate '%ls' for hostname: %ls:%d", sczAppId, sczId, sczHost, iPort); 290 ExitOnFailure(hr, "Failed to convert AppId '%ls' back to GUID for SSL certificate '%ls' for hostname: %ls:%d", sczAppId, sczId, sczHost, iPort);
291 if (ctSniSsl == certificateType)
292 {
293 hr = AddSniSslCert(sczId, sczHost, iPort, pbCertificateThumbprint, cbCertificateThumbprint, &guidAppId, sczCertificateStore && *sczCertificateStore ? sczCertificateStore : L"MY");
294 }
295 else
296 {
297 hr = AddIpSslCert(sczId, iPort, pbCertificateThumbprint, cbCertificateThumbprint, &guidAppId, sczCertificateStore && *sczCertificateStore ? sczCertificateStore : L"MY");
298 }
249 299
250 hr = AddSniSslCert(sczId, sczHost, iPort, pbCertificateThumbprint, cbCertificateThumbprint, &guidAppId, sczCertificateStore && *sczCertificateStore ? sczCertificateStore : L"MY");
251 if (S_FALSE == hr && fFailOnExisting) 300 if (S_FALSE == hr && fFailOnExisting)
252 { 301 {
253 hr = HRESULT_FROM_WIN32(ERROR_ALREADY_EXISTS); 302 hr = HRESULT_FROM_WIN32(ERROR_ALREADY_EXISTS);
@@ -255,17 +304,17 @@ extern "C" UINT __stdcall ExecHttpSniSslCerts(
255 304
256 if (S_OK == hr) 305 if (S_OK == hr)
257 { 306 {
258 WcaLog(LOGMSG_STANDARD, "Added SNI SSL certificate '%ls' for hostname: %ls:%d with thumbprint: %ls", sczId, sczHost, iPort, sczCertificateThumbprint); 307 WcaLog(LOGMSG_STANDARD, "Added SSL certificate '%ls' for hostname: %ls:%d with thumbprint: %ls.", sczId, sczHost, iPort, sczCertificateThumbprint);
259 } 308 }
260 else if (FAILED(hr)) 309 else if (FAILED(hr))
261 { 310 {
262 if (fRollback) 311 if (fRollback)
263 { 312 {
264 WcaLogError(hr, "Failed to add SNI SSL certificate to rollback '%ls' for hostname: %ls:%d", sczId, sczHost, iPort); 313 WcaLogError(hr, "Failed to add SSL certificate to rollback '%ls' for hostname: %ls:%d.", sczId, sczHost, iPort);
265 } 314 }
266 else 315 else
267 { 316 {
268 ExitOnFailure(hr, "Failed to add SNI SSL certificate '%ls' for hostname: %ls:%d", sczId, sczHost, iPort); 317 ExitOnFailure(hr, "Failed to add SSL certificate '%ls' for hostname: %ls:%d.", sczId, sczHost, iPort);
269 } 318 }
270 } 319 }
271 320
@@ -290,7 +339,7 @@ LExit:
290 return WcaFinalize(FAILED(hr) ? ERROR_INSTALL_FAILURE : ERROR_SUCCESS); 339 return WcaFinalize(FAILED(hr) ? ERROR_INSTALL_FAILURE : ERROR_SUCCESS);
291} 340}
292 341
293static UINT SchedHttpSniSslCerts( 342static UINT SchedHttpCertificates(
294 __in WCA_TODO todoSched 343 __in WCA_TODO todoSched
295) 344)
296{ 345{
@@ -309,6 +358,7 @@ static UINT SchedHttpSniSslCerts(
309 358
310 LPWSTR sczId = NULL; 359 LPWSTR sczId = NULL;
311 LPWSTR sczComponent = NULL; 360 LPWSTR sczComponent = NULL;
361 eCertificateType certificateType = ctSniSsl;
312 WCA_TODO todoComponent = WCA_TODO_UNKNOWN; 362 WCA_TODO todoComponent = WCA_TODO_UNKNOWN;
313 LPWSTR sczHost = NULL; 363 LPWSTR sczHost = NULL;
314 int iPort = 0; 364 int iPort = 0;
@@ -318,19 +368,20 @@ static UINT SchedHttpSniSslCerts(
318 int iHandleExisting = 0; 368 int iHandleExisting = 0;
319 369
320 HTTP_SERVICE_CONFIG_SSL_SNI_SET* pExistingSniSslSet = NULL; 370 HTTP_SERVICE_CONFIG_SSL_SNI_SET* pExistingSniSslSet = NULL;
371 HTTP_SERVICE_CONFIG_SSL_SET* pExistingIpSslSet = NULL;
321 372
322 // Anything to do? 373 // Anything to do?
323 hr = WcaTableExists(L"Wix4HttpSniSslCert"); 374 hr = WcaTableExists(L"Wix6HttpCertificate");
324 ExitOnFailure(hr, "Failed to check if the Wix4HttpSniSslCert table exists"); 375 ExitOnFailure(hr, "Failed to check if the Wix6HttpCertificate table exists");
325 if (S_FALSE == hr) 376 if (S_FALSE == hr)
326 { 377 {
327 WcaLog(LOGMSG_STANDARD, "Wix4HttpSniSslCert table doesn't exist, so there are no URL reservations to configure"); 378 WcaLog(LOGMSG_STANDARD, "Wix6HttpCertificate table doesn't exist, so there are no certificates to configure.");
328 ExitFunction(); 379 ExitFunction();
329 } 380 }
330 381
331 // Query and loop through all the SNI SSL certificates. 382 // Query and loop through all the SNI SSL certificates.
332 hr = WcaOpenExecuteView(vcsWixHttpSniSslCertQuery, &hView); 383 hr = WcaOpenExecuteView(vcsHttpCertificatesQuery, &hView);
333 ExitOnFailure(hr, "Failed to open view on the Wix4HttpSniSslCert table"); 384 ExitOnFailure(hr, "Failed to open view on the Wix6HttpCertificate table");
334 385
335 hr = HRESULT_FROM_WIN32(::HttpInitialize(HTTPAPI_VERSION_1, HTTP_INITIALIZE_CONFIG, NULL)); 386 hr = HRESULT_FROM_WIN32(::HttpInitialize(HTTPAPI_VERSION_1, HTTP_INITIALIZE_CONFIG, NULL));
336 ExitOnFailure(hr, "Failed to initialize HTTP Server configuration"); 387 ExitOnFailure(hr, "Failed to initialize HTTP Server configuration");
@@ -339,70 +390,92 @@ static UINT SchedHttpSniSslCerts(
339 390
340 while (S_OK == (hr = WcaFetchRecord(hView, &hRec))) 391 while (S_OK == (hr = WcaFetchRecord(hView, &hRec)))
341 { 392 {
342 hr = WcaGetRecordString(hRec, hurqId, &sczId); 393 hr = WcaGetRecordString(hRec, hcqId, &sczId);
343 ExitOnFailure(hr, "Failed to get Wix4HttpSniSslCert.Wix4HttpSniSslCert"); 394 ExitOnFailure(hr, "Failed to get Wix6HttpCertificate.Wix6HttpCertificate");
344 395
345 hr = WcaGetRecordString(hRec, hurqComponent, &sczComponent); 396 hr = WcaGetRecordString(hRec, hcqComponent, &sczComponent);
346 ExitOnFailure(hr, "Failed to get Wix4HttpSniSslCert.Component_"); 397 ExitOnFailure(hr, "Failed to get Wix6HttpCertificate.Component_");
347 398
348 // Figure out what we're doing for this reservation, treating reinstall the same as install. 399 // Figure out what we're doing for this certificate, treating reinstall the same as install.
349 todoComponent = WcaGetComponentToDo(sczComponent); 400 todoComponent = WcaGetComponentToDo(sczComponent);
350 if ((WCA_TODO_REINSTALL == todoComponent ? WCA_TODO_INSTALL : todoComponent) != todoSched) 401 if ((WCA_TODO_REINSTALL == todoComponent ? WCA_TODO_INSTALL : todoComponent) != todoSched)
351 { 402 {
352 WcaLog(LOGMSG_STANDARD, "Component '%ls' action state (%d) doesn't match request (%d) for Wix4HttpSniSslCert '%ls'", sczComponent, todoComponent, todoSched, sczId); 403 WcaLog(LOGMSG_VERBOSE, "Component '%ls' action state (%d) doesn't match request (%d) for Wix6HttpCertificate '%ls'.", sczComponent, todoComponent, todoSched, sczId);
353 continue; 404 continue;
354 } 405 }
355 406
356 hr = WcaGetRecordFormattedString(hRec, hurqHost, &sczHost); 407 hr = WcaGetRecordInteger(hRec, hcqType, reinterpret_cast<int*>(&certificateType));
357 ExitOnFailure(hr, "Failed to get Wix4HttpSniSslCert.Host"); 408 ExitOnFailure(hr, "Failed to get Type for Wix6HttpCertificate '%ls'", sczId);
358 409
359 hr = WcaGetRecordFormattedInteger(hRec, hurqPort, &iPort); 410 hr = WcaGetRecordFormattedString(hRec, hcqHost, &sczHost);
360 ExitOnFailure(hr, "Failed to get Wix4HttpSniSslCert.Port"); 411 ExitOnFailure(hr, "Failed to get Wix6HttpCertificate.Host");
361 412
362 hr = WcaGetRecordFormattedString(hRec, hurqCertificateThumbprint, &sczCertificateThumbprint); 413 hr = WcaGetRecordFormattedInteger(hRec, hcqPort, &iPort);
363 ExitOnFailure(hr, "Failed to get Wix4HttpSniSslCert.CertificateThumbprint"); 414 ExitOnFailure(hr, "Failed to get Wix6HttpCertificate.Port");
364 415
365 if (!sczHost || !*sczHost) 416 hr = WcaGetRecordFormattedString(hRec, hcqCertificateThumbprint, &sczCertificateThumbprint);
366 { 417 ExitOnFailure(hr, "Failed to get Wix6HttpCertificate.CertificateThumbprint");
367 hr = E_INVALIDARG;
368 ExitOnFailure(hr, "Require a Host value for Wix4HttpSniSslCert '%ls'", sczId);
369 }
370 418
371 if (!iPort) 419 if (!iPort)
372 { 420 {
373 hr = E_INVALIDARG; 421 hr = E_INVALIDARG;
374 ExitOnFailure(hr, "Require a Port value for Wix4HttpSniSslCert '%ls'", sczId); 422 ExitOnFailure(hr, "Missing Port value for Wix6HttpCertificate '%ls'", sczId);
375 } 423 }
376 424
377 if (!sczCertificateThumbprint || !*sczCertificateThumbprint) 425 if (!sczCertificateThumbprint || !*sczCertificateThumbprint)
378 { 426 {
379 hr = E_INVALIDARG; 427 hr = E_INVALIDARG;
380 ExitOnFailure(hr, "Require a CertificateThumbprint value for Wix4HttpSniSslCert '%ls'", sczId); 428 ExitOnFailure(hr, "Missing CertificateThumbprint value for Wix6HttpCertificate '%ls'", sczId);
381 } 429 }
382 430
383 hr = WcaGetRecordFormattedString(hRec, hurqAppId, &sczAppId); 431 hr = WcaGetRecordFormattedString(hRec, hcqAppId, &sczAppId);
384 ExitOnFailure(hr, "Failed to get AppId for Wix4HttpSniSslCert '%ls'", sczId); 432 ExitOnFailure(hr, "Failed to get AppId for Wix6HttpCertificate '%ls'", sczId);
385 433
386 hr = WcaGetRecordFormattedString(hRec, hurqCertificateStore, &sczCertificateStore); 434 hr = WcaGetRecordFormattedString(hRec, hcqCertificateStore, &sczCertificateStore);
387 ExitOnFailure(hr, "Failed to get CertificateStore for Wix4HttpSniSslCert '%ls'", sczId); 435 ExitOnFailure(hr, "Failed to get CertificateStore for Wix6HttpCertificate '%ls'", sczId);
388 436
389 hr = WcaGetRecordInteger(hRec, hurqHandleExisting, &iHandleExisting); 437 hr = WcaGetRecordInteger(hRec, hcqHandleExisting, &iHandleExisting);
390 ExitOnFailure(hr, "Failed to get HandleExisting for Wix4HttpSniSslCert '%ls'", sczId); 438 ExitOnFailure(hr, "Failed to get HandleExisting for Wix6HttpCertificate '%ls'", sczId);
391 439
392 hr = GetSniSslCert(sczHost, iPort, &pExistingSniSslSet); 440 if (ctIpSsl == certificateType)
393 ExitOnFailure(hr, "Failed to get the existing SNI SSL certificate for Wix4HttpSniSslCert '%ls'", sczId); 441 {
442 WcaLog(LOGMSG_STANDARD, "Processing IP SSL certificate: %ls on port %d.", sczId, iPort);
443
444 hr = FindExistingIpSslCertificate(iPort, &pExistingIpSslSet);
445 ExitOnFailure(hr, "Failed to search for an existing IP SSL certificate for '%ls' on port %d", sczId, iPort);
394 446
395 hr = EnsureAppId(&sczAppId, pExistingSniSslSet); 447 if (S_FALSE != hr)
396 ExitOnFailure(hr, "Failed to ensure AppId for Wix4HttpSniSslCert '%ls'", sczId); 448 {
449 hr = WriteIpSslCertCustomActionData(todoComponent, sczId, iPort, iHandleExisting, pExistingIpSslSet, &sczRollbackCustomActionData);
450 ExitOnFailure(hr, "Failed to write rollback custom action data for IP SSL '%ls' on port %d", sczId, iPort);
451 }
397 452
398 hr = WriteExistingSniSslCert(todoComponent, sczId, sczHost, iPort, iHandleExisting, pExistingSniSslSet, &sczRollbackCustomActionData); 453 hr = EnsureAppId(&sczAppId, pExistingIpSslSet ? &(pExistingIpSslSet->ParamDesc.AppId) : NULL);
399 ExitOnFailure(hr, "Failed to write rollback custom action data for Wix4HttpSniSslCert '%ls'", sczId); 454 ExitOnFailure(hr, "Failed to ensure AppId for IP SSL '%ls'", sczId);
455 }
456 else if (ctSniSsl == certificateType)
457 {
458 WcaLog(LOGMSG_STANDARD, "Processing SNI SSL certificate: %ls on host %ls:%d.", sczId, sczHost, iPort);
400 459
401 hr = WriteSniSslCert(todoComponent, sczId, sczHost, iPort, iHandleExisting, sczCertificateThumbprint, sczAppId, sczCertificateStore, &sczCustomActionData); 460 hr = FindExistingSniSslCertificate(sczHost, iPort, &pExistingSniSslSet);
402 ExitOnFailure(hr, "Failed to write custom action data for Wix4HttpSniSslCert '%ls'", sczId); 461 ExitOnFailure(hr, "Failed to search for an existing SNI SSL certificate for '%ls' on host '%ls', port %d", sczId, sczHost, iPort);
462
463 if (S_FALSE != hr)
464 {
465 hr = WriteSniSslCertCustomActionData(todoComponent, sczId, sczHost, iPort, iHandleExisting, pExistingSniSslSet, &sczRollbackCustomActionData);
466 ExitOnFailure(hr, "Failed to write rollback custom action data for SNI SSL Wix6HttpCertificate '%ls' on host '%ls', port %d", sczId, sczHost, iPort);
467 }
468
469 hr = EnsureAppId(&sczAppId, pExistingSniSslSet ? &(pExistingSniSslSet->ParamDesc.AppId) : NULL);
470 ExitOnFailure(hr, "Failed to ensure AppId for SNI SSL '%ls'", sczId);
471 }
472
473 hr = WriteCertificateCaData(certificateType, todoComponent, sczId, sczHost, iPort, iHandleExisting, sczCertificateThumbprint, sczAppId, sczCertificateStore, &sczCustomActionData);
474 ExitOnFailure(hr, "Failed to write custom action data for SSL '%ls'", sczId);
403 ++cCertificates; 475 ++cCertificates;
404 476
405 ReleaseNullMem(pExistingSniSslSet); 477 ReleaseNullMem(pExistingSniSslSet);
478 ReleaseNullMem(pExistingIpSslSet);
406 } 479 }
407 480
408 // Reaching the end of the list is not an error. 481 // Reaching the end of the list is not an error.
@@ -410,36 +483,39 @@ static UINT SchedHttpSniSslCerts(
410 { 483 {
411 hr = S_OK; 484 hr = S_OK;
412 } 485 }
413 ExitOnFailure(hr, "Failure occurred while processing Wix4HttpSniSslCert table"); 486 ExitOnFailure(hr, "Failure occurred while processing Wix6HttpCertificate table");
487
488 WcaLog(LOGMSG_VERBOSE, "Scheduling %d certificates", cCertificates);
414 489
415 // Schedule ExecHttpSniSslCerts if there's anything to do. 490 // Schedule ExecHttpSniSslCerts if there's anything to do.
416 if (cCertificates) 491 if (cCertificates)
417 { 492 {
418 WcaLog(LOGMSG_STANDARD, "Scheduling SNI SSL certificate (%ls)", sczCustomActionData); 493 WcaLog(LOGMSG_TRACEONLY, "Scheduling SSL certificate: `%ls`", sczCustomActionData);
419 WcaLog(LOGMSG_STANDARD, "Scheduling rollback SNI SSL certificate (%ls)", sczRollbackCustomActionData); 494 WcaLog(LOGMSG_TRACEONLY, "Scheduling rollback SSL certificate: `%ls`", sczRollbackCustomActionData);
420 495
421 if (WCA_TODO_INSTALL == todoSched) 496 if (WCA_TODO_INSTALL == todoSched)
422 { 497 {
423 hr = WcaDoDeferredAction(CUSTOM_ACTION_DECORATION(L"RollbackHttpSniSslCertsInstall"), sczRollbackCustomActionData, cCertificates * COST_HTTP_SNI_SSL); 498 hr = WcaDoDeferredAction(CUSTOM_ACTION_DECORATION6(L"RollbackHttpCertificatesInstall"), sczRollbackCustomActionData, cCertificates * COST_HTTP_SNI_SSL);
424 ExitOnFailure(hr, "Failed to schedule install SNI SSL certificate rollback"); 499 ExitOnFailure(hr, "Failed to schedule install SSL certificate rollback");
425 hr = WcaDoDeferredAction(CUSTOM_ACTION_DECORATION(L"ExecHttpSniSslCertsInstall"), sczCustomActionData, cCertificates * COST_HTTP_SNI_SSL); 500 hr = WcaDoDeferredAction(CUSTOM_ACTION_DECORATION6(L"ExecHttpCertificatesInstall"), sczCustomActionData, cCertificates * COST_HTTP_SNI_SSL);
426 ExitOnFailure(hr, "Failed to schedule install SNI SSL certificate execution"); 501 ExitOnFailure(hr, "Failed to schedule install SSL certificate execution");
427 } 502 }
428 else 503 else
429 { 504 {
430 hr = WcaDoDeferredAction(CUSTOM_ACTION_DECORATION(L"RollbackHttpSniSslCertsUninstall"), sczRollbackCustomActionData, cCertificates * COST_HTTP_SNI_SSL); 505 hr = WcaDoDeferredAction(CUSTOM_ACTION_DECORATION6(L"RollbackHttpCertificatesUninstall"), sczRollbackCustomActionData, cCertificates * COST_HTTP_SNI_SSL);
431 ExitOnFailure(hr, "Failed to schedule uninstall SNI SSL certificate rollback"); 506 ExitOnFailure(hr, "Failed to schedule uninstall SSL certificate rollback");
432 hr = WcaDoDeferredAction(CUSTOM_ACTION_DECORATION(L"ExecHttpSniSslCertsUninstall"), sczCustomActionData, cCertificates * COST_HTTP_SNI_SSL); 507 hr = WcaDoDeferredAction(CUSTOM_ACTION_DECORATION6(L"ExecHttpCertificatesUninstall"), sczCustomActionData, cCertificates * COST_HTTP_SNI_SSL);
433 ExitOnFailure(hr, "Failed to schedule uninstall SNI SSL certificate execution"); 508 ExitOnFailure(hr, "Failed to schedule uninstall SSL certificate execution");
434 } 509 }
435 } 510 }
436 else 511 else
437 { 512 {
438 WcaLog(LOGMSG_STANDARD, "No SNI SSL certificates scheduled"); 513 WcaLog(LOGMSG_STANDARD, "No SNI SSL certificates scheduled.");
439 } 514 }
440 515
441LExit: 516LExit:
442 ReleaseMem(pExistingSniSslSet); 517 ReleaseMem(pExistingSniSslSet);
518 ReleaseMem(pExistingIpSslSet);
443 ReleaseStr(sczCertificateStore); 519 ReleaseStr(sczCertificateStore);
444 ReleaseStr(sczAppId); 520 ReleaseStr(sczAppId);
445 ReleaseStr(sczCertificateThumbprint); 521 ReleaseStr(sczCertificateThumbprint);
@@ -457,133 +533,171 @@ LExit:
457 return WcaFinalize(er = FAILED(hr) ? ERROR_INSTALL_FAILURE : er); 533 return WcaFinalize(er = FAILED(hr) ? ERROR_INSTALL_FAILURE : er);
458} 534}
459 535
460static HRESULT WriteExistingSniSslCert( 536static HRESULT FindExistingSniSslCertificate(
461 __in WCA_TODO action, 537 __in_z LPWSTR wzHost,
462 __in_z LPCWSTR wzId, 538 __in int nPort,
463 __in_z LPCWSTR wzHost, 539 __out HTTP_SERVICE_CONFIG_SSL_SNI_SET** ppSet
464 __in int iPort,
465 __in int iHandleExisting,
466 __in HTTP_SERVICE_CONFIG_SSL_SNI_SET* pSniSslSet,
467 __inout_z LPWSTR* psczCustomActionData
468) 540)
469{ 541{
470 HRESULT hr = S_OK; 542 HRESULT hr = S_OK;
471 LPWSTR sczCertificateThumbprint = NULL; 543 DWORD er = ERROR_SUCCESS;
472 LPWSTR sczAppId = NULL; 544 HTTP_SERVICE_CONFIG_SSL_SNI_QUERY query = { };
473 LPCWSTR wzCertificateStore = NULL; 545 HTTP_SERVICE_CONFIG_SSL_SNI_SET* pSet = NULL;
546 ULONG cbSet = 0;
474 547
475 if (pSniSslSet) 548 *ppSet = NULL;
476 {
477 hr = StrAllocHexEncode(reinterpret_cast<BYTE*>(pSniSslSet->ParamDesc.pSslHash), pSniSslSet->ParamDesc.SslHashLength, &sczCertificateThumbprint);
478 ExitOnFailure(hr, "Failed to convert existing certificate thumbprint to hex for Wix4HttpSniSslCert '%ls'", wzId);
479 549
480 hr = StringFromGuid(pSniSslSet->ParamDesc.AppId, &sczAppId); 550 query.QueryDesc = HttpServiceConfigQueryExact;
481 ExitOnFailure(hr, "Failed to copy existing AppId for Wix4HttpSniSslCert '%ls'", wzId); 551 SetSniSslCertificateKeyPort(&query.KeyDesc, wzHost, nPort);
482 552
483 wzCertificateStore = pSniSslSet->ParamDesc.pSslCertStoreName; 553 WcaLog(LOGMSG_TRACEONLY, "Querying for SNI SSL certificate on port %d...", nPort);
554
555 er = ::HttpQueryServiceConfiguration(NULL, HttpServiceConfigSslSniCertInfo, &query, sizeof(query), pSet, cbSet, &cbSet, NULL);
556 if (ERROR_INSUFFICIENT_BUFFER == er)
557 {
558 pSet = reinterpret_cast<HTTP_SERVICE_CONFIG_SSL_SNI_SET*>(MemAlloc(cbSet, TRUE));
559 ExitOnNull(pSet, hr, E_OUTOFMEMORY, "Failed to allocate query SN SSL certificate buffer");
560
561 er = ::HttpQueryServiceConfiguration(NULL, HttpServiceConfigSslSniCertInfo, &query, sizeof(query), pSet, cbSet, &cbSet, NULL);
484 } 562 }
485 563
486 hr = WriteSniSslCert(action, wzId, wzHost, iPort, iHandleExisting, sczCertificateThumbprint ? sczCertificateThumbprint : L"", sczAppId ? sczAppId : L"", wzCertificateStore ? wzCertificateStore : L"", psczCustomActionData); 564 if (ERROR_SUCCESS == er)
487 ExitOnFailure(hr, "Failed to write custom action data for Wix4HttpSniSslCert '%ls'", wzId); 565 {
566 *ppSet = pSet;
567 pSet = NULL;
568 }
569 else if (ERROR_FILE_NOT_FOUND == er || ERROR_NO_MORE_ITEMS == er)
570 {
571 hr = S_FALSE;
572 }
573 else
574 {
575 hr = HRESULT_FROM_WIN32(er);
576 }
488 577
489LExit: 578LExit:
490 ReleaseStr(sczAppId); 579 ReleaseMem(pSet);
491 ReleaseStr(sczCertificateThumbprint);
492 580
493 return hr; 581 return hr;
494} 582}
495 583
496static HRESULT WriteSniSslCert( 584static HRESULT FindExistingIpSslCertificate(
497 __in WCA_TODO action, 585 __in int nPort,
498 __in_z LPCWSTR wzId, 586 __out HTTP_SERVICE_CONFIG_SSL_SET** ppSet
499 __in_z LPCWSTR wzHost,
500 __in int iPort,
501 __in int iHandleExisting,
502 __in_z LPCWSTR wzCertificateThumbprint,
503 __in_z LPCWSTR wzAppId,
504 __in_z_opt LPCWSTR wzCertificateStore,
505 __inout_z LPWSTR* psczCustomActionData
506) 587)
507{ 588{
508 HRESULT hr = S_OK; 589 HRESULT hr = S_OK;
590 DWORD er = ERROR_SUCCESS;
591 HTTP_SERVICE_CONFIG_SSL_QUERY query = { };
592 SOCKADDR_IN sin = { };
593 HTTP_SERVICE_CONFIG_SSL_SET* pSet = NULL;
594 ULONG cbSet = 0;
509 595
510 hr = WcaWriteIntegerToCaData(action, psczCustomActionData); 596 *ppSet = NULL;
511 ExitOnFailure(hr, "Failed to write action to custom action data");
512
513 hr = WcaWriteStringToCaData(wzId, psczCustomActionData);
514 ExitOnFailure(hr, "Failed to write id to custom action data");
515 597
516 hr = WcaWriteStringToCaData(wzHost, psczCustomActionData); 598 query.QueryDesc = HttpServiceConfigQueryNext;
517 ExitOnFailure(hr, "Failed to write Host to custom action data");
518 599
519 hr = WcaWriteIntegerToCaData(iPort, psczCustomActionData); 600 SetIpSslCertificateKeyPort(&query.KeyDesc, &sin, nPort);
520 ExitOnFailure(hr, "Failed to write Port to custom action data");
521 601
522 hr = WcaWriteIntegerToCaData(iHandleExisting, psczCustomActionData); 602 WcaLog(LOGMSG_TRACEONLY, "Querying for IP SSL certificate on port %d...", nPort);
523 ExitOnFailure(hr, "Failed to write HandleExisting to custom action data");
524 603
525 hr = WcaWriteStringToCaData(wzCertificateThumbprint, psczCustomActionData); 604 er = ::HttpQueryServiceConfiguration(NULL, HttpServiceConfigSSLCertInfo, &query, sizeof(query), pSet, cbSet, &cbSet, NULL);
526 ExitOnFailure(hr, "Failed to write CertificateThumbprint to custom action data"); 605 if (ERROR_INSUFFICIENT_BUFFER == er)
606 {
607 pSet = reinterpret_cast<HTTP_SERVICE_CONFIG_SSL_SET*>(MemAlloc(cbSet, TRUE));
608 ExitOnNull(pSet, hr, E_OUTOFMEMORY, "Failed to allocate query IP SSL certificate buffer");
527 609
528 hr = WcaWriteStringToCaData(wzAppId, psczCustomActionData); 610 er = ::HttpQueryServiceConfiguration(NULL, HttpServiceConfigSSLCertInfo, &query, sizeof(query), pSet, cbSet, &cbSet, NULL);
529 ExitOnFailure(hr, "Failed to write AppId to custom action data"); 611 }
530 612
531 hr = WcaWriteStringToCaData(wzCertificateStore ? wzCertificateStore : L"", psczCustomActionData); 613 if (ERROR_SUCCESS == er)
532 ExitOnFailure(hr, "Failed to write CertificateStore to custom action data"); 614 {
615 *ppSet = pSet;
616 pSet = NULL;
617 }
618 else if (ERROR_FILE_NOT_FOUND == er || ERROR_NO_MORE_ITEMS == er)
619 {
620 hr = S_FALSE;
621 }
622 else
623 {
624 hr = HRESULT_FROM_WIN32(er);
625 }
533 626
534LExit: 627LExit:
628 ReleaseMem(pSet);
629
535 return hr; 630 return hr;
536} 631}
537 632
538static HRESULT EnsureAppId( 633static HRESULT WriteSniSslCertCustomActionData(
539 __inout_z LPWSTR* psczAppId, 634 __in WCA_TODO action,
540 __in_opt HTTP_SERVICE_CONFIG_SSL_SNI_SET* pExistingSniSslSet 635 __in_z LPCWSTR wzId,
636 __in_z LPCWSTR wzHost,
637 __in int iPort,
638 __in int iHandleExisting,
639 __in HTTP_SERVICE_CONFIG_SSL_SNI_SET* pSniSslSet,
640 __inout_z LPWSTR* psczCustomActionData
541) 641)
542{ 642{
543 HRESULT hr = S_OK; 643 HRESULT hr = S_OK;
544 RPC_STATUS rs = RPC_S_OK; 644 LPWSTR sczCertificateThumbprint = NULL;
545 GUID guid = { }; 645 LPWSTR sczAppId = NULL;
646 LPCWSTR wzCertificateStore = NULL;
546 647
547 if (!psczAppId || !*psczAppId || !**psczAppId) 648 if (pSniSslSet)
548 { 649 {
549 if (pExistingSniSslSet) 650 hr = StrAllocHexEncode(reinterpret_cast<BYTE*>(pSniSslSet->ParamDesc.pSslHash), pSniSslSet->ParamDesc.SslHashLength, &sczCertificateThumbprint);
550 { 651 ExitOnFailure(hr, "Failed to convert existing certificate thumbprint to hex for Wix6HttpCertificate '%ls'", wzId);
551 hr = StringFromGuid(pExistingSniSslSet->ParamDesc.AppId, psczAppId);
552 ExitOnFailure(hr, "Failed to ensure AppId guid");
553 }
554 else
555 {
556 rs = ::UuidCreate(&guid);
557 hr = HRESULT_FROM_RPC(rs);
558 ExitOnRootFailure(hr, "Failed to create guid for AppId");
559 652
560 hr = StringFromGuid(guid, psczAppId); 653 hr = StringFromGuid(pSniSslSet->ParamDesc.AppId, &sczAppId);
561 ExitOnFailure(hr, "Failed to ensure AppId guid"); 654 ExitOnFailure(hr, "Failed to copy existing AppId for Wix6HttpCertificate '%ls'", wzId);
562 } 655
656 wzCertificateStore = pSniSslSet->ParamDesc.pSslCertStoreName;
563 } 657 }
564 658
659 hr = WriteCertificateCaData(ctSniSsl, action, wzId, wzHost, iPort, iHandleExisting, sczCertificateThumbprint ? sczCertificateThumbprint : L"", sczAppId ? sczAppId : L"", wzCertificateStore ? wzCertificateStore : L"", psczCustomActionData);
660 ExitOnFailure(hr, "Failed to write custom action data for Wix6HttpCertificate '%ls'", wzId);
661
565LExit: 662LExit:
663 ReleaseStr(sczAppId);
664 ReleaseStr(sczCertificateThumbprint);
665
566 return hr; 666 return hr;
567} 667}
568 668
569static HRESULT StringFromGuid( 669static HRESULT WriteIpSslCertCustomActionData(
570 __in REFGUID rguid, 670 __in WCA_TODO action,
571 __inout_z LPWSTR* psczGuid 671 __in_z LPCWSTR wzId,
672 __in int iPort,
673 __in int iHandleExisting,
674 __in HTTP_SERVICE_CONFIG_SSL_SET* pSslSet,
675 __inout_z LPWSTR* psczCustomActionData
572) 676)
573{ 677{
574 HRESULT hr = S_OK; 678 HRESULT hr = S_OK;
575 WCHAR wzGuid[39]; 679 LPWSTR sczCertificateThumbprint = NULL;
680 LPWSTR sczAppId = NULL;
681 LPCWSTR wzCertificateStore = NULL;
576 682
577 if (!::StringFromGUID2(rguid, wzGuid, countof(wzGuid))) 683 if (pSslSet)
578 { 684 {
579 hr = E_OUTOFMEMORY; 685 hr = StrAllocHexEncode(reinterpret_cast<BYTE*>(pSslSet->ParamDesc.pSslHash), pSslSet->ParamDesc.SslHashLength, &sczCertificateThumbprint);
580 ExitOnRootFailure(hr, "Failed to convert guid into string"); 686 ExitOnFailure(hr, "Failed to convert existing IP SSL certificate thumbprint to hex for Wix6HttpCertificate '%ls'", wzId);
687
688 hr = StringFromGuid(pSslSet->ParamDesc.AppId, &sczAppId);
689 ExitOnFailure(hr, "Failed to copy existing IP SSL AppId for Wix6HttpCertificate '%ls'", wzId);
690
691 wzCertificateStore = pSslSet->ParamDesc.pSslCertStoreName;
581 } 692 }
582 693
583 hr = StrAllocString(psczGuid, wzGuid, 0); 694 hr = WriteCertificateCaData(ctIpSsl, action, wzId, /*wzHost*/NULL, iPort, iHandleExisting, sczCertificateThumbprint ? sczCertificateThumbprint : L"", sczAppId ? sczAppId : L"", wzCertificateStore ? wzCertificateStore : L"", psczCustomActionData);
584 ExitOnFailure(hr, "Failed to copy guid"); 695 ExitOnFailure(hr, "Failed to write custom action data for IP SSL Wix6HttpCertificate '%ls'", wzId);
585 696
586LExit: 697LExit:
698 ReleaseStr(sczAppId);
699 ReleaseStr(sczCertificateThumbprint);
700
587 return hr; 701 return hr;
588} 702}
589 703
@@ -601,7 +715,7 @@ static HRESULT AddSniSslCert(
601 DWORD er = ERROR_SUCCESS; 715 DWORD er = ERROR_SUCCESS;
602 HTTP_SERVICE_CONFIG_SSL_SNI_SET set = { }; 716 HTTP_SERVICE_CONFIG_SSL_SNI_SET set = { };
603 717
604 SetSniSslCertSetKey(&set.KeyDesc, wzHost, iPort); 718 SetSniSslCertificateKeyPort(&set.KeyDesc, wzHost, iPort);
605 set.ParamDesc.SslHashLength = cbCertificateThumbprint; 719 set.ParamDesc.SslHashLength = cbCertificateThumbprint;
606 set.ParamDesc.pSslHash = rgbCertificateThumbprint; 720 set.ParamDesc.pSslHash = rgbCertificateThumbprint;
607 set.ParamDesc.AppId = *pAppId; 721 set.ParamDesc.AppId = *pAppId;
@@ -620,38 +734,28 @@ static HRESULT AddSniSslCert(
620 return hr; 734 return hr;
621} 735}
622 736
623static HRESULT GetSniSslCert( 737static HRESULT AddIpSslCert(
624 __in_z LPWSTR wzHost, 738 __in_z LPCWSTR /*wzId*/,
625 __in int nPort, 739 __in int iPort,
626 __out HTTP_SERVICE_CONFIG_SSL_SNI_SET** ppSet 740 __in BYTE rgbCertificateThumbprint[],
741 __in DWORD cbCertificateThumbprint,
742 __in GUID* pAppId,
743 __in_z LPWSTR wzSslCertStore
627) 744)
628{ 745{
629 HRESULT hr = S_OK; 746 HRESULT hr = S_OK;
630 DWORD er = ERROR_SUCCESS; 747 DWORD er = ERROR_SUCCESS;
631 HTTP_SERVICE_CONFIG_SSL_SNI_QUERY query = { }; 748 HTTP_SERVICE_CONFIG_SSL_SET set = { };
632 HTTP_SERVICE_CONFIG_SSL_SNI_SET* pSet = NULL; 749 SOCKADDR_IN sin = { };
633 ULONG cbSet = 0;
634
635 *ppSet = NULL;
636
637 query.QueryDesc = HttpServiceConfigQueryExact;
638 SetSniSslCertSetKey(&query.KeyDesc, wzHost, nPort);
639
640 er = ::HttpQueryServiceConfiguration(NULL, HttpServiceConfigSslSniCertInfo, &query, sizeof(query), pSet, cbSet, &cbSet, NULL);
641 if (ERROR_INSUFFICIENT_BUFFER == er)
642 {
643 pSet = reinterpret_cast<HTTP_SERVICE_CONFIG_SSL_SNI_SET*>(MemAlloc(cbSet, TRUE));
644 ExitOnNull(pSet, hr, E_OUTOFMEMORY, "Failed to allocate query SN SSL certificate buffer");
645 750
646 er = ::HttpQueryServiceConfiguration(NULL, HttpServiceConfigSslSniCertInfo, &query, sizeof(query), pSet, cbSet, &cbSet, NULL); 751 SetIpSslCertificateKeyPort(&set.KeyDesc, &sin, iPort);
647 } 752 set.ParamDesc.SslHashLength = cbCertificateThumbprint;
753 set.ParamDesc.pSslHash = rgbCertificateThumbprint;
754 set.ParamDesc.AppId = *pAppId;
755 set.ParamDesc.pSslCertStoreName = wzSslCertStore;
648 756
649 if (ERROR_SUCCESS == er) 757 er = ::HttpSetServiceConfiguration(NULL, HttpServiceConfigSSLCertInfo, &set, sizeof(set), NULL);
650 { 758 if (ERROR_ALREADY_EXISTS == er)
651 *ppSet = pSet;
652 pSet = NULL;
653 }
654 else if (ERROR_FILE_NOT_FOUND == er)
655 { 759 {
656 hr = S_FALSE; 760 hr = S_FALSE;
657 } 761 }
@@ -660,14 +764,11 @@ static HRESULT GetSniSslCert(
660 hr = HRESULT_FROM_WIN32(er); 764 hr = HRESULT_FROM_WIN32(er);
661 } 765 }
662 766
663LExit:
664 ReleaseMem(pSet);
665
666 return hr; 767 return hr;
667} 768}
668 769
669static HRESULT RemoveSniSslCert( 770static HRESULT RemoveSniSslCert(
670 __in_z LPCWSTR /*wzId*/, 771 __in_z_opt LPCWSTR /*wzId*/,
671 __in_z LPWSTR wzHost, 772 __in_z LPWSTR wzHost,
672 __in int iPort 773 __in int iPort
673) 774)
@@ -676,10 +777,35 @@ static HRESULT RemoveSniSslCert(
676 DWORD er = ERROR_SUCCESS; 777 DWORD er = ERROR_SUCCESS;
677 HTTP_SERVICE_CONFIG_SSL_SNI_SET set = { }; 778 HTTP_SERVICE_CONFIG_SSL_SNI_SET set = { };
678 779
679 SetSniSslCertSetKey(&set.KeyDesc, wzHost, iPort); 780 SetSniSslCertificateKeyPort(&set.KeyDesc, wzHost, iPort);
680 781
681 er = ::HttpDeleteServiceConfiguration(NULL, HttpServiceConfigSslSniCertInfo, &set, sizeof(set), NULL); 782 er = ::HttpDeleteServiceConfiguration(NULL, HttpServiceConfigSslSniCertInfo, &set, sizeof(set), NULL);
682 if (ERROR_FILE_NOT_FOUND == er) 783 if (ERROR_FILE_NOT_FOUND == er || ERROR_NO_MORE_ITEMS == er)
784 {
785 hr = S_FALSE;
786 }
787 else
788 {
789 hr = HRESULT_FROM_WIN32(er);
790 }
791
792 return hr;
793}
794
795static HRESULT RemoveIpSslCert(
796 __in_z_opt LPCWSTR /*wzId*/,
797 __in int iPort
798)
799{
800 HRESULT hr = S_OK;
801 DWORD er = ERROR_SUCCESS;
802 HTTP_SERVICE_CONFIG_SSL_SET set = { };
803 SOCKADDR_IN sin = { };
804
805 SetIpSslCertificateKeyPort(&set.KeyDesc, &sin, iPort);
806
807 er = ::HttpDeleteServiceConfiguration(NULL, HttpServiceConfigSSLCertInfo, &set, sizeof(set), NULL);
808 if (ERROR_FILE_NOT_FOUND == er || ERROR_NO_MORE_ITEMS == er)
683 { 809 {
684 hr = S_FALSE; 810 hr = S_FALSE;
685 } 811 }
@@ -691,7 +817,7 @@ static HRESULT RemoveSniSslCert(
691 return hr; 817 return hr;
692} 818}
693 819
694static void SetSniSslCertSetKey( 820static void SetSniSslCertificateKeyPort(
695 __in HTTP_SERVICE_CONFIG_SSL_SNI_KEY* pKey, 821 __in HTTP_SERVICE_CONFIG_SSL_SNI_KEY* pKey,
696 __in_z LPWSTR wzHost, 822 __in_z LPWSTR wzHost,
697 __in int iPort 823 __in int iPort
@@ -702,3 +828,111 @@ static void SetSniSslCertSetKey(
702 pss->sin_family = AF_INET; 828 pss->sin_family = AF_INET;
703 pss->sin_port = htons(static_cast<USHORT>(iPort)); 829 pss->sin_port = htons(static_cast<USHORT>(iPort));
704} 830}
831
832static void SetIpSslCertificateKeyPort(
833 __in HTTP_SERVICE_CONFIG_SSL_KEY* pKey,
834 __in SOCKADDR_IN* pSin,
835 __in int iPort
836)
837{
838 pSin->sin_family = AF_INET;
839 pSin->sin_port = htons(static_cast<USHORT>(iPort));
840 pKey->pIpPort = reinterpret_cast<PSOCKADDR>(pSin);
841}
842
843static HRESULT EnsureAppId(
844 __inout_z LPWSTR* psczAppId,
845 __in_opt GUID* pGuid
846)
847{
848 HRESULT hr = S_OK;
849 GUID guid = { };
850
851 if (!psczAppId || !*psczAppId || !**psczAppId)
852 {
853 if (pGuid)
854 {
855 hr = StringFromGuid(*pGuid, psczAppId);
856 ExitOnFailure(hr, "Failed to ensure AppId guid");
857 }
858 else
859 {
860 hr = HRESULT_FROM_RPC(::UuidCreate(&guid));
861 ExitOnRootFailure(hr, "Failed to create guid for AppId");
862
863 hr = StringFromGuid(guid, psczAppId);
864 ExitOnFailure(hr, "Failed to ensure AppId guid");
865 }
866 }
867
868LExit:
869 return hr;
870}
871
872static HRESULT StringFromGuid(
873 __in REFGUID rguid,
874 __inout_z LPWSTR* psczGuid
875)
876{
877 HRESULT hr = S_OK;
878 WCHAR wzGuid[39];
879
880 if (!::StringFromGUID2(rguid, wzGuid, countof(wzGuid)))
881 {
882 hr = E_OUTOFMEMORY;
883 ExitOnRootFailure(hr, "Failed to convert guid into string");
884 }
885
886 hr = StrAllocString(psczGuid, wzGuid, 0);
887 ExitOnFailure(hr, "Failed to copy guid");
888
889LExit:
890 return hr;
891}
892
893static HRESULT WriteCertificateCaData(
894 __in eCertificateType certType,
895 __in WCA_TODO action,
896 __in_z LPCWSTR wzId,
897 __in_z_opt LPCWSTR wzHost,
898 __in int iPort,
899 __in int iHandleExisting,
900 __in_z LPCWSTR wzCertificateThumbprint,
901 __in_z_opt LPCWSTR wzAppId,
902 __in_z_opt LPCWSTR wzCertificateStore,
903 __inout_z LPWSTR* psczCustomActionData
904)
905{
906 HRESULT hr = S_OK;
907
908 hr = WcaWriteIntegerToCaData(certType, psczCustomActionData);
909 ExitOnFailure(hr, "Failed to write IP SSL certificate type to custom action data");
910
911 hr = WcaWriteIntegerToCaData(action, psczCustomActionData);
912 ExitOnFailure(hr, "Failed to write action to custom action data");
913
914 hr = WcaWriteStringToCaData(wzId, psczCustomActionData);
915 ExitOnFailure(hr, "Failed to write id to custom action data");
916
917 hr = WcaWriteStringToCaData(wzHost ? wzHost : L"", psczCustomActionData);
918 ExitOnFailure(hr, "Failed to write Host to custom action data");
919
920 hr = WcaWriteIntegerToCaData(iPort, psczCustomActionData);
921 ExitOnFailure(hr, "Failed to write Port to custom action data");
922
923 hr = WcaWriteIntegerToCaData(iHandleExisting, psczCustomActionData);
924 ExitOnFailure(hr, "Failed to write HandleExisting to custom action data");
925
926 hr = WcaWriteStringToCaData(wzCertificateThumbprint, psczCustomActionData);
927 ExitOnFailure(hr, "Failed to write CertificateThumbprint to custom action data");
928
929 hr = WcaWriteStringToCaData(wzAppId ? wzAppId : L"", psczCustomActionData);
930 ExitOnFailure(hr, "Failed to write AppId to custom action data");
931
932 hr = WcaWriteStringToCaData(wzCertificateStore ? wzCertificateStore : L"", psczCustomActionData);
933 ExitOnFailure(hr, "Failed to write CertificateStore to custom action data");
934
935LExit:
936 return hr;
937}
938
diff --git a/src/ext/Http/ca/precomp.h b/src/ext/Http/ca/precomp.h
index 42287cb2..bbd79ccf 100644
--- a/src/ext/Http/ca/precomp.h
+++ b/src/ext/Http/ca/precomp.h
@@ -23,3 +23,9 @@ enum eHandleExisting
23 heIgnore = 1, 23 heIgnore = 1,
24 heFail = 2 24 heFail = 2
25}; 25};
26
27enum eCertificateType
28{
29 ctSniSsl = 0,
30 ctIpSsl = 1,
31};
diff --git a/src/ext/Http/ca/wixhttpca.def b/src/ext/Http/ca/wixhttpca.def
index 281c5631..244bd987 100644
--- a/src/ext/Http/ca/wixhttpca.def
+++ b/src/ext/Http/ca/wixhttpca.def
@@ -7,6 +7,6 @@ EXPORTS
7 SchedHttpUrlReservationsInstall 7 SchedHttpUrlReservationsInstall
8 SchedHttpUrlReservationsUninstall 8 SchedHttpUrlReservationsUninstall
9 ExecHttpUrlReservations 9 ExecHttpUrlReservations
10 SchedHttpSniSslCertsInstall 10 SchedHttpCertificatesInstall
11 SchedHttpSniSslCertsUninstall 11 SchedHttpCertificatesUninstall
12 ExecHttpSniSslCerts 12 ExecHttpCertificates