public static HttpConfigSsl GetHttpSslConfig() { HttpConfigSsl result = new HttpConfigSsl(); int size; for (int count = 0;; count++) { HTTP_SERVICE_CONFIG_SSL_QUERY query = new HTTP_SERVICE_CONFIG_SSL_QUERY(HTTP_SERVICE_CONFIG_QUERY_TYPE.HttpServiceConfigQueryNext, new HTTP_SERVICE_CONFIG_SSL_KEY(), count); ErrorCode errorCode = HttpQueryServiceConfiguration(IntPtr.Zero, HTTP_SERVICE_CONFIG_ID.HttpServiceConfigSSLCertInfo, ref query, Marshal.SizeOf(query), null, 0, out size, IntPtr.Zero); if (errorCode != ErrorCode.ERROR_SUCCESS) { if (errorCode == ErrorCode.ERROR_NO_MORE_ITEMS) { break; } if (errorCode != ErrorCode.ERROR_INSUFFICIENT_BUFFER) { throw new Win32Exception((int)errorCode); } byte[] buffer = new byte[size]; fixed(byte *b = buffer) { errorCode = HttpQueryServiceConfiguration(IntPtr.Zero, HTTP_SERVICE_CONFIG_ID.HttpServiceConfigSSLCertInfo, ref query, Marshal.SizeOf(query), b, size, out size, IntPtr.Zero); if (errorCode != ErrorCode.ERROR_SUCCESS) { throw new Win32Exception((int)errorCode); } HTTP_SERVICE_CONFIG_SSL_SET output = (HTTP_SERVICE_CONFIG_SSL_SET)Marshal.PtrToStructure((IntPtr)b, typeof(HTTP_SERVICE_CONFIG_SSL_SET)); result.Add(output.KeyDesc, output.ParamDesc); } } } return(result); }
/// <summary> /// Fetches the current SSL certificate configuration. /// </summary> public static List<SslCertificateBinding> GetSslCertificateBindings() { List<SslCertificateBinding> bindings = new List<SslCertificateBinding>(); // initialize library. HttpError error = NativeMethods.HttpInitialize( new HTTPAPI_VERSION(1,0), HttpInitFlag.HTTP_INITIALIZE_CONFIG, IntPtr.Zero); if (error != HttpError.NO_ERROR) { throw ServiceResultException.Create( StatusCodes.BadUnexpectedError, "Could not initialize HTTP library.\r\nError={0}", error); } // set up the iterator. HTTP_SERVICE_CONFIG_SSL_QUERY query = new HTTP_SERVICE_CONFIG_SSL_QUERY(); query.QueryDesc = HTTP_SERVICE_CONFIG_QUERY_TYPE.HttpServiceConfigQueryNext; query.KeyDesc.pIpPort = IntPtr.Zero; IntPtr pInput = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(HTTP_SERVICE_CONFIG_SSL_QUERY))); NativeMethods.ZeroMemory(pInput, Marshal.SizeOf(typeof(HTTP_SERVICE_CONFIG_SSL_QUERY))); IntPtr pOutput = IntPtr.Zero; try { // loop through each record. for (query.dwToken = 0; error == HttpError.NO_ERROR; query.dwToken++) { // get the size of buffer to allocate. Marshal.StructureToPtr(query, pInput, true); int requiredBufferLength = 0; error = NativeMethods.HttpQueryServiceConfiguration( IntPtr.Zero, HTTP_SERVICE_CONFIG_ID.HttpServiceConfigSSLCertInfo, pInput, Marshal.SizeOf(typeof(HTTP_SERVICE_CONFIG_SSL_QUERY)), pOutput, requiredBufferLength, out requiredBufferLength, IntPtr.Zero); if (error == HttpError.ERROR_NO_MORE_ITEMS) { break; } if (error != HttpError.ERROR_INSUFFICIENT_BUFFER) { throw ServiceResultException.Create( StatusCodes.BadUnexpectedError, "Could not read SSL configuration information.\r\nError={0}", error); } // allocate the buffer. pOutput = Marshal.AllocHGlobal(requiredBufferLength); NativeMethods.ZeroMemory(pOutput, requiredBufferLength); // get the actual data. error = NativeMethods.HttpQueryServiceConfiguration( IntPtr.Zero, HTTP_SERVICE_CONFIG_ID.HttpServiceConfigSSLCertInfo, pInput, Marshal.SizeOf(typeof(HTTP_SERVICE_CONFIG_SSL_QUERY)), pOutput, requiredBufferLength, out requiredBufferLength, IntPtr.Zero); if (error != HttpError.NO_ERROR) { throw ServiceResultException.Create( StatusCodes.BadUnexpectedError, "Could not read SSL configuration information.\r\nError={0}", error); } HTTP_SERVICE_CONFIG_SSL_SET sslSet = (HTTP_SERVICE_CONFIG_SSL_SET)Marshal.PtrToStructure(pOutput, typeof(HTTP_SERVICE_CONFIG_SSL_SET)); short family = Marshal.ReadInt16(sslSet.KeyDesc.pIpPort); SslCertificateBinding binding = new SslCertificateBinding(); if (family == AF_INET) { SOCKADDR_IN inet = (SOCKADDR_IN)Marshal.PtrToStructure(sslSet.KeyDesc.pIpPort, typeof(SOCKADDR_IN)); binding.IPAddress = new IPAddress(inet.addr); binding.Port = inet.port; } if (family == AF_INET6) { SOCKADDR_IN6 inet = (SOCKADDR_IN6)Marshal.PtrToStructure(sslSet.KeyDesc.pIpPort, typeof(SOCKADDR_IN6)); binding.IPAddress = new IPAddress(inet.addr, inet.scopeID); binding.Port = inet.port; } binding.Port = (ushort)(((binding.Port & 0xFF00) >> 8) | ((binding.Port & 0x00FF) << 8)); byte[] bytes = new byte[sslSet.ParamDesc.SslHashLength]; Marshal.Copy(sslSet.ParamDesc.pSslHash, bytes, 0, bytes.Length); binding.Thumbprint = Utils.ToHexString(bytes); binding.ApplicationId = sslSet.ParamDesc.AppId; binding.StoreName = sslSet.ParamDesc.pSslCertStoreName; binding.DefaultCertCheckMode = sslSet.ParamDesc.DefaultCertCheckMode; binding.DefaultRevocationFreshnessTime = sslSet.ParamDesc.DefaultRevocationFreshnessTime; binding.DefaultRevocationUrlRetrievalTimeout = sslSet.ParamDesc.DefaultRevocationUrlRetrievalTimeout; binding.DefaultSslCtlIdentifier = sslSet.ParamDesc.pDefaultSslCtlIdentifier; binding.DefaultSslCtlStoreName = sslSet.ParamDesc.pDefaultSslCtlStoreName; binding.DefaultFlags = sslSet.ParamDesc.DefaultFlags; bindings.Add(binding); Marshal.FreeHGlobal(pOutput); pOutput = IntPtr.Zero; } } finally { if (pInput != IntPtr.Zero) { Marshal.DestroyStructure(pInput, typeof(HTTP_SERVICE_CONFIG_SSL_QUERY)); Marshal.FreeHGlobal(pInput); } if (pOutput != IntPtr.Zero) { Marshal.FreeHGlobal(pOutput); } NativeMethods.HttpTerminate(HttpInitFlag.HTTP_INITIALIZE_CONFIG, IntPtr.Zero); } return bindings; }
/// <summary> /// Fetches the current SSL certificate configuration. /// </summary> public static List <SslCertificateBinding> GetSslCertificateBindings() { List <SslCertificateBinding> bindings = new List <SslCertificateBinding>(); // initialize library. HttpError error = NativeMethods.HttpInitialize( new HTTPAPI_VERSION(1, 0), HttpInitFlag.HTTP_INITIALIZE_CONFIG, IntPtr.Zero); if (error != HttpError.NO_ERROR) { throw ServiceResultException.Create( StatusCodes.BadUnexpectedError, "Could not initialize HTTP library.\r\nError={0}", error); } // set up the iterator. HTTP_SERVICE_CONFIG_SSL_QUERY query = new HTTP_SERVICE_CONFIG_SSL_QUERY(); query.QueryDesc = HTTP_SERVICE_CONFIG_QUERY_TYPE.HttpServiceConfigQueryNext; query.KeyDesc.pIpPort = IntPtr.Zero; IntPtr pInput = Marshal.AllocHGlobal(Marshal.SizeOf <HTTP_SERVICE_CONFIG_SSL_QUERY>()); NativeMethods.ZeroMemory(pInput, Marshal.SizeOf <HTTP_SERVICE_CONFIG_SSL_QUERY>()); IntPtr pOutput = IntPtr.Zero; try { // loop through each record. for (query.dwToken = 0; error == HttpError.NO_ERROR; query.dwToken++) { // get the size of buffer to allocate. Marshal.StructureToPtr(query, pInput, true); int requiredBufferLength = 0; error = NativeMethods.HttpQueryServiceConfiguration( IntPtr.Zero, HTTP_SERVICE_CONFIG_ID.HttpServiceConfigSSLCertInfo, pInput, Marshal.SizeOf <HTTP_SERVICE_CONFIG_SSL_QUERY>(), pOutput, requiredBufferLength, out requiredBufferLength, IntPtr.Zero); if (error == HttpError.ERROR_NO_MORE_ITEMS) { break; } if (error != HttpError.ERROR_INSUFFICIENT_BUFFER) { throw ServiceResultException.Create( StatusCodes.BadUnexpectedError, "Could not read SSL configuration information.\r\nError={0}", error); } // allocate the buffer. pOutput = Marshal.AllocHGlobal(requiredBufferLength); NativeMethods.ZeroMemory(pOutput, requiredBufferLength); // get the actual data. error = NativeMethods.HttpQueryServiceConfiguration( IntPtr.Zero, HTTP_SERVICE_CONFIG_ID.HttpServiceConfigSSLCertInfo, pInput, Marshal.SizeOf <HTTP_SERVICE_CONFIG_SSL_QUERY>(), pOutput, requiredBufferLength, out requiredBufferLength, IntPtr.Zero); if (error != HttpError.NO_ERROR) { throw ServiceResultException.Create( StatusCodes.BadUnexpectedError, "Could not read SSL configuration information.\r\nError={0}", error); } HTTP_SERVICE_CONFIG_SSL_SET sslSet = (HTTP_SERVICE_CONFIG_SSL_SET)Marshal.PtrToStructure <HTTP_SERVICE_CONFIG_SSL_SET>(pOutput); short family = Marshal.ReadInt16(sslSet.KeyDesc.pIpPort); SslCertificateBinding binding = new SslCertificateBinding(); if (family == AF_INET) { SOCKADDR_IN inet = (SOCKADDR_IN)Marshal.PtrToStructure <SOCKADDR_IN>(sslSet.KeyDesc.pIpPort); binding.IPAddress = new IPAddress(inet.addr); binding.Port = inet.port; } if (family == AF_INET6) { SOCKADDR_IN6 inet = (SOCKADDR_IN6)Marshal.PtrToStructure <SOCKADDR_IN6>(sslSet.KeyDesc.pIpPort); binding.IPAddress = new IPAddress(inet.addr, inet.scopeID); binding.Port = inet.port; } binding.Port = (ushort)(((binding.Port & 0xFF00) >> 8) | ((binding.Port & 0x00FF) << 8)); byte[] bytes = new byte[sslSet.ParamDesc.SslHashLength]; Marshal.Copy(sslSet.ParamDesc.pSslHash, bytes, 0, bytes.Length); binding.Thumbprint = Utils.ToHexString(bytes); binding.ApplicationId = sslSet.ParamDesc.AppId; binding.StoreName = sslSet.ParamDesc.pSslCertStoreName; binding.DefaultCertCheckMode = sslSet.ParamDesc.DefaultCertCheckMode; binding.DefaultRevocationFreshnessTime = sslSet.ParamDesc.DefaultRevocationFreshnessTime; binding.DefaultRevocationUrlRetrievalTimeout = sslSet.ParamDesc.DefaultRevocationUrlRetrievalTimeout; binding.DefaultSslCtlIdentifier = sslSet.ParamDesc.pDefaultSslCtlIdentifier; binding.DefaultSslCtlStoreName = sslSet.ParamDesc.pDefaultSslCtlStoreName; binding.DefaultFlags = sslSet.ParamDesc.DefaultFlags; bindings.Add(binding); Marshal.FreeHGlobal(pOutput); pOutput = IntPtr.Zero; } } finally { if (pInput != IntPtr.Zero) { Marshal.DestroyStructure <HTTP_SERVICE_CONFIG_SSL_QUERY>(pInput); Marshal.FreeHGlobal(pInput); } if (pOutput != IntPtr.Zero) { Marshal.FreeHGlobal(pOutput); } NativeMethods.HttpTerminate(HttpInitFlag.HTTP_INITIALIZE_CONFIG, IntPtr.Zero); } return(bindings); }
static extern ErrorCode HttpQueryServiceConfiguration(IntPtr nullHandle, HTTP_SERVICE_CONFIG_ID ConfigId, ref HTTP_SERVICE_CONFIG_SSL_QUERY pInputConfigInfo, int InputConfigInfoLength, byte *pOutputConfigInfo, int OutputConfigInfoLength, out int pReturnLength, IntPtr pOverlapped);
/// <summary> /// Возвращает информацию о привязке сертификата к сетевому адресу и порту. /// </summary> public static BindCertificateInfo GetBindCertificate(IPEndPoint endPoint) { BindCertificateInfo result = null; CallHttpApi(() => { var socketAddressHandle = CreateNativeSocketAddress(endPoint); var socketAddressPtr = socketAddressHandle.AddrOfPinnedObject(); // Запрос на получение записи конфигурации var query = new HTTP_SERVICE_CONFIG_SSL_QUERY { QueryDesc = HTTP_SERVICE_CONFIG_QUERY_TYPE.HttpServiceConfigQueryExact, KeyDesc = new HTTP_SERVICE_CONFIG_SSL_KEY(socketAddressPtr) }; var queryPtr = Marshal.AllocCoTaskMem(Marshal.SizeOf(typeof(HTTP_SERVICE_CONFIG_SSL_QUERY))); Marshal.StructureToPtr(query, queryPtr, false); var queryResultSize = 0; var queryResultPtr = IntPtr.Zero; const HTTP_SERVICE_CONFIG_ID queryType = HTTP_SERVICE_CONFIG_ID.HttpServiceConfigSSLCertInfo; try { // Получение записи конфигурации var querySize = Marshal.SizeOf(query); var invokeResult = HttpQueryServiceConfiguration(IntPtr.Zero, queryType, queryPtr, querySize, queryResultPtr, queryResultSize, out queryResultSize, IntPtr.Zero); // По запросу ничего не найдено if (invokeResult == ERROR_FILE_NOT_FOUND) { return; } // Недостаточный размер буфера для помещения результата запроса if (invokeResult == ERROR_INSUFFICIENT_BUFFER) { queryResultPtr = Marshal.AllocCoTaskMem(queryResultSize); try { // Получение записи конфигурации (вторая попытка) invokeResult = HttpQueryServiceConfiguration(IntPtr.Zero, queryType, queryPtr, querySize, queryResultPtr, queryResultSize, out queryResultSize, IntPtr.Zero); ThrowWin32ExceptionIfError(invokeResult); // Интерпретация полученного результата запроса из указателя var queryResult = (HTTP_SERVICE_CONFIG_SSL_SET) Marshal.PtrToStructure(queryResultPtr, typeof(HTTP_SERVICE_CONFIG_SSL_SET)); var certificate = new byte[queryResult.ParamDesc.SslHashLength]; Marshal.Copy(queryResult.ParamDesc.pSslHash, certificate, 0, certificate.Length); StoreName certificateStore; Enum.TryParse(queryResult.ParamDesc.pSslCertStoreName, out certificateStore); result = new BindCertificateInfo { EndPoint = endPoint, Certificate = certificate, CertificateStore = certificateStore, ApplicationId = queryResult.ParamDesc.AppId }; } finally { Marshal.FreeCoTaskMem(queryResultPtr); } } else { ThrowWin32ExceptionIfError(invokeResult); } } finally { Marshal.FreeCoTaskMem(queryPtr); if (socketAddressHandle.IsAllocated) { socketAddressHandle.Free(); } } }); return(result); }
/// <summary> /// Возвращает список с информацией о привязках сертификатов к сетевому адресу и порту. /// </summary> public static BindCertificateInfo[] GetBindCertificates() { var result = new List <BindCertificateInfo>(); CallHttpApi(() => { uint index = 0; uint invokeResult; do { // Запрос на получение записи конфигурации var query = new HTTP_SERVICE_CONFIG_SSL_QUERY { QueryDesc = HTTP_SERVICE_CONFIG_QUERY_TYPE.HttpServiceConfigQueryNext, dwToken = index }; var queryPtr = Marshal.AllocCoTaskMem(Marshal.SizeOf(typeof(HTTP_SERVICE_CONFIG_SSL_QUERY))); Marshal.StructureToPtr(query, queryPtr, false); var queryResultSize = 0; var queryResultPtr = IntPtr.Zero; const HTTP_SERVICE_CONFIG_ID queryType = HTTP_SERVICE_CONFIG_ID.HttpServiceConfigSSLCertInfo; try { // Получение записи конфигурации var querySize = Marshal.SizeOf(query); invokeResult = HttpQueryServiceConfiguration(IntPtr.Zero, queryType, queryPtr, querySize, queryResultPtr, queryResultSize, out queryResultSize, IntPtr.Zero); // Перечисление не содержит элементов if (invokeResult == ERROR_NO_MORE_ITEMS) { break; } // Недостаточный размер буфера для помещения результата запроса if (invokeResult == ERROR_INSUFFICIENT_BUFFER) { queryResultPtr = Marshal.AllocCoTaskMem(queryResultSize); try { // Получение записи конфигурации (вторая попытка) invokeResult = HttpQueryServiceConfiguration(IntPtr.Zero, queryType, queryPtr, querySize, queryResultPtr, queryResultSize, out queryResultSize, IntPtr.Zero); ThrowWin32ExceptionIfError(invokeResult); // Интерпретация полученного результата запроса из указателя var queryResult = (HTTP_SERVICE_CONFIG_SSL_SET) Marshal.PtrToStructure(queryResultPtr, typeof(HTTP_SERVICE_CONFIG_SSL_SET)); var certificate = new byte[queryResult.ParamDesc.SslHashLength]; Marshal.Copy(queryResult.ParamDesc.pSslHash, certificate, 0, certificate.Length); StoreName certificateStore; Enum.TryParse(queryResult.ParamDesc.pSslCertStoreName, out certificateStore); result.Add(new BindCertificateInfo { EndPoint = CreateManagedSocketAddress(queryResult.KeyDesc.pIpPort), Certificate = certificate, CertificateStore = certificateStore, ApplicationId = queryResult.ParamDesc.AppId }); index++; } finally { Marshal.FreeCoTaskMem(queryResultPtr); } } else { ThrowWin32ExceptionIfError(invokeResult); } } finally { Marshal.FreeCoTaskMem(queryPtr); } }while (invokeResult == NOERROR); }); return(result.ToArray()); }
public static SslCertificateInfo[] QuerySslCertificateInfo() { var result = new List<SslCertificateInfo>(); CallHttpApi( delegate { uint token = 0; uint retVal; do { HTTP_SERVICE_CONFIG_SSL_QUERY inputConfigInfoQuery = new HTTP_SERVICE_CONFIG_SSL_QUERY { QueryDesc = HTTP_SERVICE_CONFIG_QUERY_TYPE.HttpServiceConfigQueryNext, dwToken = token }; IntPtr pInputConfigInfo = Marshal.AllocCoTaskMem(Marshal.SizeOf(typeof(HTTP_SERVICE_CONFIG_SSL_QUERY))); Marshal.StructureToPtr(inputConfigInfoQuery, pInputConfigInfo, false); IntPtr pOutputConfigInfo = IntPtr.Zero; int returnLength = 0; const HTTP_SERVICE_CONFIG_ID queryType = HTTP_SERVICE_CONFIG_ID.HttpServiceConfigSSLCertInfo; try { int inputConfigInfoSize = Marshal.SizeOf(inputConfigInfoQuery); retVal = HttpQueryServiceConfiguration(IntPtr.Zero, queryType, pInputConfigInfo, inputConfigInfoSize, pOutputConfigInfo, returnLength, out returnLength, IntPtr.Zero); if (ERROR_NO_MORE_ITEMS == retVal) break; if (ERROR_INSUFFICIENT_BUFFER == retVal) // ERROR_INSUFFICIENT_BUFFER = 122 { pOutputConfigInfo = Marshal.AllocCoTaskMem(returnLength); try { retVal = HttpQueryServiceConfiguration( IntPtr.Zero, queryType, pInputConfigInfo, inputConfigInfoSize, pOutputConfigInfo, returnLength, out returnLength, IntPtr.Zero); ThrowWin32ExceptionIfError(retVal); var outputConfigInfo = (HTTP_SERVICE_CONFIG_SSL_SET) Marshal.PtrToStructure(pOutputConfigInfo, typeof(HTTP_SERVICE_CONFIG_SSL_SET)); byte[] hash = new byte[outputConfigInfo.ParamDesc.SslHashLength]; Marshal.Copy(outputConfigInfo.ParamDesc.pSslHash, hash, 0, hash.Length); Guid appId = outputConfigInfo.ParamDesc.AppId; string storeName = outputConfigInfo.ParamDesc.pSslCertStoreName; IPEndPoint ipPort = ReadSockaddrStructure(outputConfigInfo.KeyDesc.pIpPort); var resultItem = new SslCertificateInfo { AppId = appId, Hash = hash, StoreName = storeName, IpPort = ipPort }; result.Add(resultItem); token++; } finally { Marshal.FreeCoTaskMem(pOutputConfigInfo); } } else { ThrowWin32ExceptionIfError(retVal); } } finally { Marshal.FreeCoTaskMem(pInputConfigInfo); } } while (NOERROR == retVal); }); return result.ToArray(); }
public static SslCertificateInfo QuerySslCertificateInfo(IPEndPoint ipPort) { SslCertificateInfo result = null; uint retVal; CallHttpApi(delegate { GCHandle sockAddrHandle = CreateSockaddrStructure(ipPort); IntPtr pIpPort = sockAddrHandle.AddrOfPinnedObject(); HTTP_SERVICE_CONFIG_SSL_KEY sslKey = new HTTP_SERVICE_CONFIG_SSL_KEY(pIpPort); HTTP_SERVICE_CONFIG_SSL_QUERY inputConfigInfoQuery = new HTTP_SERVICE_CONFIG_SSL_QUERY { QueryDesc = HTTP_SERVICE_CONFIG_QUERY_TYPE.HttpServiceConfigQueryExact, KeyDesc = sslKey }; IntPtr pInputConfigInfo = Marshal.AllocCoTaskMem(Marshal.SizeOf(typeof(HTTP_SERVICE_CONFIG_SSL_QUERY))); Marshal.StructureToPtr(inputConfigInfoQuery, pInputConfigInfo, false); IntPtr pOutputConfigInfo = IntPtr.Zero; int returnLength = 0; try { HTTP_SERVICE_CONFIG_ID queryType = HTTP_SERVICE_CONFIG_ID.HttpServiceConfigSSLCertInfo; int inputConfigInfoSize = Marshal.SizeOf(inputConfigInfoQuery); retVal = HttpQueryServiceConfiguration(IntPtr.Zero, queryType, pInputConfigInfo, inputConfigInfoSize, pOutputConfigInfo, returnLength, out returnLength, IntPtr.Zero); if (retVal == ERROR_FILE_NOT_FOUND) return; if (ERROR_INSUFFICIENT_BUFFER == retVal) // ERROR_INSUFFICIENT_BUFFER = 122 { pOutputConfigInfo = Marshal.AllocCoTaskMem(returnLength); try { retVal = HttpQueryServiceConfiguration(IntPtr.Zero, queryType, pInputConfigInfo, inputConfigInfoSize, pOutputConfigInfo, returnLength, out returnLength, IntPtr.Zero); ThrowWin32ExceptionIfError(retVal); var outputConfigInfo = (HTTP_SERVICE_CONFIG_SSL_SET) Marshal.PtrToStructure(pOutputConfigInfo, typeof(HTTP_SERVICE_CONFIG_SSL_SET)); byte[] hash = new byte[outputConfigInfo.ParamDesc.SslHashLength]; Marshal.Copy(outputConfigInfo.ParamDesc.pSslHash, hash, 0, hash.Length); Guid appId = outputConfigInfo.ParamDesc.AppId; string storeName = outputConfigInfo.ParamDesc.pSslCertStoreName; result = new SslCertificateInfo { AppId = appId, Hash = hash, StoreName = storeName, IpPort = ipPort }; } finally { Marshal.FreeCoTaskMem(pOutputConfigInfo); } } else { ThrowWin32ExceptionIfError(retVal); } } finally { Marshal.FreeCoTaskMem(pInputConfigInfo); if (sockAddrHandle.IsAllocated) sockAddrHandle.Free(); } }); return result; }
public static SslCertificateBinding[] GetSslCertificateBindings() { InitializeHttp(); try { var bindings = new List <SslCertificateBinding>(); uint recordNum = 0; while (true) { var inputConfigInfoQuery = new HTTP_SERVICE_CONFIG_SSL_QUERY { QueryDesc = HTTP_SERVICE_CONFIG_QUERY_TYPE.HttpServiceConfigQueryNext, dwToken = recordNum++ }; var size = Marshal.SizeOf(typeof(HTTP_SERVICE_CONFIG_SSL_QUERY)); var pInputConfigInfo = Marshal.AllocCoTaskMem(size); Marshal.StructureToPtr(inputConfigInfoQuery, pInputConfigInfo, false); var pOutputConfigInfo = Marshal.AllocCoTaskMem(0); var returnLength = 0; var retVal = HttpQueryServiceConfiguration(IntPtr.Zero, HTTP_SERVICE_CONFIG_ID.HttpServiceConfigSSLCertInfo, pInputConfigInfo, Marshal.SizeOf(inputConfigInfoQuery), pOutputConfigInfo, returnLength, out returnLength, IntPtr.Zero); if (Win32ErrorCodes.InsufficientBuffer == retVal) { Marshal.FreeCoTaskMem(pOutputConfigInfo); pOutputConfigInfo = Marshal.AllocCoTaskMem(Convert.ToInt32(returnLength)); retVal = HttpQueryServiceConfiguration(IntPtr.Zero, HTTP_SERVICE_CONFIG_ID.HttpServiceConfigSSLCertInfo, pInputConfigInfo, Marshal.SizeOf(inputConfigInfoQuery), pOutputConfigInfo, returnLength, out returnLength, IntPtr.Zero); } else if (Win32ErrorCodes.NoMoreItems == retVal) { break; } if (Win32ErrorCodes.Ok == retVal) { var outputConfigInfo = (HTTP_SERVICE_CONFIG_SSL_SET) Marshal.PtrToStructure(pOutputConfigInfo, typeof(HTTP_SERVICE_CONFIG_SSL_SET)); var paramInfo = outputConfigInfo.ParamDesc; ushort port; var ipAddress = ConvertSockAddrPtrToIPAddress(outputConfigInfo.KeyDesc.pIpPort, out port); var portBytes = BitConverter.GetBytes(port); var reversedPortBytes = new [] { portBytes[1], portBytes[0] }; port = BitConverter.ToUInt16(reversedPortBytes, 0); var hash = new byte[outputConfigInfo.ParamDesc.SslHashLength]; Marshal.Copy(outputConfigInfo.ParamDesc.pSslHash, hash, 0, hash.Length); var hex = new StringBuilder(hash.Length * 2); foreach (var b in hash) { hex.AppendFormat("{0:x2}", b); } var certificateHash = hex.ToString(); var appID = paramInfo.AppId; var storeName = ConvertToStoreName(paramInfo.pSslCertStoreName); var verifyClientCertRevocation = ((paramInfo.DefaultCertCheckMode & 1) == 0); var verifyRevocationUsingCachedClientCertsOnly = (paramInfo.DefaultCertCheckMode & 2) == 2; var usageCheckEnabled = (paramInfo.DefaultCertCheckMode & 16) == 0; var revocationFreshnessTime = (uint)paramInfo.DefaultRevocationFreshnessTime; var urlRetrievalTimeout = (uint)paramInfo.DefaultRevocationUrlRetrievalTimeout; string ctlIdentifier = paramInfo.pDefaultSslCtlIdentifier ?? String.Empty; string ctlStoreName = paramInfo.pDefaultSslCtlStoreName ?? String.Empty; var dsMapperUsageEnabled = paramInfo.DefaultFlags.HasFlag(SslParamDefaultFlags.UseDsMapper); var negotiateClientCertificate = paramInfo.DefaultFlags.HasFlag(SslParamDefaultFlags.NegotiateClientCert); var binding = new SslCertificateBinding(ipAddress, port, certificateHash, appID, storeName, verifyClientCertRevocation, verifyRevocationUsingCachedClientCertsOnly, usageCheckEnabled, revocationFreshnessTime, urlRetrievalTimeout, ctlIdentifier, ctlStoreName, dsMapperUsageEnabled, negotiateClientCertificate); bindings.Add(binding); } else { throw new Win32Exception(); } } return(bindings.ToArray()); } finally { TerminateHttp(); } }
public static SslCertificateInfo[] QuerySslCertificateInfo() { var result = new List <SslCertificateInfo>(); CallHttpApi( delegate { uint token = 0; uint retVal; do { HTTP_SERVICE_CONFIG_SSL_QUERY inputConfigInfoQuery = new HTTP_SERVICE_CONFIG_SSL_QUERY { QueryDesc = HTTP_SERVICE_CONFIG_QUERY_TYPE.HttpServiceConfigQueryNext, dwToken = token }; IntPtr pInputConfigInfo = Marshal.AllocCoTaskMem(Marshal.SizeOf(typeof(HTTP_SERVICE_CONFIG_SSL_QUERY))); Marshal.StructureToPtr(inputConfigInfoQuery, pInputConfigInfo, false); IntPtr pOutputConfigInfo = IntPtr.Zero; int returnLength = 0; const HTTP_SERVICE_CONFIG_ID queryType = HTTP_SERVICE_CONFIG_ID.HttpServiceConfigSSLCertInfo; try { int inputConfigInfoSize = Marshal.SizeOf(inputConfigInfoQuery); retVal = HttpQueryServiceConfiguration(IntPtr.Zero, queryType, pInputConfigInfo, inputConfigInfoSize, pOutputConfigInfo, returnLength, out returnLength, IntPtr.Zero); if (ERROR_NO_MORE_ITEMS == retVal) { break; } if (ERROR_INSUFFICIENT_BUFFER == retVal) // ERROR_INSUFFICIENT_BUFFER = 122 { pOutputConfigInfo = Marshal.AllocCoTaskMem(returnLength); try { retVal = HttpQueryServiceConfiguration( IntPtr.Zero, queryType, pInputConfigInfo, inputConfigInfoSize, pOutputConfigInfo, returnLength, out returnLength, IntPtr.Zero); ThrowWin32ExceptionIfError(retVal); var outputConfigInfo = (HTTP_SERVICE_CONFIG_SSL_SET) Marshal.PtrToStructure(pOutputConfigInfo, typeof(HTTP_SERVICE_CONFIG_SSL_SET)); byte[] hash = new byte[outputConfigInfo.ParamDesc.SslHashLength]; Marshal.Copy(outputConfigInfo.ParamDesc.pSslHash, hash, 0, hash.Length); Guid appId = outputConfigInfo.ParamDesc.AppId; string storeName = outputConfigInfo.ParamDesc.pSslCertStoreName; IPEndPoint ipPort = ReadSockaddrStructure(outputConfigInfo.KeyDesc.pIpPort); var resultItem = new SslCertificateInfo { AppId = appId, Hash = hash, StoreName = storeName, IpPort = ipPort }; result.Add(resultItem); token++; } finally { Marshal.FreeCoTaskMem(pOutputConfigInfo); } } else { ThrowWin32ExceptionIfError(retVal); } } finally { Marshal.FreeCoTaskMem(pInputConfigInfo); } } while (NOERROR == retVal); }); return(result.ToArray()); }
public static SslCertificateInfo QuerySslCertificateInfo(IPEndPoint ipPort) { SslCertificateInfo result = null; uint retVal; CallHttpApi(delegate { GCHandle sockAddrHandle = CreateSockaddrStructure(ipPort); IntPtr pIpPort = sockAddrHandle.AddrOfPinnedObject(); HTTP_SERVICE_CONFIG_SSL_KEY sslKey = new HTTP_SERVICE_CONFIG_SSL_KEY(pIpPort); HTTP_SERVICE_CONFIG_SSL_QUERY inputConfigInfoQuery = new HTTP_SERVICE_CONFIG_SSL_QUERY { QueryDesc = HTTP_SERVICE_CONFIG_QUERY_TYPE.HttpServiceConfigQueryExact, KeyDesc = sslKey }; IntPtr pInputConfigInfo = Marshal.AllocCoTaskMem(Marshal.SizeOf(typeof(HTTP_SERVICE_CONFIG_SSL_QUERY))); Marshal.StructureToPtr(inputConfigInfoQuery, pInputConfigInfo, false); IntPtr pOutputConfigInfo = IntPtr.Zero; int returnLength = 0; try { HTTP_SERVICE_CONFIG_ID queryType = HTTP_SERVICE_CONFIG_ID.HttpServiceConfigSSLCertInfo; int inputConfigInfoSize = Marshal.SizeOf(inputConfigInfoQuery); retVal = HttpQueryServiceConfiguration(IntPtr.Zero, queryType, pInputConfigInfo, inputConfigInfoSize, pOutputConfigInfo, returnLength, out returnLength, IntPtr.Zero); if (retVal == ERROR_FILE_NOT_FOUND) { return; } if (ERROR_INSUFFICIENT_BUFFER == retVal) // ERROR_INSUFFICIENT_BUFFER = 122 { pOutputConfigInfo = Marshal.AllocCoTaskMem(returnLength); try { retVal = HttpQueryServiceConfiguration(IntPtr.Zero, queryType, pInputConfigInfo, inputConfigInfoSize, pOutputConfigInfo, returnLength, out returnLength, IntPtr.Zero); ThrowWin32ExceptionIfError(retVal); var outputConfigInfo = (HTTP_SERVICE_CONFIG_SSL_SET) Marshal.PtrToStructure(pOutputConfigInfo, typeof(HTTP_SERVICE_CONFIG_SSL_SET)); byte[] hash = new byte[outputConfigInfo.ParamDesc.SslHashLength]; Marshal.Copy(outputConfigInfo.ParamDesc.pSslHash, hash, 0, hash.Length); Guid appId = outputConfigInfo.ParamDesc.AppId; string storeName = outputConfigInfo.ParamDesc.pSslCertStoreName; result = new SslCertificateInfo { AppId = appId, Hash = hash, StoreName = storeName, IpPort = ipPort }; } finally { Marshal.FreeCoTaskMem(pOutputConfigInfo); } } else { ThrowWin32ExceptionIfError(retVal); } } finally { Marshal.FreeCoTaskMem(pInputConfigInfo); if (sockAddrHandle.IsAllocated) { sockAddrHandle.Free(); } } }); return(result); }