| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579 |
- commit 065e9bb57a5f8900dc2fc7cc8d94c71135cde9e5
- Author: Andrew Stanton-Nurse <[email protected]>
- Date: Mon Nov 13 15:54:16 2017 -0800
- Update "temporary" OpenSSL wrapper to support 1.1, and add HTTP/2 sample with docker (#2149)
- diff --git a/KestrelHttpServer.sln b/KestrelHttpServer.sln
- index 8ec3d0f3a65..6cdeaa1464e 100644
- --- a/KestrelHttpServer.sln
- +++ b/KestrelHttpServer.sln
- @@ -1,6 +1,6 @@
- Microsoft Visual Studio Solution File, Format Version 12.00
- # Visual Studio 15
- -VisualStudioVersion = 15.0.26730.16
- +VisualStudioVersion = 15.0.27101.0
- MinimumVisualStudioVersion = 15.0.26730.03
- Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{7972A5D6-3385-4127-9277-428506DD44FF}"
- ProjectSection(SolutionItems) = preProject
- @@ -121,6 +121,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Kestrel.Transport.Libuv.Fun
- EndProject
- Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Kestrel.Transport.Sockets.FunctionalTests", "test\Kestrel.Transport.Sockets.FunctionalTests\Kestrel.Transport.Sockets.FunctionalTests.csproj", "{9C7B6B5F-088A-436E-834B-6373EA36DEEE}"
- EndProject
- +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Http2SampleApp", "samples\Http2SampleApp\Http2SampleApp.csproj", "{7BC22A4A-15D2-44C2-AB45-049F0FB562FA}"
- +EndProject
- Global
- GlobalSection(SolutionConfigurationPlatforms) = preSolution
- Debug|Any CPU = Debug|Any CPU
- @@ -335,6 +337,18 @@ Global
- {9C7B6B5F-088A-436E-834B-6373EA36DEEE}.Release|x64.Build.0 = Release|Any CPU
- {9C7B6B5F-088A-436E-834B-6373EA36DEEE}.Release|x86.ActiveCfg = Release|Any CPU
- {9C7B6B5F-088A-436E-834B-6373EA36DEEE}.Release|x86.Build.0 = Release|Any CPU
- + {7BC22A4A-15D2-44C2-AB45-049F0FB562FA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- + {7BC22A4A-15D2-44C2-AB45-049F0FB562FA}.Debug|Any CPU.Build.0 = Debug|Any CPU
- + {7BC22A4A-15D2-44C2-AB45-049F0FB562FA}.Debug|x64.ActiveCfg = Debug|Any CPU
- + {7BC22A4A-15D2-44C2-AB45-049F0FB562FA}.Debug|x64.Build.0 = Debug|Any CPU
- + {7BC22A4A-15D2-44C2-AB45-049F0FB562FA}.Debug|x86.ActiveCfg = Debug|Any CPU
- + {7BC22A4A-15D2-44C2-AB45-049F0FB562FA}.Debug|x86.Build.0 = Debug|Any CPU
- + {7BC22A4A-15D2-44C2-AB45-049F0FB562FA}.Release|Any CPU.ActiveCfg = Release|Any CPU
- + {7BC22A4A-15D2-44C2-AB45-049F0FB562FA}.Release|Any CPU.Build.0 = Release|Any CPU
- + {7BC22A4A-15D2-44C2-AB45-049F0FB562FA}.Release|x64.ActiveCfg = Release|Any CPU
- + {7BC22A4A-15D2-44C2-AB45-049F0FB562FA}.Release|x64.Build.0 = Release|Any CPU
- + {7BC22A4A-15D2-44C2-AB45-049F0FB562FA}.Release|x86.ActiveCfg = Release|Any CPU
- + {7BC22A4A-15D2-44C2-AB45-049F0FB562FA}.Release|x86.Build.0 = Release|Any CPU
- EndGlobalSection
- GlobalSection(SolutionProperties) = preSolution
- HideSolutionNode = FALSE
- @@ -359,6 +373,7 @@ Global
- {B7B0EA74-528F-46B8-9BC4-909D9A67C194} = {D3273454-EA07-41D2-BF0B-FCC3675C2483}
- {74032D79-8EA7-4483-BD82-C38370420FFF} = {D3273454-EA07-41D2-BF0B-FCC3675C2483}
- {9C7B6B5F-088A-436E-834B-6373EA36DEEE} = {D3273454-EA07-41D2-BF0B-FCC3675C2483}
- + {7BC22A4A-15D2-44C2-AB45-049F0FB562FA} = {8A3D00B8-1CCF-4BE6-A060-11104CE2D9CE}
- EndGlobalSection
- GlobalSection(ExtensibilityGlobals) = postSolution
- SolutionGuid = {2D10D020-6770-47CA-BB8D-2C23FE3AE071}
- diff --git a/samples/Http2SampleApp/Dockerfile b/samples/Http2SampleApp/Dockerfile
- new file mode 100644
- index 00000000000..e93d563bde5
- --- /dev/null
- +++ b/samples/Http2SampleApp/Dockerfile
- @@ -0,0 +1,14 @@
- +FROM microsoft/aspnetcore:2.0.0-stretch
- +
- +RUN apt-get update && \
- + apt-get install -y --no-install-recommends \
- + libssl-dev && \
- + rm -rf /var/lib/apt/lists/*
- +
- +ARG CONFIGURATION=Debug
- +
- +WORKDIR /app
- +
- +COPY ./bin/${CONFIGURATION}/netcoreapp2.0/publish/ /app
- +
- +ENTRYPOINT [ "/usr/bin/dotnet", "/app/Http2SampleApp.dll" ]
- diff --git a/samples/Http2SampleApp/Http2SampleApp.csproj b/samples/Http2SampleApp/Http2SampleApp.csproj
- new file mode 100644
- index 00000000000..0fd184ca8d2
- --- /dev/null
- +++ b/samples/Http2SampleApp/Http2SampleApp.csproj
- @@ -0,0 +1,21 @@
- +<Project Sdk="Microsoft.NET.Sdk.Web">
- +
- + <PropertyGroup>
- + <TargetFrameworks>netcoreapp2.0</TargetFrameworks>
- + <IsPackable>false</IsPackable>
- + </PropertyGroup>
- +
- + <ItemGroup>
- + <ProjectReference Include="..\..\src\Kestrel\Kestrel.csproj" />
- + <ProjectReference Include="..\..\src\Kestrel.Tls\Kestrel.Tls.csproj" />
- + </ItemGroup>
- +
- + <ItemGroup>
- + <PackageReference Include="Microsoft.Extensions.Logging.Console" Version="$(MicrosoftExtensionsLoggingConsolePackageVersion)" />
- + </ItemGroup>
- +
- + <ItemGroup>
- + <Content Include="../../test/shared/TestCertificates/testCert.pfx" CopyToOutputDirectory="PreserveNewest" />
- + </ItemGroup>
- +
- +</Project>
- diff --git a/samples/Http2SampleApp/Program.cs b/samples/Http2SampleApp/Program.cs
- new file mode 100644
- index 00000000000..249c41347c7
- --- /dev/null
- +++ b/samples/Http2SampleApp/Program.cs
- @@ -0,0 +1,50 @@
- +using System.Globalization;
- +using System.IO;
- +using System.Net;
- +using Microsoft.AspNetCore.Hosting;
- +using Microsoft.AspNetCore.Server.Kestrel.Core;
- +using Microsoft.AspNetCore.Server.Kestrel.Transport.Abstractions.Internal;
- +using Microsoft.Extensions.Configuration;
- +using Microsoft.Extensions.Logging;
- +
- +namespace Http2SampleApp
- +{
- + public class Program
- + {
- + public static void Main(string[] args)
- + {
- + var configuration = new ConfigurationBuilder()
- + .AddEnvironmentVariables()
- + .Build();
- +
- + if (!ushort.TryParse(configuration["BASE_PORT"], NumberStyles.None, CultureInfo.InvariantCulture, out var basePort))
- + {
- + basePort = 5000;
- + }
- +
- + var hostBuilder = new WebHostBuilder()
- + .ConfigureLogging((_, factory) =>
- + {
- + // Set logging to the MAX.
- + factory.SetMinimumLevel(LogLevel.Trace);
- + factory.AddConsole();
- + })
- + .UseKestrel(options =>
- + {
- + // Run callbacks on the transport thread
- + options.ApplicationSchedulingMode = SchedulingMode.Inline;
- +
- + options.Listen(IPAddress.Any, basePort, listenOptions =>
- + {
- + listenOptions.Protocols = HttpProtocols.Http1AndHttp2;
- + listenOptions.UseTls("testCert.pfx", "testPassword");
- + listenOptions.UseConnectionLogging();
- + });
- + })
- + .UseContentRoot(Directory.GetCurrentDirectory())
- + .UseStartup<Startup>();
- +
- + hostBuilder.Build().Run();
- + }
- + }
- +}
- diff --git a/samples/Http2SampleApp/Startup.cs b/samples/Http2SampleApp/Startup.cs
- new file mode 100644
- index 00000000000..6dce6b8a196
- --- /dev/null
- +++ b/samples/Http2SampleApp/Startup.cs
- @@ -0,0 +1,29 @@
- +using System;
- +using System.Collections.Generic;
- +using System.Linq;
- +using System.Threading.Tasks;
- +using Microsoft.AspNetCore.Builder;
- +using Microsoft.AspNetCore.Hosting;
- +using Microsoft.AspNetCore.Http;
- +using Microsoft.Extensions.DependencyInjection;
- +
- +namespace Http2SampleApp
- +{
- + public class Startup
- + {
- + // This method gets called by the runtime. Use this method to add services to the container.
- + // For more information on how to configure your application, visit https://go.microsoft.com/fwlink/?LinkID=398940
- + public void ConfigureServices(IServiceCollection services)
- + {
- + }
- +
- + // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
- + public void Configure(IApplicationBuilder app, IHostingEnvironment env)
- + {
- + app.Run(async (context) =>
- + {
- + await context.Response.WriteAsync("Hello World!");
- + });
- + }
- + }
- +}
- diff --git a/samples/Http2SampleApp/scripts/build-docker.ps1 b/samples/Http2SampleApp/scripts/build-docker.ps1
- new file mode 100644
- index 00000000000..eda82ace6f8
- --- /dev/null
- +++ b/samples/Http2SampleApp/scripts/build-docker.ps1
- @@ -0,0 +1,3 @@
- +dotnet publish --framework netcoreapp2.0 "$PSScriptRoot/../Http2SampleApp.csproj"
- +
- +docker build -t kestrel-http2-sample (Convert-Path "$PSScriptRoot/..")
- diff --git a/samples/Http2SampleApp/scripts/build-docker.sh b/samples/Http2SampleApp/scripts/build-docker.sh
- new file mode 100755
- index 00000000000..ca226f0b53d
- --- /dev/null
- +++ b/samples/Http2SampleApp/scripts/build-docker.sh
- @@ -0,0 +1,6 @@
- +#!/usr/bin/env bash
- +DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
- +
- +dotnet publish --framework netcoreapp2.0 "$DIR/../Http2SampleApp.csproj"
- +
- +docker build -t kestrel-http2-sample "$DIR/.."
- diff --git a/samples/Http2SampleApp/scripts/run-docker.ps1 b/samples/Http2SampleApp/scripts/run-docker.ps1
- new file mode 100644
- index 00000000000..7b371b6dde9
- --- /dev/null
- +++ b/samples/Http2SampleApp/scripts/run-docker.ps1
- @@ -0,0 +1 @@
- +docker run -p 5000:5000 -it --rm kestrel-http2-sample
- diff --git a/samples/Http2SampleApp/scripts/run-docker.sh b/samples/Http2SampleApp/scripts/run-docker.sh
- new file mode 100755
- index 00000000000..3039b34a988
- --- /dev/null
- +++ b/samples/Http2SampleApp/scripts/run-docker.sh
- @@ -0,0 +1,2 @@
- +#!/usr/bin/env bash
- +docker run -it -p 5000:5000 --rm kestrel-http2-sample
- diff --git a/samples/SampleApp/SampleApp.csproj b/samples/SampleApp/SampleApp.csproj
- index 7d62f701775..2225608125f 100644
- --- a/samples/SampleApp/SampleApp.csproj
- +++ b/samples/SampleApp/SampleApp.csproj
- @@ -6,10 +6,6 @@
- <NoDefaultLaunchSettingsFile>true</NoDefaultLaunchSettingsFile>
- </PropertyGroup>
-
- - <ItemGroup>
- - <Content Include="testCert.pfx" CopyToOutputDirectory="PreserveNewest" />
- - </ItemGroup>
- -
- <ItemGroup>
- <ProjectReference Include="..\..\src\Kestrel\Kestrel.csproj" />
- <ProjectReference Include="..\..\src\Kestrel.Https\Kestrel.Https.csproj" />
- @@ -19,4 +15,8 @@
- <PackageReference Include="Microsoft.Extensions.Logging.Console" Version="$(MicrosoftExtensionsLoggingConsolePackageVersion)" />
- </ItemGroup>
-
- + <ItemGroup>
- + <Content Include="../../test/shared/TestCertificates/testCert.pfx" CopyToOutputDirectory="PreserveNewest" />
- + </ItemGroup>
- +
- </Project>
- diff --git a/samples/SampleApp/testCert.pfx b/samples/SampleApp/testCert.pfx
- deleted file mode 100644
- index 7118908c2d7..00000000000
- Binary files a/samples/SampleApp/testCert.pfx and /dev/null differ
- diff --git a/src/Kestrel.Core/Internal/Http2/Http2Frame.Data.cs b/src/Kestrel.Core/Internal/Http2/Http2Frame.Data.cs
- index 9a0760fe6e6..91f0edb72a6 100644
- --- a/src/Kestrel.Core/Internal/Http2/Http2Frame.Data.cs
- +++ b/src/Kestrel.Core/Internal/Http2/Http2Frame.Data.cs
- @@ -2,6 +2,7 @@
- // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
-
- using System;
- +using Microsoft.Extensions.Logging;
-
- namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http2
- {
- @@ -40,5 +41,10 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http2
- Payload.Slice(Length - padLength.Value).Fill(0);
- }
- }
- +
- + private void DataTraceFrame(ILogger logger)
- + {
- + logger.LogTrace("'DATA' Frame. Flags = {DataFlags}, PadLength = {PadLength}, PayloadLength = {PayloadLength}", DataFlags, DataPadLength, DataPayload.Count);
- + }
- }
- }
- diff --git a/src/Kestrel.Core/Internal/Http2/Http2Frame.cs b/src/Kestrel.Core/Internal/Http2/Http2Frame.cs
- index e0dbf8bd091..f983b632a39 100644
- --- a/src/Kestrel.Core/Internal/Http2/Http2Frame.cs
- +++ b/src/Kestrel.Core/Internal/Http2/Http2Frame.cs
- @@ -2,6 +2,7 @@
- // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
-
- using System;
- +using Microsoft.Extensions.Logging;
-
- namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http2
- {
- diff --git a/src/Kestrel.Tls/ListenOptionsTlsExtensions.cs b/src/Kestrel.Tls/ListenOptionsTlsExtensions.cs
- index cb2c459152f..695297eb56c 100644
- --- a/src/Kestrel.Tls/ListenOptionsTlsExtensions.cs
- +++ b/src/Kestrel.Tls/ListenOptionsTlsExtensions.cs
- @@ -10,12 +10,12 @@ namespace Microsoft.AspNetCore.Hosting
- {
- public static class ListenOptionsTlsExtensions
- {
- - public static ListenOptions UseTls(this ListenOptions listenOptions, string certificatePath, string privateKeyPath)
- + public static ListenOptions UseTls(this ListenOptions listenOptions, string certificatePath, string password)
- {
- return listenOptions.UseTls(new TlsConnectionAdapterOptions
- {
- CertificatePath = certificatePath,
- - PrivateKeyPath = privateKeyPath,
- + Password = password,
- Protocols = listenOptions.Protocols
- });
- }
- diff --git a/src/Kestrel.Tls/OpenSsl.cs b/src/Kestrel.Tls/OpenSsl.cs
- index 17568e4b9c8..52af7a88570 100644
- --- a/src/Kestrel.Tls/OpenSsl.cs
- +++ b/src/Kestrel.Tls/OpenSsl.cs
- @@ -15,23 +15,46 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Tls
- public const int OPENSSL_NPN_NEGOTIATED = 1;
- public const int SSL_TLSEXT_ERR_OK = 0;
- public const int SSL_TLSEXT_ERR_NOACK = 3;
- + public const int SSL_CTRL_CHAIN = 88;
-
- private const int BIO_C_SET_BUF_MEM_EOF_RETURN = 130;
- private const int SSL_CTRL_SET_ECDH_AUTO = 94;
-
- - public static int SSL_library_init()
- + public static void SSL_library_init()
- {
- - return NativeMethods.SSL_library_init();
- + try
- + {
- + // Try OpenSSL 1.0.2
- + NativeMethods.SSL_library_init();
- + }
- + catch (EntryPointNotFoundException)
- + {
- + // It's fine, OpenSSL 1.1 doesn't need initialization
- + }
- }
-
- public static void SSL_load_error_strings()
- {
- - NativeMethods.SSL_load_error_strings();
- + try
- + {
- + NativeMethods.SSL_load_error_strings();
- + }
- + catch (EntryPointNotFoundException)
- + {
- + // Also fine, OpenSSL 1.1 doesn't need it.
- + }
- }
-
- public static void OpenSSL_add_all_algorithms()
- {
- - NativeMethods.OPENSSL_add_all_algorithms_noconf();
- + try
- + {
- + NativeMethods.OPENSSL_add_all_algorithms_noconf();
- + }
- + catch (EntryPointNotFoundException)
- + {
- + // Also fine, OpenSSL 1.1 doesn't need it.
- + }
- }
-
- public static IntPtr TLSv1_2_method()
- @@ -49,6 +72,41 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Tls
- NativeMethods.SSL_CTX_free(ctx);
- }
-
- + public unsafe static int SSL_CTX_Set_Pfx(IntPtr ctx, string path, string password)
- + {
- + var pass = Marshal.StringToHGlobalAnsi(password);
- + var key = IntPtr.Zero;
- + var cert = IntPtr.Zero;
- + var ca = IntPtr.Zero;
- +
- + try
- + {
- + var file = System.IO.File.ReadAllBytes(path);
- +
- + fixed (void* f = file)
- + {
- + var buffer = (IntPtr)f;
- + var pkcs = NativeMethods.d2i_PKCS12(IntPtr.Zero, ref buffer, file.Length);
- + var result = NativeMethods.PKCS12_parse(pkcs, pass, ref key, ref cert, ref ca);
- + if (result != 1)
- + {
- + return -1;
- + }
- + if (NativeMethods.SSL_CTX_use_certificate(ctx, cert) != 1) return -1;
- + if (NativeMethods.SSL_CTX_use_PrivateKey(ctx, key) != 1) return -1;
- + if (NativeMethods.SSL_CTX_ctrl(ctx, SSL_CTRL_CHAIN, 1, ca) != 1) return -1;
- + return 1;
- + }
- + }
- + finally
- + {
- + Marshal.FreeHGlobal(pass);
- + if (key != IntPtr.Zero) NativeMethods.EVP_PKEY_free(key);
- + if (cert != IntPtr.Zero) NativeMethods.X509_free(cert);
- + if (ca != IntPtr.Zero) NativeMethods.sk_X509_pop_free(ca);
- + }
- + }
- +
- public static int SSL_CTX_set_ecdh_auto(IntPtr ctx, int onoff)
- {
- return (int)NativeMethods.SSL_CTX_ctrl(ctx, SSL_CTRL_SET_ECDH_AUTO, onoff, IntPtr.Zero);
- @@ -109,6 +167,19 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Tls
- return NativeMethods.SSL_get_error(ssl, ret);
- }
-
- + public static int ERR_get_error()
- + {
- + return NativeMethods.ERR_get_error();
- + }
- +
- + public static string ERR_error_string(int error)
- + {
- + var buf = NativeMethods.ERR_error_string(error, IntPtr.Zero);
- +
- + // Don't free the buffer! It's a static buffer
- + return Marshal.PtrToStringAnsi(buf);
- + }
- +
- public static void SSL_set_accept_state(IntPtr ssl)
- {
- NativeMethods.SSL_set_accept_state(ssl);
- @@ -263,6 +334,42 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Tls
-
- [DllImport("libssl", CallingConvention = CallingConvention.Cdecl)]
- public static extern void ERR_load_BIO_strings();
- +
- + [DllImport("libssl", CallingConvention = CallingConvention.Cdecl)]
- + public static extern int ERR_get_error();
- +
- + [DllImport("libssl", CallingConvention = CallingConvention.Cdecl)]
- + public static extern IntPtr ERR_error_string(int error, IntPtr buf);
- +
- + [DllImport("libssl", CallingConvention = CallingConvention.Cdecl)]
- + public static extern IntPtr d2i_PKCS12(IntPtr unsused, ref IntPtr bufferPointer, long length);
- +
- + [DllImport("libssl", CallingConvention = CallingConvention.Cdecl)]
- + public static extern int PKCS12_parse(IntPtr p12, IntPtr pass, ref IntPtr pkey, ref IntPtr cert, ref IntPtr ca);
- +
- + [DllImport("libssl", CallingConvention = CallingConvention.Cdecl)]
- + public static extern void PKCS12_free(IntPtr p12);
- +
- + [DllImport("libssl", CallingConvention = CallingConvention.Cdecl)]
- + public static extern void EVP_PKEY_free(IntPtr pkey);
- +
- + [DllImport("libssl", CallingConvention = CallingConvention.Cdecl)]
- + public static extern void X509_free(IntPtr a);
- +
- + [DllImport("libssl", CallingConvention = CallingConvention.Cdecl)]
- + public static extern void sk_X509_pop_free(IntPtr ca);
- +
- + [DllImport("libssl", CallingConvention = CallingConvention.Cdecl)]
- + public static extern int SSL_CTX_ctrl(IntPtr ctx, int cmd, int larg, IntPtr parg);
- +
- + [DllImport("libssl", CallingConvention = CallingConvention.Cdecl)]
- + public static extern int SSL_CTX_set1_chain(IntPtr ctx, IntPtr sk);
- +
- + [DllImport("libssl", CallingConvention = CallingConvention.Cdecl)]
- + public static extern int SSL_CTX_use_certificate(IntPtr ctx, IntPtr x509);
- +
- + [DllImport("libssl", CallingConvention = CallingConvention.Cdecl)]
- + public static extern int SSL_CTX_use_PrivateKey(IntPtr ctx, IntPtr pkey);
- }
- }
- }
- diff --git a/src/Kestrel.Tls/TlsConnectionAdapter.cs b/src/Kestrel.Tls/TlsConnectionAdapter.cs
- index 539c8404f3b..8dee80eb689 100644
- --- a/src/Kestrel.Tls/TlsConnectionAdapter.cs
- +++ b/src/Kestrel.Tls/TlsConnectionAdapter.cs
- @@ -40,9 +40,9 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Tls
- throw new ArgumentException("Certificate path must be non-null.", nameof(options));
- }
-
- - if (options.PrivateKeyPath == null)
- + if (options.Password == null)
- {
- - throw new ArgumentException("Private key path must be non-null.", nameof(options));
- + throw new ArgumentException("Password must be non-null.", nameof(options));
- }
-
- _options = options;
- @@ -70,7 +70,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Tls
-
- private async Task<IAdaptedConnection> InnerOnConnectionAsync(ConnectionAdapterContext context)
- {
- - var tlsStream = new TlsStream(context.ConnectionStream, _options.CertificatePath, _options.PrivateKeyPath, _serverProtocols);
- + var tlsStream = new TlsStream(context.ConnectionStream, _options.CertificatePath, _options.Password, _serverProtocols);
-
- try
- {
- diff --git a/src/Kestrel.Tls/TlsConnectionAdapterOptions.cs b/src/Kestrel.Tls/TlsConnectionAdapterOptions.cs
- index 88d107ffdd4..220bd47d9c7 100644
- --- a/src/Kestrel.Tls/TlsConnectionAdapterOptions.cs
- +++ b/src/Kestrel.Tls/TlsConnectionAdapterOptions.cs
- @@ -9,7 +9,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Tls
- {
- public string CertificatePath { get; set; } = string.Empty;
-
- - public string PrivateKeyPath { get; set; } = string.Empty;
- + public string Password { get; set; } = string.Empty;
-
- public HttpProtocols Protocols { get; set; }
- }
- diff --git a/src/Kestrel.Tls/TlsStream.cs b/src/Kestrel.Tls/TlsStream.cs
- index 0b1b583167e..497317bab7a 100644
- --- a/src/Kestrel.Tls/TlsStream.cs
- +++ b/src/Kestrel.Tls/TlsStream.cs
- @@ -9,11 +9,15 @@ using System.Runtime.InteropServices;
- using System.Text;
- using System.Threading;
- using System.Threading.Tasks;
- +using Microsoft.Extensions.Logging;
-
- namespace Microsoft.AspNetCore.Server.Kestrel.Tls
- {
- public class TlsStream : Stream
- {
- + // Error code that indicates that a handshake failed because unencrypted HTTP was sent
- + private const int SSL_ERROR_HTTP_REQUEST = 336130204;
- +
- private static unsafe OpenSsl.alpn_select_cb_t _alpnSelectCallback = AlpnSelectCallback;
-
- private readonly Stream _innerStream;
- @@ -36,7 +40,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Tls
- OpenSsl.OpenSSL_add_all_algorithms();
- }
-
- - public TlsStream(Stream innerStream, string certificatePath, string privateKeyPath, IEnumerable<string> protocols)
- + public TlsStream(Stream innerStream, string certificatePath, string password, IEnumerable<string> protocols)
- {
- _innerStream = innerStream;
- _protocols = ToWireFormat(protocols);
- @@ -49,18 +53,13 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Tls
- throw new Exception("Unable to create SSL context.");
- }
-
- - OpenSsl.SSL_CTX_set_ecdh_auto(_ctx, 1);
- -
- - if (OpenSsl.SSL_CTX_use_certificate_file(_ctx, certificatePath, 1) != 1)
- + if(OpenSsl.SSL_CTX_Set_Pfx(_ctx, certificatePath, password) != 1)
- {
- - throw new Exception("Unable to load certificate file.");
- - }
- -
- - if (OpenSsl.SSL_CTX_use_PrivateKey_file(_ctx, privateKeyPath, 1) != 1)
- - {
- - throw new Exception("Unable to load private key file.");
- + throw new InvalidOperationException("Unable to load PFX");
- }
-
- + OpenSsl.SSL_CTX_set_ecdh_auto(_ctx, 1);
- +
- OpenSsl.SSL_CTX_set_alpn_select_cb(_ctx, _alpnSelectCallback, GCHandle.ToIntPtr(_protocolsHandle));
-
- _ssl = OpenSsl.SSL_new(_ctx);
- @@ -181,9 +180,16 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Tls
- {
- var error = OpenSsl.SSL_get_error(_ssl, ret);
-
- - if (error != 2)
- + if (error == 1)
- {
- - throw new IOException($"TLS handshake failed: {nameof(OpenSsl.SSL_do_handshake)} error {error}.");
- + // SSL error, get it from the OpenSSL error queue
- + error = OpenSsl.ERR_get_error();
- + if (error == SSL_ERROR_HTTP_REQUEST)
- + {
- + throw new InvalidOperationException("Unencrypted HTTP traffic was sent to an HTTPS endpoint");
- + }
- + var errorString = OpenSsl.ERR_error_string(error);
- + throw new IOException($"TLS handshake failed: {nameof(OpenSsl.SSL_do_handshake)} error {error}. {errorString}");
- }
- }
-
|