Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
dotNET Platform
runtime
提交
c3df339c
R
runtime
项目概览
dotNET Platform
/
runtime
12 个月 前同步成功
通知
1
Star
1
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
DevOps
流水线
流水线任务
计划
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
R
runtime
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
DevOps
DevOps
流水线
流水线任务
计划
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
流水线任务
提交
Issue看板
体验新版 GitCode,发现更多精彩内容 >>
未验证
提交
c3df339c
编写于
3月 10, 2023
作者:
T
Tomas Weinfurt
提交者:
GitHub
3月 10, 2023
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
Support sites with invalid IDN in SslStream (#82934)
* initial test * 'update' * feedback from review * android
上级
86175a9e
变更
4
隐藏空白更改
内联
并排
Showing
4 changed file
with
134 addition
and
39 deletion
+134
-39
src/libraries/Common/src/Interop/Unix/System.Security.Cryptography.Native/Interop.OpenSsl.cs
...ix/System.Security.Cryptography.Native/Interop.OpenSsl.cs
+25
-24
src/libraries/Common/src/Interop/Windows/SspiCli/SecuritySafeHandles.cs
...Common/src/Interop/Windows/SspiCli/SecuritySafeHandles.cs
+3
-13
src/libraries/System.Net.Security/src/System/Net/Security/SslAuthenticationOptions.cs
...urity/src/System/Net/Security/SslAuthenticationOptions.cs
+24
-2
src/libraries/System.Net.Security/tests/FunctionalTests/SslStreamSniTest.cs
...em.Net.Security/tests/FunctionalTests/SslStreamSniTest.cs
+82
-0
未找到文件。
src/libraries/Common/src/Interop/Unix/System.Security.Cryptography.Native/Interop.OpenSsl.cs
浏览文件 @
c3df339c
...
...
@@ -5,7 +5,6 @@
using
System.Collections.Concurrent
;
using
System.Collections.Generic
;
using
System.Diagnostics
;
using
System.Globalization
;
using
System.IO
;
using
System.Net
;
using
System.Net.Security
;
...
...
@@ -25,7 +24,6 @@ internal static partial class OpenSsl
private
const
string
TlsCacheSizeCtxName
=
"System.Net.Security.TlsCacheSize"
;
private
const
string
TlsCacheSizeEnvironmentVariable
=
"DOTNET_SYSTEM_NET_SECURITY_TLSCACHESIZE"
;
private
const
SslProtocols
FakeAlpnSslProtocol
=
(
SslProtocols
)
1
;
// used to distinguish server sessions with ALPN
private
static
readonly
IdnMapping
s_idnMapping
=
new
IdnMapping
();
private
static
readonly
ConcurrentDictionary
<
SslProtocols
,
SafeSslContextHandle
>
s_clientSslContexts
=
new
ConcurrentDictionary
<
SslProtocols
,
SafeSslContextHandle
>();
#
region
internal
methods
...
...
@@ -385,21 +383,22 @@ internal static SafeSslHandle AllocateSslHandle(SslAuthenticationOptions sslAuth
if
(
sslAuthenticationOptions
.
IsClient
)
{
// The IdnMapping converts unicode input into the IDNA punycode sequence.
string
punyCode
=
string
.
IsNullOrEmpty
(
sslAuthenticationOptions
.
TargetHost
)
?
string
.
Empty
:
s_idnMapping
.
GetAscii
(
sslAuthenticationOptions
.
TargetHost
!);
// Similar to windows behavior, set SNI on openssl by default for client context, ignore errors.
if
(!
Ssl
.
SslSetTlsExtHostName
(
sslHandle
,
punyCode
))
if
(!
string
.
IsNullOrEmpty
(
sslAuthenticationOptions
.
TargetHost
))
{
Crypto
.
ErrClearError
();
}
// Similar to windows behavior, set SNI on openssl by default for client context, ignore errors.
if
(!
Ssl
.
SslSetTlsExtHostName
(
sslHandle
,
sslAuthenticationOptions
.
TargetHost
))
{
Crypto
.
ErrClearError
();
}
if
(
cacheSslContext
&&
!
string
.
IsNullOrEmpty
(
punyCode
))
{
sslCtxHandle
.
TrySetSession
(
sslHandle
,
punyCode
);
bool
ignored
=
false
;
sslCtxHandle
.
DangerousAddRef
(
ref
ignored
);
sslHandle
.
SslContextHandle
=
sslCtxHandle
;
if
(
cacheSslContext
)
{
sslCtxHandle
.
TrySetSession
(
sslHandle
,
sslAuthenticationOptions
.
TargetHost
);
bool
ignored
=
false
;
sslCtxHandle
.
DangerousAddRef
(
ref
ignored
);
sslHandle
.
SslContextHandle
=
sslCtxHandle
;
}
}
// relevant to TLS 1.3 only: if user supplied a client cert or cert callback,
...
...
@@ -745,16 +744,18 @@ private static unsafe int NewSessionCallback(IntPtr ssl, IntPtr session)
Debug
.
Assert
(
session
!=
IntPtr
.
Zero
);
IntPtr
ptr
=
Ssl
.
SslGetData
(
ssl
);
Debug
.
Assert
(
ptr
!=
IntPtr
.
Zero
);
GCHandle
gch
=
GCHandle
.
FromIntPtr
(
ptr
);
SafeSslContextHandle
?
ctxHandle
=
gch
.
Target
as
SafeSslContextHandle
;
// There is no relation between SafeSslContextHandle and SafeSslHandle so the handle
// may be released while the ssl session is still active.
if
(
ctxHandle
!=
null
&&
ctxHandle
.
TryAddSession
(
Ssl
.
SslGetServerName
(
ssl
),
session
))
if
(
ptr
!=
IntPtr
.
Zero
)
{
// offered session was stored in our cache.
return
1
;
GCHandle
gch
=
GCHandle
.
FromIntPtr
(
ptr
);
SafeSslContextHandle
?
ctxHandle
=
gch
.
Target
as
SafeSslContextHandle
;
// There is no relation between SafeSslContextHandle and SafeSslHandle so the handle
// may be released while the ssl session is still active.
if
(
ctxHandle
!=
null
&&
ctxHandle
.
TryAddSession
(
Ssl
.
SslGetServerName
(
ssl
),
session
))
{
// offered session was stored in our cache.
return
1
;
}
}
// OpenSSL will destroy session.
...
...
src/libraries/Common/src/Interop/Windows/SspiCli/SecuritySafeHandles.cs
浏览文件 @
c3df339c
...
...
@@ -2,7 +2,6 @@
// The .NET Foundation licenses this file to you under the MIT license.
using
System.Diagnostics
;
using
System.Globalization
;
using
System.Runtime.InteropServices
;
using
System.Security.Authentication.ExtendedProtection
;
using
System.Security.Cryptography.X509Certificates
;
...
...
@@ -334,9 +333,6 @@ internal abstract partial class SafeDeleteContext : DebugSafeHandle
internal
abstract
partial
class
SafeDeleteContext
:
SafeHandle
{
#endif
private
const
string
dummyStr
=
" "
;
private
static
readonly
IdnMapping
s_idnMapping
=
new
IdnMapping
();
protected
SafeFreeCredentials
?
_EffectiveCredential
;
//-------------------------------------------------------------------
...
...
@@ -453,18 +449,12 @@ internal abstract partial class SafeDeleteContext : SafeHandle
}
}
if
(
targetName
==
null
||
targetName
.
Length
==
0
)
{
targetName
=
dummyStr
;
}
string
punyCode
=
s_idnMapping
.
GetAscii
(
targetName
);
fixed
(
char
*
namePtr
=
punyCode
)
fixed
(
char
*
namePtr
=
targetName
)
{
errorCode
=
MustRunInitializeSecurityContext
(
ref
inCredentials
,
isContextAbsent
,
(
byte
*)
(((
object
)
targetName
==
(
object
)
dummyStr
)
?
null
:
namePtr
)
,
(
byte
*)
namePtr
,
inFlags
,
endianness
,
&
inSecurityBufferDescriptor
,
...
...
@@ -514,7 +504,7 @@ internal abstract partial class SafeDeleteContext : SafeHandle
errorCode
=
MustRunInitializeSecurityContext
(
ref
inCredentials
,
isContextAbsent
,
(
byte
*)
(((
object
)
targetName
==
(
object
)
dummyStr
)
?
null
:
namePtr
)
,
(
byte
*)
namePtr
,
inFlags
,
endianness
,
&
inSecurityBufferDescriptor
,
...
...
src/libraries/System.Net.Security/src/System/Net/Security/SslAuthenticationOptions.cs
浏览文件 @
c3df339c
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
using
System.Buffers
;
using
System.Collections.Generic
;
using
System.Diagnostics
;
using
System.Globalization
;
using
System.Runtime.InteropServices
;
using
System.Security.Authentication
;
using
System.Security.Cryptography.X509Certificates
;
...
...
@@ -11,6 +13,8 @@ namespace System.Net.Security
{
internal
sealed
class
SslAuthenticationOptions
{
private
static
readonly
IdnMapping
s_idnMapping
=
new
IdnMapping
();
// Simplified version of IPAddressParser.Parse to avoid allocations and dependencies.
// It purposely ignores scopeId as we don't really use so we do not need to map it to actual interface id.
private
static
unsafe
bool
IsValidAddress
(
ReadOnlySpan
<
char
>
ipSpan
)
...
...
@@ -46,6 +50,12 @@ private static unsafe bool IsValidAddress(ReadOnlySpan<char> ipSpan)
return
false
;
}
private
static
readonly
IndexOfAnyValues
<
char
>
s_safeDnsChars
=
IndexOfAnyValues
.
Create
(
"-.0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz"
);
private
static
bool
IsSafeDnsString
(
ReadOnlySpan
<
char
>
name
)
=>
name
.
IndexOfAnyExcept
(
s_safeDnsChars
)
<
0
;
internal
SslAuthenticationOptions
()
{
TargetHost
=
string
.
Empty
;
...
...
@@ -86,13 +96,25 @@ internal void UpdateOptions(SslClientAuthenticationOptions sslClientAuthenticati
if
(!
string
.
IsNullOrEmpty
(
sslClientAuthenticationOptions
.
TargetHost
))
{
// RFC 6066 section 3 says to exclude trailing dot from fully qualified DNS hostname
T
argetHost
=
sslClientAuthenticationOptions
.
TargetHost
.
TrimEnd
(
'.'
);
string
t
argetHost
=
sslClientAuthenticationOptions
.
TargetHost
.
TrimEnd
(
'.'
);
// RFC 6066 forbids IP literals
if
(
IsValidAddress
(
T
argetHost
))
if
(
IsValidAddress
(
t
argetHost
))
{
TargetHost
=
string
.
Empty
;
}
else
{
try
{
TargetHost
=
s_idnMapping
.
GetAscii
(
targetHost
);
}
catch
(
ArgumentException
)
when
(
IsSafeDnsString
(
targetHost
))
{
// Seems like name that does not confrom to IDN but apers somewhat valid according to orogional DNS rfc.
TargetHost
=
targetHost
;
}
}
}
// Client specific options.
...
...
src/libraries/System.Net.Security/tests/FunctionalTests/SslStreamSniTest.cs
浏览文件 @
c3df339c
...
...
@@ -202,6 +202,88 @@ public async Task SslStream_IpLiteral_NotSend(string target)
Assert
.
Equal
(
string
.
Empty
,
server
.
TargetHostName
);
}
[
Theory
]
[
InlineData
(
"\u00E1b\u00E7d\u00EB.com"
)]
[
InlineData
(
"\u05D1\u05F1.com"
)]
[
InlineData
(
"\u30B6\u30C7\u30D8.com"
)]
public
async
Task
SslStream_ValidIdn_Success
(
string
name
)
{
(
SslStream
client
,
SslStream
server
)
=
TestHelper
.
GetConnectedSslStreams
();
using
(
client
)
using
(
server
)
{
using
X509Certificate2
serverCertificate
=
Configuration
.
Certificates
.
GetServerCertificate
();
using
X509Certificate2
clientCertificate
=
Configuration
.
Certificates
.
GetClientCertificate
();
SslServerAuthenticationOptions
serverOptions
=
new
SslServerAuthenticationOptions
()
{
ServerCertificate
=
serverCertificate
};
SslClientAuthenticationOptions
clientOptions
=
new
SslClientAuthenticationOptions
()
{
TargetHost
=
name
,
CertificateChainPolicy
=
new
X509ChainPolicy
()
{
VerificationFlags
=
X509VerificationFlags
.
IgnoreInvalidName
},
RemoteCertificateValidationCallback
=
(
sender
,
certificate
,
chain
,
sslPolicyErrors
)
=>
true
};
await
TestConfiguration
.
WhenAllOrAnyFailedWithTimeout
(
client
.
AuthenticateAsClientAsync
(
clientOptions
,
default
),
server
.
AuthenticateAsServerAsync
(
serverOptions
,
default
));
await
TestHelper
.
PingPong
(
client
,
server
,
default
);
Assert
.
Equal
(
name
,
server
.
TargetHostName
);
}
}
[
Theory
]
[
InlineData
(
"www-.volal.cz"
)]
[
InlineData
(
"www-.colorhexa.com"
)]
[
InlineData
(
"xn--www-7m0a.thegratuit.com"
)]
[
ActiveIssue
(
"https://github.com/dotnet/runtime/issues/68206"
,
TestPlatforms
.
Android
)]
public
async
Task
SslStream_SafeInvalidIdn_Success
(
string
name
)
{
(
SslStream
client
,
SslStream
server
)
=
TestHelper
.
GetConnectedSslStreams
();
using
(
client
)
using
(
server
)
{
using
X509Certificate2
serverCertificate
=
Configuration
.
Certificates
.
GetServerCertificate
();
using
X509Certificate2
clientCertificate
=
Configuration
.
Certificates
.
GetClientCertificate
();
SslServerAuthenticationOptions
serverOptions
=
new
SslServerAuthenticationOptions
()
{
ServerCertificate
=
serverCertificate
};
SslClientAuthenticationOptions
clientOptions
=
new
SslClientAuthenticationOptions
()
{
TargetHost
=
name
,
CertificateChainPolicy
=
new
X509ChainPolicy
()
{
VerificationFlags
=
X509VerificationFlags
.
IgnoreInvalidName
},
RemoteCertificateValidationCallback
=
(
sender
,
certificate
,
chain
,
sslPolicyErrors
)
=>
true
};
await
TestConfiguration
.
WhenAllOrAnyFailedWithTimeout
(
client
.
AuthenticateAsClientAsync
(
clientOptions
,
default
),
server
.
AuthenticateAsServerAsync
(
serverOptions
,
default
));
await
TestHelper
.
PingPong
(
client
,
server
,
default
);
Assert
.
Equal
(
name
,
server
.
TargetHostName
);
}
}
[
Theory
]
[
InlineData
(
"\u0000\u00E7d\u00EB.com"
)]
public
async
Task
SslStream_UnsafeInvalidIdn_Throws
(
string
name
)
{
(
SslStream
client
,
SslStream
server
)
=
TestHelper
.
GetConnectedSslStreams
();
using
(
client
)
using
(
server
)
{
using
X509Certificate2
serverCertificate
=
Configuration
.
Certificates
.
GetServerCertificate
();
SslClientAuthenticationOptions
clientOptions
=
new
SslClientAuthenticationOptions
()
{
TargetHost
=
name
,
CertificateChainPolicy
=
new
X509ChainPolicy
()
{
VerificationFlags
=
X509VerificationFlags
.
IgnoreInvalidName
},
RemoteCertificateValidationCallback
=
(
sender
,
certificate
,
chain
,
sslPolicyErrors
)
=>
true
};
await
Assert
.
ThrowsAsync
<
ArgumentException
>(()
=>
client
.
AuthenticateAsClientAsync
(
clientOptions
,
default
));
}
}
private
static
Func
<
Task
>
WithAggregateExceptionUnwrapping
(
Func
<
Task
>
a
)
{
return
async
()
=>
{
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录