4

I am facing this issue when I am trying to invoke a COM Visible c# class in classic ASP Page which tries to execute one MySQL query against database.(Here MySQL is on TLS).

Here in my case one of the classic asp page, we create instance of SomeUser class and then call SetId method on that which will try to create MySQL connection and fails with this stacktrace. Just for complete clarity, here SomeUser class is COMVisible.

Classic ASP code snippet

dim dummy: set dummy= new SomeUser
dim dummyObj: set dummyObj= dummy.obj

dummyObj.SetId(ID)

Exception

System.Security.Cryptography.CryptographicException: The system cannot find the file specified. 
at System.Security.Cryptography.CryptographicException.ThrowCryptographicException(Int32 hr) 
at System.Security.Cryptography.X509Certificates.X509Utils._LoadCertFromFile(String fileName, IntPtr password, UInt32 dwFlags, Boolean persistKeySet, SafeCertContextHandle& pCertCtx) at System.Security.Cryptography.X509Certificates.X509Utils.LoadCertFromFile(String fileName, IntPtr password, UInt32 dwFlags, Boolean persistKeySet, SafeCertContextHandle pCertCtx) 
at System.Security.Cryptography.X509Certificates.X509Certificate.LoadCertificateFromFile(String fileName, Object password, X509KeyStorageFlags keyStorageFlags) 
at System.Security.Cryptography.X509Certificates.X509Certificate2..ctor(String fileName, String password) at MySql.Data.MySqlClient.NativeDriver.GetClientCertificates() 
at MySql.Data.MySqlClient.NativeDriver.StartSSL() 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 System.Data.Common.DbDataAdapter.FillInternal(DataSet dataset, DataTable[] datatables, Int32 startRecord, Int32 maxRecords, String srcTable, IDbCommand command, CommandBehavior behavior) 
at System.Data.Common.DbDataAdapter.Fill(DataTable[] dataTables, Int32 startRecord, Int32 maxRecords, IDbCommand command, CommandBehavior behavior) 
at System.Data.Common.DbDataAdapter.Fill(DataTable dataTable) at Some.Other.Namespace.Execute(MySqlConnection connection, String sql, DataTable table, DataParameter[] dataParameters) at Some.Other.Namespace.Execute(MySqlConnection connection, String sql, DataParameter[] dataParameters) at Some.Other.Namespace.Execute(String sql, DataParameter[] dataParameters) 
at SomeNamespace.SomeDc.GetData(UInt32 Id) at 
SomeNamespace.User.GetData(UInt32 ID) at SomeNameSpace.SomeUser.SetId(Int32 Id)

Similar question on Stack Overflow on this.

In my case, this solution(Setting Load User Profile to true) work for ASPX pages only but not in this case.

One more point I would like to highlight w3wp.exe is running in Default App Pool with ApplicationPoolIdentity.

I have tried many things so far but no luck. Any point in the right direction will be of great help.

Things I have tried so far.

  • Setting Load User Profile to true for all the application pools.
  • Changing Application Pool Identity to Network Service, Local System and others present in IIS.
  • Changing Application Pool Identity to a custom account(I used an administrator account to try this)
user692942
  • 16,398
  • 7
  • 76
  • 175
