1
1
using System . Diagnostics ;
2
2
using System . Security . Cryptography . X509Certificates ;
3
+ using System . Text . RegularExpressions ;
3
4
4
5
namespace HttpSys
5
6
{
6
7
public static class NetShWrapper
7
8
{
8
- public static void DisableHttpSysMutualTlsIfExists ( string ipPort )
9
+ public static void DeleteBindingIfExists ( string ipPort )
9
10
{
10
11
try
11
12
{
12
- DisableHttpSysMutualTls ( ipPort ) ;
13
+ DeleteBinding ( ipPort ) ;
13
14
}
14
15
catch
15
16
{
16
17
// ignore
17
18
}
18
19
}
19
20
20
- public static void DisableHttpSysMutualTls ( string ipPort )
21
+ public static void DeleteBinding ( string ipPort )
21
22
{
22
23
Console . WriteLine ( "Disabling mTLS for http.sys" ) ;
23
24
@@ -27,14 +28,42 @@ public static void DisableHttpSysMutualTls(string ipPort)
27
28
Console . WriteLine ( "Disabled http.sys settings for mTLS" ) ;
28
29
}
29
30
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
+
30
59
public static void Show ( )
31
60
{
32
61
ExecuteNetShCommand ( "http show sslcert" , alwaysLogOutput : true ) ;
33
62
}
34
63
35
- public static void EnableHttpSysMutualTls ( string ipPort )
64
+ public static void SetTestCertBinding ( string ipPort , bool enableClientCertNegotiation )
36
65
{
37
- Console . WriteLine ( "Setting up mTLS for http.sys" ) ;
66
+ Console . WriteLine ( "Setting up binding for testCert for http.sys" ) ;
38
67
39
68
var certificate = LoadCertificate ( ) ;
40
69
Console . WriteLine ( "Loaded `testCert.pfx` from local file system" ) ;
@@ -47,25 +76,36 @@ public static void EnableHttpSysMutualTls(string ipPort)
47
76
}
48
77
49
78
string certThumbprint = certificate . Thumbprint ;
50
- string appId = Guid . NewGuid ( ) . ToString ( ) ;
79
+ SetCertBinding ( ipPort , certThumbprint , enableClientCertNegotiation : enableClientCertNegotiation ) ;
51
80
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
+ }
54
83
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 ) ;
56
93
}
57
94
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 )
59
99
{
60
- ProcessStartInfo processInfo = new ProcessStartInfo ( "netsh" , command )
100
+ ProcessStartInfo processInfo = new ProcessStartInfo ( fileName , command )
61
101
{
62
102
RedirectStandardOutput = true ,
63
103
RedirectStandardError = true ,
64
104
UseShellExecute = false ,
65
105
CreateNoWindow = true
66
106
} ;
67
107
68
- Console . WriteLine ( $ "Executing command: `netsh { command } `") ;
108
+ Console . WriteLine ( $ "Executing command: `{ fileName } { command } `") ;
69
109
using Process process = Process . Start ( processInfo ) ! ;
70
110
string output = process . StandardOutput . ReadToEnd ( ) ;
71
111
process . WaitForExit ( ) ;
@@ -77,8 +117,10 @@ private static void ExecuteNetShCommand(string command, bool alwaysLogOutput = f
77
117
78
118
if ( process . ExitCode != 0 )
79
119
{
80
- throw new InvalidOperationException ( $ "netsh command execution failure: { output } ") ;
120
+ throw new InvalidOperationException ( $ "{ fileName } command execution failure: { output } ") ;
81
121
}
122
+
123
+ return output ;
82
124
}
83
125
84
126
private static X509Certificate2 LoadCertificate ( )
0 commit comments