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

SecurityContext is not handling Handshake properly: Unhandled Exception: HandshakeException: Handshake error in client #47420

Closed
DiaaEddin opened this issue Oct 9, 2021 · 10 comments
Labels
area-core-library SDK core library issues (core, async, ...); use area-vm or area-web for platform specific libraries. library-io

Comments

@DiaaEddin
Copy link

DiaaEddin commented Oct 9, 2021

As of September 2021 my https request to my api which has a valid certificate from letsecnrypt ca is not working anymore from dart HttpClient throwing the following error

HandshakeException: Handshake error in client (OS Error: 
	CERTIFICATE_VERIFY_FAILED: certificate has expired(../../third_party/boringssl/src/ssl/handshake.cc:359))

it is only happening on some windows builds and Android 6 / 4 . I tried the program on other windows machines and it is working perfectly .
After A little digging I found this solution witch basically adds isrgrootx1.pem to SecurityContext.default
I tried that but then I got this error message

TlsException: Failure trusting builtin roots (OS Error: 
	CERT_ALREADY_IN_HASH_TABLE(../../third_party/boringssl/src/crypto/x509/x509_lu.c:356), errno = 0)

it seems that isrgrootx1.pem is already in the trusted root certificates list.
so what is the problem then?!

Finally I tried to create SecurityContext(withTrustedRoots: false) then add isrgrootx1.pem to it and then I passed it to HttpClient. And it worked. but the trusted root certificates list for the client does not include other trusted issuers certificates. so this client will only work for isrgrootx1 signed certificates which is not ideal solution.
I could not find the cause of this problem.

this is my code to reproduce

import 'dart:io';

const String validISGROOTX1Url = "https://valid-isrgrootx1.letsencrypt.org";

Future makeRequest(HttpClient client) async {
  try {
    final request = await client.getUrl(Uri.parse(validISGROOTX1Url));
    final response = await request.close();
    print(response.statusCode);
  } on HandshakeException catch (e) {
    print(e.toString());
  }
}

Future<void> testDefault() async {
  print("## test HttpClient with no parameters ");

  await makeRequest(HttpClient());

  print("------------------------------------------------");
}

Future<void> testWithSecurityContextTrustedRoots() async {
  print("## test HttpClient with SecurityContext(withTrustedRoots: true) ");
  SecurityContext context = SecurityContext(withTrustedRoots: true);

  await makeRequest(HttpClient(context: context));
  print("------------------------------------------------");
}

Future<void> testWithSecurityContextTrustedRootsAndIsgrootx1() async {
  print(
      "## test HttpClient with SecurityContext(withTrustedRoots: true) and isgrootx1.pem ");
  SecurityContext context = SecurityContext(withTrustedRoots: true);
  try {
    context.setTrustedCertificates("isrgrootx1.pem");
  } on TlsException catch (e) {
    print(e.toString());
  }

  await makeRequest(HttpClient(context: context));
  print("------------------------------------------------");
}

Future<void> testWithSecurityContextWithIsgrootx1() async {
  print(
      "## test HttpClient with SecurityContext(withTrustedRoots: false) and isgrootx1.pem ");
  SecurityContext context = SecurityContext(withTrustedRoots: false);
  try {
    context.setTrustedCertificates("isrgrootx1.pem");
  } on TlsException catch (e) {
    print(e.toString());
  }

  await makeRequest(HttpClient(context: context));
  print("------------------------------------------------");
}

main() async {
  await testDefault();
  await testWithSecurityContextTrustedRoots();
  await testWithSecurityContextTrustedRootsAndIsgrootx1();
  await testWithSecurityContextWithIsgrootx1();
}

the output on my machine

## test HttpClient with no parameters 
HandshakeException: Handshake error in client (OS Error: 
        CERTIFICATE_VERIFY_FAILED: certificate has expired(../../third_party/boringssl/src/ssl/handshake.cc:359))
