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,36 @@ 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 void SetCertBinding ( string ipPort , string certThumbprint , string appId = null , bool enableClientCertNegotiation = false )
85+ {
86+ var negotiateClientCert = enableClientCertNegotiation ? "enable" : "disable" ;
87+ if ( string . IsNullOrEmpty ( appId ) )
88+ {
89+ appId = "00000000-0000-0000-0000-000000000000" ;
90+ }
91+ string command = $ "http add sslcert ipport={ ipPort } certstorename=MY certhash={ certThumbprint } appid={{{appId}}} clientcertnegotiation={ negotiateClientCert } ";
92+ ExecuteNetShCommand ( command ) ;
5693 }
5794
58- private static void ExecuteNetShCommand ( string command , bool alwaysLogOutput = false )
95+ private static string ExecuteNetShCommand ( string command , bool alwaysLogOutput = false )
96+ => ExecuteCommand ( "netsh" , command , alwaysLogOutput ) ;
97+
98+ private static string ExecuteCommand ( string fileName , string command , bool alwaysLogOutput = false )
5999 {
60- ProcessStartInfo processInfo = new ProcessStartInfo ( "netsh" , command )
100+ ProcessStartInfo processInfo = new ProcessStartInfo ( fileName , command )
61101 {
62102 RedirectStandardOutput = true ,
63103 RedirectStandardError = true ,
64104 UseShellExecute = false ,
65105 CreateNoWindow = true
66106 } ;
67107
68- Console . WriteLine ( $ "Executing command: `netsh { command } `") ;
108+ Console . WriteLine ( $ "Executing command: `{ fileName } { command } `") ;
69109 using Process process = Process . Start ( processInfo ) ! ;
70110 string output = process . StandardOutput . ReadToEnd ( ) ;
71111 process . WaitForExit ( ) ;
@@ -77,8 +117,10 @@ private static void ExecuteNetShCommand(string command, bool alwaysLogOutput = f
77117
78118 if ( process . ExitCode != 0 )
79119 {
80- throw new InvalidOperationException ( $ "netsh command execution failure: { output } ") ;
120+ throw new InvalidOperationException ( $ "{ fileName } command execution failure: { output } ") ;
81121 }
122+
123+ return output ;
82124 }
83125
84126 private static X509Certificate2 LoadCertificate ( )
0 commit comments