Reqwest: example failed on Android for cert verification

Created on 23 Mar 2017  ·  17Comments  ·  Source: seanmonstar/reqwest

cargo dinghy run --example simple

thread 'main' panicked at 'called Result::unwrap() on an Err value: Http(Ssl(Failure(Ssl(ErrorStack([Error { code: 336134278, library: "SSL routines", function: "ssl3_get_server_certificate", reason: "certificate verify failed", file: "s3_clnt.c", line: 1264 }])))))', /checkout/src/libcore/result.rs:859
note: Run with RUST_BACKTRACE=1 for a backtrace.

All 17 comments

Setting envar on android device like this solved the problem:

SSL_CERT_FILE=/sdcard/cacert.pem

But I wonder if is there a way to use the system wide ca cert file such as the ones in /system/etc/security/cacerts.

Does Android always have certs installed there? If so, sounds like we could file in the openssl crate to look there when on Android?

I am also getting this error which makes reqwest unusable for https on Android

android's certificates are stored not as a pem but separate files with the filename being hash.n from looking / trying openssl won't read that format if you set SSL_CERT_DIR instead I've had to do as @king6cong did and provide a cacert.pem with my app's assets (i used the one from curl) and set SSL_CERT_FILE when the app starts. I don't like it but it works.

edit: this works when running cargo's tests from the command line, but setting it in an app isn't working

Do you compile openssl yourself to ship with your app, or is it always available on Android?

If compiling yourself, the rust-openssl crate has instructions on configuring custom builds.

If it is always there, in an expected location and format, perhaps the rust-openssl crate could take a patch to look for it on Android.

I'm compiling openssl and statically linking into a my cdylib crate which uses reqwest. Then calling some exposed functions through JNI. Http works but https requests fail with the above error. I'm going to keep at this and hopefully will come back with answer. Surely C++ using openssl also has this problem, but i cant find any one with the answer.

So, to be clear, the instructions (here) from rust-openssl don't help? Perhaps once the steps are found, the instructions there could be updated with an Android section as well.

Yes those settings are already in use otherwise you can't even get passed the openssl build script.
This error is much later and is more related to the SslContext not being able to verify certificates because it hasn't loaded Android's ca store

@seanmonstar @dten

I have looked into this today:

  1. setting env vars make the rust binary runnable under adb shell, but for the .so generated and embedded in android app, this does not work.
  2. add_root_certificate should have worked, but indeed not. I haven't figured out the reason. https://github.com/king6cong/rust-native-tls/commit/56a78d0568325f23a8edb3631ee236e762facbe0 @seanmonstar any suggestions?
  3. set_ca_file works, but a cert file is needed. Bundle it in android app assets makes it hard to get the cert file on Rust side (or any good ideas?). I write the cert file first and use set_ca_file with this file. Dirty but it works. https://github.com/king6cong/rust-openssl/commit/6233276df23c3e9e3e364200e950a3568ea7e474

Any suggestions are welcome. Rust SSL support on android is really a big deal. 😃

Getting the asset shouldn't be too bad with android glue. https://github.com/tomaka/android-rs-glue/tree/master/examples/use_assets

Can't you set these from outside of reqwest

@dten Yeah, but load_asset(filename: &str) -> Result<Vec<u8>, AssetError> returned Vec which set_ca_file can not use directly.

Ah yes sorry :) have to write it out somewhere first which would be awkward. I feel there should be a sensible answer for this. Investigation counties

@king6cong add_root_certificate didn't work because Certificate::from_pem only returns the first certificate as far as I can tell. I tried include_str! instead of bytes and string split to add each key to the key_store and it worked.

my fork of rust-openssl has a commit that will read the system certs and it's working without any messing with files and assets
https://github.com/dten/rust-openssl/commit/72da006c498f8ae518be0bc936c78de2b86a0f1d
all i need to use it is this replace block in my Cargo.toml

[replace]
"openssl:0.9.10" = { git = "git://github.com/dten/rust-openssl" }

it should really also account for the user-added and user-removed keys that are elsewhere on the system but i haven't bothered yet

@dten That's awesome! 👍

In this way we can just use android system ca certs.
A little consideration regarding older Android versions:

according to http://wiki.cacert.org/FAQ/ImportRootCert

Before Android version 4.0, with Android version Gingerbread & Froyo, there was a single read-only file ( /system/etc/security/cacerts.bks ) containing the trust store with all the CA ('system') certificates trusted by default on Android. Both system apps and all applications developed with the Android SDK use this. Use these instructions on installing CAcert certificates on Android Gingerbread, Froyo, ...

Starting from Android 4.0 (Android ICS/'Ice Cream Sandwich', Android 4.3 'Jelly Bean' & Android 4.4 'KitKat'), system trusted certificates are on the (read-only) system partition in the folder '/system/etc/security/' as individual files. However, users can now easily add their own 'user' certificates which will be stored in '/data/misc/keychain/certs-added'.

Take older versions of Android into consideration and openssl on android will no longer be a problem :)

Awesome work! I see you've filed an pull request to get this into the openssl crate, great. I'm going to close this issue then.

Hi guys,

maybe I am missing something, but when I try to use the API of a site with the default client:

let client = reqwest::Client::new();

I get a “certificate verify failed”. I tried to use the dangerous method like this guy:

let client = reqwest::ClientBuilder::new().danger_disable_hostname_verification().build()?;

but I get the exact same error. What am I missing there?

@Boiethios the dangerous method disable only verification of the hostname in the certificate, but not that the certificate itself is trust by the current client configuration.

See https://github.com/seanmonstar/reqwest/pull/198 for what's holding up the ability to disable total certificate verification.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

CGQAQ picture CGQAQ  ·  4Comments

encombhat picture encombhat  ·  6Comments

samuela picture samuela  ·  5Comments

silvioprog picture silvioprog  ·  5Comments

nuxeh picture nuxeh  ·  4Comments