Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commitf7d098a

Browse files
committed
Expose certificate selection in MQTTnet options
1 parentfe9c239 commitf7d098a

File tree

6 files changed

+120
-31
lines changed

6 files changed

+120
-31
lines changed
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
// Licensed to the .NET Foundation under one or more agreements.
2+
// The .NET Foundation licenses this file to you under the MIT license.
3+
// See the LICENSE file in the project root for more information.
4+
5+
usingSystem;
6+
usingSystem.Security.Cryptography.X509Certificates;
7+
8+
namespaceMQTTnet.Client
9+
{
10+
publicsealedclassMqttClientCertificateSelectionEventArgs:EventArgs
11+
{
12+
publicMqttClientCertificateSelectionEventArgs(
13+
stringtargetHost,
14+
X509CertificateCollectionlocalCertificates,
15+
X509CertificateremoteCertificate,
16+
string[]acceptableIssuers,
17+
MqttClientTcpOptionstcpOptions)
18+
{
19+
TargetHost=targetHost;
20+
LocalCertificates=localCertificates;
21+
RemoveCertificate=remoteCertificate;
22+
AcceptableIssuers=acceptableIssuers;
23+
TcpOptions=tcpOptions??thrownewArgumentNullException(nameof(tcpOptions));
24+
}
25+
26+
publicstring[]AcceptableIssuers{get;}
27+
28+
publicX509CertificateCollectionLocalCertificates{get;}
29+
30+
publicX509CertificateRemoveCertificate{get;}
31+
32+
publicstringTargetHost{get;}
33+
34+
publicMqttClientTcpOptionsTcpOptions{get;}
35+
}
36+
}

‎Source/MQTTnet/Client/Options/MqttClientCertificateValidationEventArgs.cs‎

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,18 +10,27 @@ namespace MQTTnet.Client
1010
{
1111
publicsealedclassMqttClientCertificateValidationEventArgs:EventArgs
1212
{
13-
publicX509CertificateCertificate{get;set;}
13+
publicMqttClientCertificateValidationEventArgs(X509Certificatecertificate,X509Chainchain,SslPolicyErrorssslPolicyErrors,IMqttClientChannelOptionsclientOptions)
14+
{
15+
Certificate=certificate;
16+
Chain=chain;
17+
ClientOptions=clientOptions;
18+
SslPolicyErrors=sslPolicyErrors;
19+
}
1420

15-
publicX509ChainChain{get;set;}
21+
publicX509CertificateCertificate{get;}
22+
23+
publicX509ChainChain{get;}
24+
25+
publicIMqttClientChannelOptionsClientOptions{get;}
1626

17-
publicIMqttClientChannelOptionsClientOptions{get;set;}
1827
#ifNET452||NET461||NET48
1928
/// <summary>
2029
/// Can be a host string name or an object derived from WebRequest.
2130
/// </summary>
2231
publicobjectSender{get;set;}
2332
#endif
2433

25-
publicSslPolicyErrorsSslPolicyErrors{get;set;}
34+
publicSslPolicyErrorsSslPolicyErrors{get;}
2635
}
2736
}

