reqwest: Failing to connect with rustls-tls in reqwest 0.12

I’ve been using the reqwest library for a long time with rustls-tls and self-signed certificates. However, when upgrading to version 0.12 the connection fails and the returning error does not help much. It simply says connection error.

What changed in this version that could cause the failure?

The code is very much like this:

  let mut contents_cert = Vec::new();
  File::open("./pki/ECC-secp256r1/ca_cert_and_key.pem").unwrap()
      .read_to_end(&mut contents_cert).unwrap();
  let root_cert = reqwest::Certificate::from_pem(&contents_cert).unwrap();

  let mut client_cert = Vec::new();
  let cert_and_key_name = "./pki/ECC-secp256r1/meter_client01_cert_and_key.pem".to_string();
  File::open(cert_and_key_name).unwrap()
      .read_to_end(&mut client_cert).unwrap();
  let identify = reqwest::Identity::from_pem(&client_cert).unwrap();

  // Cria um cliente que ira fazer as requisições para o servidor IEEE 2030.5
  let client = Client::builder()
      .timeout(Duration::from_secs(5))
      .add_root_certificate(root_cert)
      .identity(identify)
      .connection_verbose(true)
      .https_only(true)
      .danger_accept_invalid_certs(true) // para rustls
      .max_tls_version(reqwest::tls::Version::TLS_1_2)
      .use_rustls_tls()
      .build().unwrap();

      let result = client.get (url.clone())
          .send()
          .await;

Thank you very much in advance, Gustavo

About this issue

  • Original URL
  • State: closed
  • Created 3 months ago
  • Reactions: 1
  • Comments: 21 (10 by maintainers)

Most upvoted comments

Thank you all! With that, and another release of reqwest this morning, a cargo update should help. Feel free to open an issue again if there’s different problems.

Thank both of you. I tested reqwest 0.12.2 and it working again. 😃

I think that’s one option - you could change your NoVerifier impl to return the default list we were using before it was removed from the trait. I think you could also just remove SignatureScheme::ECDSA_SHA1_Legacy.

On the other hand, Ctz worked up a fix on our side as well: https://github.com/rustls/rustls/pull/1869 and we’re backporting it into 0.22: https://github.com/rustls/rustls/pull/1870 I believe taking that fix in an updated Rustls dependency would also resolve the problem without needing a change on your side.

So, getting to the bottom of the cause of this on discord with @cpu :

In rustls 0.22 we removed the default function definition for ServerCertVerifier::supported_verify_schemes. In eb94f26919e881177ad3d9cd172f47d1a8263799 (contained in reqwest 0.12.0 & 0.12.1) this was supplied in reqwest’s verifier (see https://github.com/seanmonstar/reqwest/blob/master/src/tls.rs#L557-L558, compare to https://github.com/rustls/rustls/commit/e9c15abe0633416aefc783bbc5f7ab525e899c77#diff-6a346e34b62dcc7aa7ea373ca29791ac4c81c55202d265397418507d3235a4e3R408) but with a larger than previous set of offered signature schemes (and, because that list is in priority order, SHA1 is preferred).

Would you be able to post a packet capture of this failure happening, and/or warn-level logs emitted from the rustls client? (RUST_LOG=warn if your process incorporates env_logger).

[2024-03-22T14:25:47Z WARN rustls::client::tls12] peer signed kx with wrong algorithm (got Unknown(0) expect [ED25519, ECDSA_NISTP521_SHA512, ECDSA_NISTP384_SHA384, ECDSA_NISTP256_SHA256]) Error: reqwest::Error { kind: Request, url: Url { scheme: “https”, cannot_be_a_base: false, username: “”, password: None, host: Some(Domain(“utfpr.edu.br”)), port: Some(8443), path: “/upt”, query: None, fragment: None }, source: Error { kind: Connect, source: Some(Custom { kind: Other, error: Custom { kind: InvalidData, error: PeerMisbehaved(SignedKxWithWrongAlgorithm) } }) } }

Thanks!

Over here https://github.com/seanmonstar/reqwest/blob/master/src/tls.rs#L557-L558 offers SignatureScheme::ECDSA_SHA1_Legacy, but rustls has so little support for ECDSA-SHA1 nowadays that it cannot check that it is compatible with the selected ciphersuite.

We could resolve that by:

  • reqwest doesn’t offer SHA1 – but that seems silly in the context of the purpose of that code
  • rustls could regain enough knowledge about SHA1 to pass this check – I think this resolution seems preferable?