Register a Windows server to use https
<?xml version="1.0" encoding="utf-8"?> <xsharper xmlns="http://www.xsharper.com/schemas/1.0" requireAdmin="1"> <versionInfo>Program to grant access to a HTTP/HTTPS registration to a given user, as well as associate an SSL certificate with such address.</versionInfo> <usage options="ifNoArguments default autosuffix" /> <param name="listenUri" required="true" value="Server URI, for example https://127.0.0.1:443/cp/ " /> <param name="accountName" default="${=WindowsIdentity.GetCurrent().Name}" value="Account to grant privileges to." /> <param name="certFilter" value="Certificate subject filter for MY store of the local machine, if an SSL certificate is to be associated with the address. * and ? characters can be used." /> <param name="certGuid" value="Application GUID to identify the owning application. New GUID is generated if not specified." /> <param /> <param>Switches:</param> <param /> <param switch="unregister" count="none" default="0" unspecified="1" value="Unregister the URI" /> <param switch="unregisterSSL" count="none" default="0" unspecified="1" value="Unregister the URI and remove the SSL certificate from port:host" /> <set sid="${accountName}" /> <if isFalse="${=$sid.StartsWith('S-1-')}"> <set sid="${=new NTAccount($accountName).Translate(typeof(SecurityIdentifier)).ToString()}" /> </if> <set sddl="D:(A;;GX;;;${sid})" /> <?_ var store=new X509Store(StoreName.My,StoreLocation.LocalMachine); var ub=new UriBuilder(c.GetStr("listenUri")); try { var uri=ub.Scheme+"://+:"+ub.Port+ub.Path; if (c.GetBool("unregister") || c.GetBool("unregisterSSL")) { HttpCfg.ReserveUrl(uri, null); c.Info.WriteLine("Access to "+uri+" removed."); if (c.GetBool("unregisterSSL")) { HttpCfg.SetSslCert(new Guid(c.GetStr("certGuid",Guid.Empty.ToString())), ub.Host, ub.Port, null,null); c.Info.WriteLine("SSL certificate for "+ub.Host+":"+ub.Port+" removed."); } } else { HttpCfg.ReserveUrl(uri, c.GetStr("sddl")); c.Info.WriteLine("Access to "+uri+" granted to user "+c.GetStr("accountName")); if (c.IsSet("certFilter")) { store.Open(OpenFlags.OpenExistingOnly | OpenFlags.ReadOnly); X509Certificate2 cert=null; var filter=new XS.StringFilter(c.GetStr("certFilter")); foreach (var crt in store.Certificates) if (filter.IsMatch(crt.SubjectName.Format(false))) { if (cert!=null) throw new ApplicationException("Too many certificates match the filter"); cert=crt; } if (cert==null) throw new ApplicationException("Certificate not found"); HttpCfg.SetSslCert(new Guid(c.GetStr("certGuid",Guid.NewGuid().ToString())), ub.Host, ub.Port, store.Name, cert.GetCertHash()); c.Info.WriteLine("SSL certificate '"+cert.SubjectName.Format(false) +"' registered for "+ub.Host+":"+ub.Port+"."); } } } finally { store.Close(); } ?> <!-- =========================================================================== --> <?h using System.Security.Principal; using System.Runtime.InteropServices; using System.Net; using System.ComponentModel; using System.Security.Cryptography.X509Certificates; public static class HttpCfg { public static void SetSslCert(Guid appId, string ipAddress, int port, string storeName, byte[] hash) { var httpApiVersion = new HTTPAPI_VERSION(1, 0); uint retVal = HttpInitialize(httpApiVersion, HTTP_INITIALIZE_CONFIG, IntPtr.Zero); if (NOERROR != retVal) throw new Win32Exception(Convert.ToInt32(retVal)); try { IPAddress ip = IPAddress.Parse(ipAddress); var ipEndPoint = new IPEndPoint(ip, port); // serialize the endpoint to a SocketAddress and create an array to hold the values. Pin the array. SocketAddress socketAddress = ipEndPoint.Serialize(); byte[] socketBytes = new byte[socketAddress.Size]; GCHandle handleSocketAddress = GCHandle.Alloc(socketBytes, GCHandleType.Pinned); // Should copy the first 16 bytes (the SocketAddress has a 32 byte buffer, the size will only be 16, //which is what the SOCKADDR accepts for (int i = 0; i < socketAddress.Size; ++i) socketBytes[i] = socketAddress[i]; if (hash == null) hash = new byte[0]; GCHandle handleHash = GCHandle.Alloc(hash, GCHandleType.Pinned); var configSslSet = new HTTP_SERVICE_CONFIG_SSL_SET { ParamDesc = new HTTP_SERVICE_CONFIG_SSL_PARAM { AppId = appId, DefaultCertCheckMode = 0, DefaultFlags = HTTP_SERVICE_CONFIG_SSL_FLAG_NEGOTIATE_CLIENT_CERT, DefaultRevocationFreshnessTime = 0, DefaultRevocationUrlRetrievalTimeout = 0, pSslCertStoreName = storeName, SslHashLength = hash.Length, pSslHash = handleHash.AddrOfPinnedObject() }, KeyDesc = new HTTP_SERVICE_CONFIG_SSL_KEY { pIpPort = handleSocketAddress.AddrOfPinnedObject() } }; IntPtr pInputConfigInfo = Marshal.AllocCoTaskMem(Marshal.SizeOf(typeof(HTTP_SERVICE_CONFIG_SSL_SET))); try { Marshal.StructureToPtr(configSslSet, pInputConfigInfo, false); retVal = HttpDeleteServiceConfiguration(IntPtr.Zero, HTTP_SERVICE_CONFIG_ID.HttpServiceConfigSSLCertInfo, pInputConfigInfo, Marshal.SizeOf(configSslSet), IntPtr.Zero); if (storeName != null) retVal = HttpSetServiceConfiguration(IntPtr.Zero, HTTP_SERVICE_CONFIG_ID.HttpServiceConfigSSLCertInfo, pInputConfigInfo, Marshal.SizeOf(configSslSet), IntPtr.Zero); } finally { handleSocketAddress.Free(); handleHash.Free(); Marshal.FreeCoTaskMem(pInputConfigInfo); } if (NOERROR != retVal && !(retVal == ERROR_NOT_FOUND && storeName == null)) throw new Win32Exception(Convert.ToInt32(retVal)); } finally { HttpTerminate(HTTP_INITIALIZE_CONFIG, IntPtr.Zero); } } public static void ReserveUrl(string networkUrl, string sddl) { var version = new HTTPAPI_VERSION(1, 0); uint retVal = HttpInitialize(version, HTTP_INITIALIZE_CONFIG, IntPtr.Zero); if (NOERROR != retVal) throw new Win32Exception(Convert.ToInt32(retVal)); try { var keyDesc = new HTTP_SERVICE_CONFIG_URLACL_KEY { UrlPrefix = networkUrl }; var paramDesc = new HTTP_SERVICE_CONFIG_URLACL_PARAM { Sddl = sddl ?? "" }; var inputConfigInfoSet = new HTTP_SERVICE_CONFIG_URLACL_SET { Key = keyDesc, Param = paramDesc }; var pInputConfigInfo = Marshal.AllocCoTaskMem(Marshal.SizeOf(typeof(HTTP_SERVICE_CONFIG_URLACL_SET))); try { Marshal.StructureToPtr(inputConfigInfoSet, pInputConfigInfo, false); retVal = HttpDeleteServiceConfiguration(IntPtr.Zero, HTTP_SERVICE_CONFIG_ID.HttpServiceConfigUrlAclInfo, pInputConfigInfo, Marshal.SizeOf(inputConfigInfoSet), IntPtr.Zero); if (sddl != null) retVal = HttpSetServiceConfiguration(IntPtr.Zero, HTTP_SERVICE_CONFIG_ID.HttpServiceConfigUrlAclInfo, pInputConfigInfo, Marshal.SizeOf(inputConfigInfoSet), IntPtr.Zero); } finally { Marshal.FreeCoTaskMem(pInputConfigInfo); } if (NOERROR != retVal && !(retVal==ERROR_NOT_FOUND && sddl==null)) throw new Win32Exception(Convert.ToInt32(retVal)); } finally { HttpTerminate(HTTP_INITIALIZE_CONFIG, IntPtr.Zero); } } #region DllImport [DllImport("httpapi.dll", SetLastError = true)] static extern uint HttpInitialize(HTTPAPI_VERSION Version, uint Flags, IntPtr pReserved); [DllImport("httpapi.dll", SetLastError = true)] static extern uint HttpSetServiceConfiguration(IntPtr ServiceIntPtr, HTTP_SERVICE_CONFIG_ID ConfigId, IntPtr pConfigInformation, int ConfigInformationLength, IntPtr pOverlapped); [DllImport("httpapi.dll", SetLastError = true)] static extern uint HttpDeleteServiceConfiguration(IntPtr ServiceIntPtr, HTTP_SERVICE_CONFIG_ID ConfigId, IntPtr pConfigInformation, int ConfigInformationLength, IntPtr pOverlapped); [DllImport("httpapi.dll", SetLastError = true)] static extern uint HttpTerminate(uint Flags, IntPtr pReserved); [StructLayout(LayoutKind.Sequential)] struct HTTP_SERVICE_CONFIG_URLACL_KEY { [MarshalAs(UnmanagedType.LPWStr)] public string UrlPrefix; } [StructLayout(LayoutKind.Sequential)] struct HTTP_SERVICE_CONFIG_URLACL_PARAM { [MarshalAs(UnmanagedType.LPWStr)] public string Sddl; } [StructLayout(LayoutKind.Sequential)] struct HTTP_SERVICE_CONFIG_URLACL_SET { public HTTP_SERVICE_CONFIG_URLACL_KEY Key; public HTTP_SERVICE_CONFIG_URLACL_PARAM Param; } enum HTTP_SERVICE_CONFIG_ID { HttpServiceConfigIPListenList = 0, HttpServiceConfigSSLCertInfo, HttpServiceConfigUrlAclInfo, HttpServiceConfigMax } [StructLayout(LayoutKind.Sequential)] struct HTTP_SERVICE_CONFIG_IP_LISTEN_PARAM { public ushort AddrLength; public IntPtr pAddress; } [StructLayout(LayoutKind.Sequential)] struct HTTP_SERVICE_CONFIG_SSL_SET { public HTTP_SERVICE_CONFIG_SSL_KEY KeyDesc; public HTTP_SERVICE_CONFIG_SSL_PARAM ParamDesc; } [StructLayout(LayoutKind.Sequential)] public struct HTTP_SERVICE_CONFIG_SSL_KEY { public IntPtr pIpPort; } [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)] struct HTTP_SERVICE_CONFIG_SSL_PARAM { public int SslHashLength; public IntPtr pSslHash; public Guid AppId; [MarshalAs(UnmanagedType.LPWStr)] public string pSslCertStoreName; public uint DefaultCertCheckMode; public int DefaultRevocationFreshnessTime; public int DefaultRevocationUrlRetrievalTimeout; [MarshalAs(UnmanagedType.LPWStr)] public string pDefaultSslCtlIdentifier; [MarshalAs(UnmanagedType.LPWStr)] public string pDefaultSslCtlStoreName; public uint DefaultFlags; } [StructLayout(LayoutKind.Sequential, Pack = 2)] struct HTTPAPI_VERSION { public ushort HttpApiMajorVersion; public ushort HttpApiMinorVersion; public HTTPAPI_VERSION(ushort majorVersion, ushort minorVersion) { HttpApiMajorVersion = majorVersion; HttpApiMinorVersion = minorVersion; } } #endregion #region Constants public const uint HTTP_INITIALIZE_CONFIG = 0x00000002; public const uint HTTP_SERVICE_CONFIG_SSL_FLAG_USE_DS_MAPPER = 0x00000001; public const uint HTTP_SERVICE_CONFIG_SSL_FLAG_NEGOTIATE_CLIENT_CERT = 0x00000002; public const uint HTTP_SERVICE_CONFIG_SSL_FLAG_NO_RAW_FILTER = 0x00000004; private const uint NOERROR = 0; private const uint ERROR_NOT_FOUND = 2; #endregion } ?> </xsharper>