I have been provided a certificate for a SQL Server, which has been successfully installed and activated. I can confirm this from the logs:
The certificate [Cert Hash(sha1) "xxxxxxxxxxxxxxxxxxE5C050F7D75F58E4E2F"] was successfully loaded for encryption.
Connecting to the database using SSMS is successful, simply by encrypting the connection without trusing the server certificate.
I wanted to replicate this using WSL and later on - docker.
I am testing this with a simple .net 6 console application:
var con = new SqlConnection("Server=domain.host.eu,50730;Database=databasename;User Id=user;Password='password';");
await con.OpenAsync();
var version = con.ExecuteScalar<string>("SELECT ##VERSION");
Console.WriteLine(version);
This works, if I add Trust Server Certificate=True; to the connection string. Without it, the connection fails:
Unhandled exception. Microsoft.Data.SqlClient.SqlException (0x80131904): A connection was successfully established with the server, but then an error occurred during the pre-login handshake. (provider: TCP Provider, error: 35 - An internal exception was caught)
---> System.Security.Authentication.AuthenticationException: The remote certificate was rejected by the provided RemoteCertificateValidationCallback.
at System.Net.Security.SslStream.SendAuthResetSignal(ProtocolToken message, ExceptionDispatchInfo exception)
at System.Net.Security.SslStream.CompleteHandshake(SslAuthenticationOptions sslAuthenticationOptions)
at System.Net.Security.SslStream.ForceAuthenticationAsync[TIOAdapter](TIOAdapter adapter, Boolean receiveFirst, Byte[] reAuthenticationData, Boolean isApm)
at System.Net.Security.SslStream.AuthenticateAsClient(SslClientAuthenticationOptions sslClientAuthenticationOptions)
at System.Net.Security.SslStream.AuthenticateAsClient(String targetHost, X509CertificateCollection clientCertificates, SslProtocols enabledSslProtocols, Boolean checkCertificateRevocation)
I wanted to extract the certificate from the pfx:
openssl pkcs12 -in host.domain.eu.pem.pfx -clcerts -nokeys -out host.domain.eu.crt
sudo cp host.domain.eu.crt /usr/local/share/ca-certificates/
sudo update-ca-certificates
Unfortunately, this fails with the same error messages and I don't know where I went wrong. I can only assume, that my handling of the certs on Linux is wrong.
If you're connecting to something unimportant, I was experiencing this error connecting from my dotnetcore API, to a microsoft sql server contained in a docker container (all locally) for dev work. My solution was putting encrypt=False at the end of my connection string like so (within appsettings.json):
"DefaultConnection": "server=localhost;database=newcomparer;trusted_connection=false;User Id=sa;Password=reallyStrongPwd123;Persist Security Info=False;Encrypt=False"
I double blindsided myself and got distracted by 2 mishaps at the same time.
After importing a certificate into the SQL Configuration Manager, you can choose from 2 nigh on identical entries. The difference beeing one having a friendly name of host.domain (FQDN), while the other has no friendly name.
Naturally I have not double checked and just stayed with the one without the FQDN as the friendly name, which was pre-selected after the import and looked valid.
The second mistake was to not realize, that WSL was not part of our domain and could not resolve the database name. So I used to the FQDN to reach it. This caused the mismatch between host, which the database instance expected and host.domain, which the client from inside WSL used.
After this I borrowed an Ubuntu vm inside our domain and verified, that using only the host,port schema in the connection string works.
And to make it explicit and work inside wsl I switched the certificates around to require the FQDN as the friendly namae while connecting, so connections can be made from inside the domain, as well as "outside" (from wsl).
tl;dr: One possible explanation for the exception The remote certificate was rejected by the provided RemoteCertificateValidationCallback. is, that the instance name in the connection string and the expected name from the instance do not match.
Related
I'm attempting to connect to an IMAP server using the following code on a Windows Server 2019 machine:
using (var client = new ImapClient(new ProtocolLogger("protocol.log")))
{
var address = EnvReader.GetStringValue("EMAIL_ADDRESS");
var password = EnvReader.GetStringValue("EMAIL_PASSWORD");
var creds = new NetworkCredential(address, password);
client.CheckCertificateRevocation = false;
client.ServerCertificateValidationCallback = (s, c, h, e) =>
{
Console.WriteLine("ALL UP IN THIS CALLBACK" + e.ToString());
return true;
};
client.Connect("outlook.office365.com", 993, SecureSocketOptions.SslOnConnect);
client.Authenticate(address, password);
}
On my Mac, this code runs perfectly fine, I can connect and subsequently authenticate just fine.
On the Windows machine I receive the following exception:
MailKit.Security.SslHandshakeException: An error occurred while attempting to establish an SSL or TLS connection.
This usually means that the SSL certificate presented by the server is not trusted by the system for one or more of
the following reasons:
1. The server is using a self-signed certificate which cannot be verified.
2. The local system is missing a Root or Intermediate certificate needed to verify the server's certificate.
3. A Certificate Authority CRL server for one or more of the certificates in the chain is temporarily unavailable.
4. The certificate presented by the server is expired or invalid.
5. The set of SSL/TLS protocols supported by the client and server do not match.
6. You are trying to connect to a port which does not support SSL/TLS.
See https://github.com/jstedfast/MailKit/blob/master/FAQ.md#SslHandshakeException for possible solutions
Based on the info in the linked FAQ, I added the ServerCertificateValidationCallback, however the callback is never hit (The previously mentioned exception is still thrown, the relevant console logging never occurs, and a breakpoint inside the callback is never hit while debugging).
From my reading, the ServerCertificateValidationCallback should handle cases #1-4 that the exception message mentions. The fact that I can connect on the specified port on my Mac would seem to rule out case #6 (I also tried port 143 + SecureSocketOptions.StartTls). That leaves case #5, however, I can't find any information suggesting that Windows Server 2019 can't handle SSL/TSL protocols.
Any ideas for a) dealing with this exception and/or b) figuring out why the ServerCertificateValidationCallback is not firing would be greatly appreciated.
Edit: My project is referencing .NET 5.0
Let's go through each of the possibilities:
The server is using a self-signed certificate which cannot be verified.
outlook.office365.com would not be using a self-signed certificate, so that wouldn't be an issue in this case.
The local system is missing a Root or Intermediate certificate needed to verify the server's certificate.
This one is very possible, but the ServerCertificateValidationCallback override should be overriding this failure. However, it's not getting hit... so it's not actually bypassing this potential error.
A Certificate Authority CRL server for one or more of the certificates in the chain is temporarily unavailable.
This would be negated by client.CheckCertificateRevocation = false;
The certificate presented by the server is expired or invalid.
This is not the case because the certificate does not expire until 1/21/2022.
The set of SSL/TLS protocols supported by the client and server do not match.
The server supports at least TLSv1.2 which is a default TLS protocol version supported by MailKit in all target framework versions (.NET 4.5 -> 5.0 + netstandard2.x's).
You are trying to connect to a port which does not support SSL/TLS.
Port 993 is the correct port and SslOnConnect is the correct option, so this is not the issue.
Assuming there isn't a bug in MailKit's SslStream.AuthenticateAsClientAsync() call that passes in the validation callback method (.NET 5.0 is different than other versions), what is the InnerException? Maybe that will provide some insight.
I have a web API hosted on Heroku. It serves data from a ClearDB via a Golang program. I have a C# .NET script that will need to insert data into that ClearDB. I had this idea working on my local machine, but as I moved everything over to heroku, the C# part stopped working.
I have been successful in connecting with MySQL Workbench 8.0 and with my Golang program itself. The GO program can successfully connect, query, and serve data.
I know there are many other questions like this, and most of them seem to be solved with the connection string. I have tried almost ALL of the different ways you can string up a connection string. This is what i last tried (credentials have been changed to random letters):
connectionData = #"Server = eu-cd-steel-west-01.cleardb.net; Port = 3306; Database = heroku_555555555; Uid = b7039sldk253; Pwd = e3502ldks;";
The error I am getting happens when I run this:
connection = new MySqlConnection(connectionData);
connection.Open();
Error:
MySql.Data.MySqlClient.MySqlException (0x80004005): Unable to connect to any of the specified MySQL hosts.
---> System.InvalidOperationException: Sequence contains more than one matching element
at System.Linq.ThrowHelper.ThrowMoreThanOneMatchException()
at System.Linq.Enumerable.SingleOrDefault[TSource](IEnumerable`1 source, Func`2 predicate)
at MySql.Data.Common.StreamCreator.GetTcpStream(MySqlConnectionStringBuilder settings)
at MySql.Data.Common.StreamCreator.GetStream(MySqlConnectionStringBuilder settings)
at MySql.Data.MySqlClient.NativeDriver.Open()
at MySql.Data.MySqlClient.NativeDriver.Open()
at MySql.Data.MySqlClient.Driver.Open()
at MySql.Data.MySqlClient.Driver.Create(MySqlConnectionStringBuilder settings)
at MySql.Data.MySqlClient.MySqlPool.CreateNewPooledConnection()
at MySql.Data.MySqlClient.MySqlPool.GetPooledConnection()
at MySql.Data.MySqlClient.MySqlPool.TryToGetDriver()
at MySql.Data.MySqlClient.MySqlPool.GetConnection()
at MySql.Data.MySqlClient.MySqlConnection.Open()
at DatabaseTesting.DataBaser.connect() in C:\Users\surf.user\source\repos\DatabaseTesting\DatabaseTesting\DataBaser.cs:line 38
I understand there are SSL credentials and all sorts of stuff, but I am lead to believe that doesn't matter as I didn't have to configure anything special to connect on workbench. Is there anything extra I need to do to successfully open the ClearDB connection on C#?
I suspect you're running into this known bug in Oracle's MySQL Connector/NET: bug 97448. (I can't resolve the domain name you gave in the question, but if it resolves to more than one A record then that will trigger the bug.)
The fix is to uninstall the MySql.Data NuGet package and install MySqlConnector instead: https://www.nuget.org/packages/MySqlConnector/
This supports the same API as MySql.Data, so it should be a drop-in replacement.
I have written my own webserver in C#.
And I always established SSL certificates for my sites in new IP on port 443. And always it works fine.
But this time I get this error:
Secure Connection Failed
An error occurred during a connection to www.sayehrooshan-co.com. SSL received a record that exceeded the maximum permissible length. Error code:
SSL_ERROR_RX_RECORD_TOO_LONG
The page you are trying to view cannot be shown because the authenticity of the received data could not be verified.
Please contact the website owners to inform them of this problem.
this is page address:
https://www.sayehrooshan-co.com
this is my code always worked with .pfx file for other sites:
sslstream = new SslStream(new NetworkStream(mySocket, false), false);
//commented for nedaye arzhang
X509Certificate2 serverCertificate = new X509Certificate2(Path, Password);
//X509Certificate2 serverCertificate = new X509Certificate2("www_nedaye-arzhang_com.cer");
sslstream.AuthenticateAsServer(serverCertificate, false, System.Security.Authentication.SslProtocols.Tls, true);
searched alot but didn't get any solution
Anyone get any idea?
The server is broken. Trying with openssl s_client shows that the TLS handshake is done successfully and the certificate is fine, but that it breaks later in the communication:
$ openssl s_client -connect www.sayehrooshan-co.com:443 -servername www.sayehrooshan-co.com -crlf
CONNECTED(00000003)
...
SSL-Session:
Protocol : TLSv1
Cipher : ECDHE-RSA-AES256-SHA
...
Verify return code: 0 (ok)
---
GET / HTTP/1.1
Host: www.sayehrooshan-co.com
140040623380160:error:1408F10B:SSL routines:SSL3_GET_RECORD:wrong version number:s3_pkt.c:365:
Doing a packet capture during the experiment one can see that the server sends plain text on the TLS connection:
> various TLS encrypted stuff from client (likely HTTP request) ....
< followed by sudden plain text from the server:
Cannot find table 0.
at System.Data.DataTableCollection.get_Item(Int32 index)
at MyWebServerNamespace.MyWebServer.SetTableRowValue(DataSet& ds, String type, String name, String value) in D:\iteration source - table 13 removed\MyWebServer\MyWebServer.cs:line 4024
at MyWebServerNamespace.MyWebServer.LoadCmsValues(Content cms, Ssl sslClass, DataSet& Ds, DataTable& fileDt, Socket& mySocket, Byte[]& contentBytes, Boolean& showCmsError) in D:\iteration source - table 13 removed\MyWebServer\MyWebServer.cs:line 1761
at MyWebServerNamespace.MyWebServer.HandleTcpRequest(Object state) in D:\iteration source - table 13 removed\MyWebServer\MyWebServer.cs:line 1027
LoadCmsValues enter
The client will try to interpret this plain text message as a TLS record. This means it will parse the initial bytes and extract the TLS protocol version and payload length. Given that this is no TLS record at all these values will be garbage. Depending on the actual implementation of the TLS stack in the client this will then result in error messages like "wrong version number" (the claimed TLS protocol version is not supported) or "SSL_ERROR_RX_RECORD_TOO_LONG" (the length of the payload as specified is not the actual length of the payload) or the more general "ERR_SSL_PROTOCOL_ERROR" or similar.
It is not just C#, Firefox shows the same error message.
"Error code: ssl_error_rx_record_too_long. This usually means the implementation of SSL on your server is not correct. The error is usually caused by a server side problem which the server administrator will need to investigate."
Source
Another page discussing this issue
Firefox:
Chrome
IE
Grasshopper has same problem possibly because of two routers and dns bind being installed on one ip address and ssl mod the other. The fact that Apache2 status is up and running like a charm tells me that it’s an install/ops error. Tomorrow is another day.
I have a really strange issue when Visual Studio resolves the server SSL certificate.
The API I am using requires me to send a certificate along with the request to 'verify who I am'. Initially I referred to this certificate within my UnitTest using X509Certificate2 and then importing it as a byte[]. What I didn't want to do, is have this laying around in my code referring to a specific location on my local disk (I want to run the unit tests automatically on my build server) so opted to install the certificate within the certificate store (which I could later install on the build server). And when I tested this Uri within the browser (IE) it asked for the certificate I wanted to use and rather stupidly I clicked OK without really reading what it was asking me to do.
Problem is, since doing this I am unable to run my unit test (I am making an HttpWebRequest) - as soon as it hits the following line it throws a WebException.
using (var response = request.GetResponse())
{
// Removed content ...
}
The exception response is null , here is the exception
System.Net.WebException: The underlying connection was closed: An
unexpected error occurred on a receive. ---> System.IO.IOException:
Unable to read data from the transport connection: An existing
connection was forcibly closed by the remote host. --->
System.Net.Sockets.SocketException: An existing connection was
forcibly closed by the remote host
The only reason I can see for this error is that Visual Studio is using the wrong SSL certificate for the server connection (as I am using the test API Uri, I can verify this is sort of the case by using the live API Uri which works fine)
I have tried the following:
Removing the certificate from the store
Adding the certificate back to the store
Clearing all browser cache
Restoring IE back to 'factory settings'
Clearing the SSL cache within IE
Tried setting Keepalive to true and then false
This issue was affecting all browsers but I have managed to get it working. I have tried to use Fiddler to identify if the server is doing something crazy (including decrypting SSL connections) and I can see this is actually responding with a 403 error.
Has anyone else got any ideas?
Edit
Just tried to run this on the build server, still get the same error so I will check with the API provider to see if a/ my certificate has expired b/ their service is actually up!
System.Net.WebException: The underlying connection was closed: An
unexpected error occurred on a receive. ---> System.IO.IOException:
Unable to read data from the transport connection: An existing
connection was forcibly closed by the remote host. --->
System.Net.Sockets.SocketException: An existing connection was
forcibly closed by the remote host
Issue was with the API provider.
I'm using Encrypt=yes in a SQL Server connection string, as I need the TCPIP traffic to be encrypted, but on opening the connection I get an error:
A connection was successfully established with the server, but then an error
occurred during the pre-login handshake. (provider: SSL Provider, error: 0 -
The certificate's CN name does not match the passed value.)
Any suggestions how to fix this? I assume I need some sort of certificate relationship between my servers, but have no idea where to start.
I need this for two connections, one each to a SQL 2000 server and one to a 2005 server.
Your database connection can be configured to encrypt traffic and to accept any certificate from your server. Not a grand solution, but it worked for me.
The resulting connection string should look like this:
"[...];Encrypt=True;TrustServerCertificate=True"
I realize this is pretty old, but thought this might still help someone.
If the server you are connecting to does not have a certificate installed, a default certificate number is generated each time the server is restarted. When this happens the CN number changes, and might not match the one you have.
I read this recently, but I'm still trying to find the link for you.
I'd suggest you makes sure that the server you are connecting to has explicitly installed a certificate, and that your client has it too.
I'll update this as soon as I find the link.
You can't encrypt the the connection without also having a certificate installed on the Server. By default SQL Server will present a self signed certificate, and this is (and should be) rejected by clients.
Your options are:
a) The solution is to install a real certificate on the SQL Server:
Certificate Management (SQL Server Configuration Manager)
b) If you aren't able to install a real certificate on the SQL Server (a few $/year). You can issue a self signed certificate and trust this specific certificate on your client machines.
c) If you really do want to ignore this security problem. Please don't do this you do have the option to add an "ignore this security warning flag" (TrustServerCertificate) to the connectstring:
Encrypt=Yes;TrustServerCertificate=Yes
d) If you are using JDBC there is an addition connectstring property that can be used instead of TrustServerCertificate
Encrypt=Yes;hostNameInCertificate=<myservername>