‎Source/MQTTnet/Client/Options/MqttClientTlsOptions.cs‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@ public sealed class MqttClientTlsOptions
1414
{
1515
publicFunc<MqttClientCertificateValidationEventArgs,bool>CertificateValidationHandler{get;set;}
1616

17+
publicFunc<MqttClientCertificateSelectionEventArgs,X509Certificate>CertificateSelectionHandler{get;set;}
18+
1719
publicboolUseTls{get;set;}
1820

1921
publicboolIgnoreCertificateRevocationErrors{get;set;}

‎Source/MQTTnet/Client/Options/MqttClientTlsOptionsBuilder.cs‎

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,17 @@ public MqttClientTlsOptionsBuilder WithCertificateValidationHandler(Func<MqttCli
4949
returnthis;
5050
}
5151

52+
publicMqttClientTlsOptionsBuilderWithCertificateSelectionHandler(Func<MqttClientCertificateSelectionEventArgs,X509Certificate>certificateSelectionHandler)
53+
{
54+
if(certificateSelectionHandler==null)
55+
{
56+
thrownewArgumentNullException(nameof(certificateSelectionHandler));
57+
}
58+
59+
_tlsOptions.CertificateSelectionHandler=certificateSelectionHandler;
60+
returnthis;
61+
}
62+
5263
publicMqttClientTlsOptionsBuilderWithClientCertificates(IEnumerable<X509Certificate2>certificates)
5364
{
5465
if(certificates==null)

‎Source/MQTTnet/Implementations/MqttTcpChannel.cs‎

Lines changed: 45 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -106,10 +106,29 @@ public async Task ConnectAsync(CancellationToken cancellationToken)
106106
{
107107
if(_tcpOptions.RemoteEndpointisDnsEndPointdns)
108108
{
109-
targetHost=dns.Host;
109+
targetHost=dns.Host;
110110
}
111111
}
112-
varsslStream=newSslStream(networkStream,false,InternalUserCertificateValidationCallback);
112+
113+
SslStreamsslStream;
114+
if(_tcpOptions.TlsOptions.CertificateSelectionHandler!=null)
115+
{
116+
sslStream=newSslStream(
117+
networkStream,
118+
false,
119+
InternalUserCertificateValidationCallback,
120+
InternalUserCertificateSelectionCallback);
121+
}
122+
else
123+
{
124+
// Use a different constructor depending on the options for MQTTnet so that we do not have
125+
// to copy the exact same behavior of the selection handler.
126+
sslStream=newSslStream(
127+
networkStream,
128+
false,
129+
InternalUserCertificateValidationCallback);
130+
}
131+
113132
try
114133
{
115134
#ifNETCOREAPP3_1_OR_GREATER
@@ -134,9 +153,7 @@ public async Task ConnectAsync(CancellationToken cancellationToken)
134153
{
135154
TrustMode=X509ChainTrustMode.CustomRootTrust,
136155
VerificationFlags=X509VerificationFlags.IgnoreEndRevocationUnknown,
137-
RevocationMode=_tcpOptions.TlsOptions.IgnoreCertificateRevocationErrors
138-
?X509RevocationMode.NoCheck
139-
:_tcpOptions.TlsOptions.RevocationMode
156+
RevocationMode=_tcpOptions.TlsOptions.IgnoreCertificateRevocationErrors?X509RevocationMode.NoCheck:_tcpOptions.TlsOptions.RevocationMode
140157
};
141158

142159
sslOptions.CertificateChainPolicy.CustomTrustStore.AddRange(_tcpOptions.TlsOptions.TrustChain);
@@ -292,19 +309,34 @@ public async Task WriteAsync(ArraySegment<byte> buffer, bool isEndOfPacket, Canc
292309
}
293310
}
294311

312+
X509CertificateInternalUserCertificateSelectionCallback(
313+
objectsender,
314+
stringtargetHost,
315+
X509CertificateCollectionlocalCertificates,
316+
X509CertificateremoteCertificate,
317+
string[]acceptableIssuers)
318+
{
319+
varcertificateSelectionHandler=_tcpOptions?.TlsOptions?.CertificateSelectionHandler;
320+
if(certificateSelectionHandler!=null)
321+
{
322+
vareventArgs=newMqttClientCertificateSelectionEventArgs(targetHost,localCertificates,remoteCertificate,acceptableIssuers,_tcpOptions);
323+
returncertificateSelectionHandler(eventArgs);
324+
}
325+
326+
if(localCertificates?.Count>0)
327+
{
328+
returnlocalCertificates[0];
329+
}
330+
331+
returnnull;
332+
}
333+
295334
boolInternalUserCertificateValidationCallback(objectsender,X509Certificatex509Certificate,X509Chainchain,SslPolicyErrorssslPolicyErrors)
296335
{
297336
varcertificateValidationHandler=_tcpOptions?.TlsOptions?.CertificateValidationHandler;
298337
if(certificateValidationHandler!=null)
299338
{
300-
vareventArgs=newMqttClientCertificateValidationEventArgs
301-
{
302-
Certificate=x509Certificate,
303-
Chain=chain,
304-
SslPolicyErrors=sslPolicyErrors,
305-
ClientOptions=_tcpOptions
306-
};
307-
339+
vareventArgs=newMqttClientCertificateValidationEventArgs(x509Certificate,chain,sslPolicyErrors,_tcpOptions);
308340
returncertificateValidationHandler(eventArgs);
309341
}
310342

‎Source/MQTTnet/Implementations/MqttWebSocketChannel.cs‎

Lines changed: 13 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -109,7 +109,7 @@ public async Task WriteAsync(ArraySegment<byte> buffer, bool isEndOfPacket, Canc
109109
// A single WebSocket data frame can contain multiple or partial MQTT Control Packets. The receiver MUST NOT assume that MQTT Control Packets are aligned on WebSocket frame boundaries [MQTT-6.0.0-2].
110110
await_webSocket.SendAsync(buffer,WebSocketMessageType.Binary,isEndOfPacket,cancellationToken).ConfigureAwait(false);
111111
#else
112-
// The lock is required because the client will throw an exception if _SendAsync_ is
112+
// The lock is required because the client will throw an exception if _SendAsync_ is
113113
// called from multiple threads at the same time. But this issue only happens with several
114114
// framework versions.
115115
if(_sendLock==null)
@@ -156,17 +156,17 @@ IWebProxy CreateProxy()
156156
#else
157157
varproxyUri=newUri(_options.ProxyOptions.Address);
158158
WebProxywebProxy;
159-
159+
160160
if(!string.IsNullOrEmpty(_options.ProxyOptions.Username)&&!string.IsNullOrEmpty(_options.ProxyOptions.Password))
161161
{
162162
varcredentials=newNetworkCredential(_options.ProxyOptions.Username,_options.ProxyOptions.Password,_options.ProxyOptions.Domain);
163163
webProxy=newWebProxy(proxyUri,_options.ProxyOptions.BypassOnLocal,_options.ProxyOptions.BypassList,credentials);
164164
}
165165
else
166166
{
167-
webProxy=newWebProxy(proxyUri,_options.ProxyOptions.BypassOnLocal,_options.ProxyOptions.BypassList);
167+
webProxy=newWebProxy(proxyUri,_options.ProxyOptions.BypassOnLocal,_options.ProxyOptions.BypassList);
168168
}
169-
169+
170170
if(_options.ProxyOptions.UseDefaultCredentials)
171171
{
172172
// Only update the property if required because setting it to false will alter
@@ -234,7 +234,7 @@ void SetupClientWebSocket(ClientWebSocket clientWebSocket)
234234
{
235235
clientWebSocket.Options.Credentials=_options.Credentials;
236236
}
237-
237+
238238
varcertificateValidationHandler=_options.TlsOptions?.CertificateValidationHandler;
239239
if(certificateValidationHandler!=null)
240240
{
@@ -245,7 +245,7 @@ void SetupClientWebSocket(ClientWebSocket clientWebSocket)
245245
#elifWINDOWS_UWP
246246
thrownewNotSupportedException("Remote certificate validation callback is not supported when using 'uap10.0'.");
247247
#elifNET452||NET461||NET48
248-
ServicePointManager.ServerCertificateValidationCallback+=(sender,certificate,chain,sslPolicyErrors)=>
248+
ServicePointManager.ServerCertificateValidationCallback+=(sender,certificate,chain,sslPolicyErrors)=>
249249
{
250250
varcontext=newMqttClientCertificateValidationEventArgs
251251
{
@@ -262,17 +262,16 @@ void SetupClientWebSocket(ClientWebSocket clientWebSocket)
262262
clientWebSocket.Options.RemoteCertificateValidationCallback=(sender,certificate,chain,sslPolicyErrors)=>
263263
{
264264
// TODO: Find a way to add client options to same callback. Problem is that they have a different type.
265-
varcontext=newMqttClientCertificateValidationEventArgs
266-
{
267-
Certificate=certificate,
268-
Chain=chain,
269-
SslPolicyErrors=sslPolicyErrors,
270-
ClientOptions=_options
271-
};
272-
265+
varcontext=newMqttClientCertificateValidationEventArgs(certificate,chain,sslPolicyErrors,_options);
273266
returncertificateValidationHandler(context);
274267
};
275268
#endif
269+
270+
varcertificateSelectionHandler=_options.TlsOptions?.CertificateSelectionHandler;
271+
if(certificateSelectionHandler!=null)
272+
{
273+
thrownewNotSupportedException("Remote certificate selection callback is not supported for WebSocket connections.");
274+
}
276275
}
277276
}
278277
}

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp