Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Unix: machine certificate store throws on load when it contains certificates the user has no read permission for #26294

Closed
tmds opened this issue May 28, 2018 · 36 comments
Labels
area-System.Security bug tenet-compatibility Incompatibility with previous versions or .NET Framework
Milestone

Comments

@tmds
Copy link
Member

tmds commented May 28, 2018

On Fedora 27:

       static async Task Main(string[] args)
        {
            using (var httpClient = new HttpClient())
            {
                var response = await httpClient.GetAsync("https://www.microsoft.com");
                System.Console.WriteLine(response.StatusCode);
            }
        }

With 2.1.300-rc1-008673 gives

OK

But with the 2.1.300 (https://github.com/aspnet/Home/wiki/2.1.0-Early-Access-Downloads) throws:

Unhandled Exception: System.Net.Http.HttpRequestException: The SSL connection could not be established, see inner exception. ---> Interop+Crypto+OpenSslCryptographicException: error:2006D002:BIO routines:BIO_new_file:system lib
   at Interop.Crypto.CheckValidOpenSslHandle(SafeHandle handle)
   at Internal.Cryptography.Pal.StorePal.LoadMachineStores()
   at Internal.Cryptography.Pal.StorePal.FromSystemStore(String storeName, StoreLocation storeLocation, OpenFlags openFlags)
   at System.Security.Cryptography.X509Certificates.X509Store.Open(OpenFlags flags)
   at Internal.Cryptography.Pal.OpenSslX509ChainProcessor.FindCandidates(X509Certificate2 leaf, X509Certificate2Collection extraStore, HashSet`1 downloaded, HashSet`1 systemTrusted, TimeSpan& remainingDownloadTime)
   at Internal.Cryptography.Pal.ChainPal.BuildChain(Boolean useMachineContext, ICertificatePal cert, X509Certificate2Collection extraStore, OidCollection applicationPolicy, OidCollection certificatePolicy, X509RevocationMode revocationMode, X509RevocationFlag revocationFlag, DateTime verificationTime, TimeSpan timeout)
   at System.Security.Cryptography.X509Certificates.X509Chain.Build(X509Certificate2 certificate, Boolean throwOnException)
   at System.Security.Cryptography.X509Certificates.X509Chain.Build(X509Certificate2 certificate)
   at System.Net.Security.CertificateValidation.BuildChainAndVerifyProperties(X509Chain chain, X509Certificate2 remoteCertificate, Boolean checkCertName, String hostName)
   at System.Net.Security.SecureChannel.VerifyRemoteCertificate(RemoteCertValidationCallback remoteCertValidationCallback, ProtocolToken& alertToken)
   at System.Net.Security.SslState.CompleteHandshake(ProtocolToken& alertToken)
   at System.Net.Security.SslState.CheckCompletionBeforeNextReceive(ProtocolToken message, AsyncProtocolRequest asyncRequest)
   at System.Net.Security.SslState.StartSendBlob(Byte[] incoming, Int32 count, AsyncProtocolRequest asyncRequest)
   at System.Net.Security.SslState.ProcessReceivedBlob(Byte[] buffer, Int32 count, AsyncProtocolRequest asyncRequest)
   at System.Net.Security.SslState.StartReadFrame(Byte[] buffer, Int32 readBytes, AsyncProtocolRequest asyncRequest)
   at System.Net.Security.SslState.StartReceiveBlob(Byte[] buffer, AsyncProtocolRequest asyncRequest)
   at System.Net.Security.SslState.CheckCompletionBeforeNextReceive(ProtocolToken message, AsyncProtocolRequest asyncRequest)
   at System.Net.Security.SslState.StartSendBlob(Byte[] incoming, Int32 count, AsyncProtocolRequest asyncRequest)
   at System.Net.Security.SslState.ProcessReceivedBlob(Byte[] buffer, Int32 count, AsyncProtocolRequest asyncRequest)
   at System.Net.Security.SslState.StartReadFrame(Byte[] buffer, Int32 readBytes, AsyncProtocolRequest asyncRequest)
   at System.Net.Security.SslState.StartReceiveBlob(Byte[] buffer, AsyncProtocolRequest asyncRequest)
   at System.Net.Security.SslState.CheckCompletionBeforeNextReceive(ProtocolToken message, AsyncProtocolRequest asyncRequest)
   at System.Net.Security.SslState.StartSendBlob(Byte[] incoming, Int32 count, AsyncProtocolRequest asyncRequest)
   at System.Net.Security.SslState.ProcessReceivedBlob(Byte[] buffer, Int32 count, AsyncProtocolRequest asyncRequest)
   at System.Net.Security.SslState.StartReadFrame(Byte[] buffer, Int32 readBytes, AsyncProtocolRequest asyncRequest)
   at System.Net.Security.SslState.PartialFrameCallback(AsyncProtocolRequest asyncRequest)
--- End of stack trace from previous location where exception was thrown ---
   at System.Net.Security.SslState.ThrowIfExceptional()
   at System.Net.Security.SslState.InternalEndProcessAuthentication(LazyAsyncResult lazyResult)
   at System.Net.Security.SslState.EndProcessAuthentication(IAsyncResult result)
   at System.Net.Security.SslStream.EndAuthenticateAsClient(IAsyncResult asyncResult)
   at System.Net.Security.SslStream.<>c.<AuthenticateAsClientAsync>b__47_1(IAsyncResult iar)
   at System.Threading.Tasks.TaskFactory`1.FromAsyncCoreLogic(IAsyncResult iar, Func`2 endFunction, Action`1 endAction, Task`1 promise, Boolean requiresSynchronization)
