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

acceptor config SSLRequireClientCertificate=N causes ArgumentNullException in acceptor #568

Open
aerlian opened this issue Dec 19, 2019 · 2 comments

Comments

@aerlian
Copy link

aerlian commented Dec 19, 2019

I am seeing an unhandled exception being raised in the acceptor (System.ArgumentNullException: 'Value cannot be null. Parameter name: cert') when SSL is activated in both initiator and acceptor (SSLEnable=Y) and configured such that:

  1. A server certificate is specified in acceptor config
  2. A client certificate is NOT specified in initiator config (note, I specify SSLRequireClientCertificate=N in the acceptor to permit this)

To reproduce, see steps below [1]

It would appear that in the QuickFix/N method StreamFactory.CreateServerStreamAndAuthenticate, a call is made to Microsoft code SslStream.AuthenticateAsServer that results in the exception. I can see that the second parameter passed (socketSettings_.RequireClientCertificate) to SslStream.AuthenticateAsServer is false (as per the config setting: SSLRequireClientCertificate=N), but this does not suppress a callback to StreamFactory.ValidateClientCertificate from SslStream. Since there is no client certificate presented (it's runtime value is null), the callback barfs with the exception specified above.

I believe there is a workaround (which appears to work, but is not thoroughly tested) and that is to use the config setting when instantiating the SslStream instance to pass a null for the callback when validation is not required (i.e. when SSLRequireClientCertificate=N) since I noticed the SslStream handles a null callback by simply not calling it. Here’s the workaround:

e.g.:
SslStream sslStream = new SslStream(innerStream, false, socketSettings_.RequireClientCertificate ? ValidateClientCertificate : (RemoteCertificateValidationCallback)null, SelectLocalCertificate);

But I suspect this workaround may point to potentially a deeper issue in perhaps how SslStream has evolved since the QuickFix/N code was written (i.e. a breaking change in SslStream). So I would only tentatively propose this workaround.

If you confirm this as a genuine issue and you think the workaround is correct, then I would be happy to submit a PR for it

[1]
Steps to repro

  1. Clone QuickFix/N source code

  2. Configure executor SSL settings (executor_ssl.cfg)
    SSLEnable=Y
    SSLCertificate=QuickFixn-TestServer.pfx
    SSLCertificatePassword=QuickFixn-TestServer
    SSLCACertificate=QuickFixn-TestCA.cer
    SSLCheckCertificateRevocation=N
    SSLRequireClientCertificate=N

  3. Configure TradeClient SSL settings (tradeclient_ssl.cfg)
    SSLEnable=Y
    SSLServerName=QuickFixn-TestServer
    SSLCACertificate=QuickFixn-TestCA.cer

  4. Build target for both executor & tradeclient. NB both csproj configured with TargetFrameworks value net461

  5. Configure command line arguments in Visual Studio as follows:
    Executor -> executor_ssl.cfg
    TradeClient -> tradeclient_ssl.cfg

  6. Run the tradeclient

  7. Run the executor

  8. Executor will throw an exception in StreamFactory.ContainsEnhancedKeyUsage

@gbirchmeier
Copy link
Member

Is this related to #446?

@oclancy
Copy link
Contributor

oclancy commented Jul 7, 2023

If you end up here like I did (TradeWeb has a server cert but no client cert)

Your server .cfg should have:
SSLEnable=Y
SSLRequireClientCertificate=N
SSLValidateCertificates=N <-- this stops the Exception mentioned above (even though SSLRequireClientCertificate=N)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants