834 lines
19 KiB
C++
834 lines
19 KiB
C++
//
|
|
// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
|
|
// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
|
|
// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
|
|
// PARTICULAR PURPOSE.
|
|
//
|
|
// Copyright (c) Microsoft Corporation. All rights reserved
|
|
//
|
|
// Abstract:
|
|
//
|
|
// This sample demonstrates how to set, query, and delete a SSL
|
|
// configuration for Hostname:Port based SSL endpoint binding(SNI)
|
|
// or port based wildcard binding when central certificate storage(CCS)
|
|
// is deployed.
|
|
//
|
|
// To use this sample, certificate must be present in some store under the
|
|
// Local Machine for a Hostname:Port based SSL endpoint binding.
|
|
//
|
|
// SslConfig <Port> [<Hostname> <CertSubjectName> <StoreName>]
|
|
//
|
|
// where:
|
|
//
|
|
// Port is port number for either hostname based or port based
|
|
// SSL binding.
|
|
//
|
|
// Hostname is the hostname for the hostname based binding.
|
|
//
|
|
// CertSubjectName is the subject name of the certificate to be associated
|
|
// with the SSL endpoint binding. This must be provided
|
|
// if hostname based binding is specified.
|
|
//
|
|
// StoreName is the store under the Local Machine where certificate
|
|
// is present. This must be provided if hostname based
|
|
// binding is specified.
|
|
//
|
|
|
|
#pragma warning(disable:4201) // nameless struct/union
|
|
#pragma warning(disable:4214) // bit field types other than int
|
|
|
|
#include <windows.h>
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <http.h>
|
|
#include <wincrypt.h>
|
|
#include <mstcpip.h>
|
|
|
|
//
|
|
// A unique identifier that can be used to identify this application
|
|
//
|
|
|
|
static const GUID AppId = {0xAAAABBBB, 0xCCCC, 0xDDDD, 0xEE, 0xEE, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00};
|
|
|
|
//
|
|
// Function prototypes.
|
|
//
|
|
|
|
_Must_inspect_result_
|
|
_Success_(return == ERROR_SUCCESS)
|
|
DWORD
|
|
ParseParameters(
|
|
int Argc,
|
|
_In_reads_(Argc) PWCHAR Argv[],
|
|
_Out_ PUSHORT Port,
|
|
_Outptr_result_maybenull_ PWSTR* Hostname,
|
|
_Outptr_result_maybenull_ PWSTR* CertSubjectName,
|
|
_Outptr_result_maybenull_ PWSTR* StoreName
|
|
);
|
|
|
|
DWORD
|
|
SniConfiguration(
|
|
USHORT Port,
|
|
_In_ PCWSTR Hostname,
|
|
_In_ PCWSTR CertSubjectName,
|
|
_In_ PCWSTR StoreName
|
|
);
|
|
|
|
DWORD
|
|
CcsConfiguration(
|
|
USHORT Port
|
|
);
|
|
|
|
int
|
|
__cdecl
|
|
wmain(
|
|
int Argc,
|
|
_In_reads_(Argc) PWCHAR Argv[]
|
|
)
|
|
{
|
|
DWORD Error = ERROR_SUCCESS;
|
|
PWSTR Hostname = NULL;
|
|
PWSTR CertSubjectName = NULL;
|
|
USHORT Port = 0;
|
|
PWSTR StoreName = NULL;
|
|
HTTPAPI_VERSION Version = HTTPAPI_VERSION_2;
|
|
BOOL ApiInitialized = FALSE;
|
|
|
|
//
|
|
// Get parameters from input command line.
|
|
//
|
|
|
|
Error = ParseParameters(Argc,
|
|
Argv,
|
|
&Port,
|
|
&Hostname,
|
|
&CertSubjectName,
|
|
&StoreName);
|
|
|
|
if (Error != ERROR_SUCCESS)
|
|
{
|
|
goto exit;
|
|
}
|
|
|
|
//
|
|
// Initialize HTTPAPI in config mode.
|
|
//
|
|
|
|
Error = HttpInitialize(Version, HTTP_INITIALIZE_CONFIG, NULL);
|
|
|
|
if (Error != ERROR_SUCCESS)
|
|
{
|
|
goto exit;
|
|
}
|
|
|
|
ApiInitialized = TRUE;
|
|
|
|
if (Hostname != NULL &&
|
|
CertSubjectName != NULL &&
|
|
StoreName != NULL)
|
|
{
|
|
Error = SniConfiguration(Port,
|
|
Hostname,
|
|
CertSubjectName,
|
|
StoreName);
|
|
}
|
|
else
|
|
{
|
|
Error = CcsConfiguration(Port);
|
|
}
|
|
|
|
if (Error != ERROR_SUCCESS)
|
|
{
|
|
goto exit;
|
|
}
|
|
|
|
wprintf(L"SSL set/query/delete configuration succeed.\n");
|
|
|
|
exit:
|
|
|
|
if (ApiInitialized)
|
|
{
|
|
HttpTerminate(HTTP_INITIALIZE_CONFIG, NULL);
|
|
ApiInitialized = FALSE;
|
|
}
|
|
|
|
if (Error != ERROR_SUCCESS)
|
|
{
|
|
wprintf(L"Error code = %#lx.\n", Error);
|
|
}
|
|
|
|
return Error;
|
|
}
|
|
|
|
/***************************************************************************++
|
|
|
|
Routine Description:
|
|
|
|
Get parameters from input command line.
|
|
|
|
Arguments:
|
|
|
|
Argc - The number of parameters.
|
|
|
|
Argv - The parameter array.
|
|
|
|
Port - Supplies a pointer to access the port.
|
|
|
|
Hostname - Supplies a pointer to access the hostname.
|
|
|
|
CertSubjectName - Supplies a pointer to access the subject name of a
|
|
certificate.
|
|
|
|
StoreName - Supplies a pointer to access the name of the store under Local
|
|
Machine where certificate is present.
|
|
|
|
Return Value:
|
|
|
|
Status.
|
|
|
|
--***************************************************************************/
|
|
_Must_inspect_result_
|
|
_Success_(return == ERROR_SUCCESS)
|
|
DWORD
|
|
ParseParameters(
|
|
int Argc,
|
|
_In_reads_(Argc) PWCHAR Argv[],
|
|
_Out_ PUSHORT Port,
|
|
_Outptr_result_maybenull_ PWSTR* Hostname,
|
|
_Outptr_result_maybenull_ PWSTR* CertSubjectName,
|
|
_Outptr_result_maybenull_ PWSTR* StoreName
|
|
)
|
|
{
|
|
DWORD Error = ERROR_SUCCESS;
|
|
DWORD TempPort = 0;
|
|
PWSTR HostnameString = NULL;
|
|
PWSTR PortString = NULL;
|
|
PWSTR CertSubjectNameString = NULL;
|
|
PWSTR StoreNameString = NULL;
|
|
PWSTR Remaining = NULL;
|
|
|
|
if (Argc == 2)
|
|
{
|
|
PortString = Argv[1];
|
|
}
|
|
else if (Argc == 5)
|
|
{
|
|
PortString = Argv[1];
|
|
HostnameString = Argv[2];
|
|
CertSubjectNameString = Argv[3];
|
|
StoreNameString = Argv[4];
|
|
}
|
|
else
|
|
{
|
|
wprintf(L"Usage: SslConfig <Port> [<Hostname> <CertSubjectName> <StoreName>]\n");
|
|
Error = ERROR_INVALID_PARAMETER;
|
|
goto exit;
|
|
}
|
|
|
|
TempPort = wcstoul(PortString, &Remaining, 0);
|
|
|
|
if (*Remaining != L'\0' ||
|
|
TempPort == 0 ||
|
|
TempPort > USHRT_MAX)
|
|
{
|
|
wprintf(L"%s is not a valid port.\n", PortString);
|
|
Error = ERROR_INVALID_PARAMETER;
|
|
goto exit;
|
|
}
|
|
|
|
//
|
|
// Everything succeeded. Commit results.
|
|
//
|
|
|
|
*Hostname = HostnameString;
|
|
*Port = (USHORT)TempPort;
|
|
*CertSubjectName = CertSubjectNameString;
|
|
*StoreName = StoreNameString;
|
|
|
|
Error = ERROR_SUCCESS;
|
|
|
|
exit:
|
|
|
|
return Error;
|
|
}
|
|
|
|
/***************************************************************************++
|
|
|
|
Routine Description:
|
|
|
|
Get certificate hash from the certificate subject name.
|
|
|
|
Arguments:
|
|
|
|
CertSubjectName - Subject name of the certificate to find.
|
|
|
|
StoreName - Name of the store under Local Machine where certificate
|
|
is present.
|
|
|
|
CertHash - Buffer to return certificate hash.
|
|
|
|
CertHashLength - Buffer length on input, hash length on output (element
|
|
count).
|
|
|
|
Return Value:
|
|
|
|
Status.
|
|
|
|
--***************************************************************************/
|
|
DWORD
|
|
GetCertificateHash(
|
|
_In_ PCWSTR CertSubjectName,
|
|
_In_ PCWSTR StoreName,
|
|
_Out_writes_bytes_to_(*CertHashLength, *CertHashLength) PBYTE CertHash,
|
|
_Inout_ PDWORD CertHashLength
|
|
)
|
|
{
|
|
HCERTSTORE SystemStore = NULL;
|
|
PCCERT_CONTEXT CertContext = NULL;
|
|
DWORD Error = ERROR_SUCCESS;
|
|
|
|
RtlZeroMemory(CertHash, *CertHashLength);
|
|
|
|
//
|
|
// Open the store under local machine.
|
|
//
|
|
|
|
SystemStore = CertOpenStore(CERT_STORE_PROV_SYSTEM,
|
|
0,
|
|
(HCRYPTPROV_LEGACY)NULL,
|
|
CERT_SYSTEM_STORE_LOCAL_MACHINE,
|
|
StoreName);
|
|
|
|
if (SystemStore == NULL)
|
|
{
|
|
Error = GetLastError();
|
|
goto exit;
|
|
}
|
|
|
|
//
|
|
// Find the certificate from the subject name and get the hash.
|
|
//
|
|
|
|
CertContext = CertFindCertificateInStore(SystemStore,
|
|
X509_ASN_ENCODING,
|
|
0,
|
|
CERT_FIND_SUBJECT_STR,
|
|
CertSubjectName,
|
|
NULL);
|
|
|
|
if (CertContext == NULL)
|
|
{
|
|
Error = GetLastError();
|
|
goto exit;
|
|
}
|
|
|
|
if (!CertGetCertificateContextProperty(CertContext,
|
|
CERT_HASH_PROP_ID,
|
|
CertHash,
|
|
CertHashLength))
|
|
{
|
|
|
|
Error = GetLastError();
|
|
goto exit;
|
|
}
|
|
|
|
exit:
|
|
|
|
//
|
|
// Free the certificate context.
|
|
//
|
|
|
|
if (CertContext != NULL)
|
|
{
|
|
CertFreeCertificateContext(CertContext);
|
|
}
|
|
|
|
//
|
|
// Close the certificate store if it was opened.
|
|
//
|
|
|
|
if (SystemStore != NULL)
|
|
{
|
|
CertCloseStore(SystemStore, 0);
|
|
}
|
|
|
|
return Error;
|
|
}
|
|
|
|
/***************************************************************************++
|
|
|
|
Routine Description:
|
|
|
|
Get certificate hash and set the SNI configuration.
|
|
|
|
Arguments:
|
|
|
|
SniKey - SSL endpoint key: host and port.
|
|
|
|
CertSubjectName - Subject name of the certificate to find.
|
|
|
|
StoreName - Name of the store under Local Machine where certificate
|
|
is present.
|
|
|
|
Return Value:
|
|
|
|
Status.
|
|
|
|
--***************************************************************************/
|
|
DWORD
|
|
SetSniConfiguration(
|
|
_In_ PHTTP_SERVICE_CONFIG_SSL_SNI_KEY SniKey,
|
|
_In_ PCWSTR CertSubjectName,
|
|
_In_ PCWSTR StoreName
|
|
)
|
|
{
|
|
DWORD Error = ERROR_SUCCESS;
|
|
BYTE CertHash[50] = {};
|
|
DWORD CertHashLength = ARRAYSIZE(CertHash);
|
|
HTTP_SERVICE_CONFIG_SSL_SNI_SET SniConfig = {};
|
|
|
|
Error = GetCertificateHash(CertSubjectName,
|
|
StoreName,
|
|
CertHash,
|
|
&CertHashLength);
|
|
|
|
if (Error != ERROR_SUCCESS)
|
|
{
|
|
goto exit;
|
|
}
|
|
|
|
SniConfig.KeyDesc = *SniKey;
|
|
SniConfig.ParamDesc.pSslHash = CertHash;
|
|
SniConfig.ParamDesc.SslHashLength = CertHashLength;
|
|
SniConfig.ParamDesc.pSslCertStoreName = (PWSTR)StoreName;
|
|
SniConfig.ParamDesc.AppId = AppId;
|
|
|
|
Error = HttpSetServiceConfiguration(NULL,
|
|
HttpServiceConfigSslSniCertInfo,
|
|
&SniConfig,
|
|
sizeof(SniConfig),
|
|
NULL);
|
|
|
|
exit:
|
|
|
|
return Error;
|
|
}
|
|
|
|
/***************************************************************************++
|
|
|
|
Routine Description:
|
|
|
|
Query the SNI configuration.
|
|
|
|
Arguments:
|
|
|
|
SniKey - SSL endpoint key: host and port.
|
|
|
|
Return Value:
|
|
|
|
Status.
|
|
|
|
--***************************************************************************/
|
|
DWORD
|
|
QuerySniConfiguration(
|
|
_In_ PHTTP_SERVICE_CONFIG_SSL_SNI_KEY SniKey
|
|
)
|
|
{
|
|
DWORD Error = ERROR_SUCCESS;
|
|
PHTTP_SERVICE_CONFIG_SSL_SNI_SET SniConfig = NULL;
|
|
HTTP_SERVICE_CONFIG_SSL_SNI_QUERY SniQuery = {};
|
|
DWORD ReturnLength = 0;
|
|
|
|
SniQuery.KeyDesc = *SniKey;
|
|
SniQuery.QueryDesc = HttpServiceConfigQueryExact;
|
|
|
|
//
|
|
// Get the size of the buffer required to query the config.
|
|
//
|
|
|
|
Error = HttpQueryServiceConfiguration(NULL,
|
|
HttpServiceConfigSslSniCertInfo,
|
|
&SniQuery,
|
|
sizeof(SniQuery),
|
|
NULL,
|
|
0,
|
|
&ReturnLength,
|
|
NULL);
|
|
|
|
if (Error != ERROR_INSUFFICIENT_BUFFER)
|
|
{
|
|
goto exit;
|
|
}
|
|
|
|
//
|
|
// Allocate buffer and query again.
|
|
//
|
|
|
|
SniConfig = (PHTTP_SERVICE_CONFIG_SSL_SNI_SET)malloc(ReturnLength);
|
|
|
|
if (SniConfig == NULL)
|
|
{
|
|
Error = ERROR_NOT_ENOUGH_MEMORY;
|
|
goto exit;
|
|
}
|
|
|
|
Error = HttpQueryServiceConfiguration(NULL,
|
|
HttpServiceConfigSslSniCertInfo,
|
|
&SniQuery,
|
|
sizeof(SniQuery),
|
|
SniConfig,
|
|
ReturnLength,
|
|
&ReturnLength,
|
|
NULL);
|
|
|
|
if (Error != ERROR_SUCCESS)
|
|
{
|
|
goto exit;
|
|
}
|
|
|
|
exit:
|
|
|
|
if (SniConfig != NULL)
|
|
{
|
|
free(SniConfig);
|
|
SniConfig = NULL;
|
|
}
|
|
|
|
return Error;
|
|
}
|
|
|
|
/***************************************************************************++
|
|
|
|
Routine Description:
|
|
|
|
Delete the SNI configuration.
|
|
|
|
Arguments:
|
|
|
|
SniKey - SSL endpoint key: host and port.
|
|
|
|
Return Value:
|
|
|
|
Status.
|
|
|
|
--***************************************************************************/
|
|
DWORD
|
|
DeleteSniConfiguration(
|
|
_In_ PHTTP_SERVICE_CONFIG_SSL_SNI_KEY SniKey
|
|
)
|
|
{
|
|
DWORD Error = ERROR_SUCCESS;
|
|
HTTP_SERVICE_CONFIG_SSL_SNI_SET SniConfig = {};
|
|
|
|
SniConfig.KeyDesc = *SniKey;
|
|
|
|
Error = HttpDeleteServiceConfiguration(NULL,
|
|
HttpServiceConfigSslSniCertInfo,
|
|
&SniConfig,
|
|
sizeof(SniConfig),
|
|
NULL);
|
|
return Error;
|
|
}
|
|
|
|
/***************************************************************************++
|
|
|
|
Routine Description:
|
|
|
|
Demonstrate how to set, query, and delete the hostname based SSL configuration.
|
|
|
|
Arguments:
|
|
|
|
Port - Port for the hostname based SSL binding.
|
|
|
|
Hostname - Hostname for the SSL binding.
|
|
|
|
CertSubjectName - Subject name of the certificate using in the SSL binding.
|
|
|
|
StoreName - Name of the store under Local Machine where certificate
|
|
is present.
|
|
|
|
Return Value:
|
|
|
|
Status.
|
|
|
|
--***************************************************************************/
|
|
DWORD
|
|
SniConfiguration(
|
|
USHORT Port,
|
|
_In_ PCWSTR Hostname,
|
|
_In_ PCWSTR CertSubjectName,
|
|
_In_ PCWSTR StoreName
|
|
)
|
|
{
|
|
DWORD Error = ERROR_SUCCESS;
|
|
HTTP_SERVICE_CONFIG_SSL_SNI_KEY SniKey = {};
|
|
|
|
//
|
|
// Create SniKey.
|
|
// N.B. An SNI binding is IP version agnostic but for API purposes we are
|
|
// required to specify the IP address to be (IPv4) 0.0.0.0 in the key.
|
|
//
|
|
|
|
SniKey.Host = (PWSTR)Hostname;
|
|
IN4ADDR_SETANY((PSOCKADDR_IN)&SniKey.IpPort);
|
|
SS_PORT(&SniKey.IpPort) = htons(Port);
|
|
|
|
//
|
|
// Create the SNI binding.
|
|
//
|
|
|
|
Error = SetSniConfiguration(&SniKey, CertSubjectName, StoreName);
|
|
|
|
if (Error != ERROR_SUCCESS)
|
|
{
|
|
goto exit;
|
|
}
|
|
|
|
//
|
|
// Query the SNI configuration.
|
|
//
|
|
|
|
Error = QuerySniConfiguration(&SniKey);
|
|
|
|
if (Error != ERROR_SUCCESS)
|
|
{
|
|
goto exit;
|
|
}
|
|
|
|
//
|
|
// Delete the SNI configuration.
|
|
//
|
|
|
|
Error = DeleteSniConfiguration(&SniKey);
|
|
|
|
if (Error != ERROR_SUCCESS)
|
|
{
|
|
goto exit;
|
|
}
|
|
|
|
exit:
|
|
|
|
return Error;
|
|
}
|
|
|
|
/***************************************************************************++
|
|
|
|
Routine Description:
|
|
|
|
Create the port based SSL binding.
|
|
|
|
Arguments:
|
|
|
|
CcsKey - CCS endpoint key.
|
|
|
|
Return Value:
|
|
|
|
Status.
|
|
|
|
--***************************************************************************/
|
|
DWORD
|
|
SetCcsConfiguration(
|
|
_In_ PHTTP_SERVICE_CONFIG_SSL_CCS_KEY CcsKey
|
|
)
|
|
{
|
|
DWORD Error = ERROR_SUCCESS;
|
|
HTTP_SERVICE_CONFIG_SSL_CCS_SET CcsConfig = {};
|
|
|
|
CcsConfig.KeyDesc = *CcsKey;
|
|
CcsConfig.ParamDesc.AppId = AppId;
|
|
|
|
Error = HttpSetServiceConfiguration(NULL,
|
|
HttpServiceConfigSslCcsCertInfo,
|
|
&CcsConfig,
|
|
sizeof(CcsConfig),
|
|
NULL);
|
|
|
|
return Error;
|
|
}
|
|
|
|
/***************************************************************************++
|
|
|
|
Routine Description:
|
|
|
|
Query the port based SSL binding.
|
|
|
|
Arguments:
|
|
|
|
CcsKey - CCS endpoint key: 0.0.0.0:Port.
|
|
|
|
Return Value:
|
|
|
|
Status.
|
|
|
|
--***************************************************************************/
|
|
DWORD
|
|
QueryCcsConfiguration(
|
|
_In_ PHTTP_SERVICE_CONFIG_SSL_CCS_KEY CcsKey
|
|
)
|
|
{
|
|
DWORD Error = ERROR_SUCCESS;
|
|
PHTTP_SERVICE_CONFIG_SSL_CCS_SET CcsConfig = NULL;
|
|
HTTP_SERVICE_CONFIG_SSL_CCS_QUERY CcsQuery = {};
|
|
DWORD ReturnLength = 0;
|
|
|
|
CcsQuery.KeyDesc = *CcsKey;
|
|
CcsQuery.QueryDesc = HttpServiceConfigQueryExact;
|
|
|
|
//
|
|
// Get the size of the buffer required to query the config.
|
|
//
|
|
|
|
Error = HttpQueryServiceConfiguration(NULL,
|
|
HttpServiceConfigSslCcsCertInfo,
|
|
&CcsQuery,
|
|
sizeof(CcsQuery),
|
|
NULL,
|
|
0,
|
|
&ReturnLength,
|
|
NULL);
|
|
|
|
if (Error != ERROR_INSUFFICIENT_BUFFER)
|
|
{
|
|
goto exit;
|
|
}
|
|
|
|
//
|
|
// Allocate buffer and query again.
|
|
//
|
|
|
|
CcsConfig = (PHTTP_SERVICE_CONFIG_SSL_CCS_SET)malloc(ReturnLength);
|
|
|
|
if (CcsConfig == NULL)
|
|
{
|
|
Error = ERROR_NOT_ENOUGH_MEMORY;
|
|
goto exit;
|
|
}
|
|
|
|
Error = HttpQueryServiceConfiguration(NULL,
|
|
HttpServiceConfigSslCcsCertInfo,
|
|
&CcsQuery,
|
|
sizeof(CcsQuery),
|
|
CcsConfig,
|
|
ReturnLength,
|
|
&ReturnLength,
|
|
NULL);
|
|
|
|
if (Error != ERROR_SUCCESS)
|
|
{
|
|
goto exit;
|
|
}
|
|
|
|
exit:
|
|
|
|
if (CcsConfig != NULL)
|
|
{
|
|
free(CcsConfig);
|
|
CcsConfig = NULL;
|
|
}
|
|
|
|
return Error;
|
|
}
|
|
|
|
/***************************************************************************++
|
|
|
|
Routine Description:
|
|
|
|
Delete the port based SSL binding.
|
|
|
|
Arguments:
|
|
|
|
CcsKey - CCS endpoint key.
|
|
|
|
Return Value:
|
|
|
|
Status.
|
|
|
|
--***************************************************************************/
|
|
DWORD
|
|
DeleteCcsConfiguration(
|
|
_In_ PHTTP_SERVICE_CONFIG_SSL_CCS_KEY CcsKey
|
|
)
|
|
{
|
|
DWORD Error = ERROR_SUCCESS;
|
|
HTTP_SERVICE_CONFIG_SSL_CCS_SET CcsConfig = {};
|
|
|
|
CcsConfig.KeyDesc = *CcsKey;
|
|
|
|
Error = HttpDeleteServiceConfiguration(NULL,
|
|
HttpServiceConfigSslCcsCertInfo,
|
|
&CcsConfig,
|
|
sizeof(CcsConfig),
|
|
NULL);
|
|
return Error;
|
|
}
|
|
|
|
/***************************************************************************++
|
|
|
|
Routine Description:
|
|
|
|
Demonstrate how to set, query, and delete a port based SSL binding.
|
|
|
|
Arguments:
|
|
|
|
Port - CCS binding port.
|
|
|
|
Return Value:
|
|
|
|
Status.
|
|
|
|
--***************************************************************************/
|
|
DWORD
|
|
CcsConfiguration(
|
|
USHORT Port
|
|
)
|
|
{
|
|
DWORD Error = ERROR_SUCCESS;
|
|
HTTP_SERVICE_CONFIG_SSL_CCS_KEY CcsKey = {};
|
|
|
|
//
|
|
// Create CcsKey.
|
|
// N.B. A CCS binding is IP version agnostic but for API purposes we are
|
|
// required to specify the IP address to be (IPv4) 0.0.0.0 in the key.
|
|
//
|
|
|
|
IN4ADDR_SETANY((PSOCKADDR_IN)&CcsKey.LocalAddress);
|
|
SS_PORT(&CcsKey.LocalAddress) = htons(Port);
|
|
|
|
//
|
|
// Create the port based SSL binding.
|
|
//
|
|
|
|
Error = SetCcsConfiguration(&CcsKey);
|
|
|
|
if (Error == ERROR_SUCCESS)
|
|
{
|
|
goto exit;
|
|
}
|
|
|
|
//
|
|
// Query the port based SSL binding.
|
|
//
|
|
|
|
Error = QueryCcsConfiguration(&CcsKey);
|
|
|
|
if (Error != ERROR_SUCCESS)
|
|
{
|
|
goto exit;
|
|
}
|
|
|
|
//
|
|
// Delete the port based SSL binding.
|
|
//
|
|
|
|
Error = DeleteCcsConfiguration(&CcsKey);
|
|
|
|
if (Error != ERROR_SUCCESS)
|
|
{
|
|
goto exit;
|
|
}
|
|
|
|
exit:
|
|
|
|
return Error;
|
|
}
|