├── .gitattributes ├── .gitignore ├── HttpSysManager ├── HttpSysManager.Core │ ├── CertificateHelper.cs │ ├── HttpSysManager.Core.csproj │ ├── InteropHelper.cs │ ├── Properties │ │ └── AssemblyInfo.cs │ └── Thumbprint.cs ├── HttpSysManager.Native │ ├── AssemblyInfo.cpp │ ├── CTLInfo.cpp │ ├── HttpApiHelper.cpp │ ├── HttpInitializeScope.cpp │ ├── HttpSysManager.Native.vcxproj │ ├── HttpSysManager.Native.vcxproj.filters │ ├── HttpSysManager.h │ ├── ManagedSet.cpp │ ├── SSLInfo.cpp │ ├── SafeHandles.cpp │ ├── Security.cpp │ ├── UrlAcl.cpp │ ├── app.ico │ ├── app.rc │ └── mauto_ptr.h ├── HttpSysManager.Tests │ ├── Certificates │ │ └── HttpSysManager.cer │ ├── HttpSysManager.Tests.csproj │ ├── Program.cs │ ├── Properties │ │ └── AssemblyInfo.cs │ ├── TestClass.cs │ ├── app.config │ ├── authroot.stl │ └── xunit │ │ ├── xunit.dll │ │ ├── xunit.extensions.dll │ │ └── xunit.runner.utility.dll ├── HttpSysManager.sln └── HttpSysManager │ ├── App.xaml │ ├── App.xaml.cs │ ├── CertificateHelper.cs │ ├── CertificateListView.xaml │ ├── CertificateListView.xaml.cs │ ├── CertificateSelector.xaml │ ├── CertificateSelector.xaml.cs │ ├── CertificateSelectorWindow.xaml │ ├── CertificateSelectorWindow.xaml.cs │ ├── CreateCTLWizard.xaml │ ├── CreateCTLWizard.xaml.cs │ ├── Extensions.cs │ ├── HttpAPIManager.cs │ ├── HttpSysManager.csproj │ ├── HyperlinkButton.cs │ ├── LICENSE.txt │ ├── MainWindow.xaml │ ├── MainWindow.xaml.cs │ ├── MainWindowViewModel.cs │ ├── Properties │ ├── AssemblyInfo.cs │ ├── Resources.Designer.cs │ ├── Resources.resx │ ├── Settings.Designer.cs │ └── Settings.settings │ ├── SSLInfoOptionWindow.xaml │ ├── SSLInfoOptionWindow.xaml.cs │ ├── Themes │ └── Generic.xaml │ ├── X509CertificateNameConverter.cs │ ├── app.config │ ├── app.manifest │ └── bins │ ├── LICENSE.txt │ ├── ProcessHacker.Common.dll │ ├── ProcessHacker.Native.dll │ ├── ProcessHacker.Native.dll.config │ ├── SlasheneFramework.UI.dll │ ├── SlasheneFramework.dll │ └── WPFToolkit.Extended.dll ├── License.txt └── README.md /.gitattributes: -------------------------------------------------------------------------------- 1 | ############################################################################### 2 | # Set default behavior to automatically normalize line endings. 3 | ############################################################################### 4 | * text=auto 5 | 6 | ############################################################################### 7 | # Set default behavior for command prompt diff. 8 | # 9 | # This is need for earlier builds of msysgit that does not have it on by 10 | # default for csharp files. 11 | # Note: This is only used by command line 12 | ############################################################################### 13 | #*.cs diff=csharp 14 | 15 | ############################################################################### 16 | # Set the merge driver for project and solution files 17 | # 18 | # Merging from the command prompt will add diff markers to the files if there 19 | # are conflicts (Merging from VS is not affected by the settings below, in VS 20 | # the diff markers are never inserted). Diff markers may cause the following 21 | # file extensions to fail to load in VS. An alternative would be to treat 22 | # these files as binary and thus will always conflict and require user 23 | # intervention with every merge. To do so, just uncomment the entries below 24 | ############################################################################### 25 | #*.sln merge=binary 26 | #*.csproj merge=binary 27 | #*.vbproj merge=binary 28 | #*.vcxproj merge=binary 29 | #*.vcproj merge=binary 30 | #*.dbproj merge=binary 31 | #*.fsproj merge=binary 32 | #*.lsproj merge=binary 33 | #*.wixproj merge=binary 34 | #*.modelproj merge=binary 35 | #*.sqlproj merge=binary 36 | #*.wwaproj merge=binary 37 | 38 | ############################################################################### 39 | # behavior for image files 40 | # 41 | # image files are treated as binary by default. 42 | ############################################################################### 43 | #*.jpg binary 44 | #*.png binary 45 | #*.gif binary 46 | 47 | ############################################################################### 48 | # diff behavior for common document formats 49 | # 50 | # Convert binary document formats to text before diffing them. This feature 51 | # is only available from the command line. Turn it on by uncommenting the 52 | # entries below. 53 | ############################################################################### 54 | #*.doc diff=astextplain 55 | #*.DOC diff=astextplain 56 | #*.docx diff=astextplain 57 | #*.DOCX diff=astextplain 58 | #*.dot diff=astextplain 59 | #*.DOT diff=astextplain 60 | #*.pdf diff=astextplain 61 | #*.PDF diff=astextplain 62 | #*.rtf diff=astextplain 63 | #*.RTF diff=astextplain 64 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | ## Ignore Visual Studio temporary files, build results, and 2 | ## files generated by popular Visual Studio add-ons. 3 | 4 | # User-specific files 5 | *.suo 6 | *.user 7 | *.sln.docstates 8 | 9 | # Build results 10 | 11 | [Dd]ebug/ 12 | [Rr]elease/ 13 | x64/ 14 | build/ 15 | [Bb]in/ 16 | [Oo]bj/ 17 | 18 | # Enable "build/" folder in the NuGet Packages folder since NuGet packages use it for MSBuild targets 19 | !packages/*/build/ 20 | 21 | # MSTest test Results 22 | [Tt]est[Rr]esult*/ 23 | [Bb]uild[Ll]og.* 24 | 25 | *_i.c 26 | *_p.c 27 | *.ilk 28 | *.meta 29 | *.obj 30 | *.pch 31 | *.pdb 32 | *.pgc 33 | *.pgd 34 | *.rsp 35 | *.sbr 36 | *.tlb 37 | *.tli 38 | *.tlh 39 | *.tmp 40 | *.tmp_proj 41 | *.log 42 | *.vspscc 43 | *.vssscc 44 | .builds 45 | *.pidb 46 | *.log 47 | *.scc 48 | 49 | # Visual C++ cache files 50 | ipch/ 51 | *.aps 52 | *.ncb 53 | *.opensdf 54 | *.sdf 55 | *.cachefile 56 | 57 | # Visual Studio profiler 58 | *.psess 59 | *.vsp 60 | *.vspx 61 | 62 | # Guidance Automation Toolkit 63 | *.gpState 64 | 65 | # ReSharper is a .NET coding add-in 66 | _ReSharper*/ 67 | *.[Rr]e[Ss]harper 68 | 69 | # TeamCity is a build add-in 70 | _TeamCity* 71 | 72 | # DotCover is a Code Coverage Tool 73 | *.dotCover 74 | 75 | # NCrunch 76 | *.ncrunch* 77 | .*crunch*.local.xml 78 | 79 | # Installshield output folder 80 | [Ee]xpress/ 81 | 82 | # DocProject is a documentation generator add-in 83 | DocProject/buildhelp/ 84 | DocProject/Help/*.HxT 85 | DocProject/Help/*.HxC 86 | DocProject/Help/*.hhc 87 | DocProject/Help/*.hhk 88 | DocProject/Help/*.hhp 89 | DocProject/Help/Html2 90 | DocProject/Help/html 91 | 92 | # Click-Once directory 93 | publish/ 94 | 95 | # Publish Web Output 96 | *.Publish.xml 97 | 98 | # NuGet Packages Directory 99 | ## TODO: If you have NuGet Package Restore enabled, uncomment the next line 100 | #packages/ 101 | 102 | # Windows Azure Build Output 103 | csx 104 | *.build.csdef 105 | 106 | # Windows Store app package directory 107 | AppPackages/ 108 | 109 | # Others 110 | sql/ 111 | *.Cache 112 | ClientBin/ 113 | [Ss]tyle[Cc]op.* 114 | ~$* 115 | *~ 116 | *.dbmdl 117 | *.[Pp]ublish.xml 118 | *.pfx 119 | *.publishsettings 120 | 121 | # RIA/Silverlight projects 122 | Generated_Code/ 123 | 124 | # Backup & report files from converting an old project file to a newer 125 | # Visual Studio version. Backup files are not needed, because we have git ;-) 126 | _UpgradeReport_Files/ 127 | Backup*/ 128 | UpgradeLog*.XML 129 | UpgradeLog*.htm 130 | 131 | # SQL Server files 132 | App_Data/*.mdf 133 | App_Data/*.ldf 134 | 135 | 136 | #LightSwitch generated files 137 | GeneratedArtifacts/ 138 | _Pvt_Extensions/ 139 | ModelManifest.xml 140 | 141 | # ========================= 142 | # Windows detritus 143 | # ========================= 144 | 145 | # Windows image file caches 146 | Thumbs.db 147 | ehthumbs.db 148 | 149 | # Folder config file 150 | Desktop.ini 151 | 152 | # Recycle Bin used on file shares 153 | $RECYCLE.BIN/ 154 | 155 | # Mac desktop service store files 156 | .DS_Store 157 | -------------------------------------------------------------------------------- /HttpSysManager/HttpSysManager.Core/CertificateHelper.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Security.Cryptography.X509Certificates; 6 | using System.Text.RegularExpressions; 7 | 8 | namespace HttpSysManager.Core 9 | { 10 | public class CertificateHelper 11 | { 12 | public static X509Certificate2 GetCertificate(StoreLocation storeLocation, System.Security.Cryptography.X509Certificates.StoreName storeName, X509FindType x509FindType, object value) 13 | { 14 | X509Store store = new X509Store(storeName, storeLocation); 15 | store.Open(OpenFlags.ReadOnly); 16 | try 17 | { 18 | var certs = store.Certificates.Find(x509FindType, value, false); 19 | if(certs.Count == 0) 20 | return null; 21 | return certs[0]; 22 | } 23 | finally 24 | { 25 | store.Close(); 26 | } 27 | } 28 | 29 | public static string GetFriendlyNameOrName(X509Certificate2 SelectedCertificate) 30 | { 31 | if(!string.IsNullOrEmpty(SelectedCertificate.FriendlyName)) 32 | return SelectedCertificate.FriendlyName; 33 | else 34 | { 35 | var match = Regex.Match(SelectedCertificate.Subject, "^(CN=)?(?[^,]*)", RegexOptions.IgnoreCase); 36 | if(!match.Success) 37 | return SelectedCertificate.Subject; 38 | return match.Groups["Name"].Value.Trim(); 39 | } 40 | } 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /HttpSysManager/HttpSysManager.Core/HttpSysManager.Core.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Debug 6 | AnyCPU 7 | {CB03213B-4CBB-4E09-8739-59D9FCFB71BF} 8 | Library 9 | Properties 10 | HttpSysManager.Core 11 | HttpSysManager.Core 12 | v4.0 13 | 512 14 | 15 | 16 | 17 | true 18 | full 19 | false 20 | bin\Debug\ 21 | DEBUG;TRACE 22 | prompt 23 | 4 24 | true 25 | 26 | 27 | pdbonly 28 | true 29 | bin\Release\ 30 | TRACE 31 | prompt 32 | 4 33 | true 34 | 35 | 36 | 37 | ..\HttpSysManager\bins\ProcessHacker.Common.dll 38 | 39 | 40 | ..\HttpSysManager\bins\ProcessHacker.Native.dll 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 64 | -------------------------------------------------------------------------------- /HttpSysManager/HttpSysManager.Core/InteropHelper.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Runtime.InteropServices; 5 | using System.Text; 6 | using ProcessHacker.Native; 7 | 8 | namespace HttpSysManager.Core 9 | { 10 | public class InteropHelper 11 | { 12 | public static unsafe byte[] ToCSharpArray(byte* bytes, int lenght) 13 | { 14 | byte[] output = new byte[lenght]; 15 | for(int i = 0 ; i < lenght ; i++) 16 | output[i] = (byte)bytes[i]; 17 | return output; 18 | } 19 | 20 | public static unsafe LocalMemoryAlloc ToCArray(byte[] array) 21 | { 22 | var ptr = (byte*)Marshal.AllocHGlobal(array.Length).ToPointer(); 23 | for(int i = 0 ; i < array.Length ; i++) 24 | ptr[i] = array[i]; 25 | return new LocalMemoryAlloc(new IntPtr(ptr)); 26 | } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /HttpSysManager/HttpSysManager.Core/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyTitle("HttpSysManager.Core")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("Microsoft")] 12 | [assembly: AssemblyProduct("HttpSysManager.Core")] 13 | [assembly: AssemblyCopyright("Copyright © Microsoft 2012")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // Setting ComVisible to false makes the types in this assembly not visible 18 | // to COM components. If you need to access a type in this assembly from 19 | // COM, set the ComVisible attribute to true on that type. 20 | [assembly: ComVisible(false)] 21 | 22 | // The following GUID is for the ID of the typelib if this project is exposed to COM 23 | [assembly: Guid("6d56ce9a-ae79-4d04-9aa6-ba263b04c8c6")] 24 | 25 | // Version information for an assembly consists of the following four values: 26 | // 27 | // Major Version 28 | // Minor Version 29 | // Build Number 30 | // Revision 31 | // 32 | // You can specify all the values or you can default the Build and Revision Numbers 33 | // by using the '*' as shown below: 34 | // [assembly: AssemblyVersion("1.0.*")] 35 | [assembly: AssemblyVersion("1.0.0.0")] 36 | [assembly: AssemblyFileVersion("1.0.0.0")] 37 | -------------------------------------------------------------------------------- /HttpSysManager/HttpSysManager.Core/Thumbprint.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace HttpSysManager.Core 8 | { 9 | public class Thumbprint 10 | { 11 | byte[] bytes; 12 | string bytesStr; 13 | 14 | public unsafe Thumbprint(byte* bytes, int lenght) 15 | :this(InteropHelper.ToCSharpArray(bytes,lenght)) 16 | { 17 | } 18 | public Thumbprint(string bytes) 19 | { 20 | if(bytes == null) 21 | throw new ArgumentNullException("bytes"); 22 | bytesStr = Normalize(bytes); 23 | } 24 | 25 | private string Normalize(string bytes) 26 | { 27 | return String.Join("", bytes.Split(' ', '-')); 28 | } 29 | public Thumbprint(byte[] bytes) 30 | { 31 | if(bytes == null) 32 | throw new ArgumentNullException("bytes"); 33 | this.bytes = bytes; 34 | } 35 | 36 | public byte[] Data 37 | { 38 | get 39 | { 40 | if(bytes == null) 41 | { 42 | bytes = Enumerable.Range(0, bytesStr.Length) 43 | .Where(x => x % 2 == 0) 44 | .Select(x => Convert.ToByte(bytesStr.Substring(x, 2), 16)) 45 | .ToArray(); 46 | } 47 | return bytes; 48 | } 49 | } 50 | 51 | public override string ToString() 52 | { 53 | if(bytesStr == null) 54 | { 55 | bytesStr = Normalize(BitConverter.ToString(bytes)); 56 | } 57 | return bytesStr; 58 | } 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /HttpSysManager/HttpSysManager.Native/AssemblyInfo.cpp: -------------------------------------------------------------------------------- 1 | //#include "stdafx.h" 2 | 3 | using namespace System; 4 | using namespace System::Reflection; 5 | using namespace System::Runtime::CompilerServices; 6 | using namespace System::Runtime::InteropServices; 7 | using namespace System::Security::Permissions; 8 | 9 | // 10 | // General Information about an assembly is controlled through the following 11 | // set of attributes. Change these attribute values to modify the information 12 | // associated with an assembly. 13 | // 14 | [assembly:AssemblyTitleAttribute("HttpSysManagerNative")]; 15 | [assembly:AssemblyDescriptionAttribute("")]; 16 | [assembly:AssemblyConfigurationAttribute("")]; 17 | [assembly:AssemblyCompanyAttribute("Microsoft")]; 18 | [assembly:AssemblyProductAttribute("HttpSysManagerNative")]; 19 | [assembly:AssemblyCopyrightAttribute("Copyright (c) Microsoft 2012")]; 20 | [assembly:AssemblyTrademarkAttribute("")]; 21 | [assembly:AssemblyCultureAttribute("")]; 22 | 23 | // 24 | // Version information for an assembly consists of the following four values: 25 | // 26 | // Major Version 27 | // Minor Version 28 | // Build Number 29 | // Revision 30 | // 31 | // You can specify all the value or you can default the Revision and Build Numbers 32 | // by using the '*' as shown below: 33 | 34 | [assembly:AssemblyVersionAttribute("1.0.*")]; 35 | 36 | [assembly:ComVisible(false)]; 37 | 38 | [assembly:CLSCompliantAttribute(true)]; 39 | 40 | [assembly:SecurityPermission(SecurityAction::RequestMinimum, UnmanagedCode = true)]; 41 | -------------------------------------------------------------------------------- /HttpSysManager/HttpSysManager.Native/CTLInfo.cpp: -------------------------------------------------------------------------------- 1 | #include "HttpSysManager.h" 2 | #include 3 | #include 4 | #include 5 | #include "SafeHandles.cpp" 6 | 7 | 8 | typedef std::vector> CTL_ENTRIES; 9 | 10 | 11 | BeginHttpSysManager 12 | #define DEFAULT_ENCODING X509_ASN_ENCODING | PKCS_7_ASN_ENCODING 13 | //http://msdn.microsoft.com/en-us/library/windows/desktop/aa381487(v=vs.85).aspx 14 | public ref class CTLEntry 15 | { 16 | private:CTL_ENTRY& entry; 17 | public: CTLEntry(CTL_ENTRY& entry):entry(entry) 18 | { 19 | } 20 | private: array^ _SubjectIdentifier; 21 | public: property array^ SubjectIdentifier 22 | { 23 | array^ get() 24 | { 25 | return InteropHelper::ToCSharpArray(entry.SubjectIdentifier.pbData, entry.SubjectIdentifier.cbData); 26 | } 27 | } 28 | 29 | }; 30 | 31 | //http://msdn.microsoft.com/en-us/library/windows/desktop/aa381491(v=vs.85).aspx 32 | public ref class CTLInfo 33 | { 34 | internal: mauto_handle nativeCtlInfo; 35 | private : mauto_handle allocatedEntries; 36 | private: mauto_handle nativeCtlInfoEntries; 37 | private: mauto_handle allocatedUsages; 38 | private: LocalMemoryAlloc^ listIdentifier; 39 | private: static DWORD encoding = X509_ASN_ENCODING | PKCS_7_ASN_ENCODING; 40 | 41 | 42 | public: CTLInfo(PCTL_INFO nativeCtlInfo) 43 | :nativeCtlInfo(new CTL_INFO(*nativeCtlInfo)) 44 | { 45 | Init(); 46 | } 47 | public: CTLInfo(mauto_handle nativeCtlInfo) 48 | :nativeCtlInfo(nativeCtlInfo) 49 | { 50 | Init(); 51 | } 52 | public: CTLInfo(mauto_handle nativeCtlInfo, mauto_handle nativeCtlInfoEntries, mauto_handle allocatedEntries, mauto_handle allocatedUsages, LocalMemoryAlloc^ listIdentifier) 53 | :nativeCtlInfo(nativeCtlInfo), 54 | allocatedEntries(allocatedEntries), 55 | nativeCtlInfoEntries(nativeCtlInfoEntries), 56 | allocatedUsages(allocatedUsages), 57 | listIdentifier(listIdentifier) 58 | { 59 | Init(); 60 | } 61 | private: void Init() 62 | { 63 | _Entries = gcnew List(); 64 | for(DWORD i = 0; i < nativeCtlInfo->cCTLEntry; i++) 65 | { 66 | CTLEntry^ entry = gcnew CTLEntry(nativeCtlInfo->rgCTLEntry[i]); 67 | _Entries->Add(entry); 68 | } 69 | } 70 | private: List^ _Entries; 71 | public: property IList^ Entries 72 | { 73 | IList^ get() 74 | { 75 | return _Entries; 76 | }; 77 | } 78 | 79 | public: property String^ ListIdentifier 80 | { 81 | String^ get() 82 | { 83 | if(!nativeCtlInfo->ListIdentifier.pbData || !nativeCtlInfo->ListIdentifier.cbData) 84 | return nullptr; 85 | return Marshal::PtrToStringUni(IntPtr(nativeCtlInfo->ListIdentifier.pbData)); 86 | } 87 | } 88 | 89 | public: static CTLInfo^ Load(array^ bytes) 90 | { 91 | auto encoded = InteropHelper::ToCArray(bytes); 92 | DWORD size; 93 | CryptDecodeObject(encoding, PKCS_CTL,(BYTE*)(void*)encoded,bytes->Length,0,NULL, &size); 94 | mauto_handle ctlInfo((CTL_INFO*)new Byte[size]); 95 | ASSERT_TRUE(CryptDecodeObject(DEFAULT_ENCODING, PKCS_CTL,(BYTE*)(void*)encoded,bytes->Length,0,ctlInfo.get(), &size)); 96 | return gcnew CTLInfo(ctlInfo); 97 | }; 98 | //Creating, Signing, and Storing a CTL http://msdn.microsoft.com/en-us/library/windows/desktop/aa379867(v=vs.85).aspx 99 | public: array^ ToBytes() 100 | { 101 | DWORD size; 102 | std::auto_ptr encoded(ToCBytes(&size)); 103 | return InteropHelper::ToCSharpArray(encoded.get(),size); 104 | } 105 | private: std::auto_ptr ToCBytes(DWORD* size) 106 | { 107 | CryptEncodeObject(DEFAULT_ENCODING,PKCS_CTL, nativeCtlInfo.get(),NULL,size); 108 | std::auto_ptr encoded(new Byte[*size]); 109 | ASSERT_TRUE(CryptEncodeObject(DEFAULT_ENCODING,PKCS_CTL, nativeCtlInfo.get(),encoded.get(),size)); 110 | return encoded; 111 | } 112 | }; 113 | 114 | public ref class CTLInfoBuilder 115 | { 116 | public: CTLInfoBuilder() 117 | { 118 | _Certificates = gcnew List(); 119 | } 120 | 121 | private: List^ _Certificates; 122 | public: property IList^ Certificates 123 | { 124 | IList^ get() 125 | { 126 | return _Certificates; 127 | } 128 | } 129 | private: String^ _ListIdentifier; 130 | public: property String^ ListIdentifier 131 | { 132 | String^ get() 133 | { 134 | return _ListIdentifier; 135 | } 136 | void set(String^ value) 137 | { 138 | _ListIdentifier = value; 139 | } 140 | } 141 | 142 | private: mauto_handle CreateArrayFromVector(std::vector vector) 143 | { 144 | mauto_handle output(new LPSTR[vector.size()]); 145 | memcpy(output.get(),&vector[0],sizeof(LPSTR) * vector.size()); 146 | return output; 147 | } 148 | //Add certificates http://msdn.microsoft.com/en-us/library/windows/desktop/aa376038(v=vs.85).aspx 149 | public:CTLInfo^ ToCTLInfo() 150 | { 151 | mauto_handle ctl(new CTL_INFO()); 152 | ZeroMemory(ctl.get(),sizeof(CTL_INFO)); 153 | 154 | 155 | 156 | std::vector usages; 157 | usages.push_back(szOID_ROOT_LIST_SIGNER); 158 | usages.push_back(szOID_CTL); 159 | usages.push_back(szOID_TRUSTED_CLIENT_AUTH_CA_LIST); 160 | usages.push_back(szOID_PKIX_KP_CLIENT_AUTH); 161 | usages.push_back(szOID_PKIX_KP_SERVER_AUTH); 162 | //usages.push_back(szOID_IIS_VIRTUAL_SERVER); 163 | 164 | mauto_handle usagesArray(CreateArrayFromVector(usages)); 165 | 166 | 167 | ctl->dwVersion = CTL_V1; 168 | 169 | ctl->SubjectUsage.cUsageIdentifier = usages.size(); 170 | ctl->SubjectUsage.rgpszUsageIdentifier = usagesArray.get(); 171 | 172 | LocalMemoryAlloc^ listIdentifierPtr; 173 | if(!String::IsNullOrEmpty(ListIdentifier)) 174 | { 175 | listIdentifierPtr = gcnew LocalMemoryAlloc(Marshal::StringToHGlobalUni(ListIdentifier)); 176 | ctl->ListIdentifier.cbData = (ListIdentifier->Length +1)* sizeof(WCHAR); 177 | ctl->ListIdentifier.pbData = (BYTE*)(void*)listIdentifierPtr; 178 | } 179 | 180 | ctl->SubjectAlgorithm.pszObjId = szOID_OIWSEC_sha1; 181 | 182 | ctl->cCTLEntry = Certificates->Count; 183 | 184 | mauto_handle ctlEntries(new CTL_ENTRY[ctl->cCTLEntry]); 185 | ctl->rgCTLEntry = ctlEntries.get(); 186 | 187 | mauto_handle allocatedEntries(new CTL_ENTRIES()); 188 | 189 | int i = 0; 190 | for each (X509Certificate2^ cert in Certificates) 191 | { 192 | PCCERT_CONTEXT certContext = (PCCERT_CONTEXT)cert->Handle.ToPointer(); 193 | DWORD size; 194 | CertCreateCTLEntryFromCertificateContextProperties(certContext,0,NULL,CTL_ENTRY_FROM_PROP_CHAIN_FLAG,NULL,NULL, &size); 195 | 196 | std::shared_ptr ctlEntry((CTL_ENTRY*)new Byte[size]); 197 | allocatedEntries->push_back(ctlEntry); 198 | ASSERT_TRUE(CertCreateCTLEntryFromCertificateContextProperties(certContext,0,NULL,CTL_ENTRY_FROM_PROP_CHAIN_FLAG,NULL,ctlEntry.get(), &size)); 199 | ctl->rgCTLEntry[i] = *(ctlEntry.get()); 200 | i++; 201 | } 202 | return gcnew CTLInfo(ctl, ctlEntries, allocatedEntries, usagesArray, listIdentifierPtr); 203 | } 204 | }; 205 | 206 | typedef CTLInfo TCTLInfo; 207 | public ref class CTLContext 208 | { 209 | internal: SafeCTLHandle^ handle; 210 | 211 | 212 | public: CTLContext(SafeCTLHandle^ handle) 213 | { 214 | this->handle=handle; 215 | _CTLInfo = gcnew TCTLInfo(handle->Handle->pCtlInfo); 216 | if(!String::IsNullOrEmpty(_CTLInfo->ListIdentifier)) 217 | FriendlyName = _CTLInfo->ListIdentifier; 218 | } 219 | 220 | private: 221 | void SetContextProperty(DWORD dwPropId, String^ value) 222 | { 223 | HGlobalHandle identifier(Marshal::StringToHGlobalUni(value)); 224 | CRYPT_DATA_BLOB blob; 225 | blob.cbData = (value->Length + 1) * sizeof(WCHAR); 226 | blob.pbData = (BYTE*)identifier.Handle; 227 | CertSetCTLContextProperty(handle->Handle,dwPropId,NULL, &blob); 228 | } 229 | String^ GetContextProperty(DWORD dwPropId) 230 | { 231 | DWORD size; 232 | CertGetCTLContextProperty(handle->Handle, dwPropId,NULL,&size); 233 | std::auto_ptr buffer((WCHAR*)new BYTE[size]); 234 | if(CertGetCTLContextProperty(handle->Handle, dwPropId,buffer.get(),&size)) 235 | { 236 | return Marshal::PtrToStringUni(IntPtr(buffer.get())); 237 | } 238 | auto lastError = GetLastError(); 239 | if(lastError == CRYPT_E_NOT_FOUND) 240 | return nullptr; 241 | Win32::Throw((int)lastError); 242 | return nullptr; 243 | } 244 | 245 | public: property String^ FriendlyName 246 | { 247 | String^ get() 248 | { 249 | return GetContextProperty(CERT_FRIENDLY_NAME_PROP_ID); 250 | } 251 | void set(String^ value) 252 | { 253 | SetContextProperty(CERT_FRIENDLY_NAME_PROP_ID, value); 254 | } 255 | } 256 | 257 | public: array^ ToBytes() 258 | { 259 | DWORD size; 260 | std::auto_ptr encoded(ToCBytes(&size)); 261 | return InteropHelper::ToCSharpArray(encoded.get(),size); 262 | } 263 | private: std::auto_ptr ToCBytes(DWORD* size) 264 | { 265 | *size = handle->Handle->cbCtlEncoded; 266 | std::auto_ptr cpy(new Byte[*size]); 267 | memcpy(cpy.get(), handle->Handle->pbCtlEncoded, *size); 268 | return cpy; 269 | } 270 | public: static CTLContext^ Load(Byte* bytes, DWORD size) 271 | { 272 | SafeCTLHandle^ ctlContext = gcnew SafeCTLHandle(CertCreateCTLContext(DEFAULT_ENCODING, bytes, size)); 273 | if(ctlContext->Handle == NULL) 274 | Win32::Throw(); 275 | return gcnew CTLContext(ctlContext); 276 | } 277 | public: static CTLContext^ Load(array^ bytes) 278 | { 279 | return Load((Byte*)(void*)InteropHelper::ToCArray(bytes), bytes->Length); 280 | } 281 | 282 | 283 | public: void ImportInStore(TStoreLocation location, TStoreName storeName) 284 | { 285 | msclr::interop::marshal_context mashal; 286 | SafeStoreHandle storeHandle(CertOpenStore(CERT_STORE_PROV_SYSTEM, 287 | 0, 288 | NULL, 289 | location == TStoreLocation::LocalMachine ? CERT_SYSTEM_STORE_LOCAL_MACHINE : CERT_SYSTEM_STORE_CURRENT_USER, 290 | mashal.marshal_as(Enum::GetName(TStoreName::typeid, storeName)->ToUpper()))); 291 | ASSERT_TRUE(CertAddCTLContextToStore(storeHandle.Handle,handle->Handle,CERT_STORE_ADD_REPLACE_EXISTING,NULL)); 292 | } 293 | 294 | public: void RemoveFromStore(TStoreLocation storeLocation, TStoreName storeName) 295 | { 296 | CTLContext::RemoveFromStore(storeLocation,storeName, CTLInfo->ListIdentifier); 297 | } 298 | public: static void RemoveFromStore(TStoreLocation location, TStoreName storeName, String^ listIdentifier) 299 | { 300 | auto_handle context(Get(location,storeName,listIdentifier)); 301 | if(context.get() == nullptr) 302 | return; 303 | auto handle = CertDuplicateCTLContext(context->handle->Handle); //CertDeleteCTLFromStore Free the handle 304 | if(handle == NULL) 305 | Win32::Throw(); 306 | ASSERT_TRUE(CertDeleteCTLFromStore(handle)); 307 | } 308 | public: static CTLContext^ Get(TStoreLocation location, TStoreName storeName, String^ listIdentifier) 309 | { 310 | if(listIdentifier == nullptr) 311 | return nullptr; 312 | msclr::interop::marshal_context mashal; 313 | SafeStoreHandle storeHandle(CertOpenStore(CERT_STORE_PROV_SYSTEM, 314 | 0, 315 | NULL, 316 | location == TStoreLocation::LocalMachine ? CERT_SYSTEM_STORE_LOCAL_MACHINE : CERT_SYSTEM_STORE_CURRENT_USER, 317 | mashal.marshal_as(Enum::GetName(TStoreName::typeid, storeName)->ToUpper()))); 318 | 319 | auto result = mashal.marshal_as(listIdentifier); 320 | CTL_FIND_USAGE_PARA para; 321 | ZeroMemory(¶,sizeof(CTL_FIND_USAGE_PARA)); 322 | para.cbSize = sizeof(CTL_FIND_USAGE_PARA); 323 | para.ListIdentifier.cbData = (listIdentifier->Length + 1) * sizeof(WCHAR); 324 | para.ListIdentifier.pbData = (BYTE*)result; 325 | 326 | auto context = gcnew SafeCTLHandle(CertFindCTLInStore(storeHandle.Handle, DEFAULT_ENCODING,0,CTL_FIND_USAGE,¶,NULL)); 327 | if(context->Handle == NULL) 328 | { 329 | auto error = GetLastError(); 330 | if(error == CRYPT_E_NOT_FOUND) 331 | return nullptr; 332 | Win32::Throw(error); 333 | } 334 | return gcnew CTLContext(context); 335 | } 336 | private: CTLInfo^ _CTLInfo; 337 | public: property CTLInfo^ CTLInfo 338 | { 339 | TCTLInfo^ get() 340 | { 341 | return _CTLInfo; 342 | } 343 | } 344 | 345 | 346 | ~CTLContext() 347 | { 348 | this->!CTLContext(); 349 | } 350 | !CTLContext() 351 | { 352 | delete handle; 353 | } 354 | }; 355 | public ref class CTLContextBuilder 356 | { 357 | public : CTLContextBuilder() 358 | { 359 | _CTLInfo = gcnew CTLInfoBuilder(); 360 | _Signers = gcnew List(); 361 | } 362 | 363 | 364 | private: List^ _Signers; 365 | public: property IList^ Signers 366 | { 367 | IList^ get() 368 | { 369 | return _Signers; 370 | } 371 | } 372 | 373 | public: CTLContext^ ToCTLContext() 374 | { 375 | auto_handle ctlInfo(_CTLInfo->ToCTLInfo()); 376 | CMSG_SIGNED_ENCODE_INFO encodeInfo; 377 | ZeroMemory(&encodeInfo, sizeof(CMSG_SIGNED_ENCODE_INFO)); 378 | encodeInfo.cbSize = sizeof(CMSG_SIGNED_ENCODE_INFO); 379 | 380 | mauto_handle certificates; 381 | if(_CTLInfo->Certificates->Count > 0) 382 | { 383 | certificates = mauto_handle(new CERT_BLOB[_CTLInfo->Certificates->Count]); 384 | ZeroMemory(certificates.get(), sizeof(CERT_BLOB) * _CTLInfo->Certificates->Count); 385 | encodeInfo.rgCertEncoded = certificates.get(); 386 | encodeInfo.cCertEncoded = _CTLInfo->Certificates->Count; 387 | for(int i = 0; i < _CTLInfo->Certificates->Count; i++) 388 | { 389 | PCCERT_CONTEXT certHandle = (PCCERT_CONTEXT)_CTLInfo->Certificates[i]->Handle.ToPointer(); 390 | encodeInfo.rgCertEncoded[i].cbData = certHandle->cbCertEncoded; 391 | encodeInfo.rgCertEncoded[i].pbData = certHandle->pbCertEncoded; 392 | } 393 | } 394 | mauto_handle signers; 395 | if(Signers->Count > 0) 396 | { 397 | signers = mauto_handle(new CMSG_SIGNER_ENCODE_INFO[Signers->Count]); 398 | ZeroMemory(signers.get(), sizeof(CMSG_SIGNER_ENCODE_INFO) * Signers->Count); 399 | encodeInfo.rgSigners = signers.get(); 400 | encodeInfo.cSigners = Signers->Count; 401 | for(int i = 0; i < Signers->Count; i++) 402 | { 403 | PCCERT_CONTEXT certHandle = (PCCERT_CONTEXT)Signers[i]->Handle.ToPointer(); 404 | HCRYPTPROV privateKey; 405 | BOOL freePrivateKey; 406 | DWORD privateKeyType; 407 | encodeInfo.rgSigners[i].cbSize = sizeof(CMSG_SIGNER_ENCODE_INFO); 408 | encodeInfo.rgSigners[i].pCertInfo = certHandle->pCertInfo; 409 | ASSERT_TRUE(CryptAcquireCertificatePrivateKey( 410 | certHandle, 411 | CRYPT_ACQUIRE_CACHE_FLAG, 412 | NULL, 413 | &privateKey, 414 | &privateKeyType, 415 | &freePrivateKey)); 416 | encodeInfo.rgSigners[i].hCryptProv = privateKey; 417 | encodeInfo.rgSigners[i].dwKeySpec = privateKeyType; 418 | encodeInfo.rgSigners[i].HashAlgorithm.pszObjId = szOID_OIWSEC_sha1RSASign; 419 | } 420 | } 421 | 422 | DWORD flags = CMSG_ENCODE_SORTED_CTL_FLAG| CMSG_ENCODE_HASHED_SUBJECT_IDENTIFIER_FLAG; 423 | DWORD size; 424 | CryptMsgEncodeAndSignCTL(DEFAULT_ENCODING, (PCTL_INFO)ctlInfo->nativeCtlInfo.get(), &encodeInfo, flags,NULL,&size); 425 | std::auto_ptr encoded(new BYTE[size]); 426 | ASSERT_TRUE(CryptMsgEncodeAndSignCTL(DEFAULT_ENCODING, (PCTL_INFO)ctlInfo->nativeCtlInfo.get(), &encodeInfo, flags,encoded.get(),&size)); 427 | return CTLContext::Load(encoded.get(), size); 428 | }; 429 | 430 | private: CTLInfoBuilder^ _CTLInfo; 431 | public: property CTLInfoBuilder^ CTLInfo 432 | { 433 | CTLInfoBuilder^ get() 434 | { 435 | return _CTLInfo; 436 | } 437 | } 438 | }; 439 | 440 | 441 | 442 | EndHttpSysManager -------------------------------------------------------------------------------- /HttpSysManager/HttpSysManager.Native/HttpApiHelper.cpp: -------------------------------------------------------------------------------- 1 | #include "HttpSysManager.h" 2 | 3 | 4 | BeginHttpSysManager 5 | 6 | public class HttpApiHelper 7 | { 8 | public: 9 | template 10 | static mauto_handle HttpQueryServiceConfiguration(HTTP_SERVICE_CONFIG_ID configId, TQueryConfig& query, PULONG result) 11 | { 12 | ULONG length; 13 | ULONG firstCallResult = ::HttpQueryServiceConfiguration(NULL, 14 | configId, 15 | &query, 16 | sizeof(TQueryConfig), 17 | NULL, 18 | 0, 19 | &length, 20 | NULL); 21 | ASSERT_HTTPAPI_INITIALIZED(firstCallResult); 22 | mauto_handle buffer((TOutputConfig*)new BYTE[length]); 23 | ZeroMemory(buffer.get(),length); 24 | *result = ::HttpQueryServiceConfiguration(NULL, 25 | configId, 26 | &query, 27 | sizeof(TQueryConfig), 28 | buffer.get(), 29 | length, 30 | &length, 31 | NULL); 32 | return buffer; 33 | } 34 | }; 35 | 36 | EndHttpSysManager -------------------------------------------------------------------------------- /HttpSysManager/HttpSysManager.Native/HttpInitializeScope.cpp: -------------------------------------------------------------------------------- 1 | #include "HttpSysManager.h" 2 | 3 | BeginHttpSysManager 4 | 5 | public ref class HttpInitializeScope 6 | { 7 | ULONG flags; 8 | public: 9 | HttpInitializeScope() 10 | { 11 | HTTPAPI_VERSION v; 12 | v.HttpApiMajorVersion = 2; 13 | v.HttpApiMinorVersion = 0; 14 | Init(v,HTTP_INITIALIZE_CONFIG); 15 | } 16 | HttpInitializeScope(HTTPAPI_VERSION& version,ULONG flags) 17 | { 18 | Init(version, flags); 19 | } 20 | void Init(HTTPAPI_VERSION& version,ULONG flags) 21 | { 22 | ASSERT_SUCCESS(HttpInitialize(version,flags,NULL)); 23 | this->flags = flags; 24 | } 25 | 26 | ~HttpInitializeScope() 27 | { 28 | this->!HttpInitializeScope(); 29 | } 30 | 31 | !HttpInitializeScope() 32 | { 33 | ASSERT_SUCCESS(HttpTerminate(flags,NULL)); 34 | } 35 | }; 36 | 37 | EndHttpSysManager -------------------------------------------------------------------------------- /HttpSysManager/HttpSysManager.Native/HttpSysManager.Native.vcxproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Debug 6 | Win32 7 | 8 | 9 | Release 10 | Win32 11 | 12 | 13 | 14 | $(VCTargetsPath10) 15 | 16 | 17 | {BCEB0E3D-DAE6-4110-8C1E-1BC6202C31F4} 18 | v4.5 19 | ManagedCProj 20 | HttpSysManagerNative 21 | v120 22 | 23 | 24 | 25 | DynamicLibrary 26 | true 27 | true 28 | Unicode 29 | Debug_NonRedist\x86\Microsoft.VC100.DebugCRT\ 30 | 31 | 32 | DynamicLibrary 33 | false 34 | true 35 | Unicode 36 | x86\Microsoft.VC100.CRT\ 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | true 50 | $(ReferencePath) 51 | 52 | 53 | false 54 | 55 | 56 | 57 | httpapi.lib;Cryptui.lib;Crypt32.lib;%(AdditionalDependencies) 58 | 59 | 60 | 61 | 62 | Level3 63 | Disabled 64 | WIN32;_DEBUG;%(PreprocessorDefinitions) 65 | NotUsing 66 | MultiThreadedDebugDLL 67 | 68 | 69 | true 70 | 71 | 72 | 73 | 74 | Level3 75 | WIN32;NDEBUG;%(PreprocessorDefinitions) 76 | NotUsing 77 | MultiThreadedDLL 78 | 79 | 80 | true 81 | 82 | 83 | 84 | 85 | ..\HttpSysManager\bins\ProcessHacker.Common.dll 86 | 87 | 88 | ..\HttpSysManager\bins\ProcessHacker.Native.dll 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | {cb03213b-4cbb-4e09-8739-59d9fcfb71bf} 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | -------------------------------------------------------------------------------- /HttpSysManager/HttpSysManager.Native/HttpSysManager.Native.vcxproj.filters: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 6 | cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx 7 | 8 | 9 | {93995380-89BD-4b04-88EB-625FBE52EBFB} 10 | h;hpp;hxx;hm;inl;inc;xsd 11 | 12 | 13 | {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} 14 | rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms 15 | 16 | 17 | 18 | 19 | Source Files 20 | 21 | 22 | Source Files 23 | 24 | 25 | Source Files 26 | 27 | 28 | Source Files 29 | 30 | 31 | Source Files 32 | 33 | 34 | Source Files 35 | 36 | 37 | Source Files 38 | 39 | 40 | Source Files 41 | 42 | 43 | Source Files 44 | 45 | 46 | 47 | 48 | Resource Files 49 | 50 | 51 | 52 | 53 | Header Files 54 | 55 | 56 | Header Files 57 | 58 | 59 | 60 | 61 | Resource Files 62 | 63 | 64 | -------------------------------------------------------------------------------- /HttpSysManager/HttpSysManager.Native/HttpSysManager.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #define BeginHttpSysManager namespace HttpSysManager { namespace Native { 4 | #define EndHttpSysManager } } 5 | 6 | 7 | #include "mauto_ptr.h" 8 | #define WIN32_LEAN_AND_MEAN 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | 16 | BeginHttpSysManager 17 | #define ASSERT_SUCCESS(result) ULONG r = result; if(r != ERROR_SUCCESS) Win32::Throw(r); 18 | #define ASSERT_HTTPAPI_INITIALIZED(result) ULONG r = result; if(r == ERROR_INVALID_HANDLE) throw gcnew System::InvalidOperationException("You should first initialize HTTP Server API with HttpInitializeScope"); 19 | #define ASSERT_TRUE(result) if(!result) Win32::Throw(); 20 | 21 | using namespace System::Security::Cryptography::X509Certificates; 22 | using namespace System; 23 | using namespace System::Net; 24 | using namespace System::Net::Sockets; 25 | using namespace System::Runtime::InteropServices; 26 | using namespace HttpSysManager::Core; 27 | using namespace ProcessHacker::Native::Api; 28 | using namespace ProcessHacker::Native; 29 | using namespace System::ComponentModel; 30 | using namespace ProcessHacker::Native::Security; 31 | using namespace ProcessHacker::Native::Security::AccessControl; 32 | using namespace System::Collections::Generic; 33 | 34 | typedef System::Security::Cryptography::X509Certificates::StoreName TStoreName; 35 | typedef System::Security::Cryptography::X509Certificates::StoreLocation TStoreLocation; 36 | typedef System::Security::Cryptography::X509Certificates::X509FindType TX509FindType; 37 | 38 | typedef HttpSysManager::Core::Thumbprint TThumbprint; 39 | typedef System::Net::Sockets::AddressFamily TAddressFamily; 40 | 41 | 42 | EndHttpSysManager 43 | -------------------------------------------------------------------------------- /HttpSysManager/HttpSysManager.Native/ManagedSet.cpp: -------------------------------------------------------------------------------- 1 | #include "HttpSysManager.h" 2 | 3 | BeginHttpSysManager 4 | 5 | template 6 | public ref class ManagedSet 7 | { 8 | protected: mauto_handle Set; 9 | HTTP_SERVICE_CONFIG_ID ConfigId; 10 | 11 | public: ManagedSet(mauto_handle set, HTTP_SERVICE_CONFIG_ID configId) 12 | :Set(set), ConfigId(configId) 13 | { 14 | } 15 | public: ManagedSet(HTTP_SERVICE_CONFIG_ID configId) 16 | :Set(new TSet()),ConfigId(configId) 17 | { 18 | ZeroMemory(Set.get(),sizeof(TSet)); 19 | } 20 | 21 | 22 | public: virtual void Add() 23 | { 24 | ULONG result = HttpSetServiceConfiguration(NULL, 25 | ConfigId, 26 | Set.get(), 27 | sizeof(TSet), 28 | 0); 29 | ASSERT_HTTPAPI_INITIALIZED(result); 30 | if(result == ERROR_NO_SUCH_LOGON_SESSION) 31 | throw gcnew ArgumentException("Invalid Certificate"); 32 | if(result != 0) 33 | Win32::Throw(result); 34 | } 35 | public: virtual void Update() 36 | { 37 | try 38 | { 39 | Add(); 40 | }catch(WindowsException^ ex) 41 | { 42 | if((LONG)ex->ErrorCode != ERROR_ALREADY_EXISTS) 43 | throw; 44 | Delete(); 45 | Add(); 46 | } 47 | } 48 | public: virtual void Delete() 49 | { 50 | auto result = HttpDeleteServiceConfiguration(NULL, 51 | ConfigId, 52 | Set.get(), 53 | sizeof(TSet), 54 | 0); 55 | ASSERT_HTTPAPI_INITIALIZED(result); 56 | if(result != 0) 57 | Win32::Throw(result); 58 | } 59 | }; 60 | 61 | EndHttpSysManager -------------------------------------------------------------------------------- /HttpSysManager/HttpSysManager.Native/SSLInfo.cpp: -------------------------------------------------------------------------------- 1 | #include "HttpSysManager.h" 2 | #include "HttpApiHelper.cpp" 3 | #include "ManagedSet.cpp" 4 | #include "CTLInfo.cpp" 5 | 6 | BeginHttpSysManager 7 | 8 | public ref class SSLInfo : public ManagedSet 9 | { 10 | 11 | private: static System::Guid ToCLRGuid(GUID& guid) 12 | { 13 | return *reinterpret_cast(&guid); 14 | } 15 | private: static GUID ToNativeGuid(System::Guid& guid) 16 | { 17 | return *reinterpret_cast(&guid); 18 | } 19 | 20 | 21 | public: static SSLInfo^ Get(int index) 22 | { 23 | HTTP_SERVICE_CONFIG_SSL_QUERY query; 24 | query.dwToken = index; 25 | query.QueryDesc = HttpServiceConfigQueryNext; 26 | ULONG result; 27 | auto buffer = 28 | HttpApiHelper::HttpQueryServiceConfiguration(HttpServiceConfigSSLCertInfo, query, &result); 29 | if(result == ERROR_NO_MORE_ITEMS) 30 | return nullptr; 31 | ASSERT_SUCCESS(result); 32 | return gcnew SSLInfo(buffer); 33 | } 34 | public: static SSLInfo^ Get(IPEndPoint^ endpoint) 35 | { 36 | HTTP_SERVICE_CONFIG_SSL_QUERY query; 37 | query.QueryDesc = HttpServiceConfigQueryExact; 38 | SSLInfo info; 39 | info.Endpoint = endpoint; 40 | query.KeyDesc.pIpPort = info.Set->KeyDesc.pIpPort; 41 | ULONG result; 42 | auto buffer = 43 | HttpApiHelper::HttpQueryServiceConfiguration(HttpServiceConfigSSLCertInfo, query, &result); 44 | if(result == ERROR_FILE_NOT_FOUND) 45 | return nullptr; 46 | ASSERT_SUCCESS(result); 47 | return gcnew SSLInfo(buffer); 48 | } 49 | public: SSLInfo() 50 | :ManagedSet(HttpServiceConfigSSLCertInfo) 51 | { 52 | Init(TStoreName::My, nullptr); 53 | } 54 | public: SSLInfo(String^ thumbprint) 55 | :ManagedSet(HttpServiceConfigSSLCertInfo) 56 | { 57 | Init(TStoreName::My, thumbprint); 58 | } 59 | public: SSLInfo(TStoreName storeName, String^ thumbprint) 60 | :ManagedSet(HttpServiceConfigSSLCertInfo) 61 | { 62 | Init(storeName, thumbprint); 63 | } 64 | 65 | public: SSLInfo(mauto_handle set) 66 | :ManagedSet(set, HttpServiceConfigSSLCertInfo), 67 | marshal(gcnew msclr::interop::marshal_context()) 68 | { 69 | InternalSetCertificate(Thumbprint,false); 70 | } 71 | 72 | private: void Init(TStoreName storeName, String^ thumbprint) 73 | { 74 | marshal = auto_handle(gcnew msclr::interop::marshal_context()); 75 | StoreName = storeName; 76 | if(thumbprint != nullptr) 77 | Thumbprint = gcnew TThumbprint(thumbprint); 78 | } 79 | 80 | 81 | 82 | private: LocalMemoryAlloc^ _Thumbprint; 83 | public: property TThumbprint^ Thumbprint 84 | { 85 | TThumbprint^ get() 86 | { 87 | return gcnew TThumbprint((BYTE*)Set->ParamDesc.pSslHash, Set->ParamDesc.SslHashLength); 88 | } 89 | void set(TThumbprint^ value) 90 | { 91 | InternalSetCertificate(value); 92 | SetThumbprint(value); 93 | } 94 | } 95 | 96 | typedef CTLInfo TCTLInfo; 97 | 98 | private: CTLContext^ _CTLContext; 99 | 100 | private: LocalMemoryAlloc^ _CTLListIdentifier; 101 | //public: property CTLContext^ CTLInfo 102 | // { 103 | // CTLContext^ get() 104 | // { 105 | // return _CTLContext; 106 | // } 107 | // void set(CTLContext^ value) 108 | // { 109 | // _CTLContext = value; 110 | // if(_CTLContext == nullptr || _CTLContext->Store == nullptr) 111 | // { 112 | // Set->ParamDesc.pDefaultSslCtlStoreName = NULL; 113 | // Set->ParamDesc.pDefaultSslCtlIdentifier = NULL; 114 | // } 115 | // else 116 | // { 117 | // if(_CTLContext->Store->Name != nullptr) 118 | // { 119 | // _CTLStoreName = gcnew LocalMemoryAlloc(Marshal::StringToHGlobalUni(_CTLContext->Store->Name)); 120 | // Set->ParamDesc.pSslCertStoreName = (PWSTR)(void*)_CTLStoreName; 121 | // } 122 | // else 123 | // { 124 | // Set->ParamDesc.pDefaultSslCtlStoreName = NULL; 125 | // } 126 | // //_CTLStoreName = gcnew LocalMemoryAlloc(InteropHelper::ToCArray(_CTLInfo->ListIdentifier)); 127 | // } 128 | // if(_CTLContext != nullptr && !String::IsNullOrEmpty(_CTLContext->CTLInfo->ListIdentifier)) 129 | // { 130 | // _CTLListIdentifier = gcnew LocalMemoryAlloc(Marshal::StringToHGlobalUni(_CTLContext->CTLInfo->ListIdentifier)); 131 | // Set->ParamDesc.pDefaultSslCtlIdentifier = (PWSTR)(void*)_CTLListIdentifier; 132 | // } 133 | // else 134 | // { 135 | // Set->ParamDesc.pDefaultSslCtlIdentifier = NULL; 136 | // } 137 | // } 138 | // } 139 | 140 | auto_handle marshal; 141 | public: property String^ CTLIdentifier 142 | { 143 | String^ get() 144 | { 145 | if(Set->ParamDesc.pDefaultSslCtlIdentifier == NULL) 146 | return nullptr; 147 | return Marshal::PtrToStringUni(IntPtr(Set->ParamDesc.pDefaultSslCtlIdentifier)); 148 | } 149 | void set(String^ value) 150 | { 151 | if(String::IsNullOrEmpty(value)) 152 | { 153 | Set->ParamDesc.pDefaultSslCtlIdentifier = NULL; 154 | return; 155 | } 156 | Set->ParamDesc.pDefaultSslCtlIdentifier = (PWSTR)marshal->marshal_as(value); 157 | } 158 | } 159 | 160 | private: LocalMemoryAlloc^ _CTLStoreName; 161 | public: property Nullable CTLStoreName 162 | { 163 | Nullable get() 164 | { 165 | if(Set->ParamDesc.pDefaultSslCtlStoreName == NULL) 166 | { 167 | return Nullable(); 168 | } 169 | String^ store = Marshal::PtrToStringUni(IntPtr(Set->ParamDesc.pDefaultSslCtlStoreName)); 170 | return Nullable((TStoreName)Enum::Parse(TStoreName::typeid,store,true)); 171 | } 172 | void set(Nullable value) 173 | { 174 | if(!value.HasValue) 175 | { 176 | Set->ParamDesc.pDefaultSslCtlStoreName = NULL; 177 | return; 178 | } 179 | String^ str = Enum::GetName(TStoreName::typeid, value.Value)->ToUpper(); 180 | _CTLStoreName = gcnew LocalMemoryAlloc(IntPtr((PWSTR)Marshal::StringToHGlobalUni(str).ToPointer())); 181 | Set->ParamDesc.pDefaultSslCtlStoreName = (PWSTR)(void*)_CTLStoreName; 182 | } 183 | } 184 | 185 | private: void SetThumbprint(TThumbprint^ value) 186 | { 187 | if(value == nullptr) 188 | { 189 | Set->ParamDesc.SslHashLength = 0; 190 | return; 191 | } 192 | 193 | Set->ParamDesc.SslHashLength = value->Data->Length; 194 | _Thumbprint = InteropHelper::ToCArray(value->Data); 195 | Set->ParamDesc.pSslHash = (void*)_Thumbprint; 196 | } 197 | private: void InternalSetCertificate(TThumbprint^ thumbprint) 198 | { 199 | InternalSetCertificate(thumbprint,true); 200 | } 201 | private: void InternalSetCertificate(TThumbprint^ thumbprint, bool throwOnNotFound) 202 | { 203 | if(thumbprint == nullptr) 204 | { 205 | _Certificate = nullptr; 206 | return; 207 | } 208 | auto cert = CertificateHelper::GetCertificate(TStoreLocation::LocalMachine, StoreName, TX509FindType::FindByThumbprint, thumbprint->ToString()); 209 | if(cert == nullptr && throwOnNotFound) 210 | { 211 | throw gcnew ArgumentException("Certificate " + thumbprint + " not found in the store " + Enum::GetName(TStoreName::typeid, StoreName) + " of the local machine"); 212 | } 213 | _Certificate = cert; 214 | } 215 | 216 | public: void SetCertificate(TStoreName store, String^ thumbprint) 217 | { 218 | Certificate = CertificateHelper::GetCertificate(TStoreLocation::LocalMachine, StoreName, TX509FindType::FindByThumbprint, thumbprint); 219 | } 220 | private: X509Certificate2^ _Certificate; 221 | public: property X509Certificate2^ Certificate 222 | { 223 | X509Certificate2^ get() 224 | { 225 | return _Certificate; 226 | } 227 | void set(X509Certificate2^ value) 228 | { 229 | TThumbprint^ thumbprint = gcnew TThumbprint(value->Thumbprint); 230 | InternalSetCertificate(thumbprint); 231 | SetThumbprint(thumbprint); 232 | } 233 | } 234 | 235 | private: IPEndPoint^ _Endpoint; 236 | public: property IPEndPoint^ Endpoint 237 | { 238 | IPEndPoint^ get() 239 | { 240 | BYTE* socketAddress = (BYTE*)Set->KeyDesc.pIpPort; 241 | auto family = (TAddressFamily)((int)socketAddress[0] | (int)socketAddress[1] << 8); 242 | if(family == TAddressFamily::InterNetworkV6) 243 | { 244 | array^ arr = gcnew array(16); 245 | for(int i = 0 ; i < arr->Length ; i++) 246 | { 247 | arr[i] = socketAddress[i + 8]; 248 | } 249 | int port = ((int)socketAddress[2] << 8 & 65280) | (int)socketAddress[3]; 250 | UInt64 scopeid = (UInt64)(((int)socketAddress[27] << 24) + ((int)socketAddress[26] << 16) + ((int)socketAddress[25] << 8) + (int)socketAddress[24]); 251 | return gcnew IPEndPoint(gcnew IPAddress(arr, scopeid), port); 252 | } 253 | if(family != TAddressFamily::InterNetwork) 254 | throw gcnew NotSupportedException(family.ToString()); 255 | int port2 = ((int)socketAddress[2] << 8 & 65280) | (int)socketAddress[3]; 256 | long address = (long)((int)(socketAddress[4] & 255) | ((int)socketAddress[5] << 8 & 65280) | ((int)socketAddress[6] << 16 & 16711680) | (int)socketAddress[7] << 24) & (UInt64)-1; 257 | return gcnew IPEndPoint(address, port2); 258 | } 259 | void set(IPEndPoint^ value) 260 | { 261 | SocketAddress^ address = value->Serialize(); 262 | _SocketAddress = mauto_handle(new BYTE[address->Size]()); 263 | Set->KeyDesc.pIpPort = (PSOCKADDR)_SocketAddress.get(); 264 | BYTE* socketBytes=(BYTE*)_SocketAddress.get(); 265 | for(int i = 0; i < address->Size;i++) 266 | socketBytes[i] = address[i]; 267 | } 268 | } 269 | mauto_handle _SocketAddress; 270 | public: property Guid AppId 271 | { 272 | Guid get() 273 | { 274 | return ToCLRGuid(Set->ParamDesc.AppId); 275 | } 276 | void set(Guid value) 277 | { 278 | Set->ParamDesc.AppId = ToNativeGuid(value); 279 | } 280 | } 281 | 282 | private: LocalMemoryAlloc^ _StoreName; 283 | public: property TStoreName StoreName 284 | { 285 | TStoreName get() 286 | { 287 | if(Set->ParamDesc.pSslCertStoreName == NULL) 288 | { 289 | return TStoreName::My; 290 | } 291 | String^ store = Marshal::PtrToStringUni(IntPtr(Set->ParamDesc.pSslCertStoreName)); 292 | return (TStoreName)Enum::Parse(TStoreName::typeid,store,true); 293 | } 294 | void set(TStoreName value) 295 | { 296 | String^ str = Enum::GetName(TStoreName::typeid, value)->ToUpper(); 297 | _StoreName = gcnew LocalMemoryAlloc(IntPtr((PWSTR)Marshal::StringToHGlobalUni(str).ToPointer())); 298 | Set->ParamDesc.pSslCertStoreName = (PWSTR)(void*)_StoreName; 299 | } 300 | } 301 | public: property bool NegotiateClientCert 302 | { 303 | bool get() 304 | { 305 | return (Set->ParamDesc.DefaultFlags & HTTP_SERVICE_CONFIG_SSL_FLAG_NEGOTIATE_CLIENT_CERT) != 0; 306 | } 307 | void set(bool value) 308 | { 309 | if(value) 310 | Set->ParamDesc.DefaultFlags |= HTTP_SERVICE_CONFIG_SSL_FLAG_NEGOTIATE_CLIENT_CERT; 311 | else 312 | Set->ParamDesc.DefaultFlags &= ~HTTP_SERVICE_CONFIG_SSL_FLAG_NEGOTIATE_CLIENT_CERT; 313 | } 314 | } 315 | public: property bool CertificateAccountMapping 316 | { 317 | bool get() 318 | { 319 | return (Set->ParamDesc.DefaultFlags & HTTP_SERVICE_CONFIG_SSL_FLAG_USE_DS_MAPPER) != 0; 320 | } 321 | void set(bool value) 322 | { 323 | if(value) 324 | Set->ParamDesc.DefaultFlags |= HTTP_SERVICE_CONFIG_SSL_FLAG_USE_DS_MAPPER; 325 | else 326 | Set->ParamDesc.DefaultFlags &= ~HTTP_SERVICE_CONFIG_SSL_FLAG_USE_DS_MAPPER; 327 | } 328 | } 329 | public: property bool CheckClientCertificate 330 | { 331 | bool get() 332 | { 333 | return Set->ParamDesc.DefaultCertCheckMode == 0; 334 | } 335 | void set(bool value) 336 | { 337 | Set->ParamDesc.DefaultCertCheckMode = value ? 0 : 1; 338 | } 339 | } 340 | }; 341 | 342 | EndHttpSysManager -------------------------------------------------------------------------------- /HttpSysManager/HttpSysManager.Native/SafeHandles.cpp: -------------------------------------------------------------------------------- 1 | #include "HttpSysManager.h" 2 | 3 | template 4 | public ref class MySafeHandle 5 | { 6 | public:MySafeHandle(THandle handle):_Handle(handle) 7 | { 8 | 9 | } 10 | private: THandle _Handle; 11 | public: property THandle Handle 12 | { 13 | THandle get() 14 | { 15 | return _Handle; 16 | } 17 | void set(THandle value) 18 | { 19 | _Handle = value; 20 | } 21 | } 22 | ~MySafeHandle() 23 | { 24 | this->!MySafeHandle(); 25 | } 26 | !MySafeHandle() 27 | { 28 | if(Handle != NULL) 29 | Release(); 30 | } 31 | protected: virtual void Release() 32 | {} 33 | }; 34 | 35 | public ref class SafeStoreHandle : MySafeHandle 36 | { 37 | public:SafeStoreHandle(HCERTSTORE handle):MySafeHandle(handle) 38 | { 39 | 40 | } 41 | protected: virtual void Release() override 42 | { 43 | CertCloseStore(Handle,0); 44 | } 45 | }; 46 | public ref class SafeCertHandle : MySafeHandle 47 | { 48 | public:SafeCertHandle(PCCERT_CONTEXT handle):MySafeHandle(handle) 49 | { 50 | } 51 | protected: virtual void Release() override 52 | { 53 | CertFreeCertificateContext(Handle); 54 | } 55 | }; 56 | 57 | public ref class SafeCTLHandle : MySafeHandle 58 | { 59 | public:SafeCTLHandle(PCCTL_CONTEXT handle):MySafeHandle(handle) 60 | { 61 | 62 | } 63 | protected: virtual void Release() override 64 | { 65 | CertFreeCTLContext(Handle); 66 | } 67 | }; 68 | 69 | public ref class HGlobalHandle : MySafeHandle 70 | { 71 | public:HGlobalHandle(System::IntPtr handle):MySafeHandle(handle.ToPointer()) 72 | { 73 | 74 | } 75 | public:HGlobalHandle(void* handle):MySafeHandle(handle) 76 | { 77 | 78 | } 79 | protected: virtual void Release() override 80 | { 81 | System::Runtime::InteropServices::Marshal::FreeHGlobal(System::IntPtr(Handle)); 82 | } 83 | }; -------------------------------------------------------------------------------- /HttpSysManager/HttpSysManager.Native/Security.cpp: -------------------------------------------------------------------------------- 1 | #include "HttpSysManager.h" 2 | #include "SafeHandles.cpp" 3 | 4 | BeginHttpSysManager 5 | public ref class Security 6 | { 7 | 8 | public: static X509Certificate2^ SelectCertificate() 9 | { 10 | SafeStoreHandle storeHandle(CertOpenStore(CERT_STORE_PROV_SYSTEM,0,NULL,CERT_SYSTEM_STORE_LOCAL_MACHINE, L"MY")); 11 | SafeCertHandle certHandle(CryptUIDlgSelectCertificateFromStore(storeHandle.Handle,NULL,NULL,NULL,0,0,0)); 12 | if(certHandle.Handle == NULL) 13 | return nullptr; 14 | return gcnew X509Certificate2(IntPtr((void*)certHandle.Handle)); //X509Certificate2 duplicate the handle 15 | }; 16 | }; 17 | EndHttpSysManager -------------------------------------------------------------------------------- /HttpSysManager/HttpSysManager.Native/UrlAcl.cpp: -------------------------------------------------------------------------------- 1 | #include "HttpSysManager.h" 2 | #include "HttpInitializeScope.cpp" 3 | #include "HttpApiHelper.cpp" 4 | #include "ManagedSet.cpp" 5 | 6 | typedef ProcessHacker::Native::Security::AccessControl::SecurityDescriptor TSecurityDescriptor; 7 | 8 | BeginHttpSysManager 9 | 10 | public ref class UrlAcl : public ManagedSet, public ISecurable 11 | { 12 | public: UrlAcl() 13 | :ManagedSet(HttpServiceConfigUrlAclInfo) 14 | { 15 | } 16 | public: UrlAcl(mauto_handle urlAcl): 17 | ManagedSet(urlAcl, HttpServiceConfigUrlAclInfo) 18 | { 19 | } 20 | 21 | 22 | LocalMemoryAlloc^ _Prefix; 23 | public: property String^ Prefix 24 | { 25 | String^ get() 26 | { 27 | return Marshal::PtrToStringUni(IntPtr(Set->KeyDesc.pUrlPrefix)); 28 | } 29 | void set(String^ value) 30 | { 31 | _Prefix = gcnew LocalMemoryAlloc(IntPtr((PWSTR)Marshal::StringToHGlobalUni(value).ToPointer())); 32 | Set->KeyDesc.pUrlPrefix = (PWSTR)(void*)_Prefix; 33 | } 34 | } 35 | LocalMemoryAlloc^ _SecurityDescriptor; 36 | public: property TSecurityDescriptor^ SecurityDescriptor 37 | { 38 | TSecurityDescriptor^ get() 39 | { 40 | return TSecurityDescriptor::FromSDDL(Marshal::PtrToStringUni(IntPtr(Set->ParamDesc.pStringSecurityDescriptor))); 41 | } 42 | void set(TSecurityDescriptor^ value) 43 | { 44 | if(value == nullptr) 45 | throw gcnew ArgumentNullException("value"); 46 | _SecurityDescriptor = gcnew LocalMemoryAlloc(Marshal::StringToHGlobalUni(value->ToString())); 47 | Set->ParamDesc.pStringSecurityDescriptor = (PWSTR)(void*)_SecurityDescriptor; 48 | } 49 | } 50 | 51 | public: static UrlAcl^ Get(int index) 52 | { 53 | HTTP_SERVICE_CONFIG_URLACL_QUERY query; 54 | query.dwToken = index; 55 | query.QueryDesc = HttpServiceConfigQueryNext; 56 | ULONG result; 57 | auto buffer = 58 | HttpApiHelper::HttpQueryServiceConfiguration(HttpServiceConfigUrlAclInfo, query, &result); 59 | if(result == ERROR_NO_MORE_ITEMS) 60 | return nullptr; 61 | ASSERT_SUCCESS(result); 62 | return gcnew UrlAcl(buffer); 63 | } 64 | public: static UrlAcl^ Get(String^ prefix) 65 | { 66 | HTTP_SERVICE_CONFIG_URLACL_QUERY query; 67 | query.QueryDesc = HttpServiceConfigQueryExact; 68 | UrlAcl info; 69 | info.Prefix = prefix; 70 | query.KeyDesc.pUrlPrefix = info.Set->KeyDesc.pUrlPrefix; 71 | ULONG result; 72 | auto buffer = 73 | HttpApiHelper::HttpQueryServiceConfiguration(HttpServiceConfigUrlAclInfo, query, &result); 74 | if(result == ERROR_FILE_NOT_FOUND) 75 | return nullptr; 76 | ASSERT_SUCCESS(result); 77 | return gcnew UrlAcl(buffer); 78 | } 79 | 80 | private: virtual TSecurityDescriptor^ GetSecurity(SecurityInformation securityInformation) sealed = ISecurable::GetSecurity 81 | { 82 | return SecurityDescriptor; 83 | } 84 | 85 | private: virtual void SetSecurity(SecurityInformation securityInformation, TSecurityDescriptor^ securityDescriptor) sealed = ISecurable::SetSecurity 86 | { 87 | if(securityDescriptor->ToString() == TSecurityDescriptor::Empty->ToString()) 88 | return; 89 | HttpInitializeScope scope; 90 | SecurityDescriptor = securityDescriptor; 91 | Update(); 92 | } 93 | public: 94 | void SetSecurity(TSecurityDescriptor^ securityDescriptor) 95 | { 96 | ((ISecurable^)this)->SetSecurity(SecurityInformation::Dacl, securityDescriptor); 97 | } 98 | 99 | }; 100 | 101 | EndHttpSysManager -------------------------------------------------------------------------------- /HttpSysManager/HttpSysManager.Native/app.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kstrauss/HttpSysManager/f5276b8aa8180d071a08b8e708739171ce2248ba/HttpSysManager/HttpSysManager.Native/app.ico -------------------------------------------------------------------------------- /HttpSysManager/HttpSysManager.Native/app.rc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kstrauss/HttpSysManager/f5276b8aa8180d071a08b8e708739171ce2248ba/HttpSysManager/HttpSysManager.Native/app.rc -------------------------------------------------------------------------------- /HttpSysManager/HttpSysManager.Native/mauto_ptr.h: -------------------------------------------------------------------------------- 1 | #if !defined(MAUTO_PTR) 2 | 3 | #ifndef __cplusplus_cli 4 | #error ERROR: msclr libraries are not compatible with /clr:oldSyntax 5 | #endif 6 | 7 | #include 8 | #include "HttpSysManager.h" 9 | 10 | 11 | using namespace msclr; 12 | 13 | BeginHttpSysManager 14 | 15 | // wrap a resource to enforce strict ownership and ensure proper cleanup 16 | template 17 | public ref class mauto_handle 18 | { 19 | private: 20 | // disallow explicit comparisons to _safe_bool 21 | bool operator==( _detail_class::_safe_bool ); 22 | bool operator!=( _detail_class::_safe_bool ); 23 | 24 | public: 25 | 26 | // Constructors 27 | 28 | mauto_handle() 29 | : m_handle( nullptr ) 30 | { 31 | } 32 | 33 | // construct from object pointer 34 | mauto_handle( _element_type * _ptr ) 35 | : m_handle( _ptr ) 36 | { 37 | } 38 | 39 | // construct by assuming pointer from _right auto_handle 40 | mauto_handle(mauto_handle<_element_type> % _right ) 41 | : m_handle( _right.release() ) 42 | { 43 | } 44 | 45 | template 46 | mauto_handle( mauto_handle<_other_type> % _right ) 47 | : m_handle( _right.release() ) 48 | { 49 | } 50 | 51 | // assign compatible _right 52 | mauto_handle<_element_type> % operator=( 53 | mauto_handle<_element_type> % _right ) 54 | { 55 | reset( _right.release() ); 56 | return *this; 57 | } 58 | 59 | 60 | template 61 | mauto_handle<_element_type> % operator=( 62 | mauto_handle<_other_type> % _right ) 63 | { 64 | reset( _right.release() ); 65 | return *this; 66 | } 67 | 68 | _element_type * get() 69 | { 70 | return m_handle; 71 | } 72 | 73 | // return pointer to class object (assume pointer) 74 | _element_type * operator->() 75 | { 76 | return m_handle; 77 | } 78 | 79 | // for use when auto_handle appears in a conditional 80 | operator _detail_class::_safe_bool() 81 | { 82 | return valid() ? _detail_class::_safe_true : _detail_class::_safe_false; 83 | } 84 | 85 | // for use when auto_handle appears in a conditional 86 | bool operator!() 87 | { 88 | return ! valid(); 89 | } 90 | 91 | 92 | template 93 | operator mauto_handle<_other_type>() 94 | { 95 | return auto_handle<_other_type>( *this ); 96 | } 97 | 98 | void swap( mauto_handle<_element_type> % _right ) 99 | { 100 | mauto_handle<_element_type> tmp = _right; 101 | _right = *this; 102 | *this = tmp; 103 | } 104 | 105 | void reset( _element_type * _new_ptr ) 106 | { 107 | if( m_handle != _new_ptr ) 108 | { 109 | if( valid() ) 110 | { 111 | delete m_handle; 112 | } 113 | m_handle = _new_ptr; 114 | } 115 | } 116 | 117 | void reset( ) 118 | { 119 | reset(nullptr); 120 | } 121 | 122 | _element_type * release() 123 | { 124 | _element_type *_tmp_ptr = m_handle; 125 | m_handle = nullptr; 126 | return _tmp_ptr; 127 | } 128 | 129 | // destroy the object 130 | ~mauto_handle() 131 | { 132 | (*this).!mauto_handle(); 133 | } 134 | // destroy the object 135 | !mauto_handle() 136 | { 137 | if( valid() ) 138 | { 139 | delete m_handle; 140 | } 141 | } 142 | 143 | private: 144 | 145 | bool valid() 146 | { 147 | // see if the managed resource is in the invalid state. 148 | return m_handle != nullptr; 149 | 150 | } 151 | 152 | // the wrapped object 153 | _element_type * m_handle; 154 | }; 155 | 156 | // swap the contents of two auto_handle objects 157 | template 158 | void swap( mauto_handle<_element_type> % _left, 159 | mauto_handle<_element_type> % _right ) 160 | { 161 | _left.swap( _right ); 162 | } 163 | 164 | EndHttpSysManager 165 | 166 | #define MAUTO_PTR 167 | 168 | #endif // MAUTO_PTR -------------------------------------------------------------------------------- /HttpSysManager/HttpSysManager.Tests/Certificates/HttpSysManager.cer: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kstrauss/HttpSysManager/f5276b8aa8180d071a08b8e708739171ce2248ba/HttpSysManager/HttpSysManager.Tests/Certificates/HttpSysManager.cer -------------------------------------------------------------------------------- /HttpSysManager/HttpSysManager.Tests/HttpSysManager.Tests.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | Debug 5 | x86 6 | 8.0.30703 7 | 2.0 8 | {8C28AF8E-9597-4A2A-A874-31998DEBFFC0} 9 | Exe 10 | Properties 11 | HttpSysManager.Tests 12 | HttpSysManager.Tests 13 | v4.5 14 | 15 | 16 | 512 17 | 18 | 19 | x86 20 | true 21 | full 22 | false 23 | bin\Debug\ 24 | DEBUG;TRACE 25 | prompt 26 | 4 27 | false 28 | 29 | 30 | x86 31 | pdbonly 32 | true 33 | bin\Release\ 34 | TRACE 35 | prompt 36 | 4 37 | false 38 | 39 | 40 | 41 | {cb03213b-4cbb-4e09-8739-59d9fcfb71bf} 42 | HttpSysManager.Core 43 | 44 | 45 | HttpSysManager.Native 46 | 47 | 48 | ..\HttpSysManager\bins\ProcessHacker.Common.dll 49 | 50 | 51 | ..\HttpSysManager\bins\ProcessHacker.Native.dll 52 | 53 | 54 | False 55 | ..\HttpSysManager\bins\SlasheneFramework.dll 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | False 66 | xunit\xunit.dll 67 | 68 | 69 | False 70 | xunit\xunit.extensions.dll 71 | 72 | 73 | False 74 | xunit\xunit.runner.utility.dll 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | {910CE5E7-9DD1-46E9-90C4-AB89B086D45F} 90 | HttpSysManager 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 108 | -------------------------------------------------------------------------------- /HttpSysManager/HttpSysManager.Tests/Program.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using Xunit; 6 | using System.Diagnostics; 7 | using System.Reflection; 8 | using System.Runtime.InteropServices; 9 | using HttpSysManager.HttpAPI; 10 | using System.Security.Cryptography.X509Certificates; 11 | 12 | namespace HttpSysManager.Tests 13 | { 14 | class CertificateInstallation : IDisposable 15 | { 16 | private X509Certificate2 certificate; 17 | StoreName storeName; 18 | StoreLocation location; 19 | 20 | public CertificateInstallation(X509Certificate2 certificate, StoreLocation location, StoreName storeName) 21 | { 22 | this.certificate = certificate; 23 | this.location = location; 24 | this.storeName = storeName; 25 | Install(certificate); 26 | } 27 | 28 | private void Install(X509Certificate2 certificate) 29 | { 30 | X509Store store = new X509Store(storeName, location); 31 | store.Open(OpenFlags.ReadWrite); 32 | try 33 | { 34 | var foundCert = store.Certificates.Find(X509FindType.FindByThumbprint, certificate.Thumbprint, false).OfType().FirstOrDefault(); 35 | if(foundCert != null) 36 | return; 37 | store.Add(certificate); 38 | } 39 | finally 40 | { 41 | store.Close(); 42 | } 43 | } 44 | #region IDisposable Members 45 | 46 | public void Dispose() 47 | { 48 | X509Store store = new X509Store(storeName, location); 49 | store.Open(OpenFlags.ReadWrite); 50 | try 51 | { 52 | var foundCert = store.Certificates.Find(X509FindType.FindByThumbprint, certificate.Thumbprint, false).OfType().FirstOrDefault(); 53 | if(foundCert != null) 54 | { 55 | store.Remove(foundCert); 56 | } 57 | } 58 | finally 59 | { 60 | store.Close(); 61 | } 62 | } 63 | 64 | #endregion 65 | } 66 | class Program : ITestMethodRunnerCallback 67 | { 68 | static void Main(string[] args) 69 | { 70 | using(AssertIsInstalled(TestClass.TestCertificate)) 71 | { 72 | var env = new MultiAssemblyTestEnvironment(); 73 | env.Load(Assembly.GetExecutingAssembly().Location); 74 | var methods = env.EnumerateTestMethods(); 75 | env.Run(methods, new Program()); 76 | } 77 | } 78 | 79 | private static IDisposable AssertIsInstalled(X509Certificate2 certificate) 80 | { 81 | return new CertificateInstallation(certificate, StoreLocation.LocalMachine, StoreName.My); 82 | } 83 | 84 | 85 | #region ITestMethodRunnerCallback Members 86 | 87 | public void AssemblyFinished(TestAssembly testAssembly, int total, int failed, int skipped, double time) 88 | { 89 | 90 | } 91 | 92 | public void AssemblyStart(TestAssembly testAssembly) 93 | { 94 | 95 | } 96 | 97 | public bool ClassFailed(Xunit.TestClass testClass, string exceptionType, string message, string stackTrace) 98 | { 99 | return false; 100 | } 101 | 102 | public void ExceptionThrown(TestAssembly testAssembly, Exception exception) 103 | { 104 | 105 | } 106 | 107 | public bool TestFinished(TestMethod testMethod) 108 | { 109 | if(testMethod.RunStatus == TestStatus.Passed) 110 | { 111 | Console.ForegroundColor = ConsoleColor.Green; 112 | WriteLine(testMethod.MethodName + " passed"); 113 | } 114 | if(testMethod.RunStatus == TestStatus.Failed) 115 | { 116 | Console.ForegroundColor = ConsoleColor.Red; 117 | WriteLine(testMethod.MethodName + " failed"); 118 | } 119 | Console.ForegroundColor = ConsoleColor.White; 120 | WriteLine(GetLog(testMethod)); 121 | return true; 122 | } 123 | 124 | private string GetLog(TestMethod testMethod) 125 | { 126 | var result = testMethod.RunResults.First(); 127 | if(result is TestPassedResult) 128 | { 129 | return ((TestPassedResult)result).Output; 130 | } 131 | else if(result is TestFailedResult) 132 | { 133 | return ((TestFailedResult)result).Output; 134 | } 135 | return ""; 136 | } 137 | 138 | private void WriteLine(string str) 139 | { 140 | Console.WriteLine(str); 141 | Trace.WriteLine(str); 142 | } 143 | 144 | public bool TestStart(TestMethod testMethod) 145 | { 146 | return true; 147 | } 148 | 149 | #endregion 150 | } 151 | } 152 | -------------------------------------------------------------------------------- /HttpSysManager/HttpSysManager.Tests/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyTitle("HttpSysManager.Tests")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("")] 12 | [assembly: AssemblyProduct("HttpSysManager.Tests")] 13 | [assembly: AssemblyCopyright("Copyright © 2011")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // Setting ComVisible to false makes the types in this assembly not visible 18 | // to COM components. If you need to access a type in this assembly from 19 | // COM, set the ComVisible attribute to true on that type. 20 | [assembly: ComVisible(false)] 21 | 22 | // The following GUID is for the ID of the typelib if this project is exposed to COM 23 | [assembly: Guid("601dea46-9cee-4373-b499-c37b91e538ed")] 24 | 25 | // Version information for an assembly consists of the following four values: 26 | // 27 | // Major Version 28 | // Minor Version 29 | // Build Number 30 | // Revision 31 | // 32 | // You can specify all the values or you can default the Build and Revision Numbers 33 | // by using the '*' as shown below: 34 | // [assembly: AssemblyVersion("1.0.*")] 35 | [assembly: AssemblyVersion("1.0.0.0")] 36 | [assembly: AssemblyFileVersion("1.0.0.0")] 37 | -------------------------------------------------------------------------------- /HttpSysManager/HttpSysManager.Tests/TestClass.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using Xunit; 6 | using HttpSysManager.HttpAPI; 7 | using ProcessHacker.Native.Security.AccessControl; 8 | using ProcessHacker.Native.Security; 9 | using System.Runtime.InteropServices; 10 | using System.Net; 11 | using System.Security.Cryptography.X509Certificates; 12 | using HttpSysManager.Native; 13 | using System.IO; 14 | using HttpSysManager.Core; 15 | 16 | namespace HttpSysManager.Tests 17 | { 18 | public class TestAcl : IDisposable 19 | { 20 | readonly string _Url; 21 | public string Url 22 | { 23 | get 24 | { 25 | return _Url; 26 | } 27 | } 28 | public TestAcl() 29 | { 30 | _Url = "http://+:9393/"; 31 | HttpAPIManager manager = new HttpAPIManager(); 32 | manager.SetUrlAcl(_Url, SecurityDescriptor.FromSDDL("D:(A;;GX;;;WD)")); 33 | } 34 | #region IDisposable Members 35 | 36 | public void Dispose() 37 | { 38 | HttpAPIManager manager = new HttpAPIManager(); 39 | manager.RemoveUrlAcl(_Url); 40 | } 41 | 42 | #endregion 43 | } 44 | 45 | public class TestClass 46 | { 47 | [Fact] 48 | public void CanQueryAcls() 49 | { 50 | HttpAPIManager manager = new HttpAPIManager(); 51 | var testUrl = "http://+:9399/CanQueryAclsTest"; 52 | manager.SetUrlAcl(testUrl, SecurityDescriptor.FromSDDL("D:(A;;;;;WD)")); 53 | try 54 | { 55 | var containsTemporaryUrl = manager.GetAclInfo().Any(url => url.Prefix.Contains("CanQueryAclsTest")); 56 | Assert.True(containsTemporaryUrl, "You should be able to retrieve Acls"); 57 | } 58 | finally 59 | { 60 | manager.RemoveUrlAcl(testUrl); 61 | } 62 | } 63 | [Fact] 64 | public void CanAddAndRemoveAcl() 65 | { 66 | var testUrl = "http://+:9393/"; 67 | HttpAPIManager manager = new HttpAPIManager(); 68 | manager.SetUrlAcl(testUrl, SecurityDescriptor.FromSDDL("D:(A;;GX;;;WD)")); 69 | try 70 | { 71 | var acl = manager.GetAclInfo(testUrl); 72 | Assert.NotNull(acl); 73 | var fakeAcl = manager.GetAclInfo("unknown"); 74 | Assert.Null(fakeAcl); 75 | } 76 | finally 77 | { 78 | manager.RemoveUrlAcl(testUrl); 79 | } 80 | var oldAcl = manager.GetAclInfo(testUrl); 81 | Assert.Null(oldAcl); 82 | } 83 | 84 | [Fact] 85 | public void HasMeaningfulErrorMessageIfHttpApiNotInitialized() 86 | { 87 | try 88 | { 89 | SSLInfo.Get(0); 90 | } 91 | catch(InvalidOperationException ex) 92 | { 93 | Assert.Equal("You should first initialize HTTP Server API with HttpInitializeScope", ex.Message); 94 | } 95 | } 96 | [Fact] 97 | public void CanSetUrlTwiceAndSetToNullToRemove() 98 | { 99 | var testUrl = "http://+:9394/"; 100 | HttpAPIManager manager = new HttpAPIManager(); 101 | manager.SetUrlAcl(testUrl, SecurityDescriptor.FromSDDL("D:(A;;GX;;;WD)")); 102 | manager.SetUrlAcl(testUrl, SecurityDescriptor.FromSDDL("D:(A;;;;;WD)")); 103 | Assert.Equal("D:(A;;;;;WD)", manager.GetAclInfo(testUrl).SecurityDescriptor.ToString()); 104 | manager.SetUrlAcl(testUrl, null); 105 | Assert.Null(manager.GetAclInfo(testUrl)); 106 | } 107 | 108 | [Fact] 109 | public void CanSetCertificates() 110 | { 111 | var testEndpoint = new IPEndPoint(IPAddress.Parse("127.0.0.1"), 462); 112 | HttpAPIManager manager = new HttpAPIManager(); 113 | manager.SetSSLInfo(testEndpoint, new SSLInfo(TestCertificate.Thumbprint)); 114 | try 115 | { 116 | var sslInfo = manager.GetSSLInfo(testEndpoint); 117 | Assert.NotNull(sslInfo); 118 | Assert.Equal(TestCertificate.Thumbprint, sslInfo.Certificate.Thumbprint); 119 | } 120 | finally 121 | { 122 | manager.RemoveSSLInfo(testEndpoint); 123 | var sslInfo = manager.GetSSLInfo(testEndpoint); 124 | Assert.Null(sslInfo); 125 | } 126 | } 127 | [Fact] 128 | public void CanListCertificates() 129 | { 130 | var testEndpoints = new[] 131 | { 132 | new IPEndPoint(IPAddress.Parse("127.0.0.1"), 462), 133 | new IPEndPoint(IPAddress.Parse("127.0.0.2"), 462) 134 | }; 135 | HttpAPIManager manager = new HttpAPIManager(); 136 | var oldSslCount = manager.GetSSLInfos().Count(); 137 | try 138 | { 139 | foreach(var endpoint in testEndpoints) 140 | manager.SetSSLInfo(endpoint, new SSLInfo(TestCertificate.Thumbprint)); 141 | var newSslCount = manager.GetSSLInfos().Count(); 142 | Assert.Equal(oldSslCount + testEndpoints.Length, newSslCount); 143 | } 144 | finally 145 | { 146 | foreach(var endpoint in testEndpoints) 147 | manager.RemoveSSLInfo(endpoint); 148 | } 149 | } 150 | 151 | [Fact] 152 | public void CanSetSSLInfoTwiceAndSetToNullToRemove() 153 | { 154 | var testEndpoint = new IPEndPoint(IPAddress.Parse("127.0.0.1"), 464); 155 | var info = new SSLInfo(TestCertificate.Thumbprint); 156 | 157 | HttpAPIManager manager = new HttpAPIManager(); 158 | 159 | manager.SetSSLInfo(testEndpoint, info); 160 | try 161 | { 162 | Assert.NotNull(manager.GetSSLInfo(testEndpoint)); 163 | Assert.Equal(false, manager.GetSSLInfo(testEndpoint).NegotiateClientCert); 164 | info.NegotiateClientCert = true; 165 | manager.SetSSLInfo(testEndpoint, info); 166 | Assert.NotNull(manager.GetSSLInfo(testEndpoint)); 167 | Assert.Equal(true, manager.GetSSLInfo(testEndpoint).NegotiateClientCert); 168 | } 169 | finally 170 | { 171 | manager.SetSSLInfo(testEndpoint, null); 172 | Assert.Null(manager.GetSSLInfo(testEndpoint)); 173 | } 174 | } 175 | public static X509Certificate2 TestCertificate 176 | { 177 | get 178 | { 179 | return new X509Certificate2("../../Certificates/HttpSysManager.pfx", "", X509KeyStorageFlags.PersistKeySet | X509KeyStorageFlags.MachineKeySet); 180 | } 181 | } 182 | public static X509Certificate2 Verisign 183 | { 184 | get 185 | { 186 | return CertificateHelper.GetCertificate(StoreLocation.LocalMachine, StoreName.Root, X509FindType.FindByThumbprint, "13 2d 0d 45 53 4b 69 97 cd b2 d5 c3 39 e2 55 76 60 9b 5c c6"); 187 | } 188 | } 189 | 190 | public static X509Certificate2 KisaRoot1 191 | { 192 | get 193 | { 194 | return CertificateHelper.GetCertificate(StoreLocation.LocalMachine, StoreName.Root, X509FindType.FindByThumbprint, "02 72 68 29 3e 5f 5d 17 aa a4 b3 c3 e6 36 1e 1f 92 57 5e aa"); 195 | } 196 | } 197 | 198 | 199 | [Fact] 200 | public void CanAttachCTLToSSLInfo() 201 | { 202 | var testEndpoint = new IPEndPoint(IPAddress.Parse("127.0.0.1"), 2924); 203 | CTLContextBuilder builder = new CTLContextBuilder(); 204 | builder.CTLInfo.ListIdentifier = "my test list binding"; 205 | builder.CTLInfo.Certificates.Add(Verisign); 206 | builder.CTLInfo.Certificates.Add(KisaRoot1); 207 | builder.Signers.Add(TestCertificate); 208 | HttpAPIManager manager = new HttpAPIManager(); 209 | var context = builder.ToCTLContext(); 210 | 211 | try 212 | { 213 | context.ImportInStore(StoreLocation.LocalMachine, StoreName.Root); 214 | SSLInfo info = new SSLInfo(); 215 | info.CheckClientCertificate = false; 216 | info.NegotiateClientCert = true; 217 | info.CTLIdentifier = context.CTLInfo.ListIdentifier; 218 | info.CTLStoreName = StoreName.Root; 219 | info.Certificate = TestCertificate; 220 | manager.SetSSLInfo(testEndpoint, info); 221 | } 222 | finally 223 | { 224 | context.RemoveFromStore(StoreLocation.LocalMachine, StoreName.Root); 225 | manager.RemoveSSLInfo(testEndpoint); 226 | } 227 | } 228 | 229 | public byte[] AuthRootCTL 230 | { 231 | get 232 | { 233 | return File.ReadAllBytes("../../authroot.stl"); 234 | } 235 | } 236 | 237 | 238 | [Fact] 239 | public void CanReadExistingCTL() 240 | { 241 | var ctl = CTLContext.Load(AuthRootCTL); 242 | Assert.NotNull(ctl); 243 | } 244 | [Fact] 245 | public void CanCreateCTL() 246 | { 247 | var ctlBuilder = new CTLInfoBuilder(); 248 | ctlBuilder.ListIdentifier = "Test list"; 249 | ctlBuilder.Certificates.Add(TestCertificate); 250 | var ctlInfo = ctlBuilder.ToCTLInfo(); 251 | var bytes = ctlInfo.ToBytes(); 252 | var loadedCtlInfo = CTLInfo.Load(bytes); 253 | AssertCollectionEquals(TestCertificate.GetCertHash(), loadedCtlInfo.Entries[0].SubjectIdentifier); 254 | Assert.Equal("Test list", ctlInfo.ListIdentifier); 255 | } 256 | [Fact] 257 | public void CanCreateSerializeAndReloadCTLContext() 258 | { 259 | var ctlBuilder = new CTLContextBuilder(); 260 | ctlBuilder.CTLInfo.Certificates.Add(TestCertificate); 261 | ctlBuilder.CTLInfo.ListIdentifier = "test list"; 262 | var ctlContext = ctlBuilder.ToCTLContext(); 263 | Assert.Equal("test list", ctlContext.FriendlyName); 264 | var bytes = ctlContext.ToBytes(); 265 | var loadedCtlContext = CTLContext.Load(bytes); 266 | Assert.Equal("test list", loadedCtlContext.FriendlyName); 267 | AssertCollectionEquals(TestCertificate.GetCertHash(), loadedCtlContext.CTLInfo.Entries[0].SubjectIdentifier); 268 | } 269 | 270 | [Fact] 271 | public void CanImportLoadThenDeleteCTLInStore() 272 | { 273 | var ctlBuilder = new CTLContextBuilder(); 274 | ctlBuilder.CTLInfo.Certificates.Add(TestCertificate); 275 | ctlBuilder.CTLInfo.ListIdentifier = "test list import"; 276 | var ctlContext = ctlBuilder.ToCTLContext(); 277 | ctlContext.ImportInStore(StoreLocation.CurrentUser, StoreName.My); 278 | try 279 | { 280 | Assert.NotNull(CTLContext.Get(StoreLocation.CurrentUser, StoreName.My, "test list import")); 281 | ctlContext.RemoveFromStore(StoreLocation.CurrentUser, StoreName.My); 282 | Assert.Null(CTLContext.Get(StoreLocation.CurrentUser, StoreName.My, "test list import")); 283 | ctlContext.RemoveFromStore(StoreLocation.CurrentUser, StoreName.My); //Does not throw if does not exist 284 | } 285 | finally 286 | { 287 | ctlContext.RemoveFromStore(StoreLocation.CurrentUser, StoreName.My); 288 | } 289 | } 290 | 291 | 292 | void AssertCollectionEquals(byte[] expected, byte[] actual) 293 | { 294 | Assert.True(expected.Length == actual.Length, "both array should be same size"); 295 | for(int i = 0 ; i < expected.Length ; i++) 296 | Assert.True(expected[i] == actual[i], "Difference spotted at index " + i.ToString()); 297 | } 298 | //[Fact] 299 | //public void CanAddEmptyAcl() 300 | //{ 301 | // var testUrl = "http://test2:3827/"; 302 | // HttpAPIManager manager = new HttpAPIManager(); 303 | // try 304 | // { 305 | // manager.SetUrlAcl(testUrl, SecurityDescriptor.Empty); 306 | // var acl = manager.GetAclInfo(testUrl); 307 | // Assert.Equal(SecurityDescriptor.Empty.ToString(), acl.SecurityDescriptor.ToString()); 308 | // } 309 | // finally 310 | // { 311 | // manager.RemoveUrlAcl(testUrl); 312 | // } 313 | //} 314 | 315 | //[Fact] 316 | //public void CanBrowseCertificates() 317 | //{ 318 | // HttpAPIManager manager = new HttpAPIManager(); 319 | // Assert.True(1 <= manager.GetSSLInfos().Count()); 320 | //} 321 | } 322 | } 323 | -------------------------------------------------------------------------------- /HttpSysManager/HttpSysManager.Tests/app.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /HttpSysManager/HttpSysManager.Tests/authroot.stl: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kstrauss/HttpSysManager/f5276b8aa8180d071a08b8e708739171ce2248ba/HttpSysManager/HttpSysManager.Tests/authroot.stl -------------------------------------------------------------------------------- /HttpSysManager/HttpSysManager.Tests/xunit/xunit.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kstrauss/HttpSysManager/f5276b8aa8180d071a08b8e708739171ce2248ba/HttpSysManager/HttpSysManager.Tests/xunit/xunit.dll -------------------------------------------------------------------------------- /HttpSysManager/HttpSysManager.Tests/xunit/xunit.extensions.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kstrauss/HttpSysManager/f5276b8aa8180d071a08b8e708739171ce2248ba/HttpSysManager/HttpSysManager.Tests/xunit/xunit.extensions.dll -------------------------------------------------------------------------------- /HttpSysManager/HttpSysManager.Tests/xunit/xunit.runner.utility.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kstrauss/HttpSysManager/f5276b8aa8180d071a08b8e708739171ce2248ba/HttpSysManager/HttpSysManager.Tests/xunit/xunit.runner.utility.dll -------------------------------------------------------------------------------- /HttpSysManager/HttpSysManager.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 2012 4 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "HttpSysManager", "HttpSysManager\HttpSysManager.csproj", "{910CE5E7-9DD1-46E9-90C4-AB89B086D45F}" 5 | EndProject 6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "HttpSysManager.Tests", "HttpSysManager.Tests\HttpSysManager.Tests.csproj", "{8C28AF8E-9597-4A2A-A874-31998DEBFFC0}" 7 | EndProject 8 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "HttpSysManager.Native", "HttpSysManager.Native\HttpSysManager.Native.vcxproj", "{BCEB0E3D-DAE6-4110-8C1E-1BC6202C31F4}" 9 | EndProject 10 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "HttpSysManager.Core", "HttpSysManager.Core\HttpSysManager.Core.csproj", "{CB03213B-4CBB-4E09-8739-59D9FCFB71BF}" 11 | EndProject 12 | Global 13 | GlobalSection(SubversionScc) = preSolution 14 | Manager = AnkhSVN - Subversion Support for Visual Studio 15 | Svn-Managed = True 16 | EndGlobalSection 17 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 18 | Debug|Any CPU = Debug|Any CPU 19 | Debug|Mixed Platforms = Debug|Mixed Platforms 20 | Debug|Win32 = Debug|Win32 21 | Debug|x86 = Debug|x86 22 | Release|Any CPU = Release|Any CPU 23 | Release|Mixed Platforms = Release|Mixed Platforms 24 | Release|Win32 = Release|Win32 25 | Release|x86 = Release|x86 26 | EndGlobalSection 27 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 28 | {8C28AF8E-9597-4A2A-A874-31998DEBFFC0}.Debug|Any CPU.ActiveCfg = Debug|x86 29 | {8C28AF8E-9597-4A2A-A874-31998DEBFFC0}.Debug|Mixed Platforms.ActiveCfg = Debug|x86 30 | {8C28AF8E-9597-4A2A-A874-31998DEBFFC0}.Debug|Mixed Platforms.Build.0 = Debug|x86 31 | {8C28AF8E-9597-4A2A-A874-31998DEBFFC0}.Debug|Win32.ActiveCfg = Debug|x86 32 | {8C28AF8E-9597-4A2A-A874-31998DEBFFC0}.Debug|Win32.Build.0 = Debug|x86 33 | {8C28AF8E-9597-4A2A-A874-31998DEBFFC0}.Debug|x86.ActiveCfg = Debug|x86 34 | {8C28AF8E-9597-4A2A-A874-31998DEBFFC0}.Debug|x86.Build.0 = Debug|x86 35 | {8C28AF8E-9597-4A2A-A874-31998DEBFFC0}.Release|Any CPU.ActiveCfg = Release|x86 36 | {8C28AF8E-9597-4A2A-A874-31998DEBFFC0}.Release|Mixed Platforms.ActiveCfg = Release|x86 37 | {8C28AF8E-9597-4A2A-A874-31998DEBFFC0}.Release|Mixed Platforms.Build.0 = Release|x86 38 | {8C28AF8E-9597-4A2A-A874-31998DEBFFC0}.Release|Win32.ActiveCfg = Release|x86 39 | {8C28AF8E-9597-4A2A-A874-31998DEBFFC0}.Release|Win32.Build.0 = Release|x86 40 | {8C28AF8E-9597-4A2A-A874-31998DEBFFC0}.Release|x86.ActiveCfg = Release|x86 41 | {8C28AF8E-9597-4A2A-A874-31998DEBFFC0}.Release|x86.Build.0 = Release|x86 42 | {910CE5E7-9DD1-46E9-90C4-AB89B086D45F}.Debug|Any CPU.ActiveCfg = Debug|x86 43 | {910CE5E7-9DD1-46E9-90C4-AB89B086D45F}.Debug|Mixed Platforms.ActiveCfg = Debug|x86 44 | {910CE5E7-9DD1-46E9-90C4-AB89B086D45F}.Debug|Mixed Platforms.Build.0 = Debug|x86 45 | {910CE5E7-9DD1-46E9-90C4-AB89B086D45F}.Debug|Win32.ActiveCfg = Debug|x86 46 | {910CE5E7-9DD1-46E9-90C4-AB89B086D45F}.Debug|Win32.Build.0 = Debug|x86 47 | {910CE5E7-9DD1-46E9-90C4-AB89B086D45F}.Debug|x86.ActiveCfg = Debug|x86 48 | {910CE5E7-9DD1-46E9-90C4-AB89B086D45F}.Debug|x86.Build.0 = Debug|x86 49 | {910CE5E7-9DD1-46E9-90C4-AB89B086D45F}.Release|Any CPU.ActiveCfg = Release|x86 50 | {910CE5E7-9DD1-46E9-90C4-AB89B086D45F}.Release|Mixed Platforms.ActiveCfg = Release|x86 51 | {910CE5E7-9DD1-46E9-90C4-AB89B086D45F}.Release|Mixed Platforms.Build.0 = Release|x86 52 | {910CE5E7-9DD1-46E9-90C4-AB89B086D45F}.Release|Win32.ActiveCfg = Release|x86 53 | {910CE5E7-9DD1-46E9-90C4-AB89B086D45F}.Release|Win32.Build.0 = Release|x86 54 | {910CE5E7-9DD1-46E9-90C4-AB89B086D45F}.Release|x86.ActiveCfg = Release|x86 55 | {910CE5E7-9DD1-46E9-90C4-AB89B086D45F}.Release|x86.Build.0 = Release|x86 56 | {BCEB0E3D-DAE6-4110-8C1E-1BC6202C31F4}.Debug|Any CPU.ActiveCfg = Debug|Win32 57 | {BCEB0E3D-DAE6-4110-8C1E-1BC6202C31F4}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32 58 | {BCEB0E3D-DAE6-4110-8C1E-1BC6202C31F4}.Debug|Mixed Platforms.Build.0 = Debug|Win32 59 | {BCEB0E3D-DAE6-4110-8C1E-1BC6202C31F4}.Debug|Win32.ActiveCfg = Debug|Win32 60 | {BCEB0E3D-DAE6-4110-8C1E-1BC6202C31F4}.Debug|Win32.Build.0 = Debug|Win32 61 | {BCEB0E3D-DAE6-4110-8C1E-1BC6202C31F4}.Debug|x86.ActiveCfg = Debug|Win32 62 | {BCEB0E3D-DAE6-4110-8C1E-1BC6202C31F4}.Debug|x86.Build.0 = Debug|Win32 63 | {BCEB0E3D-DAE6-4110-8C1E-1BC6202C31F4}.Release|Any CPU.ActiveCfg = Release|Win32 64 | {BCEB0E3D-DAE6-4110-8C1E-1BC6202C31F4}.Release|Mixed Platforms.ActiveCfg = Release|Win32 65 | {BCEB0E3D-DAE6-4110-8C1E-1BC6202C31F4}.Release|Mixed Platforms.Build.0 = Release|Win32 66 | {BCEB0E3D-DAE6-4110-8C1E-1BC6202C31F4}.Release|Win32.ActiveCfg = Release|Win32 67 | {BCEB0E3D-DAE6-4110-8C1E-1BC6202C31F4}.Release|Win32.Build.0 = Release|Win32 68 | {BCEB0E3D-DAE6-4110-8C1E-1BC6202C31F4}.Release|x86.ActiveCfg = Release|Win32 69 | {BCEB0E3D-DAE6-4110-8C1E-1BC6202C31F4}.Release|x86.Build.0 = Release|Win32 70 | {CB03213B-4CBB-4E09-8739-59D9FCFB71BF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 71 | {CB03213B-4CBB-4E09-8739-59D9FCFB71BF}.Debug|Any CPU.Build.0 = Debug|Any CPU 72 | {CB03213B-4CBB-4E09-8739-59D9FCFB71BF}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU 73 | {CB03213B-4CBB-4E09-8739-59D9FCFB71BF}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU 74 | {CB03213B-4CBB-4E09-8739-59D9FCFB71BF}.Debug|Win32.ActiveCfg = Debug|Any CPU 75 | {CB03213B-4CBB-4E09-8739-59D9FCFB71BF}.Debug|x86.ActiveCfg = Debug|Any CPU 76 | {CB03213B-4CBB-4E09-8739-59D9FCFB71BF}.Release|Any CPU.ActiveCfg = Release|Any CPU 77 | {CB03213B-4CBB-4E09-8739-59D9FCFB71BF}.Release|Any CPU.Build.0 = Release|Any CPU 78 | {CB03213B-4CBB-4E09-8739-59D9FCFB71BF}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU 79 | {CB03213B-4CBB-4E09-8739-59D9FCFB71BF}.Release|Mixed Platforms.Build.0 = Release|Any CPU 80 | {CB03213B-4CBB-4E09-8739-59D9FCFB71BF}.Release|Win32.ActiveCfg = Release|Any CPU 81 | {CB03213B-4CBB-4E09-8739-59D9FCFB71BF}.Release|x86.ActiveCfg = Release|Any CPU 82 | EndGlobalSection 83 | GlobalSection(SolutionProperties) = preSolution 84 | HideSolutionNode = FALSE 85 | EndGlobalSection 86 | EndGlobal 87 | -------------------------------------------------------------------------------- /HttpSysManager/HttpSysManager/App.xaml: -------------------------------------------------------------------------------- 1 |  7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /HttpSysManager/HttpSysManager/App.xaml.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Configuration; 4 | using System.Data; 5 | using System.Linq; 6 | using System.Windows; 7 | 8 | namespace HttpSysManager 9 | { 10 | /// 11 | /// Interaction logic for App.xaml 12 | /// 13 | public partial class App : Application 14 | { 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /HttpSysManager/HttpSysManager/CertificateHelper.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Security.Cryptography.X509Certificates; 6 | 7 | namespace HttpSysManager 8 | { 9 | public class CertificateHelper 10 | { 11 | public static X509Certificate2 GetCertificate(StoreLocation storeLocation, System.Security.Cryptography.X509Certificates.StoreName storeName, X509FindType x509FindType, object value) 12 | { 13 | X509Store store = new X509Store(storeLocation); 14 | store.Open(OpenFlags.ReadOnly); 15 | try 16 | { 17 | var certs = store.Certificates.Find(x509FindType, value, false); 18 | if(certs.Count == 0) 19 | return null; 20 | return certs[0]; 21 | } 22 | finally 23 | { 24 | store.Close(); 25 | } 26 | } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /HttpSysManager/HttpSysManager/CertificateListView.xaml: -------------------------------------------------------------------------------- 1 |  9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /HttpSysManager/HttpSysManager/CertificateListView.xaml.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections; 3 | using System.Collections.Generic; 4 | using System.Linq; 5 | using System.Text; 6 | using System.Windows; 7 | using System.Windows.Controls; 8 | using System.Windows.Data; 9 | using System.Windows.Documents; 10 | using System.Windows.Input; 11 | using System.Windows.Media; 12 | using System.Windows.Media.Imaging; 13 | using System.Windows.Navigation; 14 | using System.Windows.Shapes; 15 | 16 | namespace HttpSysManager 17 | { 18 | /// 19 | /// Interaction logic for CertificateListView.xaml 20 | /// 21 | public partial class CertificateListView : UserControl 22 | { 23 | public CertificateListView() 24 | { 25 | InitializeComponent(); 26 | root.SetBinding(DataContextProperty, new Binding() 27 | { 28 | Source = this 29 | }); 30 | } 31 | 32 | 33 | 34 | 35 | public string Label 36 | { 37 | get 38 | { 39 | return (string)GetValue(LabelProperty); 40 | } 41 | set 42 | { 43 | SetValue(LabelProperty, value); 44 | } 45 | } 46 | 47 | // Using a DependencyProperty as the backing store for Label. This enables animation, styling, binding, etc... 48 | public static readonly DependencyProperty LabelProperty = 49 | DependencyProperty.Register("Label", typeof(string), typeof(CertificateListView), new PropertyMetadata(null)); 50 | 51 | 52 | 53 | 54 | public IEnumerable ItemsSource 55 | { 56 | get 57 | { 58 | return (IEnumerable)GetValue(ItemsSourceProperty); 59 | } 60 | set 61 | { 62 | SetValue(ItemsSourceProperty, value); 63 | } 64 | } 65 | 66 | // Using a DependencyProperty as the backing store for ItemsSource. This enables animation, styling, binding, etc... 67 | public static readonly DependencyProperty ItemsSourceProperty = 68 | DependencyProperty.Register("ItemsSource", typeof(IEnumerable), typeof(CertificateListView), new PropertyMetadata(null)); 69 | 70 | 71 | 72 | 73 | public bool ShouldHavePrivateKey 74 | { 75 | get 76 | { 77 | return (bool)GetValue(ShouldHavePrivateKeyProperty); 78 | } 79 | set 80 | { 81 | SetValue(ShouldHavePrivateKeyProperty, value); 82 | } 83 | } 84 | 85 | // Using a DependencyProperty as the backing store for ShouldHavePrivateKey. This enables animation, styling, binding, etc... 86 | public static readonly DependencyProperty ShouldHavePrivateKeyProperty = 87 | DependencyProperty.Register("ShouldHavePrivateKey", typeof(bool), typeof(CertificateListView), new PropertyMetadata(true)); 88 | 89 | private void AddClick(object sender, RoutedEventArgs e) 90 | { 91 | CertificateSelectorWindow selector = new CertificateSelectorWindow(); 92 | selector.ShouldImportCertificate = false; 93 | selector.ShouldHavePrivateKey = ShouldHavePrivateKey; 94 | var result = selector.ShowDialog(); 95 | if(result.HasValue && result.Value) 96 | { 97 | var certificate = selector.SelectedCertificate; 98 | if(certificate != null) 99 | { 100 | var source = ItemsSource as IList; 101 | if(source != null) 102 | { 103 | source.Add(certificate); 104 | list.ItemsSource = null; 105 | list.ItemsSource = ItemsSource; 106 | } 107 | } 108 | } 109 | } 110 | 111 | 112 | 113 | } 114 | } 115 | -------------------------------------------------------------------------------- /HttpSysManager/HttpSysManager/CertificateSelector.xaml: -------------------------------------------------------------------------------- 1 |  9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /HttpSysManager/HttpSysManager/CertificateSelector.xaml.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Windows; 6 | using System.Windows.Controls; 7 | using System.Windows.Data; 8 | using System.Windows.Documents; 9 | using System.Windows.Input; 10 | using System.Windows.Media; 11 | using System.Windows.Media.Imaging; 12 | using System.Windows.Navigation; 13 | using System.Windows.Shapes; 14 | using System.Security.Cryptography.X509Certificates; 15 | using HttpSysManager.HttpAPI; 16 | using System.Text.RegularExpressions; 17 | using HttpSysManager.Core; 18 | 19 | namespace HttpSysManager 20 | { 21 | /// 22 | /// Interaction logic for CertificateSelector.xaml 23 | /// 24 | public partial class CertificateSelector : UserControl 25 | { 26 | public CertificateSelector() 27 | { 28 | InitializeComponent(); 29 | UpdateButton(); 30 | } 31 | 32 | 33 | 34 | public X509Certificate2 SelectedCertificate 35 | { 36 | get 37 | { 38 | return (X509Certificate2)GetValue(SelectedCertificateProperty); 39 | } 40 | set 41 | { 42 | SetValue(SelectedCertificateProperty, value); 43 | } 44 | } 45 | 46 | public static readonly DependencyProperty SelectedCertificateProperty = 47 | DependencyProperty.Register("SelectedCertificate", typeof(X509Certificate2), typeof(CertificateSelector), new UIPropertyMetadata(OnSelectedCertificateChanged)); 48 | 49 | static void OnSelectedCertificateChanged(DependencyObject source, DependencyPropertyChangedEventArgs args) 50 | { 51 | CertificateSelector sender = (CertificateSelector)source; 52 | sender.UpdateButton(); 53 | } 54 | 55 | private void UpdateButton() 56 | { 57 | if(SelectedCertificate == null) 58 | button.Text = "Select a certificate"; 59 | else 60 | { 61 | button.Text = CertificateHelper.GetFriendlyNameOrName(SelectedCertificate); 62 | } 63 | } 64 | private void ModifyCertificate_Click(object sender, RoutedEventArgs e) 65 | { 66 | var dialog = new CertificateSelectorWindow(); 67 | var result = dialog.ShowDialog(); 68 | if(result != null && result.Value) 69 | { 70 | SelectedCertificate = dialog.SelectedCertificate; 71 | } 72 | } 73 | 74 | 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /HttpSysManager/HttpSysManager/CertificateSelectorWindow.xaml: -------------------------------------------------------------------------------- 1 |  8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | This certificate will be installed in LocalMachine/My 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /HttpSysManager/HttpSysManager/CertificateSelectorWindow.xaml.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Windows; 6 | using System.Windows.Controls; 7 | using System.Windows.Data; 8 | using System.Windows.Documents; 9 | using System.Windows.Input; 10 | using System.Windows.Media; 11 | using System.Windows.Media.Imaging; 12 | using System.Windows.Shapes; 13 | using System.Security.Cryptography.X509Certificates; 14 | using HttpSysManager.HttpAPI; 15 | using SlasheneFramework; 16 | using SlasheneFramework.UI; 17 | using System.IO; 18 | using HttpSysManager.Native; 19 | 20 | namespace HttpSysManager 21 | { 22 | /// 23 | /// Interaction logic for CertificateSelectorWindow.xaml 24 | /// 25 | public partial class CertificateSelectorWindow : Window 26 | { 27 | const string NoPrivateKeyAttached = "The selected certificate does not have any private key attached"; 28 | class CertificateSelectorWindowVm : NotifyPropertyChangedBase 29 | { 30 | 31 | public CertificateSelectorWindow Window 32 | { 33 | get; 34 | private set; 35 | } 36 | 37 | public CertificateSelectorWindowVm(CertificateSelectorWindow parent) 38 | { 39 | CertificatePath = ""; 40 | Password = ""; 41 | Window = parent; 42 | } 43 | class SubmitCommand : ViewModelCommand 44 | { 45 | public SubmitCommand(CertificateSelectorWindowVm vm) 46 | : base(vm) 47 | { 48 | } 49 | public override bool CanExecute(object parameter) 50 | { 51 | return File.Exists(ViewModel.CertificatePath); 52 | } 53 | 54 | public override void Execute(object parameter) 55 | { 56 | try 57 | { 58 | X509Certificate2 certificate = new X509Certificate2(ViewModel.CertificatePath, ViewModel.Password, X509KeyStorageFlags.MachineKeySet | X509KeyStorageFlags.PersistKeySet); 59 | 60 | if(ViewModel.Window.ShouldHavePrivateKey && !certificate.HasPrivateKey) 61 | { 62 | ViewModel.ErrorMessage = CertificateSelectorWindow.NoPrivateKeyAttached; 63 | return; 64 | } 65 | 66 | if(ViewModel.Window.ShouldImportCertificate) 67 | { 68 | X509Store store = new X509Store(StoreName.My, StoreLocation.LocalMachine); 69 | store.Open(OpenFlags.ReadWrite); 70 | try 71 | { 72 | store.Add(certificate); 73 | } 74 | finally 75 | { 76 | store.Close(); 77 | } 78 | } 79 | ViewModel.SelectedCertificate = certificate; 80 | } 81 | catch(Exception ex) 82 | { 83 | ViewModel.ErrorMessage = ex.Message; 84 | } 85 | } 86 | } 87 | private ICommand _Submit; 88 | public ICommand Submit 89 | { 90 | get 91 | { 92 | if(_Submit == null) 93 | _Submit = new SubmitCommand(this); 94 | return _Submit; 95 | } 96 | } 97 | private String _CertificatePath; 98 | public String CertificatePath 99 | { 100 | get 101 | { 102 | return _CertificatePath; 103 | } 104 | set 105 | { 106 | if(value != _CertificatePath) 107 | { 108 | _CertificatePath = value; 109 | OnPropertyChanged(() => this.CertificatePath); 110 | } 111 | } 112 | } 113 | private string _Password; 114 | public string Password 115 | { 116 | get 117 | { 118 | return _Password; 119 | } 120 | set 121 | { 122 | if(value != _Password) 123 | { 124 | _Password = value; 125 | OnPropertyChanged(() => this.Password); 126 | } 127 | } 128 | } 129 | 130 | private string _ErrorMessage; 131 | public string ErrorMessage 132 | { 133 | get 134 | { 135 | return _ErrorMessage; 136 | } 137 | set 138 | { 139 | if(value != _ErrorMessage) 140 | { 141 | _ErrorMessage = value; 142 | OnPropertyChanged(() => this.ErrorMessage); 143 | } 144 | } 145 | } 146 | 147 | private X509Certificate2 _SelectedCertificate; 148 | public X509Certificate2 SelectedCertificate 149 | { 150 | get 151 | { 152 | return _SelectedCertificate; 153 | } 154 | set 155 | { 156 | if(value != _SelectedCertificate) 157 | { 158 | _SelectedCertificate = value; 159 | OnPropertyChanged(() => this.SelectedCertificate); 160 | } 161 | } 162 | } 163 | } 164 | public CertificateSelectorWindow() 165 | { 166 | InitializeComponent(); 167 | ViewModel = new CertificateSelectorWindowVm(this); 168 | } 169 | 170 | 171 | 172 | 173 | 174 | 175 | public bool ShouldHavePrivateKey 176 | { 177 | get 178 | { 179 | return (bool)GetValue(ShouldHavePrivateKeyProperty); 180 | } 181 | set 182 | { 183 | SetValue(ShouldHavePrivateKeyProperty, value); 184 | } 185 | } 186 | 187 | // Using a DependencyProperty as the backing store for ShouldHavePrivateKey. This enables animation, styling, binding, etc... 188 | public static readonly DependencyProperty ShouldHavePrivateKeyProperty = 189 | DependencyProperty.Register("ShouldHavePrivateKey", typeof(bool), typeof(CertificateSelectorWindow), new PropertyMetadata(true)); 190 | 191 | 192 | 193 | 194 | public bool ShouldImportCertificate 195 | { 196 | get 197 | { 198 | return (bool)GetValue(ShouldImportCertificateProperty); 199 | } 200 | set 201 | { 202 | SetValue(ShouldImportCertificateProperty, value); 203 | } 204 | } 205 | 206 | // Using a DependencyProperty as the backing store for ShouldImportCertificate. This enables animation, styling, binding, etc... 207 | public static readonly DependencyProperty ShouldImportCertificateProperty = 208 | DependencyProperty.Register("ShouldImportCertificate", typeof(bool), typeof(CertificateSelectorWindow), new PropertyMetadata(true)); 209 | 210 | 211 | 212 | CertificateSelectorWindowVm ViewModel 213 | { 214 | get 215 | { 216 | return (CertificateSelectorWindowVm)DataContext; 217 | } 218 | set 219 | { 220 | value.PropertyChanged += new System.ComponentModel.PropertyChangedEventHandler(value_PropertyChanged); 221 | DataContext = value; 222 | } 223 | } 224 | 225 | void value_PropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e) 226 | { 227 | if(e.PropertyName == "SelectedCertificate") 228 | { 229 | SelectedCertificate = ViewModel.SelectedCertificate; 230 | DialogResult = true; 231 | } 232 | } 233 | public X509Certificate2 SelectedCertificate 234 | { 235 | get 236 | { 237 | return (X509Certificate2)GetValue(SelectedCertificateProperty); 238 | } 239 | set 240 | { 241 | SetValue(SelectedCertificateProperty, value); 242 | } 243 | } 244 | public static readonly DependencyProperty SelectedCertificateProperty = 245 | DependencyProperty.Register("SelectedCertificate", typeof(X509Certificate2), typeof(CertificateSelectorWindow), new UIPropertyMetadata(null)); 246 | 247 | private void SelectCertificate_Click(object sender, RoutedEventArgs e) 248 | { 249 | SelectedCertificate = Security.SelectCertificate(); 250 | if(SelectedCertificate != null) 251 | { 252 | if(ShouldHavePrivateKey && !SelectedCertificate.HasPrivateKey) 253 | { 254 | storeErrorMessage.Text = NoPrivateKeyAttached; 255 | return; 256 | } 257 | DialogResult = true; 258 | } 259 | } 260 | 261 | 262 | } 263 | } 264 | -------------------------------------------------------------------------------- /HttpSysManager/HttpSysManager/CreateCTLWizard.xaml: -------------------------------------------------------------------------------- 1 |  7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 19 | 24 | 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /HttpSysManager/HttpSysManager/CreateCTLWizard.xaml.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.IO; 4 | using System.Linq; 5 | using System.Text; 6 | using System.Windows; 7 | using System.Windows.Controls; 8 | using System.Windows.Data; 9 | using System.Windows.Documents; 10 | using System.Windows.Input; 11 | using System.Windows.Media; 12 | using System.Windows.Media.Imaging; 13 | using System.Windows.Shapes; 14 | using HttpSysManager.Native; 15 | using Microsoft.Win32; 16 | 17 | namespace HttpSysManager 18 | { 19 | /// 20 | /// Interaction logic for CreateCTLWizard.xaml 21 | /// 22 | public partial class CreateCTLWizard : Window 23 | { 24 | public CreateCTLWizard() 25 | { 26 | InitializeComponent(); 27 | } 28 | 29 | 30 | private void Save_Click(object sender, RoutedEventArgs e) 31 | { 32 | DialogResult = true; 33 | } 34 | 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /HttpSysManager/HttpSysManager/Extensions.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Windows.Data; 6 | using System.Windows; 7 | using System.ComponentModel; 8 | 9 | namespace HttpSysManager 10 | { 11 | public class Extensions 12 | { 13 | public static string GetSortBy(DependencyObject obj) 14 | { 15 | return (string)obj.GetValue(SortByProperty); 16 | } 17 | 18 | public static void SetSortBy(DependencyObject obj, string value) 19 | { 20 | obj.SetValue(SortByProperty, value); 21 | } 22 | 23 | public static readonly DependencyProperty SortByProperty = 24 | DependencyProperty.RegisterAttached("SortBy", typeof(string), typeof(Extensions), new PropertyMetadata(OnSortByChanged)); 25 | 26 | static void OnSortByChanged(DependencyObject source, DependencyPropertyChangedEventArgs args) 27 | { 28 | CollectionViewSource sender = (CollectionViewSource)source; 29 | sender.SortDescriptions.Clear(); 30 | if(args.NewValue != null) 31 | sender.SortDescriptions.Add(new SortDescription((string)args.NewValue, ListSortDirection.Ascending)); 32 | } 33 | 34 | 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /HttpSysManager/HttpSysManager/HttpAPIManager.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Runtime.InteropServices; 3 | using System.Collections.Generic; 4 | using System.ComponentModel; 5 | using System.Linq; 6 | using ProcessHacker.Native.Security.AccessControl; 7 | using ProcessHacker.Native; 8 | using ProcessHacker.Native.Api; 9 | using ProcessHacker.Native.Security; 10 | using System.Security.Cryptography.X509Certificates; 11 | using System.Net; 12 | using System.Net.Sockets; 13 | using HttpSysManager.Core; 14 | using HttpSysManager.Native; 15 | 16 | 17 | namespace HttpSysManager.HttpAPI 18 | { 19 | 20 | public class HttpAPIManager 21 | { 22 | public IEnumerable GetAclInfo() 23 | { 24 | using(new HttpInitializeScope()) 25 | { 26 | UrlAcl urlAcl; 27 | int i = 0; 28 | do 29 | { 30 | urlAcl = UrlAcl.Get(i); 31 | if(urlAcl != null) 32 | yield return urlAcl; 33 | i++; 34 | } while(urlAcl != null); 35 | } 36 | } 37 | 38 | public void SetUrlAcl(string url, SecurityDescriptor securityDescriptor) 39 | { 40 | using(new HttpInitializeScope()) 41 | { 42 | if(securityDescriptor == null) 43 | { 44 | RemoveUrlAcl(url); 45 | return; 46 | } 47 | var urlAcl = new UrlAcl(); 48 | urlAcl.Prefix = url; 49 | urlAcl.SecurityDescriptor = securityDescriptor; 50 | urlAcl.Update(); 51 | } 52 | } 53 | 54 | public void RemoveUrlAcl(string url) 55 | { 56 | using(new HttpInitializeScope()) 57 | { 58 | UrlAcl urlAcl = new UrlAcl(); 59 | urlAcl.Prefix = url; 60 | urlAcl.Delete(); 61 | } 62 | } 63 | static protected void CreateBuffer(object initObject, out IntPtr ptr, out int lenght) 64 | { 65 | lenght = Marshal.SizeOf(initObject); 66 | ptr = Marshal.AllocHGlobal(lenght); 67 | Marshal.StructureToPtr(initObject, ptr, false); 68 | } 69 | 70 | 71 | public UrlAcl GetAclInfo(string url) 72 | { 73 | using(new HttpInitializeScope()) 74 | { 75 | return UrlAcl.Get(url); 76 | } 77 | } 78 | 79 | public IEnumerable GetSSLInfos() 80 | { 81 | using(new HttpInitializeScope()) 82 | { 83 | SSLInfo sslInfo; 84 | int i = 0; 85 | do 86 | { 87 | sslInfo = SSLInfo.Get(i); 88 | if(sslInfo != null) 89 | yield return sslInfo; 90 | i++; 91 | } while(sslInfo != null); 92 | } 93 | } 94 | 95 | public void SetSSLInfo(IPEndPoint endpoint, SSLInfo info) 96 | { 97 | using(new HttpInitializeScope()) 98 | { 99 | if(info == null) 100 | { 101 | RemoveSSLInfo(endpoint); 102 | } 103 | else 104 | { 105 | info.Endpoint = endpoint; 106 | info.Update(); 107 | } 108 | } 109 | } 110 | 111 | public void RemoveSSLInfo(IPEndPoint endpoint) 112 | { 113 | using(new HttpInitializeScope()) 114 | { 115 | var info = new SSLInfo(); 116 | info.Endpoint = endpoint; 117 | info.Delete(); 118 | } 119 | } 120 | 121 | public SSLInfo GetSSLInfo(IPEndPoint endpoint) 122 | { 123 | using(new HttpInitializeScope()) 124 | { 125 | return SSLInfo.Get(endpoint); 126 | } 127 | } 128 | } 129 | } 130 | -------------------------------------------------------------------------------- /HttpSysManager/HttpSysManager/HttpSysManager.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | Debug 5 | x86 6 | 8.0.30703 7 | 2.0 8 | {910CE5E7-9DD1-46E9-90C4-AB89B086D45F} 9 | WinExe 10 | Properties 11 | HttpSysManager 12 | HttpSysManager 13 | v4.5 14 | 15 | 16 | 512 17 | {60dc8134-eba5-43b8-bcc9-bb4bc16c2548};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} 18 | 4 19 | 20 | 21 | x86 22 | true 23 | full 24 | false 25 | ..\Debug\ 26 | DEBUG;TRACE 27 | prompt 28 | 4 29 | false 30 | false 31 | 32 | 33 | x86 34 | pdbonly 35 | true 36 | ..\Release\ 37 | TRACE 38 | prompt 39 | 4 40 | false 41 | 42 | 43 | 44 | 45 | 46 | app.manifest 47 | 48 | 49 | 50 | HttpSysManager.Native 51 | 52 | 53 | False 54 | bins\ProcessHacker.Common.dll 55 | 56 | 57 | False 58 | bins\ProcessHacker.Native.dll 59 | 60 | 61 | False 62 | bins\SlasheneFramework.dll 63 | 64 | 65 | False 66 | bins\SlasheneFramework.UI.dll 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 4.0 79 | 80 | 81 | 82 | 83 | 84 | False 85 | bins\WPFToolkit.Extended.dll 86 | 87 | 88 | 89 | 90 | MSBuild:Compile 91 | Designer 92 | 93 | 94 | SSLInfoOptionWindow.xaml 95 | 96 | 97 | 98 | Designer 99 | MSBuild:Compile 100 | 101 | 102 | Designer 103 | MSBuild:Compile 104 | 105 | 106 | Designer 107 | MSBuild:Compile 108 | 109 | 110 | Designer 111 | MSBuild:Compile 112 | 113 | 114 | MSBuild:Compile 115 | Designer 116 | 117 | 118 | App.xaml 119 | Code 120 | 121 | 122 | CertificateListView.xaml 123 | 124 | 125 | CertificateSelector.xaml 126 | 127 | 128 | CertificateSelectorWindow.xaml 129 | 130 | 131 | CreateCTLWizard.xaml 132 | 133 | 134 | 135 | 136 | 137 | MainWindow.xaml 138 | Code 139 | 140 | 141 | Designer 142 | MSBuild:Compile 143 | 144 | 145 | MSBuild:Compile 146 | Designer 147 | 148 | 149 | 150 | 151 | 152 | Code 153 | 154 | 155 | True 156 | True 157 | Resources.resx 158 | 159 | 160 | True 161 | Settings.settings 162 | True 163 | 164 | 165 | ResXFileCodeGenerator 166 | Resources.Designer.cs 167 | 168 | 169 | Designer 170 | 171 | 172 | 173 | SettingsSingleFileGenerator 174 | Settings.Designer.cs 175 | 176 | 177 | 178 | 179 | 180 | 181 | 182 | 183 | 184 | 185 | 186 | 187 | 188 | 189 | 190 | 191 | 192 | 193 | {cb03213b-4cbb-4e09-8739-59d9fcfb71bf} 194 | HttpSysManager.Core 195 | 196 | 197 | 198 | 205 | -------------------------------------------------------------------------------- /HttpSysManager/HttpSysManager/HyperlinkButton.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Windows; 6 | using System.Windows.Controls; 7 | using System.Windows.Data; 8 | using System.Windows.Documents; 9 | using System.Windows.Input; 10 | using System.Windows.Media; 11 | using System.Windows.Media.Imaging; 12 | using System.Windows.Navigation; 13 | using System.Windows.Shapes; 14 | using System.Diagnostics; 15 | 16 | namespace HttpSysManager 17 | { 18 | /// 19 | /// Follow steps 1a or 1b and then 2 to use this custom control in a XAML file. 20 | /// 21 | /// Step 1a) Using this custom control in a XAML file that exists in the current project. 22 | /// Add this XmlNamespace attribute to the root element of the markup file where it is 23 | /// to be used: 24 | /// 25 | /// xmlns:MyNamespace="clr-namespace:HttpSysManager" 26 | /// 27 | /// 28 | /// Step 1b) Using this custom control in a XAML file that exists in a different project. 29 | /// Add this XmlNamespace attribute to the root element of the markup file where it is 30 | /// to be used: 31 | /// 32 | /// xmlns:MyNamespace="clr-namespace:HttpSysManager;assembly=HttpSysManager" 33 | /// 34 | /// You will also need to add a project reference from the project where the XAML file lives 35 | /// to this project and Rebuild to avoid compilation errors: 36 | /// 37 | /// Right click on the target project in the Solution Explorer and 38 | /// "Add Reference"->"Projects"->[Browse to and select this project] 39 | /// 40 | /// 41 | /// Step 2) 42 | /// Go ahead and use your control in the XAML file. 43 | /// 44 | /// 45 | /// 46 | /// 47 | public class HyperlinkButton : Control 48 | { 49 | static HyperlinkButton() 50 | { 51 | DefaultStyleKeyProperty.OverrideMetadata(typeof(HyperlinkButton), new FrameworkPropertyMetadata(typeof(HyperlinkButton))); 52 | } 53 | 54 | public HyperlinkButton() 55 | { 56 | this.KeyDown += new KeyEventHandler(HyperlinkButton_KeyDown); 57 | this.IsTabStop = false; 58 | } 59 | 60 | void HyperlinkButton_KeyDown(object sender, KeyEventArgs e) 61 | { 62 | if(e.Key == Key.Enter) 63 | { 64 | link_Click(null, null); 65 | e.Handled = true; 66 | } 67 | } 68 | 69 | public string GoTo 70 | { 71 | get 72 | { 73 | return (string)GetValue(GoToProperty); 74 | } 75 | set 76 | { 77 | SetValue(GoToProperty, value); 78 | } 79 | } 80 | 81 | // Using a DependencyProperty as the backing store for GoTo. This enables animation, styling, binding, etc... 82 | public static readonly DependencyProperty GoToProperty = 83 | DependencyProperty.Register("GoTo", typeof(string), typeof(HyperlinkButton), new UIPropertyMetadata(null)); 84 | 85 | 86 | 87 | public ICommand Command 88 | { 89 | get 90 | { 91 | return (ICommand)GetValue(CommandProperty); 92 | } 93 | set 94 | { 95 | SetValue(CommandProperty, value); 96 | } 97 | } 98 | 99 | // Using a DependencyProperty as the backing store for Command. This enables animation, styling, binding, etc... 100 | public static readonly DependencyProperty CommandProperty = 101 | DependencyProperty.Register("Command", typeof(ICommand), typeof(HyperlinkButton), new UIPropertyMetadata(OnPropertyChanged)); 102 | 103 | 104 | public string Text 105 | { 106 | get 107 | { 108 | return (string)GetValue(TextProperty); 109 | } 110 | set 111 | { 112 | SetValue(TextProperty, value); 113 | } 114 | } 115 | 116 | // Using a DependencyProperty as the backing store for Text. This enables animation, styling, binding, etc... 117 | public static readonly DependencyProperty TextProperty = 118 | DependencyProperty.Register("Text", typeof(string), typeof(HyperlinkButton), new UIPropertyMetadata(OnPropertyChanged)); 119 | 120 | static void OnPropertyChanged(DependencyObject source, DependencyPropertyChangedEventArgs args) 121 | { 122 | HyperlinkButton sender = (HyperlinkButton)source; 123 | sender.RefreshLink(); 124 | } 125 | 126 | public event RoutedEventHandler Click; 127 | 128 | Hyperlink link; 129 | Run run; 130 | public override void OnApplyTemplate() 131 | { 132 | base.OnApplyTemplate(); 133 | link = (Hyperlink)this.GetTemplateChild("link"); 134 | run = (Run)this.GetTemplateChild("run"); 135 | RefreshLink(); 136 | } 137 | 138 | private void RefreshLink() 139 | { 140 | if(run != null) 141 | { 142 | run.Text = Text; 143 | link.Command = Command; 144 | link.Click -= link_Click; 145 | link.Click += link_Click; 146 | } 147 | } 148 | 149 | 150 | void link_Click(object sender, RoutedEventArgs e) 151 | { 152 | if(link != null) 153 | if(Click != null) 154 | Click(this, e); 155 | else if(GoTo != null) 156 | Process.Start(GoTo); 157 | 158 | } 159 | } 160 | } 161 | -------------------------------------------------------------------------------- /HttpSysManager/HttpSysManager/MainWindow.xaml: -------------------------------------------------------------------------------- 1 |  8 | 9 | 10 | by 11 | 12 | 13 | 14 | 15 | 16 | 17 | Ip 18 | 19 | Port 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | Local administrators don't need ACL to listen url prefixes. 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | -------------------------------------------------------------------------------- /HttpSysManager/HttpSysManager/MainWindow.xaml.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Windows; 6 | using System.Windows.Controls; 7 | using System.Windows.Data; 8 | using System.Windows.Documents; 9 | using System.Windows.Input; 10 | using System.Windows.Media; 11 | using System.Windows.Media.Imaging; 12 | using System.Windows.Navigation; 13 | using System.Windows.Shapes; 14 | using ProcessHacker.Native.Security.AccessControl; 15 | using ProcessHacker.Native.Security; 16 | using ProcessHacker.Native.Api; 17 | using System.Runtime.InteropServices; 18 | using ProcessHacker.Native; 19 | using HttpSysManager.HttpAPI; 20 | using System.Net; 21 | using System.ComponentModel; 22 | using HttpSysManager.Native; 23 | using System.Diagnostics; 24 | using System.Security.Cryptography.X509Certificates; 25 | using System.IO; 26 | using Microsoft.Win32; 27 | 28 | namespace HttpSysManager 29 | { 30 | /// 31 | /// Interaction logic for MainWindow.xaml 32 | /// 33 | public partial class MainWindow : Window 34 | { 35 | public MainWindow() 36 | { 37 | InitializeComponent(); 38 | DataContext = new MainWindowViewModel(); 39 | } 40 | 41 | public MainWindowViewModel ViewModel 42 | { 43 | set 44 | { 45 | DataContext = value; 46 | } 47 | get 48 | { 49 | return (MainWindowViewModel)DataContext; 50 | } 51 | } 52 | private void Permissions_Click(object sender, RoutedEventArgs e) 53 | { 54 | var acl = (UrlAcl)((FrameworkElement)sender).DataContext; 55 | SecurityEditor.EditSecurity(null, acl, acl.Prefix, GetAccessEntries()); 56 | } 57 | 58 | private IEnumerable GetAccessEntries() 59 | { 60 | yield return new AccessEntry("Register", StandardRights.GenericExecute, true, true); 61 | yield return new AccessEntry("Delegate", StandardRights.GenericWrite, true, true); 62 | } 63 | 64 | private void Delete_Click(object sender, RoutedEventArgs e) 65 | { 66 | var acl = (UrlAcl)((FrameworkElement)sender).DataContext; 67 | RemoveACL(acl); 68 | } 69 | 70 | private void RemoveACL(UrlAcl acl) 71 | { 72 | new HttpAPIManager().RemoveUrlAcl(acl.Prefix); 73 | ViewModel.Acls.Remove(acl); 74 | } 75 | 76 | private void DeleteCertInfo_Click(object sender, RoutedEventArgs e) 77 | { 78 | var vm = (SSLInfoViewModel)(((Button)sender).DataContext); 79 | vm.DeleteSSLInfo(); 80 | } 81 | private void OptionSSLInfo_Click(object sender, RoutedEventArgs e) 82 | { 83 | var vm = (SSLInfoViewModel)(((Button)sender).DataContext); 84 | SSLInfoOptionWindow options = new SSLInfoOptionWindow(); 85 | options.SSLInfo = vm.Info; 86 | options.ShowDialog(); 87 | } 88 | 89 | 90 | private void DeleteSSLInfo_KeyDown(object sender, KeyEventArgs e) 91 | { 92 | ListView view = (ListView)sender; 93 | if(e.Key == Key.Delete) 94 | { 95 | foreach(SSLInfoViewModel sslInfo in view.SelectedItems.OfType().ToList()) 96 | sslInfo.DeleteSSLInfo(); 97 | e.Handled = true; 98 | } 99 | } 100 | 101 | 102 | private void DeleteUrlACL_KeyDown(object sender, KeyEventArgs e) 103 | { 104 | ListView view = (ListView)sender; 105 | if(e.Key == Key.Delete) 106 | { 107 | foreach(UrlAcl acl in view.SelectedItems.OfType().ToList()) 108 | RemoveACL(acl); 109 | e.Handled = true; 110 | } 111 | } 112 | 113 | private void OnNavigate(object sender, RequestNavigateEventArgs e) 114 | { 115 | Process.Start(new ProcessStartInfo(e.Uri.AbsoluteUri)); 116 | e.Handled = true; 117 | } 118 | const string DefaultFileName = "NewCTL"; 119 | 120 | private void CreateCTLClick(object sender, RoutedEventArgs e) 121 | { 122 | CreateCTLWizard wizard = new CreateCTLWizard(); 123 | var builder = new CTLContextBuilder(); 124 | builder.CTLInfo.ListIdentifier = "New CTL"; 125 | wizard.DataContext = builder; 126 | var result = wizard.ShowDialog(); 127 | if(result.HasValue && result.Value) 128 | { 129 | SaveFileDialog save = new SaveFileDialog(); 130 | var name = builder.CTLInfo.ListIdentifier; 131 | save.FileName = (String.IsNullOrEmpty(name) ? DefaultFileName : name) + ".stl"; 132 | var saveResult = save.ShowDialog(); 133 | if(saveResult.HasValue && saveResult.Value) 134 | { 135 | using(var context = builder.ToCTLContext()) 136 | { 137 | File.WriteAllBytes(save.FileName, context.ToBytes()); 138 | } 139 | } 140 | } 141 | } 142 | 143 | } 144 | } 145 | -------------------------------------------------------------------------------- /HttpSysManager/HttpSysManager/MainWindowViewModel.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using SlasheneFramework; 6 | using System.Windows.Input; 7 | using SlasheneFramework.UI; 8 | using HttpSysManager.HttpAPI; 9 | using System.Collections.ObjectModel; 10 | using ProcessHacker.Native.Security.AccessControl; 11 | using ProcessHacker.Native.Security; 12 | using System.Security.Cryptography.X509Certificates; 13 | using System.Net; 14 | using HttpSysManager.Native; 15 | 16 | namespace HttpSysManager 17 | { 18 | public class SSLInfoViewModel : NotifyPropertyChangedBase 19 | { 20 | MainWindowViewModel _Parent; 21 | public SSLInfoViewModel(SSLInfo info, MainWindowViewModel parent) 22 | { 23 | _Info = info; 24 | _Parent = parent; 25 | } 26 | 27 | 28 | private readonly SSLInfo _Info; 29 | public SSLInfo Info 30 | { 31 | get 32 | { 33 | return _Info; 34 | } 35 | } 36 | 37 | 38 | 39 | public void DeleteSSLInfo() 40 | { 41 | new HttpAPIManager().RemoveSSLInfo(Info.Endpoint); 42 | _Parent.SSLInfos.Remove(this); 43 | } 44 | } 45 | public class MainWindowViewModel : NotifyPropertyChangedBase 46 | { 47 | public static SecurityDescriptor CreateAllRightsToCurrentUser() 48 | { 49 | var descriptor = new SecurityDescriptor(); 50 | descriptor.Dacl = new Acl(800); 51 | descriptor.Dacl.AddAccessAllowed((int)StandardRights.GenericExecute, Sid.CurrentUser); 52 | descriptor.Dacl.AddAccessAllowed((int)StandardRights.GenericWrite, Sid.CurrentUser); 53 | return descriptor; 54 | } 55 | class AddSSLCertCommand : ViewModelCommand 56 | { 57 | public AddSSLCertCommand(MainWindowViewModel vm) 58 | : base(vm) 59 | { 60 | 61 | } 62 | public override bool CanExecute(object parameter) 63 | { 64 | IPAddress addr; 65 | return ViewModel.SelectedCertificate != null 66 | && ViewModel.SSLIp != null 67 | && IPAddress.TryParse(ViewModel.SSLIp, out addr) 68 | && (ViewModel.SSLPort > 0 && ViewModel.SSLPort < UInt16.MaxValue) 69 | && ViewModel.SSLInfos.Select(i=>i.Info.Endpoint).All(i=>!i.Equals(ViewModel.CreateSSLIPEndpoint())); 70 | } 71 | 72 | public override void Execute(object parameter) 73 | { 74 | if(CanExecute(null)) 75 | { 76 | var info = new SSLInfo(); 77 | info.SetCertificate(StoreName.My, ViewModel.SelectedCertificate.Thumbprint); 78 | new HttpAPIManager().SetSSLInfo(ViewModel.CreateSSLIPEndpoint(), info); 79 | ViewModel.SSLInfos.Add(new SSLInfoViewModel(info,ViewModel)); 80 | ViewModel.SSLPort = 443; 81 | ViewModel.SSLIp = ""; 82 | ViewModel.SelectedCertificate = null; 83 | } 84 | } 85 | } 86 | class CreateNewAclCommand : ViewModelCommand 87 | { 88 | public CreateNewAclCommand(MainWindowViewModel vm) 89 | : base(vm) 90 | { 91 | } 92 | public override bool CanExecute(object parameter) 93 | { 94 | if(ViewModel.NewAcl == null) 95 | return false; 96 | var url = ViewModel.NewAcl; 97 | url = RemoveWildcards(url); 98 | var isUri = Uri.IsWellFormedUriString(url, UriKind.Absolute); 99 | if(!isUri) 100 | return false; 101 | var uri = new Uri(url, UriKind.Absolute); 102 | if(uri.Scheme != "https" && uri.Scheme != "http") 103 | return false; 104 | if(ViewModel.Acls.Any(a => a.Prefix.Equals(WithPort(WithTrailingSlash(ViewModel.NewAcl)), StringComparison.InvariantCultureIgnoreCase))) 105 | return false; 106 | return true; 107 | } 108 | 109 | 110 | private string RemoveWildcards(string url) 111 | { 112 | var parts = url.Split(new char[] { '/' }); 113 | if(parts.Length < 3) 114 | return url; 115 | parts[2] = parts[2].Replace("*", "StAr").Replace("+", "PlUs"); 116 | return String.Join("/", parts); 117 | } 118 | 119 | public override void Execute(object parameter) 120 | { 121 | ViewModel.NewAcl = WithPort(WithTrailingSlash(ViewModel.NewAcl)); 122 | var manager = new HttpAPIManager(); 123 | manager.SetUrlAcl(ViewModel.NewAcl, MainWindowViewModel.CreateAllRightsToCurrentUser()); 124 | ViewModel.Acls.Insert(0, manager.GetAclInfo(ViewModel.NewAcl)); 125 | ViewModel.NewAcl = ""; 126 | } 127 | 128 | private string WithPort(string url) 129 | { 130 | var parts = url.Split(new char[] { '/' }); 131 | if(parts.Length < 3) 132 | return url; 133 | if(!parts[2].Contains(':')) 134 | parts[2] = parts[2] + ':' + DefaultPort(parts[0]); 135 | return string.Join("/", parts); 136 | } 137 | 138 | private string DefaultPort(string scheme) 139 | { 140 | if(scheme.Equals("http:", StringComparison.InvariantCultureIgnoreCase)) 141 | return "80"; 142 | if(scheme.Equals("https:", StringComparison.InvariantCultureIgnoreCase)) 143 | return "443"; 144 | throw new NotSupportedException(scheme + " is not supported"); 145 | } 146 | 147 | private string WithTrailingSlash(string url) 148 | { 149 | if(!url.EndsWith("/") && !url.EndsWith("\\")) 150 | { 151 | return url + "/"; 152 | } 153 | return url; 154 | } 155 | } 156 | 157 | public MainWindowViewModel() 158 | { 159 | SSLPort = 443; 160 | _Acls = new ObservableCollection(new HttpAPIManager().GetAclInfo()); 161 | _SSLInfos = new ObservableCollection(new HttpAPIManager().GetSSLInfos().Select(i => new SSLInfoViewModel(i,this))); 162 | } 163 | 164 | private ICommand _AddSSLCert; 165 | public ICommand AddSSLCert 166 | { 167 | get 168 | { 169 | if(_AddSSLCert == null) 170 | _AddSSLCert = new AddSSLCertCommand(this); 171 | return _AddSSLCert; 172 | } 173 | } 174 | private X509Certificate2 _SelectedCertificate; 175 | public X509Certificate2 SelectedCertificate 176 | { 177 | get 178 | { 179 | return _SelectedCertificate; 180 | } 181 | set 182 | { 183 | if(value != _SelectedCertificate) 184 | { 185 | _SelectedCertificate = value; 186 | OnPropertyChanged(() => this.SelectedCertificate); 187 | } 188 | } 189 | } 190 | private string _SSLIp; 191 | public string SSLIp 192 | { 193 | get 194 | { 195 | return _SSLIp; 196 | } 197 | set 198 | { 199 | if(value != _SSLIp) 200 | { 201 | _SSLIp = value; 202 | OnPropertyChanged(() => this.SSLIp); 203 | } 204 | } 205 | } 206 | private int _SSLPort; 207 | public int SSLPort 208 | { 209 | get 210 | { 211 | return _SSLPort; 212 | } 213 | set 214 | { 215 | if(value != _SSLPort) 216 | { 217 | _SSLPort = value; 218 | OnPropertyChanged(() => this.SSLPort); 219 | } 220 | } 221 | } 222 | 223 | private readonly ObservableCollection _SSLInfos; 224 | public ObservableCollection SSLInfos 225 | { 226 | get 227 | { 228 | return _SSLInfos; 229 | } 230 | } 231 | private string _NewAcl; 232 | public string NewAcl 233 | { 234 | get 235 | { 236 | return _NewAcl; 237 | } 238 | set 239 | { 240 | if(value != _NewAcl) 241 | { 242 | _NewAcl = value; 243 | OnPropertyChanged(() => this.NewAcl); 244 | } 245 | } 246 | } 247 | 248 | private ICommand _CreateNewAcl; 249 | public ICommand CreateNewAcl 250 | { 251 | get 252 | { 253 | if(_CreateNewAcl == null) 254 | _CreateNewAcl = new CreateNewAclCommand(this); 255 | return _CreateNewAcl; 256 | } 257 | } 258 | 259 | private ObservableCollection _Acls; 260 | public ObservableCollection Acls 261 | { 262 | get 263 | { 264 | return _Acls; 265 | } 266 | } 267 | 268 | internal IPEndPoint CreateSSLIPEndpoint() 269 | { 270 | return new IPEndPoint(IPAddress.Parse(SSLIp), SSLPort); 271 | } 272 | } 273 | } 274 | -------------------------------------------------------------------------------- /HttpSysManager/HttpSysManager/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Resources; 3 | using System.Runtime.CompilerServices; 4 | using System.Runtime.InteropServices; 5 | using System.Windows; 6 | 7 | // General Information about an assembly is controlled through the following 8 | // set of attributes. Change these attribute values to modify the information 9 | // associated with an assembly. 10 | [assembly: AssemblyTitle("HttpSysManager")] 11 | [assembly: AssemblyDescription("")] 12 | [assembly: AssemblyConfiguration("")] 13 | [assembly: AssemblyCompany("Microsoft")] 14 | [assembly: AssemblyProduct("HttpSysManager")] 15 | [assembly: AssemblyCopyright("Copyright © Microsoft 2012")] 16 | [assembly: AssemblyTrademark("")] 17 | [assembly: AssemblyCulture("")] 18 | 19 | // Setting ComVisible to false makes the types in this assembly not visible 20 | // to COM components. If you need to access a type in this assembly from 21 | // COM, set the ComVisible attribute to true on that type. 22 | [assembly: ComVisible(false)] 23 | 24 | //In order to begin building localizable applications, set 25 | //CultureYouAreCodingWith in your .csproj file 26 | //inside a . For example, if you are using US english 27 | //in your source files, set the to en-US. Then uncomment 28 | //the NeutralResourceLanguage attribute below. Update the "en-US" in 29 | //the line below to match the UICulture setting in the project file. 30 | 31 | //[assembly: NeutralResourcesLanguage("en-US", UltimateResourceFallbackLocation.Satellite)] 32 | 33 | 34 | [assembly: ThemeInfo( 35 | ResourceDictionaryLocation.None, //where theme specific resource dictionaries are located 36 | //(used if a resource is not found in the page, 37 | // or application resource dictionaries) 38 | ResourceDictionaryLocation.SourceAssembly //where the generic resource dictionary is located 39 | //(used if a resource is not found in the page, 40 | // app, or any theme specific resource dictionaries) 41 | )] 42 | 43 | 44 | // Version information for an assembly consists of the following four values: 45 | // 46 | // Major Version 47 | // Minor Version 48 | // Build Number 49 | // Revision 50 | // 51 | // You can specify all the values or you can default the Build and Revision Numbers 52 | // by using the '*' as shown below: 53 | // [assembly: AssemblyVersion("1.0.*")] 54 | [assembly: AssemblyVersion("1.0.0.0")] 55 | [assembly: AssemblyFileVersion("1.0.0.0")] 56 | -------------------------------------------------------------------------------- /HttpSysManager/HttpSysManager/Properties/Resources.Designer.cs: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | // 3 | // This code was generated by a tool. 4 | // Runtime Version:4.0.30319.34014 5 | // 6 | // Changes to this file may cause incorrect behavior and will be lost if 7 | // the code is regenerated. 8 | // 9 | //------------------------------------------------------------------------------ 10 | 11 | namespace HttpSysManager.Properties { 12 | using System; 13 | 14 | 15 | /// 16 | /// A strongly-typed resource class, for looking up localized strings, etc. 17 | /// 18 | // This class was auto-generated by the StronglyTypedResourceBuilder 19 | // class via a tool like ResGen or Visual Studio. 20 | // To add or remove a member, edit your .ResX file then rerun ResGen 21 | // with the /str option, or rebuild your VS project. 22 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")] 23 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] 24 | [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] 25 | internal class Resources { 26 | 27 | private static global::System.Resources.ResourceManager resourceMan; 28 | 29 | private static global::System.Globalization.CultureInfo resourceCulture; 30 | 31 | [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] 32 | internal Resources() { 33 | } 34 | 35 | /// 36 | /// Returns the cached ResourceManager instance used by this class. 37 | /// 38 | [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] 39 | internal static global::System.Resources.ResourceManager ResourceManager { 40 | get { 41 | if (object.ReferenceEquals(resourceMan, null)) { 42 | global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("HttpSysManager.Properties.Resources", typeof(Resources).Assembly); 43 | resourceMan = temp; 44 | } 45 | return resourceMan; 46 | } 47 | } 48 | 49 | /// 50 | /// Overrides the current thread's CurrentUICulture property for all 51 | /// resource lookups using this strongly typed resource class. 52 | /// 53 | [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] 54 | internal static global::System.Globalization.CultureInfo Culture { 55 | get { 56 | return resourceCulture; 57 | } 58 | set { 59 | resourceCulture = value; 60 | } 61 | } 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /HttpSysManager/HttpSysManager/Properties/Resources.resx: -------------------------------------------------------------------------------- 1 |  2 | 3 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | text/microsoft-resx 107 | 108 | 109 | 2.0 110 | 111 | 112 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 113 | 114 | 115 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 116 | 117 | -------------------------------------------------------------------------------- /HttpSysManager/HttpSysManager/Properties/Settings.Designer.cs: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | // 3 | // This code was generated by a tool. 4 | // Runtime Version:4.0.30319.34014 5 | // 6 | // Changes to this file may cause incorrect behavior and will be lost if 7 | // the code is regenerated. 8 | // 9 | //------------------------------------------------------------------------------ 10 | 11 | namespace HttpSysManager.Properties { 12 | 13 | 14 | [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] 15 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "12.0.0.0")] 16 | internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase { 17 | 18 | private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings()))); 19 | 20 | public static Settings Default { 21 | get { 22 | return defaultInstance; 23 | } 24 | } 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /HttpSysManager/HttpSysManager/Properties/Settings.settings: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /HttpSysManager/HttpSysManager/SSLInfoOptionWindow.xaml: -------------------------------------------------------------------------------- 1 |  9 | 10 | 11 | 12 | 13 | 14 | Negotiate client certificate 15 | Directory Service client certificate mapping 16 | Check client revocation 17 | 18 | 19 | 20 | 21 | 22 | 23 | CTL not found, import an existing CTL or create a new CTL (The CTL will be automatically imported in the selected store on LocalMachine) 24 | 25 | 26 | 27 | 28 | 29 | -------------------------------------------------------------------------------- /HttpSysManager/HttpSysManager/SSLInfoOptionWindow.xaml.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Diagnostics; 4 | using System.IO; 5 | using System.Linq; 6 | using System.Security.Cryptography.X509Certificates; 7 | using System.Text; 8 | using System.Windows; 9 | using System.Windows.Controls; 10 | using System.Windows.Data; 11 | using System.Windows.Documents; 12 | using System.Windows.Input; 13 | using System.Windows.Media; 14 | using System.Windows.Media.Imaging; 15 | using System.Windows.Shapes; 16 | using HttpSysManager.Native; 17 | using Microsoft.Win32; 18 | using SlasheneFramework; 19 | using SlasheneFramework.UI; 20 | 21 | namespace HttpSysManager 22 | { 23 | /// 24 | /// Interaction logic for SSLInfoOptionWindow.xaml 25 | /// 26 | public partial class SSLInfoOptionWindow : Window 27 | { 28 | class SSLInfoViewModel : DynamicViewModel 29 | { 30 | class SaveCommand : ViewModelCommand 31 | { 32 | public SaveCommand(SSLInfoViewModel vm) 33 | : base(vm) 34 | { 35 | 36 | } 37 | public override bool CanExecute(object parameter) 38 | { 39 | return ViewModel.IsDirty && ViewModel.HasValidCTL; 40 | } 41 | 42 | public override void Execute(object parameter) 43 | { 44 | ViewModel.ApplyChanges(); 45 | using(new HttpInitializeScope()) 46 | { 47 | try 48 | { 49 | ViewModel.Instance.Update(); 50 | ViewModel.IsDirty = false; 51 | 52 | } 53 | catch(Exception ex) 54 | { 55 | MessageBox.Show("Error " + ex.Message + ".\r\n This error comes most likely from a bug in HTTP.sys. To fix it, download and install KB981506 (http://support.microsoft.com/kb/981506)"); 56 | } 57 | } 58 | } 59 | } 60 | 61 | public SSLInfoViewModel(SSLInfo info) 62 | : base(info) 63 | { 64 | 65 | } 66 | 67 | public override bool TrySetMember(System.Dynamic.SetMemberBinder binder, object value) 68 | { 69 | IsDirty = true; 70 | _ChangedTracking[binder.Name] = value; 71 | return true; 72 | } 73 | public override bool TryGetMember(System.Dynamic.GetMemberBinder binder, out object result) 74 | { 75 | 76 | if(!_ChangedTracking.TryGetValue(binder.Name, out result)) 77 | { 78 | base.TryGetMember(binder, out result); 79 | } 80 | return true; 81 | } 82 | 83 | Dictionary _ChangedTracking = new Dictionary(); 84 | private bool _IsDirty; 85 | public bool IsDirty 86 | { 87 | get 88 | { 89 | return _IsDirty; 90 | } 91 | set 92 | { 93 | if(value != _IsDirty) 94 | { 95 | _IsDirty = value; 96 | OnPropertyChanged(() => this.IsDirty); 97 | } 98 | } 99 | } 100 | private ICommand _SaveCommand; 101 | public ICommand Save 102 | { 103 | get 104 | { 105 | if(_SaveCommand == null) 106 | _SaveCommand = new SaveCommand(this); 107 | return _SaveCommand; 108 | } 109 | } 110 | 111 | public class StoreNameViewModel 112 | { 113 | public StoreName? store; 114 | public StoreNameViewModel() 115 | { 116 | } 117 | public StoreNameViewModel(StoreName? store) 118 | { 119 | this.store = store; 120 | } 121 | 122 | public override string ToString() 123 | { 124 | if(!store.HasValue) 125 | return "Not assigned"; 126 | return store.ToString(); 127 | } 128 | public override bool Equals(object obj) 129 | { 130 | StoreNameViewModel item = obj as StoreNameViewModel; 131 | if(item == null) 132 | return false; 133 | return store.Equals(item.store); 134 | } 135 | public override int GetHashCode() 136 | { 137 | return store.GetHashCode(); 138 | } 139 | } 140 | public IEnumerable StoreNames 141 | { 142 | get 143 | { 144 | yield return new StoreNameViewModel(); 145 | foreach(var value in Enum.GetValues(typeof(StoreName)).OfType()) 146 | yield return new StoreNameViewModel(value); 147 | } 148 | } 149 | 150 | public StoreNameViewModel CTLStoreNameProxy 151 | { 152 | get 153 | { 154 | dynamic thisDynamic = this; 155 | return new StoreNameViewModel(thisDynamic.CTLStoreName); 156 | } 157 | set 158 | { 159 | dynamic thisDynamic = this; 160 | thisDynamic.CTLStoreName = value.store; 161 | if(value.store == null) 162 | CTLIdentifierProxy = null; 163 | OnPropertyChanged(() => this.HasCTLStore); 164 | OnPropertyChanged(() => this.HasValidCTL); 165 | } 166 | } 167 | 168 | public string CTLIdentifierProxy 169 | { 170 | get 171 | { 172 | dynamic thisDynamic = this; 173 | return thisDynamic.CTLIdentifier; 174 | } 175 | set 176 | { 177 | dynamic thisDynamic = this; 178 | thisDynamic.CTLIdentifier = value; 179 | CTLError = null; 180 | OnPropertyChanged(() => this.CTLIdentifierProxy); 181 | OnPropertyChanged(() => this.HasValidCTL); 182 | } 183 | } 184 | 185 | public bool HasCTLStore 186 | { 187 | get 188 | { 189 | return CTLStoreNameProxy.store != null; 190 | } 191 | } 192 | public bool HasValidCTL 193 | { 194 | get 195 | { 196 | var result = CTLStoreNameProxy.store == null || CTLContext.Get(StoreLocation.LocalMachine, CTLStoreNameProxy.store.Value, this.CTLIdentifierProxy) != null; 197 | return result; 198 | } 199 | } 200 | 201 | internal void ApplyChanges() 202 | { 203 | foreach(var change in _ChangedTracking) 204 | { 205 | Instance.GetType().GetProperty(change.Key).SetValue( 206 | Instance, change.Value, null); 207 | } 208 | _ChangedTracking.Clear(); 209 | } 210 | 211 | 212 | 213 | internal void CreateAndImportCTL(CTLContextBuilder builder) 214 | { 215 | if(String.IsNullOrEmpty(builder.CTLInfo.ListIdentifier)) 216 | { 217 | builder.CTLInfo.ListIdentifier = "New CTL"; 218 | } 219 | 220 | 221 | using(var context = builder.ToCTLContext()) 222 | { 223 | ImportCTL(context); 224 | } 225 | } 226 | 227 | internal void ImportCTL(CTLContext context) 228 | { 229 | if(context.CTLInfo.ListIdentifier == null) 230 | { 231 | CTLError = "The ListIdentifier of the CTL should be an unicode string to work correctly with http.sys"; 232 | return; 233 | } 234 | CTLError = null; 235 | CTLIdentifierProxy = context.CTLInfo.ListIdentifier; 236 | context.ImportInStore(StoreLocation.LocalMachine, CTLStoreNameProxy.store.Value); 237 | OnPropertyChanged(() => this.HasValidCTL); 238 | } 239 | 240 | private string _CTLError; 241 | public string CTLError 242 | { 243 | get 244 | { 245 | return _CTLError; 246 | } 247 | set 248 | { 249 | if(value != _CTLError) 250 | { 251 | _CTLError = value; 252 | OnPropertyChanged(() => this.CTLError); 253 | } 254 | } 255 | } 256 | } 257 | public SSLInfoOptionWindow() 258 | { 259 | InitializeComponent(); 260 | } 261 | 262 | public SSLInfo SSLInfo 263 | { 264 | get 265 | { 266 | return ViewModel.Instance; 267 | } 268 | set 269 | { 270 | root.DataContext = new SSLInfoViewModel(value); 271 | } 272 | } 273 | 274 | SSLInfoViewModel ViewModel 275 | { 276 | get 277 | { 278 | return ((SSLInfoViewModel)root.DataContext); 279 | } 280 | } 281 | 282 | private void Save_Click(object sender, RoutedEventArgs e) 283 | { 284 | DialogResult = true; 285 | } 286 | 287 | private void Import_CTL(object sender, RoutedEventArgs e) 288 | { 289 | if(ViewModel.CTLStoreNameProxy.store == null) 290 | return; 291 | OpenFileDialog fileDialog = new OpenFileDialog(); 292 | fileDialog.Filter = "STL files (*.stl)|*.stl"; 293 | fileDialog.CheckFileExists = true; 294 | fileDialog.CheckPathExists = true; 295 | var result = fileDialog.ShowDialog(); 296 | if(result.HasValue && result.Value) 297 | { 298 | var context = CTLContext.Load(File.ReadAllBytes(fileDialog.FileName)); 299 | ViewModel.ImportCTL(context); 300 | } 301 | } 302 | private void Create_CTL(object sender, RoutedEventArgs e) 303 | { 304 | if(ViewModel.CTLStoreNameProxy.store == null) 305 | return; 306 | CreateCTLWizard wizard = new CreateCTLWizard(); 307 | CTLContextBuilder builder = new CTLContextBuilder(); 308 | builder.CTLInfo.ListIdentifier = "New CTL"; 309 | wizard.DataContext = builder; 310 | 311 | var result = wizard.ShowDialog(); 312 | if(result.HasValue && result.Value) 313 | { 314 | ViewModel.CreateAndImportCTL(builder); 315 | } 316 | } 317 | } 318 | } 319 | -------------------------------------------------------------------------------- /HttpSysManager/HttpSysManager/Themes/Generic.xaml: -------------------------------------------------------------------------------- 1 | 5 | 6 | 7 | 20 | 21 | -------------------------------------------------------------------------------- /HttpSysManager/HttpSysManager/X509CertificateNameConverter.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Security.Cryptography.X509Certificates; 5 | using System.Text; 6 | using System.Windows.Data; 7 | using HttpSysManager.Core; 8 | 9 | namespace HttpSysManager 10 | { 11 | public class X509CertificateNameConverter : IValueConverter 12 | { 13 | #region IValueConverter Members 14 | 15 | public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) 16 | { 17 | var cert = value as X509Certificate2; 18 | if(cert == null) 19 | return Binding.DoNothing; 20 | return CertificateHelper.GetFriendlyNameOrName(cert); 21 | } 22 | 23 | public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) 24 | { 25 | throw new NotImplementedException(); 26 | } 27 | 28 | #endregion 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /HttpSysManager/HttpSysManager/app.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /HttpSysManager/HttpSysManager/app.manifest: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 54 | 55 | 56 | -------------------------------------------------------------------------------- /HttpSysManager/HttpSysManager/bins/ProcessHacker.Common.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kstrauss/HttpSysManager/f5276b8aa8180d071a08b8e708739171ce2248ba/HttpSysManager/HttpSysManager/bins/ProcessHacker.Common.dll -------------------------------------------------------------------------------- /HttpSysManager/HttpSysManager/bins/ProcessHacker.Native.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kstrauss/HttpSysManager/f5276b8aa8180d071a08b8e708739171ce2248ba/HttpSysManager/HttpSysManager/bins/ProcessHacker.Native.dll -------------------------------------------------------------------------------- /HttpSysManager/HttpSysManager/bins/ProcessHacker.Native.dll.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /HttpSysManager/HttpSysManager/bins/SlasheneFramework.UI.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kstrauss/HttpSysManager/f5276b8aa8180d071a08b8e708739171ce2248ba/HttpSysManager/HttpSysManager/bins/SlasheneFramework.UI.dll -------------------------------------------------------------------------------- /HttpSysManager/HttpSysManager/bins/SlasheneFramework.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kstrauss/HttpSysManager/f5276b8aa8180d071a08b8e708739171ce2248ba/HttpSysManager/HttpSysManager/bins/SlasheneFramework.dll -------------------------------------------------------------------------------- /HttpSysManager/HttpSysManager/bins/WPFToolkit.Extended.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kstrauss/HttpSysManager/f5276b8aa8180d071a08b8e708739171ce2248ba/HttpSysManager/HttpSysManager/bins/WPFToolkit.Extended.dll -------------------------------------------------------------------------------- /License.txt: -------------------------------------------------------------------------------- 1 | As indicated by the author in his code project article. 2 | 3 | The Code Project Open License (CPOL) 1.02 4 | The Code Project Open License (CPOL) is intended to provide developers who choose to share their code with a license that protects them and provides users of their code with a clear statement regarding how the code can be used. 5 | 6 | The CPOL is our gift to the community. We encourage everyone to use this license if they wish regardless of whether the code is posted on CodeProject.com. 7 | 8 | Download a copy of the CPOL. 9 | 10 | Preamble 11 | This License governs Your use of the Work. This License is intended to allow developers to use the Source Code and Executable Files provided as part of the Work in any application in any form. 12 | 13 | The main points subject to the terms of the License are: 14 | 15 | Source Code and Executable Files can be used in commercial applications; 16 | Source Code and Executable Files can be redistributed; and 17 | Source Code can be modified to create derivative works. 18 | No claim of suitability, guarantee, or any warranty whatsoever is provided. The software is provided "as-is". 19 | The Article(s) accompanying the Work may not be distributed or republished without the Author's consent 20 | This License is entered between You, the individual or other entity reading or otherwise making use of the Work licensed pursuant to this License and the individual or other entity which offers the Work under the terms of this License ("Author"). 21 | 22 | License 23 | THE WORK (AS DEFINED BELOW) IS PROVIDED UNDER THE TERMS OF THIS CODE PROJECT OPEN LICENSE ("LICENSE"). THE WORK IS PROTECTED BY COPYRIGHT AND/OR OTHER APPLICABLE LAW. ANY USE OF THE WORK OTHER THAN AS AUTHORIZED UNDER THIS LICENSE OR COPYRIGHT LAW IS PROHIBITED. 24 | 25 | BY EXERCISING ANY RIGHTS TO THE WORK PROVIDED HEREIN, YOU ACCEPT AND AGREE TO BE BOUND BY THE TERMS OF THIS LICENSE. THE AUTHOR GRANTS YOU THE RIGHTS CONTAINED HEREIN IN CONSIDERATION OF YOUR ACCEPTANCE OF SUCH TERMS AND CONDITIONS. IF YOU DO NOT AGREE TO ACCEPT AND BE BOUND BY THE TERMS OF THIS LICENSE, YOU CANNOT MAKE ANY USE OF THE WORK. 26 | 27 | Definitions. 28 | "Articles" means, collectively, all articles written by Author which describes how the Source Code and Executable Files for the Work may be used by a user. 29 | "Author" means the individual or entity that offers the Work under the terms of this License. 30 | "Derivative Work" means a work based upon the Work or upon the Work and other pre-existing works. 31 | "Executable Files" refer to the executables, binary files, configuration and any required data files included in the Work. 32 | "Publisher" means the provider of the website, magazine, CD-ROM, DVD or other medium from or by which the Work is obtained by You. 33 | "Source Code" refers to the collection of source code and configuration files used to create the Executable Files. 34 | "Standard Version" refers to such a Work if it has not been modified, or has been modified in accordance with the consent of the Author, such consent being in the full discretion of the Author. 35 | "Work" refers to the collection of files distributed by the Publisher, including the Source Code, Executable Files, binaries, data files, documentation, whitepapers and the Articles. 36 | "You" is you, an individual or entity wishing to use the Work and exercise your rights under this License. 37 | Fair Use/Fair Use Rights. Nothing in this License is intended to reduce, limit, or restrict any rights arising from fair use, fair dealing, first sale or other limitations on the exclusive rights of the copyright owner under copyright law or other applicable laws. 38 | License Grant. Subject to the terms and conditions of this License, the Author hereby grants You a worldwide, royalty-free, non-exclusive, perpetual (for the duration of the applicable copyright) license to exercise the rights in the Work as stated below: 39 | You may use the standard version of the Source Code or Executable Files in Your own applications. 40 | You may apply bug fixes, portability fixes and other modifications obtained from the Public Domain or from the Author. A Work modified in such a way shall still be considered the standard version and will be subject to this License. 41 | You may otherwise modify Your copy of this Work (excluding the Articles) in any way to create a Derivative Work, provided that You insert a prominent notice in each changed file stating how, when and where You changed that file. 42 | You may distribute the standard version of the Executable Files and Source Code or Derivative Work in aggregate with other (possibly commercial) programs as part of a larger (possibly commercial) software distribution. 43 | The Articles discussing the Work published in any form by the author may not be distributed or republished without the Author's consent. The author retains copyright to any such Articles. You may use the Executable Files and Source Code pursuant to this License but you may not repost or republish or otherwise distribute or make available the Articles, without the prior written consent of the Author. 44 | Any subroutines or modules supplied by You and linked into the Source Code or Executable Files of this Work shall not be considered part of this Work and will not be subject to the terms of this License. 45 | Patent License. Subject to the terms and conditions of this License, each Author hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, import, and otherwise transfer the Work. 46 | Restrictions. The license granted in Section 3 above is expressly made subject to and limited by the following restrictions: 47 | You agree not to remove any of the original copyright, patent, trademark, and attribution notices and associated disclaimers that may appear in the Source Code or Executable Files. 48 | You agree not to advertise or in any way imply that this Work is a product of Your own. 49 | The name of the Author may not be used to endorse or promote products derived from the Work without the prior written consent of the Author. 50 | You agree not to sell, lease, or rent any part of the Work. This does not restrict you from including the Work or any part of the Work inside a larger software distribution that itself is being sold. The Work by itself, though, cannot be sold, leased or rented. 51 | You may distribute the Executable Files and Source Code only under the terms of this License, and You must include a copy of, or the Uniform Resource Identifier for, this License with every copy of the Executable Files or Source Code You distribute and ensure that anyone receiving such Executable Files and Source Code agrees that the terms of this License apply to such Executable Files and/or Source Code. You may not offer or impose any terms on the Work that alter or restrict the terms of this License or the recipients' exercise of the rights granted hereunder. You may not sublicense the Work. You must keep intact all notices that refer to this License and to the disclaimer of warranties. You may not distribute the Executable Files or Source Code with any technological measures that control access or use of the Work in a manner inconsistent with the terms of this License. 52 | You agree not to use the Work for illegal, immoral or improper purposes, or on pages containing illegal, immoral or improper material. The Work is subject to applicable export laws. You agree to comply with all such laws and regulations that may apply to the Work after Your receipt of the Work. 53 | Representations, Warranties and Disclaimer. THIS WORK IS PROVIDED "AS IS", "WHERE IS" AND "AS AVAILABLE", WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES OR CONDITIONS OR GUARANTEES. YOU, THE USER, ASSUME ALL RISK IN ITS USE, INCLUDING COPYRIGHT INFRINGEMENT, PATENT INFRINGEMENT, SUITABILITY, ETC. AUTHOR EXPRESSLY DISCLAIMS ALL EXPRESS, IMPLIED OR STATUTORY WARRANTIES OR CONDITIONS, INCLUDING WITHOUT LIMITATION, WARRANTIES OR CONDITIONS OF MERCHANTABILITY, MERCHANTABLE QUALITY OR FITNESS FOR A PARTICULAR PURPOSE, OR ANY WARRANTY OF TITLE OR NON-INFRINGEMENT, OR THAT THE WORK (OR ANY PORTION THEREOF) IS CORRECT, USEFUL, BUG-FREE OR FREE OF VIRUSES. YOU MUST PASS THIS DISCLAIMER ON WHENEVER YOU DISTRIBUTE THE WORK OR DERIVATIVE WORKS. 54 | Indemnity. You agree to defend, indemnify and hold harmless the Author and the Publisher from and against any claims, suits, losses, damages, liabilities, costs, and expenses (including reasonable legal or attorneys’ fees) resulting from or relating to any use of the Work by You. 55 | Limitation on Liability. EXCEPT TO THE EXTENT REQUIRED BY APPLICABLE LAW, IN NO EVENT WILL THE AUTHOR OR THE PUBLISHER BE LIABLE TO YOU ON ANY LEGAL THEORY FOR ANY SPECIAL, INCIDENTAL, CONSEQUENTIAL, PUNITIVE OR EXEMPLARY DAMAGES ARISING OUT OF THIS LICENSE OR THE USE OF THE WORK OR OTHERWISE, EVEN IF THE AUTHOR OR THE PUBLISHER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. 56 | Termination. 57 | This License and the rights granted hereunder will terminate automatically upon any breach by You of any term of this License. Individuals or entities who have received Derivative Works from You under this License, however, will not have their licenses terminated provided such individuals or entities remain in full compliance with those licenses. Sections 1, 2, 6, 7, 8, 9, 10 and 11 will survive any termination of this License. 58 | If You bring a copyright, trademark, patent or any other infringement claim against any contributor over infringements You claim are made by the Work, your License from such contributor to the Work ends automatically. 59 | Subject to the above terms and conditions, this License is perpetual (for the duration of the applicable copyright in the Work). Notwithstanding the above, the Author reserves the right to release the Work under different license terms or to stop distributing the Work at any time; provided, however that any such election will not serve to withdraw this License (or any other license that has been, or is required to be, granted under the terms of this License), and this License will continue in full force and effect unless terminated as stated above. 60 | Publisher. The parties hereby confirm that the Publisher shall not, under any circumstances, be responsible for and shall not have any liability in respect of the subject matter of this License. The Publisher makes no warranty whatsoever in connection with the Work and shall not be liable to You or any party on any legal theory for any damages whatsoever, including without limitation any general, special, incidental or consequential damages arising in connection to this license. The Publisher reserves the right to cease making the Work available to You at any time without notice 61 | Miscellaneous 62 | This License shall be governed by the laws of the location of the head office of the Author or if the Author is an individual, the laws of location of the principal place of residence of the Author. 63 | If any provision of this License is invalid or unenforceable under applicable law, it shall not affect the validity or enforceability of the remainder of the terms of this License, and without further action by the parties to this License, such provision shall be reformed to the minimum extent necessary to make such provision valid and enforceable. 64 | No term or provision of this License shall be deemed waived and no breach consented to unless such waiver or consent shall be in writing and signed by the party to be charged with such waiver or consent. 65 | This License constitutes the entire agreement between the parties with respect to the Work licensed herein. There are no understandings, agreements or representations with respect to the Work not specified herein. The Author shall not be bound by any additional provisions that may appear in any communication from You. This License may not be modified without the mutual written agreement of the Author and You. 66 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | HttpSysManager 2 | ============== 3 | 4 | provides both a GUI and interface for doing netsh http urlacl stuff - this is a fork from codeplex of the same name. 5 | http://httpsysmanager.codeplex.com/ 6 | --------------------------------------------------------------------------------