------------------------------------------------
## test HttpClient with SecurityContext(withTrustedRoots: true) 
HandshakeException: Handshake error in client (OS Error: 
        CERTIFICATE_VERIFY_FAILED: certificate has expired(../../third_party/boringssl/src/ssl/handshake.cc:359))
------------------------------------------------
## test HttpClient with SecurityContext(withTrustedRoots: true) and isgrootx1.pem
TlsException: Failure trusting builtin roots (OS Error: 
        CERT_ALREADY_IN_HASH_TABLE(../../third_party/boringssl/src/crypto/x509/x509_lu.c:356), errno = 0)
HandshakeException: Handshake error in client (OS Error: 
        CERTIFICATE_VERIFY_FAILED: certificate has expired(../../third_party/boringssl/src/ssl/handshake.cc:359))
------------------------------------------------
## test HttpClient with SecurityContext(withTrustedRoots: false) and isgrootx1.pem
200
------------------------------------------------
  • Dart version 2.14.3
  • Microsoft Windows [Version 10.0.19043.1237]
@DiaaEddin
Copy link
Author

I just figured that I need to remove the expired certificate from the list. So is it possible to remove a certificate from SecurityContext? or should I create a new empty SecurityContext and provide the valid list from mozilla like https://github.com/dart-lang/root_certificates ?

@julemand101
Copy link
Contributor

Could it be related to this issue?
#46370

@DiaaEddin
Copy link
Author

I understand that this change should solve the mentioned issue . so I need to clone the repo and build the dart sdk on my machine to test it then I will report back.
if you could provide me a link for a prebuilt sdk for the above change that would be great

@julemand101
Copy link
Contributor

julemand101 commented Oct 10, 2021

You can download builds of the dev branch from: https://dart.dev/get-dart/archive#dev-channel which should have the change you linked to.

@DiaaEddin
Copy link
Author

I can confirm that the last dev build is working without any problems on my machine
and this is the output:

## test HttpClient with no parameters 
200
------------------------------------------------
## test HttpClient with SecurityContext(withTrustedRoots: true)
200
------------------------------------------------
## test HttpClient with SecurityContext(withTrustedRoots: true) and isgrootx1.pem
TlsException: Failure trusting builtin roots (OS Error: 
        CERT_ALREADY_IN_HASH_TABLE(../../third_party/boringssl/src/crypto/x509/x509_lu.c:356), errno = 0)
200
------------------------------------------------
## test HttpClient with SecurityContext(withTrustedRoots: false) and isgrootx1.pem
200
------------------------------------------------

Thank you for your help.
Any estimation when this change will be shipped on the stable channel?

@julemand101
Copy link
Contributor

@DiaaEddin I am not working on the Dart project so I can only speculate. But I do wonder why this fix was not a candidate for the 2.14 branch since I have seen at least one other person with this exact problem on Windows (some guy I helped over Discord).

If nothing is done, the change comes with the 2.15 release but I can really only guess when that becomes stable. But since 2.14 was released rather recent I would not expect 2.15 the next few months (maybe a late December? I don't really know 🦆).

@sortie
Copy link
Contributor

sortie commented Oct 11, 2021

@aam Might it make sense to cherry-pick https://dart-review.googlesource.com/c/sdk/+/211160 as a stable 2.14 patch release?

@aam
Copy link
Contributor

aam commented Oct 11, 2021

Yeah, we could file a cherry-pick request for this to be considered for 2.14 hotfix patch.

@mit-mit
Copy link
Member

mit-mit commented Oct 13, 2021

@aam this can be closed now that we have the CP in #47432, right?

@aam
Copy link
Contributor

aam commented Oct 13, 2021

Yes, CP was filed, also this can be closed as duplicate of #46370

@aam aam closed this as completed Oct 13, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area-core-library SDK core library issues (core, async, ...); use area-vm or area-web for platform specific libraries. library-io
Projects
None yet
Development

No branches or pull requests

6 participants