179 lines
6.8 KiB
C#
179 lines
6.8 KiB
C#
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.
|
|
|
|
using System.IO;
|
|
using System.Net.Http;
|
|
using System.Security.Cryptography.X509Certificates;
|
|
using System.Text;
|
|
using System.Threading.Tasks;
|
|
using Xunit;
|
|
|
|
namespace Microsoft.Net.Http.Server
|
|
{
|
|
public class HttpsTests
|
|
{
|
|
// Note these tests can't use dynamic ports or run concurrently because the ssl cert must be pre-registered with a specific port.
|
|
private const string Address = "https://localhost:9090/";
|
|
|
|
[Fact(Skip = "TODO: Add trait filtering support so these SSL tests don't get run on teamcity or the command line."), Trait("scheme", "https")]
|
|
public async Task Https_200OK_Success()
|
|
{
|
|
using (var server = Utilities.CreateHttpsServer())
|
|
{
|
|
Task<string> responseTask = SendRequestAsync(Address);
|
|
|
|
var context = await server.GetContextAsync();
|
|
context.Dispose();
|
|
|
|
string response = await responseTask;
|
|
Assert.Equal(string.Empty, response);
|
|
}
|
|
}
|
|
|
|
[Fact(Skip = "TODO: Add trait filtering support so these SSL tests don't get run on teamcity or the command line."), Trait("scheme", "https")]
|
|
public async Task Https_SendHelloWorld_Success()
|
|
{
|
|
using (var server = Utilities.CreateHttpsServer())
|
|
{
|
|
Task<string> responseTask = SendRequestAsync(Address);
|
|
|
|
var context = await server.GetContextAsync();
|
|
byte[] body = Encoding.UTF8.GetBytes("Hello World");
|
|
context.Response.ContentLength = body.Length;
|
|
await context.Response.Body.WriteAsync(body, 0, body.Length);
|
|
context.Dispose();
|
|
|
|
string response = await responseTask;
|
|
Assert.Equal("Hello World", response);
|
|
}
|
|
}
|
|
|
|
[Fact(Skip = "TODO: Add trait filtering support so these SSL tests don't get run on teamcity or the command line."), Trait("scheme", "https")]
|
|
public async Task Https_EchoHelloWorld_Success()
|
|
{
|
|
using (var server = Utilities.CreateHttpsServer())
|
|
{
|
|
Task<string> responseTask = SendRequestAsync(Address, "Hello World");
|
|
|
|
var context = await server.GetContextAsync();
|
|
string input = new StreamReader(context.Request.Body).ReadToEnd();
|
|
Assert.Equal("Hello World", input);
|
|
context.Response.ContentLength = 11;
|
|
using (var writer = new StreamWriter(context.Response.Body))
|
|
{
|
|
writer.Write("Hello World");
|
|
}
|
|
|
|
string response = await responseTask;
|
|
Assert.Equal("Hello World", response);
|
|
}
|
|
}
|
|
|
|
[Fact(Skip = "TODO: Add trait filtering support so these SSL tests don't get run on teamcity or the command line."), Trait("scheme", "https")]
|
|
public async Task Https_ClientCertNotSent_ClientCertNotPresent()
|
|
{
|
|
using (var server = Utilities.CreateHttpsServer())
|
|
{
|
|
Task<string> responseTask = SendRequestAsync(Address);
|
|
|
|
var context = await server.GetContextAsync();
|
|
var cert = await context.Request.GetClientCertificateAsync();
|
|
Assert.Null(cert);
|
|
context.Dispose();
|
|
|
|
string response = await responseTask;
|
|
Assert.Equal(string.Empty, response);
|
|
}
|
|
}
|
|
|
|
[Fact(Skip = "TODO: Add trait filtering support so these SSL tests don't get run on teamcity or the command line."), Trait("scheme", "https")]
|
|
public async Task Https_ClientCertRequested_ClientCertPresent()
|
|
{
|
|
using (var server = Utilities.CreateHttpsServer())
|
|
{
|
|
X509Certificate2 clientCert = FindClientCert();
|
|
Assert.NotNull(clientCert);
|
|
Task<string> responseTask = SendRequestAsync(Address, clientCert);
|
|
|
|
var context = await server.GetContextAsync();
|
|
var cert = await context.Request.GetClientCertificateAsync();
|
|
Assert.NotNull(cert);
|
|
context.Dispose();
|
|
|
|
string response = await responseTask;
|
|
Assert.Equal(string.Empty, response);
|
|
}
|
|
}
|
|
|
|
private async Task<string> SendRequestAsync(string uri,
|
|
X509Certificate cert = null)
|
|
{
|
|
#if NET451
|
|
WebRequestHandler handler = new WebRequestHandler();
|
|
#else
|
|
WinHttpHandler handler = new WinHttpHandler();
|
|
#endif
|
|
handler.ServerCertificateValidationCallback = (a, b, c, d) => true;
|
|
if (cert != null)
|
|
{
|
|
handler.ClientCertificates.Add(cert);
|
|
}
|
|
using (HttpClient client = new HttpClient(handler))
|
|
{
|
|
return await client.GetStringAsync(uri);
|
|
}
|
|
}
|
|
|
|
private async Task<string> SendRequestAsync(string uri, string upload)
|
|
{
|
|
#if NET451
|
|
WebRequestHandler handler = new WebRequestHandler();
|
|
#else
|
|
WinHttpHandler handler = new WinHttpHandler();
|
|
#endif
|
|
handler.ServerCertificateValidationCallback = (a, b, c, d) => true;
|
|
using (HttpClient client = new HttpClient(handler))
|
|
{
|
|
HttpResponseMessage response = await client.PostAsync(uri, new StringContent(upload));
|
|
response.EnsureSuccessStatusCode();
|
|
return await response.Content.ReadAsStringAsync();
|
|
}
|
|
}
|
|
|
|
private X509Certificate2 FindClientCert()
|
|
{
|
|
var store = new X509Store();
|
|
store.Open(OpenFlags.ReadOnly);
|
|
|
|
foreach (var cert in store.Certificates)
|
|
{
|
|
bool isClientAuth = false;
|
|
bool isSmartCard = false;
|
|
foreach (var extension in cert.Extensions)
|
|
{
|
|
var eku = extension as X509EnhancedKeyUsageExtension;
|
|
if (eku != null)
|
|
{
|
|
foreach (var oid in eku.EnhancedKeyUsages)
|
|
{
|
|
if (oid.FriendlyName == "Client Authentication")
|
|
{
|
|
isClientAuth = true;
|
|
}
|
|
else if (oid.FriendlyName == "Smart Card Logon")
|
|
{
|
|
isSmartCard = true;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if (isClientAuth && !isSmartCard)
|
|
{
|
|
return cert;
|
|
}
|
|
}
|
|
return null;
|
|
}
|
|
}
|
|
} |