--- End of stack trace from previous location where exception was thrown ---
   at System.Net.Http.ConnectHelper.EstablishSslConnectionAsyncCore(Stream stream, SslClientAuthenticationOptions sslOptions, CancellationToken cancellationToken)
   --- End of inner exception stack trace ---
   at System.Net.Http.ConnectHelper.EstablishSslConnectionAsyncCore(Stream stream, SslClientAuthenticationOptions sslOptions, CancellationToken cancellationToken)
   at System.Threading.Tasks.ValueTask`1.get_Result()
   at System.Net.Http.HttpConnectionPool.CreateConnectionAsync(HttpRequestMessage request, CancellationToken cancellationToken)
   at System.Threading.Tasks.ValueTask`1.get_Result()
   at System.Net.Http.HttpConnectionPool.WaitForCreatedConnectionAsync(ValueTask`1 creationTask)
   at System.Threading.Tasks.ValueTask`1.get_Result()
   at System.Net.Http.HttpConnectionPool.SendWithRetryAsync(HttpRequestMessage request, Boolean doRequestAuth, CancellationToken cancellationToken)
   at System.Net.Http.RedirectHandler.SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
   at System.Net.Http.HttpClient.FinishSendAsyncBuffered(Task`1 sendTask, HttpRequestMessage request, CancellationTokenSource cts, Boolean disposeCts)
   at console.Program.Main(String[] args) in /tmp/console/Program.cs:line 13
   at console.Program.<Main>(String[] args)
/tmp/console$ dotnet run

Unhandled Exception: System.Net.Http.HttpRequestException: The SSL connection could not be established, see inner exception. ---> Interop+Crypto+OpenSslCryptographicException: error:2006D002:BIO routines:BIO_new_file:system lib
   at Interop.Crypto.CheckValidOpenSslHandle(SafeHandle handle)
   at Internal.Cryptography.Pal.StorePal.LoadMachineStores()
   at Internal.Cryptography.Pal.StorePal.FromSystemStore(String storeName, StoreLocation storeLocation, OpenFlags openFlags)
   at System.Security.Cryptography.X509Certificates.X509Store.Open(OpenFlags flags)
   at Internal.Cryptography.Pal.OpenSslX509ChainProcessor.FindCandidates(X509Certificate2 leaf, X509Certificate2Collection extraStore, HashSet`1 downloaded, HashSet`1 systemTrusted, TimeSpan& remainingDownloadTime)
   at Internal.Cryptography.Pal.ChainPal.BuildChain(Boolean useMachineContext, ICertificatePal cert, X509Certificate2Collection extraStore, OidCollection applicationPolicy, OidCollection certificatePolicy, X509RevocationMode revocationMode, X509RevocationFlag revocationFlag, DateTime verificationTime, TimeSpan timeout)
   at System.Security.Cryptography.X509Certificates.X509Chain.Build(X509Certificate2 certificate, Boolean throwOnException)
   at System.Security.Cryptography.X509Certificates.X509Chain.Build(X509Certificate2 certificate)
   at System.Net.Security.CertificateValidation.BuildChainAndVerifyProperties(X509Chain chain, X509Certificate2 remoteCertificate, Boolean checkCertName, String hostName)
   at System.Net.Security.SecureChannel.VerifyRemoteCertificate(RemoteCertValidationCallback remoteCertValidationCallback, ProtocolToken& alertToken)
   at System.Net.Security.SslState.CompleteHandshake(ProtocolToken& alertToken)
   at System.Net.Security.SslState.CheckCompletionBeforeNextReceive(ProtocolToken message, AsyncProtocolRequest asyncRequest)
   at System.Net.Security.SslState.StartSendBlob(Byte[] incoming, Int32 count, AsyncProtocolRequest asyncRequest)
   at System.Net.Security.SslState.ProcessReceivedBlob(Byte[] buffer, Int32 count, AsyncProtocolRequest asyncRequest)
   at System.Net.Security.SslState.StartReadFrame(Byte[] buffer, Int32 readBytes, AsyncProtocolRequest asyncRequest)
   at System.Net.Security.SslState.StartReceiveBlob(Byte[] buffer, AsyncProtocolRequest asyncRequest)
   at System.Net.Security.SslState.CheckCompletionBeforeNextReceive(ProtocolToken message, AsyncProtocolRequest asyncRequest)
   at System.Net.Security.SslState.StartSendBlob(Byte[] incoming, Int32 count, AsyncProtocolRequest asyncRequest)
   at System.Net.Security.SslState.ProcessReceivedBlob(Byte[] buffer, Int32 count, AsyncProtocolRequest asyncRequest)
   at System.Net.Security.SslState.StartReadFrame(Byte[] buffer, Int32 readBytes, AsyncProtocolRequest asyncRequest)
   at System.Net.Security.SslState.StartReceiveBlob(Byte[] buffer, AsyncProtocolRequest asyncRequest)
   at System.Net.Security.SslState.CheckCompletionBeforeNextReceive(ProtocolToken message, AsyncProtocolRequest asyncRequest)
   at System.Net.Security.SslState.StartSendBlob(Byte[] incoming, Int32 count, AsyncProtocolRequest asyncRequest)
   at System.Net.Security.SslState.ProcessReceivedBlob(Byte[] buffer, Int32 count, AsyncProtocolRequest asyncRequest)
   at System.Net.Security.SslState.StartReadFrame(Byte[] buffer, Int32 readBytes, AsyncProtocolRequest asyncRequest)
   at System.Net.Security.SslState.PartialFrameCallback(AsyncProtocolRequest asyncRequest)
--- End of stack trace from previous location where exception was thrown ---
   at System.Net.Security.SslState.ThrowIfExceptional()
   at System.Net.Security.SslState.InternalEndProcessAuthentication(LazyAsyncResult lazyResult)
   at System.Net.Security.SslState.EndProcessAuthentication(IAsyncResult result)
   at System.Net.Security.SslStream.EndAuthenticateAsClient(IAsyncResult asyncResult)
   at System.Net.Security.SslStream.<>c.<AuthenticateAsClientAsync>b__47_1(IAsyncResult iar)
   at System.Threading.Tasks.TaskFactory`1.FromAsyncCoreLogic(IAsyncResult iar, Func`2 endFunction, Action`1 endAction, Task`1 promise, Boolean requiresSynchronization)
--- End of stack trace from previous location where exception was thrown ---
   at System.Net.Http.ConnectHelper.EstablishSslConnectionAsyncCore(Stream stream, SslClientAuthenticationOptions sslOptions, CancellationToken cancellationToken)
   --- End of inner exception stack trace ---
   at System.Net.Http.ConnectHelper.EstablishSslConnectionAsyncCore(Stream stream, SslClientAuthenticationOptions sslOptions, CancellationToken cancellationToken)
   at System.Threading.Tasks.ValueTask`1.get_Result()
   at System.Net.Http.HttpConnectionPool.CreateConnectionAsync(HttpRequestMessage request, CancellationToken cancellationToken)
   at System.Threading.Tasks.ValueTask`1.get_Result()
   at System.Net.Http.HttpConnectionPool.WaitForCreatedConnectionAsync(ValueTask`1 creationTask)
   at System.Threading.Tasks.ValueTask`1.get_Result()
   at System.Net.Http.HttpConnectionPool.SendWithRetryAsync(HttpRequestMessage request, Boolean doRequestAuth, CancellationToken cancellationToken)
   at System.Net.Http.RedirectHandler.SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
   at System.Net.Http.HttpClient.FinishSendAsyncBuffered(Task`1 sendTask, HttpRequestMessage request, CancellationTokenSource cts, Boolean disposeCts)
   at console.Program.Main(String[] args) in /tmp/console/Program.cs:line 13
   at console.Program.<Main>(String[] args)
@tmds
Copy link
Member Author

tmds commented May 28, 2018

CheckValidOpenSslHandle throws in LoadMachineStores:

https://github.com/dotnet/corefx/blob/cf195c1d0b782e1c5af8af8cf73f57b01cb41d95/src/System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.Unix/StorePal.cs#L253-L262

This was added in dotnet/corefx#29351

Instead of skipping the cert file we are now throwing.

The handle is not valid for files that the user can't read.

$ ls -lah /etc/pki/tls/certs/
total 24K
drwxr-xr-x. 2 root root 4.0K Apr 24 11:17 .
drwxr-xr-x. 5 root root 4.0K Apr  3 13:18 ..
-rw-r-----. 1 root root 1.5K Oct 28  2016 2015-RH-IT-Root-CA.pem
lrwxrwxrwx. 1 root root   49 Feb  6 14:48 ca-bundle.crt -> /etc/pki/ca-trust/extracted/pem/tls-ca-bundle.pem
lrwxrwxrwx. 1 root root   55 Feb  6 14:48 ca-bundle.trust.crt -> /etc/pki/ca-trust/extracted/openssl/ca-bundle.trust.crt
-rw-r--r--. 1 root root 2.5K Apr  3 13:18 Makefile
-rw-r-----. 1 root root 1.4K Oct 28  2016 newca.crt
-rw-r-----. 1 root root 1019 Oct 28  2016 oracle_ebs.crt

@tmds tmds changed the title HttpClient throws for SSL with 2.1.300 build and not with 2.1.300-rc1 on Fedora 27 Unix: machine certificate store throws on load when it contains certificates the user has no read permission for May 28, 2018
@stephentoub
Copy link
Member

cc: @pjanotti

@tmds
Copy link
Member Author

tmds commented May 28, 2018

The files that trigger the issue are not part of the default system installation. So it does not affect every system. You need to have installed a package that brings such files. In my case, they come with the package that configures my system for access to the corporate vpn.

@danmoseley
Copy link
Member

@tmds for shiproom do you have data suggesting how commonly systems are configured this way? Is there a feasible workaround? Do you know how long this was regressed?

@tmds
Copy link
Member Author

tmds commented May 30, 2018

for shiproom do you have data suggesting how commonly systems are configured this way?

For me it is due to the company vpn package adding certificates that are only readable by root.
I'm not sure if this is specific to the way we have packed up those certificates, or if you'd see this for other vpn packages too.
It won't affect many users.

Is there a feasible workaround?

The workaround is to change permissions on the system certificates. You need to have root permissions and be willing to change permissions on those files. This may have security side-effects.

Do you know how long this was regressed?

It regressed after 2.1-rc1.

If you're not including it for servicing we may patch our .NET Core builds for Fedora/RHEL/CentOS. Our preference is to minimize such differences, so that's why I'm asking here first.

CC @omajid

@danmoseley
Copy link
Member

danmoseley commented May 30, 2018

That's a very recent regression - you're sure the certificates were present at the time you tested with RC1?

@stephentoub any idea where the regression might have been?

@stephentoub
Copy link
Member

@pjanotti
Copy link
Contributor

I missed this earlier... yes, the recent change to keep the SSL error queue clean introduced this.

@saluton-mundo
Copy link

We've also encountered this issue on CentOS 7.5.1804. Our install of Apache (2.4.6) and mod_ssl created a default localhost.crt which the user we are running the site under did not have access to.

To avoid using a permissions workaround (running the site as root or giving read access to the certificate file) we simply moved the localhost.crt to a different folder and updated the Apache config.

stephentoub referenced this issue in dotnet/corefx Jun 5, 2018
* Skip certificates we can't read when populating machine store.

This is a regression in 2.1.0 (#29351).

Fixes https://github.com/dotnet/corefx/issues/29942.

* Add test

* Assert chmod returns 0

* Skip test on OSX

* Add valid content to the unreadable cert file
@stephentoub stephentoub reopened this Jun 5, 2018
stephentoub referenced this issue in stephentoub/corefx Jun 5, 2018
…t#29973)

* Skip certificates we can't read when populating machine store.

This is a regression in 2.1.0 (dotnet#29351).

Fixes https://github.com/dotnet/corefx/issues/29942.

* Add test

* Assert chmod returns 0

* Skip test on OSX

* Add valid content to the unreadable cert file
@stephentoub
Copy link
Member

Fixed in master

@tmds
Copy link
Member Author

tmds commented Jun 6, 2018

@danmosemsft in the meanwhile, it is not only folks with our vpn package that are hitting this.

@dlech
Copy link

dlech commented Jun 7, 2018

For me, this bug was triggered by a broken symlink in /etc/ssl/certs/. By deleting the broken link, I was able to avoid the error.

@danmoseley
Copy link
Member

@dlech thanks. Hopefully until this can be serviced, folks getting this stacktrace will find this issue and figure out the workarounds.

@bobberb
Copy link

bobberb commented Jun 9, 2018

I get this same error when a chromecast device tries to hit my nginx server running emby which depends on mono.

Should I be putting in a issue with the mono group, or is this upstream? Sorry, just came here by googling my errors.

@danmoseley
Copy link
Member

Interesting about Mono. @marek-safar do you guys need the fix dotnet/corefx#29973?

@marek-safar
Copy link
Contributor

@danmosemsft not yet, we didn't switch X509Certificates yet

@hpinsley
Copy link

hpinsley commented Jun 11, 2018

I'm getting a similar error -- except it is Interop+Crypto+OpenSslCryptographicException: error:2006D080:BIO routines:BIO_new_file:no such file without any indication of the problematic file. I suspect the pull request that addresses this issue may also fix this... Any way to determine what the problematic file would be?

[20:24:12 INF] Executing action method CoreWebLinuxContainer.Controllers.HttpTestController.GetIdentityServerPage (CoreWebLinuxContainer) - Validation state: Valid
[20:24:12 INF] Executed action CoreWebLinuxContainer.Controllers.HttpTestController.GetIdentityServerPage (CoreWebLinuxContainer) in 99.0609ms
[20:24:12 ERR] Connection id "0HLEFR536L7UI", Request id "0HLEFR536L7UI:00000003": An unhandled exception was thrown by the application.
System.Net.Http.HttpRequestException: The SSL connection could not be established, see inner exception. ---> Interop+Crypto+OpenSslCryptographicException: error:2006D080:BIO routines:BIO_new_file:no such file
   at Interop.Crypto.CheckValidOpenSslHandle(SafeHandle handle)
   at Internal.Cryptography.Pal.StorePal.LoadMachineStores()
   at Internal.Cryptography.Pal.StorePal.FromSystemStore(String storeName, StoreLocation storeLocation, OpenFlags openFlags)
   at System.Security.Cryptography.X509Certificates.X509Store.Open(OpenFlags flags)
   at Internal.Cryptography.Pal.OpenSslX509ChainProcessor.FindCandidates(X509Certificate2 leaf, X509Certificate2Collection extraStore, HashSet`1 downloaded, HashSet`1 systemTrusted, TimeSpan& remainingDownloadTime)
   at Internal.Cryptography.Pal.ChainPal.BuildChain(Boolean useMachineContext, ICertificatePal cert, X509Certificate2Collection extraStore, OidCollection applicationPolicy, OidCollection certificatePolicy, X509RevocationMode revocationMode, X509RevocationFlag revocationFlag, DateTime verificationTime, TimeSpan timeout)
   at System.Security.Cryptography.X509Certificates.X509Chain.Build(X509Certificate2 certificate, Boolean throwOnException)
   at System.Security.Cryptography.X509Certificates.X509Chain.Build(X509Certificate2 certificate)
   at System.Net.Security.CertificateValidation.BuildChainAndVerifyProperties(X509Chain chain, X509Certificate2 remoteCertificate, Boolean checkCertName, String hostName)
   at System.Net.Security.SecureChannel.VerifyRemoteCertificate(RemoteCertValidationCallback remoteCertValidationCallback, ProtocolToken& alertToken)
   at System.Net.Security.SslState.CompleteHandshake(ProtocolToken& alertToken)
   at System.Net.Security.SslState.CheckCompletionBeforeNextReceive(ProtocolToken message, AsyncProtocolRequest asyncRequest)
   at System.Net.Security.SslState.StartSendBlob(Byte[] incoming, Int32 count, AsyncProtocolRequest asyncRequest)
   at System.Net.Security.SslState.ProcessReceivedBlob(Byte[] buffer, Int32 count, AsyncProtocolRequest asyncRequest)
   at System.Net.Security.SslState.StartReadFrame(Byte[] buffer, Int32 readBytes, AsyncProtocolRequest asyncRequest)
   at System.Net.Security.SslState.PartialFrameCallback(AsyncProtocolRequest asyncRequest)

@omajid
Copy link
Member

omajid commented Jun 11, 2018

@hpinsley Try an strace and look for open or openat syscalls that failed in the strace output.

@danmoseley
Copy link
Member

@bobberb it looks like you should open an issue directly against Mono as they don't use our code for this yet.

@hpinsley
Copy link

@omajid Thanks. I neglected to mention that this was running in a Docker container. Note that I tried to install strace but when I ran it, it didn't show the failed file open for some reason.

It turned out to be a broken symbolic link in /etc/ssl/certs. We are running the container on a Linux host that has our corporate certs installed. To get SSL to work in our .NET Core code running within a hosted container, I was mapping the host's /etc/ssl/certs folder into the container. As I had already seen symbolic links from /etc/ssl/certs to /usr/share/ca-certificates, I mapped that folder as well but missed a single file that was linked to /usr/local/share/ca-certificates. I solved my problem by also mapping /usr/local/share/ca-certficates.

@ydekova
Copy link

ydekova commented Jun 13, 2018

We are having this issue after upgrade to 2.1 (from 1.1) with Ubuntu 16.04.1. There is really nothing special about this machine. Probably some of the problematic certificates are installed by AWS LB.

I'm not very familiar with how the releases are happening so what are our options in this case to get this fix?

@danmoseley
Copy link
Member

@ydekova until the patch is out, you could use a nightly build: https://github.com/dotnet/corefx/blob/master/Documentation/project-docs/dogfooding.md#advanced-scenario---using-a-nightly-build-of-microsoftnetcoreapp

Or you could follow this suggestion https://github.com/dotnet/corefx/issues/29942#issuecomment-396420408 to try to find out the problematic cert and either change access to it or move it.

@ydekova
Copy link

ydekova commented Jun 14, 2018

@danmosemsft thanks for your quick reply.

I tried to run the process with root user, check the /etc/ssl/certs/ for broken links and what their permissions are, but none of those worked for us.

I managed to work around it by overriding the server certificate validation via the ServerCertificateCustomValidationCallback property of the HttpClientHandler.

 httpClientHandler.ServerCertificateCustomValidationCallback = (message, cert, chain, errors) => {
                    if (errors != System.Net.Security.SslPolicyErrors.None)
                    {
......

Here is what I found:

The certificate (cert parameter in the method above) seems valid (It is issued by Microsoft graph/outlook API, subject name is "CN=Outlook.office.com, O=Microsoft Corporation, L=Redmond, S=Washington, C=US", I'm no expert in certificates though..). I doubt it the problem is with the certificate because:

  • This same certificate works with the previous version (net core 1.1.).
  • It is not happening on windows, just on Ubuntu.
  • Works with the certificate issued by Google APIs.

The SslPolicyError (errors param in the above code) is RemoteCertificateNameMismatch

Any idea what might this means?

I don't feel comfortable with disabling ssl certificate validation altogether. If I ignore this kind of error in the method above is this a potential security bridge?

@tmds
Copy link
Member Author

tmds commented Jun 14, 2018

@ydekova did you get a stacktrace that contains these lines:

   at Interop.Crypto.CheckValidOpenSslHandle(SafeHandle handle)
   at Internal.Cryptography.Pal.StorePal.LoadMachineStores()

Try running this on your system:

using System;
using System.Diagnostics;
using System.IO;
using System.Runtime.InteropServices;

namespace console
{
    class Program
    {
        internal const string CryptoNative = "System.Security.Cryptography.Native.OpenSsl";

        static void TryOpenFile(string filename)
        {
            try
            {
                using (File.OpenRead(filename)) {}
            }
            catch (Exception ex)
            {
                System.Console.WriteLine($"--> Cannot open file '{filename}': {ex.Message}");
            }
        }

        static void ListFiles(string path, bool isDir)
        {
            System.Console.WriteLine($"ls {path}");

            Process.Start("ls", $"-lah \"{path}\"").WaitForExit();
            System.Console.WriteLine();

            if (isDir)
            {
                foreach (var file in Directory.GetFiles(path))
                {
                    TryOpenFile(file);
                }
            }
            else
            {
                TryOpenFile(path);
            }

            System.Console.WriteLine();
        }

        static void Main(string[] args)
        {
            ListFiles(GetX509RootStorePath(), isDir: true);
            ListFiles(GetX509RootStoreFile(), isDir: false);
        }

        internal static string GetX509RootStorePath()
        {
            return Marshal.PtrToStringAnsi(GetX509RootStorePath_private());
        }

        internal static string GetX509RootStoreFile()
        {
            return Marshal.PtrToStringAnsi(GetX509RootStoreFile_private());
        }

        [DllImport(CryptoNative, EntryPoint = "CryptoNative_GetX509RootStorePath")]
        private static extern IntPtr GetX509RootStorePath_private();

        [DllImport(CryptoNative, EntryPoint = "CryptoNative_GetX509RootStoreFile")]
        private static extern IntPtr GetX509RootStoreFile_private();
    }
}

@ydekova
Copy link

ydekova commented Jun 14, 2018

@tmds this program gives me

ls /usr/lib/ssl/certs
lrwxrwxrwx 1 root root 14 Sep 23 2016 /usr/lib/ssl/certs -> /etc/ssl/certs

ls /usr/lib/ssl/cert.pem
ls: cannot access '/usr/lib/ssl/cert.pem': No such file or directory

--> Cannot open file '/usr/lib/ssl/cert.pem': Could not find file '/usr/lib/ssl/cert.pem'.

And this is the stack trace of my apps exception as far as i can track

System.Net.Http.HttpRequestException: The SSL connection could not be established, see inner exception. 
   at System.Net.Http.ConnectHelper.EstablishSslConnectionAsyncCore(Stream stream, SslClientAuthenticationOptions sslOptions, CancellationToken cancellationToken)
   at System.Threading.Tasks.ValueTask`1.get_Result()
   at System.Net.Http.HttpConnectionPool.CreateConnectionAsync(HttpRequestMessage request, CancellationToken cancellationToken)
   at System.Threading.Tasks.ValueTask`1.get_Result()
   at System.Net.Http.HttpConnectionPool.WaitForCreatedConnectionAsync(ValueTask`1 creationTask)
   at System.Threading.Tasks.ValueTask`1.get_Result()
   at System.Net.Http.HttpConnectionPool.SendWithRetryAsync(HttpRequestMessage request, Boolean doRequestAuth, CancellationToken cancellationToken)
   at System.Net.Http.RedirectHandler.SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
   at System.Net.Http.HttpClient.FinishSendAsyncBuffered(Task`1 sendTask, HttpRequestMessage request, CancellationTokenSource cts, Boolean disposeCts)
  
Inner:  
System.Security.Authentication.AuthenticationException: The remote certificate is invalid according to the validation procedure. 
   at System.Net.Security.SslState.StartSendAuthResetSignal(ProtocolToken message, AsyncProtocolRequest asyncRequest, ExceptionDispatchInfo exception)
   at System.Net.Security.SslState.CheckCompletionBeforeNextReceive(ProtocolToken message, AsyncProtocolRequest asyncRequest)
   at System.Net.Security.SslState.StartSendBlob(Byte[] incoming, Int32 count, AsyncProtocolRequest asyncRequest)
   at System.Net.Security.SslState.ProcessReceivedBlob(Byte[] buffer, Int32 count, AsyncProtocolRequest asyncRequest)
   at System.Net.Security.SslState.StartReadFrame(Byte[] buffer, Int32 readBytes, AsyncProtocolRequest asyncRequest)
   at System.Net.Security.SslState.StartReceiveBlob(Byte[] buffer, AsyncProtocolRequest asyncRequest)
   at System.Net.Security.SslState.CheckCompletionBeforeNextReceive(ProtocolToken message, AsyncProtocolRequest asyncRequest)
   at System.Net.Security.SslState.StartSendBlob(Byte[] incoming, Int32 count, AsyncProtocolRequest asyncRequest)
   at System.Net.Security.SslState.ProcessReceivedBlob(Byte[] buffer, Int32 count, AsyncProtocolRequest asyncRequest)
   at System.Net.Security.SslState.StartReadFrame(Byte[] buffer, Int32 readBytes, AsyncProtocolRequest asyncRequest)
   at System.Net.Security.SslState.PartialFrameCallback(AsyncProtocolRequest asyncRequest)
--- End of stack trace from previous location where exception was thrown ---
   at System.Net.Security.SslState.ThrowIfExceptional()
   at System.Net.Security.SslState.InternalEndProcessAuthentication(LazyAsyncResult lazyResult)
   at System.Net.Security.SslState.EndProcessAuthentication(IAsyncResult result)
   at System.Net.Security.SslStream.EndAuthenticateAsClient(IAsyncResult asyncResult)
   at System.Net.Security.SslStream.<>c.<AuthenticateAsClientAsync>b__47_1(IAsyncResult iar)
   at System.Threading.Tasks.TaskFactory`1.FromAsyncCoreLogic(IAsyncResult iar, Func`2 endFunction, Action`1 endAction, Task`1 promise, Boolean requiresSynchronization)
--- End of stack trace from previous location where exception was thrown ---
   at System.Net.Http.ConnectHelper.EstablishSslConnectionAsyncCore(Stream stream, SslClientAuthenticationOptions sslOptions, CancellationToken cancellationToken)

@tmds
Copy link
Member Author

tmds commented Jun 14, 2018

@ydekova it is a different issue, I've created https://github.com/dotnet/corefx/issues/30388 based on the info you gave. It should work on 2.1 when using the curlhandler (set DOTNET_SYSTEM_NET_HTTP_USESOCKETSHTTPHANDLER=0).

@ydekova
Copy link

ydekova commented Jun 14, 2018

@tmds thanks for your assistance.

DOTNET_SYSTEM_NET_HTTP_USESOCKETSHTTPHANDLER - if this is an environment variable setting it to 0 didn't really fixed it for us.

I'll add my temp workaround here https://github.com/dotnet/corefx/issues/30388

filipnavara referenced this issue in filipnavara/corefx Jun 25, 2018
…t#29973)

* Skip certificates we can't read when populating machine store.

This is a regression in 2.1.0 (dotnet#29351).

Fixes https://github.com/dotnet/corefx/issues/29942.

* Add test

* Assert chmod returns 0

* Skip test on OSX

* Add valid content to the unreadable cert file
marek-safar referenced this issue in mono/corefx Jun 25, 2018
…t#29973)

* Skip certificates we can't read when populating machine store.

This is a regression in 2.1.0 (dotnet#29351).

Fixes https://github.com/dotnet/corefx/issues/29942.

* Add test

* Assert chmod returns 0

* Skip test on OSX

* Add valid content to the unreadable cert file
stephentoub referenced this issue in dotnet/corefx Jun 26, 2018
… (#30155)

* Skip certificates we can't read when populating machine store.

This is a regression in 2.1.0 (#29351).

Fixes https://github.com/dotnet/corefx/issues/29942.

* Add test

* Assert chmod returns 0

* Skip test on OSX

* Add valid content to the unreadable cert file
@karelz
Copy link
Member

karelz commented Jul 8, 2018

Fixed in release/2.1 branch in PR dotnet/corefx#30155. Will be part of 2.1.3 release.

@karelz karelz closed this as completed Jul 8, 2018
@joshuataylor
Copy link

You can also try the following on Ubuntu, if you have invalid certs for whatever reason:

sudo update-ca-certificates  --fresh

This will remove invalid symlinked certs for you.

@mkurz
Copy link

mkurz commented Jul 19, 2018

@joshuataylor Thanks, that fixed the problem for me!

@danielcrabtree
Copy link

The 2.1.3 release fixed this for me on Cent OS 7.5. Thanks for getting this resolved.

@Beanow
Copy link

Beanow commented Sep 21, 2018

The 2.1.3 release is not yet available on the Ubuntu 17.10 apt repositories.

@karelz
Copy link
Member

karelz commented Sep 21, 2018

@leecow is that expected? @Beanow can you please raise it on dotnet/core repo?
For context: https://github.com/dotnet/core/blob/master/release-notes/2.1/2.1.3/2.1.3-download.md

@mkurz
Copy link

mkurz commented Sep 21, 2018

Ubuntu 17.10 is EOL:
https://wiki.ubuntu.com/Releases#End_of_Life

@karelz
Copy link
Member

karelz commented Sep 21, 2018

@leecow
Copy link
Member

leecow commented Sep 21, 2018

17.10 went EOL 7/19/2018 and 2.1.3 released 8/21. See https://github.com/dotnet/core/blob/master/os-lifecycle-policy.md for .NET Core version / distro version support details.

@msftgits msftgits transferred this issue from dotnet/corefx Jan 31, 2020
@msftgits msftgits added this to the 2.1.x milestone Jan 31, 2020
@ghost ghost locked as resolved and limited conversation to collaborators Dec 16, 2020
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
area-System.Security bug tenet-compatibility Incompatibility with previous versions or .NET Framework
Projects
None yet
Development

No branches or pull requests