Skip to content

Commit 110b5f2

Browse files
[Android] Resolve Android-specific active issues in System.Net.Security and System.Security.Cryptography (#104352)
* Enable ServerAsyncAuthenticate_MismatchProtocols_Fails * Enable subset of CertificateSelectionCallback_DelayedCertificate_OK * Enable SslStream_StreamToStream_Alpn_NonMatchingProtocols_Fail and do not assume android backend supports ALPN * Enable ConnectWithRevocation_WithCallback and pass full chain to ServerCertificateContext * Enable or permanently disable tests in SslStreamNetworkStreamTest * Adjust host name data for Android in SslStreamSniTest * Fix expected outcome of TransportContext_ConnectToServerWithSsl_GetExpectedChannelBindings for Android * Fix ChainTests active issue on Android * Fix failing test * TMP: Print full exception stacktrace * Adjust expected exception for server authentication protocol mismatch * Revert "TMP: Print full exception stacktrace" This reverts commit 1be0a16. * Adjust the expected exceptions for arm and x86/x64 * Fix assert * Address review comments
1 parent 5ee8f4a commit 110b5f2

File tree

10 files changed

+66
-23
lines changed

10 files changed

+66
-23
lines changed

src/libraries/Common/tests/TestUtilities/System/PlatformDetection.cs

+1-1
Original file line numberDiff line numberDiff line change
@@ -735,7 +735,7 @@ private static bool DetermineBinaryFormatterSupport()
735735
{
736736
return false;
737737
}
738-
738+
739739
Assembly assembly = typeof(System.Runtime.Serialization.Formatters.Binary.BinaryFormatter).Assembly;
740740
AssemblyName name = assembly.GetName();
741741
Version assemblyVersion = name.Version;

src/libraries/System.Net.Security/tests/FunctionalTests/CertificateValidationClientServer.cs

+6-1
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99

1010
using Xunit;
1111
using Xunit.Abstractions;
12+
using Microsoft.DotNet.XUnitExtensions;
1213

1314
namespace System.Net.Security.Tests
1415
{
@@ -40,9 +41,13 @@ public void Dispose()
4041
[InlineData(false, true)]
4142
[InlineData(true, false)]
4243
[InlineData(false, false)]
43-
[ActiveIssue("https://github.com/dotnet/runtime/issues/68206", TestPlatforms.Android)]
4444
public async Task CertificateSelectionCallback_DelayedCertificate_OK(bool delayCertificate, bool sendClientCertificate)
4545
{
46+
if (delayCertificate && OperatingSystem.IsAndroid())
47+
{
48+
throw new SkipTestException("Android does not support delayed certificate selection.");
49+
}
50+
4651
X509Certificate? remoteCertificate = null;
4752

4853
(SslStream client, SslStream server) = TestHelper.GetConnectedSslStreams();

src/libraries/System.Net.Security/tests/FunctionalTests/CertificateValidationRemoteServer.cs

+5-2
Original file line numberDiff line numberDiff line change
@@ -96,7 +96,6 @@ public async Task DefaultConnect_EndToEnd_Ok(string host)
9696
[Theory]
9797
[InlineData(true)]
9898
[InlineData(false)]
99-
[ActiveIssue("https://github.com/dotnet/runtime/issues/68206", TestPlatforms.Android)]
10099
public Task ConnectWithRevocation_WithCallback(bool checkRevocation)
101100
{
102101
X509RevocationMode mode = checkRevocation ? X509RevocationMode.Online : X509RevocationMode.NoCheck;
@@ -266,9 +265,13 @@ private async Task ConnectWithRevocation_WithCallback_Core(
266265

267266
if (offlineContext.HasValue)
268267
{
268+
// on android we need to include the root certificate in the certifiate context
269+
X509Certificate2[] additionalCertificates = OperatingSystem.IsAndroid()
270+
? [issuerCert, rootCert]
271+
: [issuerCert];
269272
serverOpts.ServerCertificateContext = SslStreamCertificateContext.Create(
270273
serverCert,
271-
new X509Certificate2Collection(issuerCert),
274+
new X509Certificate2Collection(additionalCertificates),
272275
offlineContext.GetValueOrDefault());
273276

274277
if (revocationMode == X509RevocationMode.Offline)

src/libraries/System.Net.Security/tests/FunctionalTests/ServerAsyncAuthenticateTest.cs

+10-2
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,6 @@ public async Task ServerAsyncAuthenticate_EachSupportedProtocol_Success(SslProto
4545

4646
[Theory]
4747
[MemberData(nameof(ProtocolMismatchData))]
48-
[ActiveIssue("https://github.com/dotnet/runtime/issues/68206", TestPlatforms.Android)]
4948
public async Task ServerAsyncAuthenticate_MismatchProtocols_Fails(
5049
SslProtocols clientProtocol,
5150
SslProtocols serverProtocol)
@@ -60,7 +59,16 @@ public async Task ServerAsyncAuthenticate_MismatchProtocols_Fails(
6059
});
6160

6261
Assert.NotNull(e);
63-
Assert.IsType<AuthenticationException>(e);
62+
63+
if (OperatingSystem.IsAndroid())
64+
{
65+
// On Android running on x64 or x86 the server side sometimes throws IOException instead of AuthenticationException
66+
Assert.True(e is IOException || e is AuthenticationException, $"Unexpected exception type: {e.GetType()}");
67+
}
68+
else
69+
{
70+
Assert.IsType<AuthenticationException>(e);
71+
}
6472
}
6573

6674
[Theory]

src/libraries/System.Net.Security/tests/FunctionalTests/SslStreamAlpnTests.cs

+2-2
Original file line numberDiff line numberDiff line change
@@ -133,7 +133,6 @@ public async Task SslStream_StreamToStream_Alpn_Success(SslProtocols protocol, L
133133
}
134134

135135
[Fact]
136-
[ActiveIssue("https://github.com/dotnet/runtime/issues/68206", TestPlatforms.Android)]
137136
public async Task SslStream_StreamToStream_Alpn_NonMatchingProtocols_Fail()
138137
{
139138
(SslStream clientStream, SslStream serverStream) = TestHelper.GetConnectedSslStreams();
@@ -155,7 +154,8 @@ public async Task SslStream_StreamToStream_Alpn_NonMatchingProtocols_Fail()
155154
};
156155

157156
// Test ALPN failure only on platforms that supports ALPN.
158-
if (BackendSupportsAlpn)
157+
// On Android, protocol mismatch won't cause an exception, even though it supports ALPN.
158+
if (BackendSupportsAlpn && !OperatingSystem.IsAndroid())
159159
{
160160
Task t1 = Assert.ThrowsAsync<AuthenticationException>(() => clientStream.AuthenticateAsClientAsync(TestAuthenticateAsync, clientOptions));
161161
await Assert.ThrowsAsync<AuthenticationException>(() => serverStream.AuthenticateAsServerAsync(TestAuthenticateAsync, serverOptions).WaitAsync(TestConfiguration.PassingTestTimeout));

src/libraries/System.Net.Security/tests/FunctionalTests/SslStreamNetworkStreamTest.cs

+8-5
Original file line numberDiff line numberDiff line change
@@ -695,10 +695,9 @@ public async Task SslStream_NestedAuth_Throws()
695695
[InlineData(false, true)]
696696
[InlineData(false, false)]
697697
[InlineData(true, true)]
698-
[ActiveIssue("https://github.com/dotnet/runtime/issues/68206", TestPlatforms.Android)]
699698
public async Task SslStream_TargetHostName_Succeeds(bool useEmptyName, bool useCallback)
700699
{
701-
string targetName = useEmptyName ? string.Empty : Guid.NewGuid().ToString("N");
700+
string targetName = useEmptyName ? string.Empty : $"{Guid.NewGuid().ToString("N")}.dot.net";
702701
int count = 0;
703702

704703
(Stream clientStream, Stream serverStream) = TestHelper.GetConnectedStreams();
@@ -751,12 +750,16 @@ await TestConfiguration.WhenAllOrAnyFailedWithTimeout(
751750
}
752751
}
753752

754-
[Theory]
753+
[ConditionalTheory]
755754
[InlineData(true)]
756755
[InlineData(false)]
757-
[ActiveIssue("https://github.com/dotnet/runtime/issues/68206", TestPlatforms.Android)]
758756
public async Task SslStream_ServerUntrustedCaWithCustomTrust_OK(bool usePartialChain)
759757
{
758+
if (usePartialChain && OperatingSystem.IsAndroid())
759+
{
760+
throw new SkipTestException("Android does not support partial chain validation.");
761+
}
762+
760763
int split = Random.Shared.Next(0, _certificates.serverChain.Count - 1);
761764

762765
var clientOptions = new SslClientAuthenticationOptions() { TargetHost = "localhost" };
@@ -854,8 +857,8 @@ private async Task SslStream_ClientSendsChain_Core(SslClientAuthenticationOption
854857
}
855858

856859
[Fact]
857-
[ActiveIssue("https://github.com/dotnet/runtime/issues/68206", TestPlatforms.Android)]
858860
[ActiveIssue("https://github.com/dotnet/runtime/issues/73862", TestPlatforms.OSX)]
861+
[SkipOnPlatform(TestPlatforms.Android, "It is not possible to add the intermediate certificates to the trust store on Android at runtime.")]
859862
public async Task SslStream_ClientCertificate_SendsChain()
860863
{
861864
// macOS ignores CertificateAuthority

src/libraries/System.Net.Security/tests/FunctionalTests/SslStreamSniTest.cs

+11-3
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,6 @@ public class SslStreamSniTest
2121
{
2222
[Theory]
2323
[MemberData(nameof(HostNameData))]
24-
[ActiveIssue("https://github.com/dotnet/runtime/issues/68206", TestPlatforms.Android)]
2524
public async Task SslStream_ClientSendsSNIServerReceives_Ok(string hostName)
2625
{
2726
using X509Certificate serverCert = Configuration.Certificates.GetSelfSignedServerCertificate();
@@ -237,7 +236,6 @@ await TestConfiguration.WhenAllOrAnyFailedWithTimeout(
237236
}
238237

239238
[Fact]
240-
[ActiveIssue("https://github.com/dotnet/runtime/issues/68206", TestPlatforms.Android)]
241239
public async Task UnencodedHostName_ValidatesCertificate()
242240
{
243241
string rawHostname = "räksmörgås.josefsson.org";
@@ -284,7 +282,7 @@ await TestConfiguration.WhenAllOrAnyFailedWithTimeout(
284282
[InlineData("www-.volal.cz")]
285283
[InlineData("www-.colorhexa.com")]
286284
[InlineData("xn--www-7m0a.thegratuit.com")]
287-
[ActiveIssue("https://github.com/dotnet/runtime/issues/68206", TestPlatforms.Android)]
285+
[SkipOnPlatform(TestPlatforms.Android, "Safe invalid IDN hostnames are not supported on Android")]
288286
public async Task SslStream_SafeInvalidIdn_Success(string name)
289287
{
290288
(SslStream client, SslStream server) = TestHelper.GetConnectedSslStreams();
@@ -369,6 +367,16 @@ private async Task WithVirtualConnection(Func<SslStream, SslStream, Task> server
369367

370368
public static IEnumerable<object[]> HostNameData()
371369
{
370+
if (OperatingSystem.IsAndroid())
371+
{
372+
yield return new object[] { "localhost" };
373+
yield return new object[] { "dot.net" };
374+
// max allowed hostname length is 63
375+
yield return new object[] { $"{new string('a', 59)}.net" };
376+
yield return new object[] { "\u017C\u00F3\u0142\u0107g\u0119\u015Bl\u0105ja\u017A\u0144.\u7EA2\u70E7.\u7167\u308A\u713C\u304D" };
377+
yield break;
378+
}
379+
372380
yield return new object[] { "a" };
373381
yield return new object[] { "test" };
374382
// max allowed hostname length is 63

src/libraries/System.Net.Security/tests/FunctionalTests/TransportContextTest.cs

+3-3
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,6 @@ namespace System.Net.Security.Tests
1414
public class TransportContextTest
1515
{
1616
[Fact]
17-
[ActiveIssue("https://github.com/dotnet/runtime/issues/68206", TestPlatforms.Android)]
1817
public async Task TransportContext_ConnectToServerWithSsl_GetExpectedChannelBindings()
1918
{
2019
(Stream clientStream, Stream serverStream) = TestHelper.GetConnectedStreams();
@@ -46,9 +45,10 @@ private static void CheckTransportContext(TransportContext context)
4645

4746
Assert.True(cbt1 != null, "ChannelBindingKind.Endpoint token data should be returned.");
4847

49-
if (OperatingSystem.IsMacOS())
48+
if (OperatingSystem.IsMacOS() || OperatingSystem.IsAndroid())
5049
{
51-
Assert.True(cbt2 == null, "ChannelBindingKind.Unique token data is not expected on OSX platform.");
50+
var platform = OperatingSystem.IsMacOS() ? "macOS" : "Android";
51+
Assert.True(cbt2 == null, $"ChannelBindingKind.Unique token data is not expected on {platform}.");
5252
}
5353
else
5454
{

src/libraries/System.Security.Cryptography/tests/X509Certificates/ChainTests.cs

+18-3
Original file line numberDiff line numberDiff line change
@@ -1270,7 +1270,6 @@ public static void BuildChainForSelfSignedSha3Certificate()
12701270
}
12711271

12721272
[Fact]
1273-
[ActiveIssue("https://github.com/dotnet/runtime/issues/100224", typeof(PlatformDetection), nameof(PlatformDetection.IsAndroid), nameof(PlatformDetection.IsArmOrArm64Process))]
12741273
public static void BuildChainForSelfSignedCertificate_WithSha256RsaSignature()
12751274
{
12761275
using (ChainHolder chainHolder = new ChainHolder())
@@ -1284,12 +1283,22 @@ public static void BuildChainForSelfSignedCertificate_WithSha256RsaSignature()
12841283
// minimum be marked UntrustedRoot.
12851284

12861285
Assert.False(chain.Build(cert));
1287-
AssertExtensions.HasFlag(X509ChainStatusFlags.UntrustedRoot, chain.AllStatusFlags());
1286+
1287+
if (PlatformDetection.IsAndroid)
1288+
{
1289+
// Android always validates trust as part of building a path,
1290+
// so violations comes back as PartialChain with no elements
1291+
Assert.Equal(X509ChainStatusFlags.PartialChain, chain.AllStatusFlags());
1292+
Assert.Equal(0, chain.ChainElements.Count);
1293+
}
1294+
else
1295+
{
1296+
AssertExtensions.HasFlag(X509ChainStatusFlags.UntrustedRoot, chain.AllStatusFlags());
1297+
}
12881298
}
12891299
}
12901300

12911301
[Fact]
1292-
[ActiveIssue("https://github.com/dotnet/runtime/issues/100224", typeof(PlatformDetection), nameof(PlatformDetection.IsAndroid), nameof(PlatformDetection.IsArmOrArm64Process))]
12931302
public static void BuildChainForSelfSignedCertificate_WithUnknownOidSignature()
12941303
{
12951304
using (ChainHolder chainHolder = new ChainHolder())
@@ -1311,6 +1320,12 @@ public static void BuildChainForSelfSignedCertificate_WithUnknownOidSignature()
13111320
Assert.False(chain.Build(cert));
13121321
AssertExtensions.HasFlag(X509ChainStatusFlags.PartialChain, chain.AllStatusFlags());
13131322
}
1323+
else if (PlatformDetection.IsAndroid)
1324+
{
1325+
Assert.False(chain.Build(cert));
1326+
AssertExtensions.HasFlag(X509ChainStatusFlags.PartialChain, chain.AllStatusFlags());
1327+
Assert.Equal(0, chain.ChainElements.Count);
1328+
}
13141329
else if (PlatformDetection.IsOpenSslSupported)
13151330
{
13161331
Assert.False(chain.Build(cert));

src/tasks/AndroidAppBuilder/Templates/AndroidManifest.xml

+2-1
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,8 @@
88
<uses-permission a:name="android.permission.READ_EXTERNAL_STORAGE"/>
99
<uses-permission a:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
1010
<application a:label="%PackageName%"
11-
a:largeHeap="true">
11+
a:largeHeap="true"
12+
a:usesCleartextTraffic="true">
1213
<activity a:name="net.dot.MainActivity" a:exported="true">
1314
<intent-filter>
1415
<category a:name="android.intent.category.LAUNCHER"/>

0 commit comments

Comments
 (0)