11using System . Diagnostics ;
22using System . Security . Cryptography . X509Certificates ;
3+ using System . Text . RegularExpressions ;
34
45namespace HttpSys
56{
67 public static class NetShWrapper
78 {
8- public static void DisableHttpSysMutualTlsIfExists ( string ipPort )
9+ public static void DeleteBindingIfExists ( string ipPort )
910 {
1011 try
1112 {
12- DisableHttpSysMutualTls ( ipPort ) ;
13+ DeleteBinding ( ipPort ) ;
1314 }
1415 catch
1516 {
1617 // ignore
1718 }
1819 }
1920
20- public static void DisableHttpSysMutualTls ( string ipPort )
21+ public static void DeleteBinding ( string ipPort )
2122 {
2223 Console . WriteLine ( "Disabling mTLS for http.sys" ) ;
2324
@@ -27,14 +28,42 @@ public static void DisableHttpSysMutualTls(string ipPort)
2728 Console . WriteLine ( "Disabled http.sys settings for mTLS" ) ;
2829 }
2930
31+ public static bool BindingExists ( string ipPort , out string certThumbprint , out string appId )
32+ {
33+ certThumbprint = string . Empty ;
34+ appId = string . Empty ;
35+
36+ var bindings = ExecuteNetShCommand ( "http show sslcert" ) ;
37+ if ( string . IsNullOrEmpty ( bindings ) || ! bindings . Contains ( ipPort ) )
38+ {
39+ return false ;
40+ }
41+
42+ // Extract the certificate thumbprint
43+ var thumbprintMatch = Regex . Match ( bindings , @"Certificate Hash\s+:\s+([a-fA-F0-9]+)" ) ;
44+ if ( thumbprintMatch . Success )
45+ {
46+ certThumbprint = thumbprintMatch . Groups [ 1 ] . Value ;
47+ }
48+
49+ // Extract the application ID
50+ var appIdMatch = Regex . Match ( bindings , @"Application ID\s+:\s+{([a-fA-F0-9-]+)}" ) ;
51+ if ( appIdMatch . Success )
52+ {
53+ appId = appIdMatch . Groups [ 1 ] . Value ;
54+ }
55+
56+ return true ;
57+ }
58+
3059 public static void Show ( )
3160 {
3261 ExecuteNetShCommand ( "http show sslcert" , alwaysLogOutput : true ) ;
3362 }
3463
35- public static void EnableHttpSysMutualTls ( string ipPort )
64+ public static void SetTestCertBinding ( string ipPort , bool enableClientCertNegotiation )
3665 {
37- Console . WriteLine ( "Setting up mTLS for http.sys" ) ;
66+ Console . WriteLine ( "Setting up binding for testCert for http.sys" ) ;
3867
3968 var certificate = LoadCertificate ( ) ;
4069 Console . WriteLine ( "Loaded `testCert.pfx` from local file system" ) ;
@@ -47,25 +76,67 @@ public static void EnableHttpSysMutualTls(string ipPort)
4776 }
4877
4978 string certThumbprint = certificate . Thumbprint ;
50- string appId = Guid . NewGuid ( ) . ToString ( ) ;
79+ SetCertBinding ( ipPort , certThumbprint , enableClientCertNegotiation : enableClientCertNegotiation ) ;
5180
52- string command = $ "http add sslcert ipport= { ipPort } certstorename=MY certhash= { certThumbprint } appid={{{appId}}} clientcertnegotiation=enable" ;
53- ExecuteNetShCommand ( command ) ;
81+ Console . WriteLine ( "Configured binding for testCert for http.sys" ) ;
82+ }
5483
55- Console . WriteLine ( "Configured http.sys settings for mTLS" ) ;
84+ public static bool TrySelfSignCertificate ( string ipPort , out string certThumbprint )
85+ {
86+ certThumbprint = string . Empty ;
87+ try
88+ {
89+ // Extract the IP address from ipPort
90+ string ipAddress = ipPort . Split ( ':' ) [ 0 ] ;
91+
92+ // Generate a self-signed certificate using PowerShell
93+ string command = $ "New-SelfSignedCertificate -CertStoreLocation cert:\\ LocalMachine\\ My -DnsName { ipAddress } ";
94+ string output = ExecutePowershellCommand ( command ) ;
95+
96+ // Extract the thumbprint from the output
97+ var lines = output . Split ( "\r \n " , StringSplitOptions . RemoveEmptyEntries ) ;
98+ var lastLine = lines [ ^ 1 ] ;
99+ certThumbprint = lastLine . Split ( " " , StringSplitOptions . RemoveEmptyEntries ) [ 0 ] ;
100+
101+ Console . WriteLine ( $ "Self-signed certificate for { ipAddress } ") ;
102+ return true ;
103+ }
104+ catch ( Exception ex )
105+ {
106+ Console . WriteLine ( "Failed to self-sign the certificate: " + ex . Message ) ;
107+ return false ;
108+ }
109+ }
110+
111+ public static void SetCertBinding ( string ipPort , string certThumbprint , string appId = null , bool enableClientCertNegotiation = false )
112+ {
113+ var negotiateClientCert = enableClientCertNegotiation ? "enable" : "disable" ;
114+ if ( string . IsNullOrEmpty ( appId ) )
115+ {
116+ appId = "00000000-0000-0000-0000-000000000000" ;
117+ }
118+ string command = $ "http add sslcert ipport={ ipPort } certstorename=MY certhash={ certThumbprint } appid={{{appId}}} clientcertnegotiation={ negotiateClientCert } ";
119+ ExecuteNetShCommand ( command ) ;
120+ Console . WriteLine ( $ "Performed cert bindign for { ipPort } ") ;
56121 }
57122
58- private static void ExecuteNetShCommand ( string command , bool alwaysLogOutput = false )
123+ private static string ExecutePowershellCommand ( string command , bool alwaysLogOutput = false )
124+ => ExecuteCommand ( "powershell.exe" , command , alwaysLogOutput ) ;
125+
126+ private static string ExecuteNetShCommand ( string command , bool alwaysLogOutput = false )
127+ => ExecuteCommand ( "netsh" , command , alwaysLogOutput ) ;
128+
129+ private static string ExecuteCommand ( string fileName , string command , bool alwaysLogOutput = false )
59130 {
60- ProcessStartInfo processInfo = new ProcessStartInfo ( "netsh" , command )
131+ ProcessStartInfo processInfo = new ProcessStartInfo ( fileName , command )
61132 {
62133 RedirectStandardOutput = true ,
63134 RedirectStandardError = true ,
64135 UseShellExecute = false ,
65136 CreateNoWindow = true
66137 } ;
67138
68- Console . WriteLine ( $ "Executing command: `netsh { command } `") ;
139+ Console . WriteLine ( $ "Executing command: `{ fileName } { command } `") ;
69140 using Process process = Process . Start ( processInfo ) ! ;
70141 string output = process . StandardOutput . ReadToEnd ( ) ;
71142 process . WaitForExit ( ) ;
@@ -77,8 +148,10 @@ private static void ExecuteNetShCommand(string command, bool alwaysLogOutput = f
77148
78149 if ( process . ExitCode != 0 )
79150 {
80- throw new InvalidOperationException ( $ "netsh command execution failure: { output } ") ;
151+ throw new InvalidOperationException ( $ "{ fileName } command execution failure: { output } ") ;
81152 }
153+
154+ return output ;
82155 }
83156
84157 private static X509Certificate2 LoadCertificate ( )
0 commit comments