RockAndRoll
  • 2,247
  • 2
  • 16
  • 35
  • How is this any different to [the question you asked on May 6th](https://stackoverflow.com/q/72139111/692942) which you deleted before posting this question? Instead of deleting a question because it was closed, [edit](https://stackoverflow.com/posts/72139111/edit) it and rectify the issues raised in the close panel. Re-posting the same question to circumvent the processes in place is not looked upon favourably. – user692942 May 10 '22 at 12:41
  • 1
    I have changed it and added more details so it does not get closed. Now it has all the details. I waited for a day for question to get reopened but it was not so took this route. Apologies if I did it incorrectly. – RockAndRoll May 10 '22 at 14:14
  • 1
    Does this answer your question? [What exactly happens when I set LoadUserProfile of IIS pool?](https://stackoverflow.com/q/17149132) *(Still relevant)*. – user692942 May 12 '22 at 09:41
  • 1
    No..I have already tried that. It works for aspx pages ..not for classic asp. – RockAndRoll May 12 '22 at 09:57
  • 1
    Yes, the problem is that. As for the solution, it entirely depends on how your accounts and permissions are set. There is not enough information here to suggest anything more than has already been indicated on both this and your previously deleted question regardless of a 500 rep bounty. – user692942 May 12 '22 at 09:59
  • Do you call `LoadCertificateFromFile` in your c# code, or is that happening inside the MySQL connection setup? Would help if you shared the relevant code in the c# `COMVisible` class that sets the MySQL connection. – user692942 May 12 '22 at 10:02

1 Answers1

3

I don't have any clue about ASP, so I don't understand what you have tried.

However, the exception log seems to tell what is going wrong. The ASP / COM application is trying to load a client certificate when connecting to the MySQL server, but can't find the respective file. This may be due to permissions, or may simply happen because that file does not exist.

Please note that this is a not-so-common problem which may keep you from finding solutions fast. Problems with certificates usually are due to server certificates not being trusted, revoked or outdated. But in this case, the COM part is trying to load a client certificate so that it can prove its identity to the server.

The way to solve the problem depends upon circumstances:

  • If you are in control of the MySQL server, you can configure it so that it does not request client certificates. Then the COM code doesn't need to load a client certificate any more, and you can change the COM object's behavior accordingly. However, turning off client authentication at the server may be insecure.

  • You seem to be in control of the COM code, so you could revisit it and look where it tries to load the MySQL client certificate. Check out which file it tries to load, and check whether you have that file on the file system. If it isn't there, and if working without client certificates is not an option, you'll have to generate the client certificate.
    I don't know how the COM object works, though. Even if you don't find a place where it tries to load a client certificate explicitly, it may evaluate some MySQL client configuration files which tell it to use a (certain) client certificate when connecting to the server. Such files may have names like mysql.ini, my.ini, my.cnf or the like.

For clarification: The above paragraphs are about MySQL client certificates for the MySQL TLS connection. This has nothing to do with web server certificates.

If you need MySQL client authentication, you should test step by step:

  1. Generate an appropriate MySQL client certificate.
  2. Put that client certificate along with the private key onto the machine where your COM application runs.
  3. Log onto that machine and install the native MySQL client there (it is available for Windows).
  4. On that machine, try to establish an encrypted connection to your MySQL server with client authentication, using the native MySQL client and using your client certificate.
    If this does not work, there probably is no chance that it works from within your COM object, so you'll need to solve that first.
  5. In the last step, try your ASP application / COM object again. Make sure that it has sufficient permissions to read the certificate and the private key, and that both exist at the expected place.

If connection with the native client succeeds, but the COM object still can't connect, I may have an additional idea of how to debug the situation. In that case, just drop a comment; I'll eventually amend this answer then.

Binarus
  • 4,005
  • 3
  • 25
  • 41
  • 1
    Yes I have full control over mysql and I am checking how I can disable client certificates request in mysql. Not finding much on internet. Any link or steps you can point to? – RockAndRoll May 18 '22 at 07:21
  • 1
    Your COM object probably would try to load a client certificate even if the server wouldn't require client authentication. It really depends on the COM object's code. Hence, I would recommend another approach: Change your COM object or its configuration so that it does not try to load a client certificate. Then the exception you have shown definitely won't occur any more. Only **if** if the MySQL requires client authentication, a different exception will be thrown, with a **different** error message. Then you know you need to re-configure the MySQL server. – Binarus May 18 '22 at 09:36
  • 1
    This page is a good starting point to learn about (mandatory) encryption in MySQL from the client's and the server's perspective: https://dev.mysql.com/doc/refman/5.7/en/using-encrypted-connections.html (it is for 5.7, but the docs exist for other versions as well). The MySQL documentation is not too bad in the first place. – Binarus May 18 '22 at 09:40
  • Two comments above, I have written: "Only if if the MySQL requires ...". That should have been: "Only if the MySQL server requires ...". Sorry for the two typos. – Binarus May 18 '22 at 13:42