5
5
6
6
namespace HttpSys
7
7
{
8
- public static class NetShWrapper
8
+ public class NetShWrapper
9
9
{
10
- public static void DeleteBindingIfExists ( string ipPort )
10
+ public bool SupportsDisableSessionId { get ; }
11
+ public bool SupportsEnableSessionTicket { get ; }
12
+
13
+ public NetShWrapper ( )
14
+ {
15
+ var sslCertCapabilitiesText = ExecuteNetShCommand ( $ "http add sslcert help") ;
16
+ if ( string . IsNullOrEmpty ( sslCertCapabilitiesText ) )
17
+ {
18
+ throw new InvalidOperationException ( "Failed to determine http.sys capabilities" ) ;
19
+ }
20
+
21
+ if ( sslCertCapabilitiesText . Contains ( "disablesessionid" ) )
22
+ {
23
+ SupportsDisableSessionId = true ;
24
+ }
25
+
26
+ if ( sslCertCapabilitiesText . Contains ( "enablesessionticket" ) )
27
+ {
28
+ SupportsEnableSessionTicket = true ;
29
+ }
30
+
31
+ Console . WriteLine ( $ """
32
+ Http.SYS Capabilities:
33
+ - SupportsDisableSessionId: { SupportsDisableSessionId } (if not supported, renegotiation will most likely be enabled by default)
34
+ - SupportsEnableSessionTicket: { SupportsEnableSessionTicket }
35
+ """ ) ;
36
+ }
37
+
38
+ public void DeleteBindingIfExists ( string ipPort )
11
39
{
12
40
try
13
41
{
@@ -19,7 +47,7 @@ public static void DeleteBindingIfExists(string ipPort)
19
47
}
20
48
}
21
49
22
- public static void DeleteBinding ( string ipPort )
50
+ public void DeleteBinding ( string ipPort )
23
51
{
24
52
Console . WriteLine ( "Disabling mTLS for http.sys" ) ;
25
53
@@ -29,9 +57,7 @@ public static void DeleteBinding(string ipPort)
29
57
Console . WriteLine ( "Disabled http.sys settings for mTLS" ) ;
30
58
}
31
59
32
-
33
-
34
- public static bool TryGetSslCertBinding ( string ipPort , out SslCertBinding result )
60
+ public bool TryGetSslCertBinding ( string ipPort , out SslCertBinding result )
35
61
{
36
62
result = new SslCertBinding ( ) ;
37
63
@@ -71,7 +97,7 @@ public static bool TryGetSslCertBinding(string ipPort, out SslCertBinding result
71
97
Max Settings Per Frame : 2796202
72
98
Max Settings Per Minute : 4294967295
73
99
*/
74
- var bindings = ExecuteNetShCommand ( $ "http show sslcert ipport={ ipPort } ") ;
100
+ var bindings = ExecuteNetShCommand ( $ "http show sslcert ipport={ ipPort } ", ignoreErrorExit : true ) ;
75
101
if ( string . IsNullOrEmpty ( bindings ) || ! bindings . Contains ( ipPort ) )
76
102
{
77
103
return false ;
@@ -123,12 +149,12 @@ public static bool TryGetSslCertBinding(string ipPort, out SslCertBinding result
123
149
} ;
124
150
}
125
151
126
- public static void LogSslCertBinding ( string ipPort )
152
+ public void LogSslCertBinding ( string ipPort )
127
153
{
128
154
ExecuteNetShCommand ( $ "http show sslcert ipport={ ipPort } ", alwaysLogOutput : true ) ;
129
155
}
130
156
131
- public static void SetTestCertBinding ( string ipPort , bool enableClientCertNegotiation )
157
+ public void SetTestCertBinding ( string ipPort , bool enableClientCertNegotiation )
132
158
{
133
159
Console . WriteLine ( "Setting up binding for testCert for http.sys" ) ;
134
160
@@ -148,7 +174,7 @@ public static void SetTestCertBinding(string ipPort, bool enableClientCertNegoti
148
174
Console . WriteLine ( "Configured binding for testCert for http.sys" ) ;
149
175
}
150
176
151
- public static bool TrySelfSignCertificate ( string ipPort , out string certThumbprint )
177
+ public bool TrySelfSignCertificate ( string ipPort , out string certThumbprint )
152
178
{
153
179
certThumbprint = string . Empty ;
154
180
try
@@ -175,31 +201,31 @@ public static bool TrySelfSignCertificate(string ipPort, out string certThumbpri
175
201
}
176
202
}
177
203
178
- public static void AddCertBinding (
204
+ public void AddCertBinding (
179
205
string ipPort , string certThumbprint ,
180
206
string ? appId = null ,
181
207
NetShFlag clientCertNegotiation = NetShFlag . Disabled ,
182
208
NetShFlag disablesessionid = NetShFlag . Enable ,
183
209
NetShFlag enablesessionticket = NetShFlag . Disabled )
184
210
=> CertBindingCore ( "add" , ipPort , certThumbprint , appId , clientCertNegotiation , disablesessionid , enablesessionticket ) ;
185
211
186
- public static void UpdateCertBinding ( string ipPort , SslCertBinding binding ) => UpdateCertBinding (
212
+ public void UpdateCertBinding ( string ipPort , SslCertBinding binding ) => UpdateCertBinding (
187
213
ipPort ,
188
214
binding . CertificateThumbprint ,
189
215
binding . ApplicationId ,
190
216
binding . NegotiateClientCertificate ,
191
217
binding . DisableSessionIdTlsResumption ,
192
218
binding . EnableSessionTicketTlsResumption ) ;
193
219
194
- public static void UpdateCertBinding (
220
+ public void UpdateCertBinding (
195
221
string ipPort , string certThumbprint ,
196
222
string ? appId = null ,
197
223
NetShFlag clientCertNegotiation = NetShFlag . Disabled ,
198
224
NetShFlag disablesessionid = NetShFlag . Enable ,
199
225
NetShFlag enablesessionticket = NetShFlag . Disabled )
200
226
=> CertBindingCore ( "update" , ipPort , certThumbprint , appId , clientCertNegotiation , disablesessionid , enablesessionticket ) ;
201
227
202
- private static void CertBindingCore (
228
+ private void CertBindingCore (
203
229
string httpOperation ,
204
230
string ipPort , string certThumbprint ,
205
231
string ? appId = null ,
@@ -224,17 +250,15 @@ private static void CertBindingCore(
224
250
225
251
// below options are supported only in later versions of HTTP.SYS
226
252
// you can identify if it is available by running `netsh http add sslcert help`
227
- // ---
228
- // workaround is to control SChannel settings via registry
229
-
230
- //if (disablesessionidFlag != null)
231
- //{
232
- // command += $" disablesessionid={disablesessionidFlag}";
233
- //}
234
- //if (enablesessionticketFlag != null)
235
- //{
236
- // command += $" enablesessionticket={enablesessionticketFlag}";
237
- //}
253
+
254
+ if ( SupportsDisableSessionId && disablesessionidFlag != null )
255
+ {
256
+ command += $ " disablesessionid={ disablesessionidFlag } ";
257
+ }
258
+ if ( SupportsEnableSessionTicket && enablesessionticketFlag != null )
259
+ {
260
+ command += $ " enablesessionticket={ enablesessionticketFlag } ";
261
+ }
238
262
239
263
ExecuteNetShCommand ( command , alwaysLogOutput : true ) ;
240
264
Console . WriteLine ( $ "Performed cert binding for { ipPort } ") ;
@@ -248,13 +272,13 @@ private static void CertBindingCore(
248
272
} ;
249
273
}
250
274
251
- private static string ExecutePowershellCommand ( string command , bool alwaysLogOutput = false )
252
- => ExecuteCommand ( "powershell.exe" , command , alwaysLogOutput ) ;
275
+ private static string ExecutePowershellCommand ( string command , bool ignoreErrorExit = false , bool alwaysLogOutput = false )
276
+ => ExecuteCommand ( "powershell.exe" , command , ignoreErrorExit , alwaysLogOutput ) ;
253
277
254
- private static string ExecuteNetShCommand ( string command , bool alwaysLogOutput = false )
255
- => ExecuteCommand ( "netsh" , command , alwaysLogOutput ) ;
278
+ private static string ExecuteNetShCommand ( string command , bool ignoreErrorExit = false , bool alwaysLogOutput = false )
279
+ => ExecuteCommand ( "netsh" , command , ignoreErrorExit , alwaysLogOutput ) ;
256
280
257
- private static string ExecuteCommand ( string fileName , string command , bool logOutput = false )
281
+ private static string ExecuteCommand ( string fileName , string command , bool ignoreErrorExit = false , bool logOutput = false )
258
282
{
259
283
ProcessStartInfo processInfo = new ProcessStartInfo ( fileName , command )
260
284
{
@@ -274,7 +298,7 @@ private static string ExecuteCommand(string fileName, string command, bool logOu
274
298
Console . WriteLine ( output ) ;
275
299
}
276
300
277
- if ( process . ExitCode != 0 )
301
+ if ( ! ignoreErrorExit && process . ExitCode != 0 )
278
302
{
279
303
throw new InvalidOperationException ( $ "{ fileName } command execution failure: { output } ") ;
280
304
}
0 commit comments