From a65ef3e49ccb098c7254d95c84b1ac850582edad Mon Sep 17 00:00:00 2001 From: afpro Date: Tue, 28 Sep 2021 17:15:11 +0800 Subject: [PATCH 1/3] android SSL support system certs --- vm/src/stdlib/ssl.rs | 83 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 83 insertions(+) diff --git a/vm/src/stdlib/ssl.rs b/vm/src/stdlib/ssl.rs index 0a196c11c4..07ad8c2b0b 100644 --- a/vm/src/stdlib/ssl.rs +++ b/vm/src/stdlib/ssl.rs @@ -285,6 +285,9 @@ impl SlotConstructor for PySslContext { let mut builder = SslContextBuilder::new(method).map_err(|e| convert_openssl_error(vm, e))?; + #[cfg(target_os = "android")] + droid::load_client_ca_list(vm, &mut builder)?; + let check_hostname = proto == SslVersion::TlsClient; builder.set_verify(if check_hostname { SslVerifyMode::PEER | SslVerifyMode::FAIL_IF_NO_PEER_CERT @@ -1257,3 +1260,83 @@ impl Write for SocketStream { socket.flush() } } + +#[cfg(target_os = "android")] +mod droid { + use std::{ + fs::{read_dir, File}, + io::Read, + path::Path, + }; + + use openssl::{ + ssl::SslContextBuilder, + x509::{store::X509StoreBuilder, X509}, + }; + + use crate::{ + exceptions::PyBaseExceptionRef, stdlib::ssl::convert_openssl_error, VirtualMachine, + }; + + static CERT_DIR: &'static str = "/system/etc/security/cacerts"; + + pub fn load_client_ca_list( + vm: &VirtualMachine, + b: &mut SslContextBuilder, + ) -> Result<(), PyBaseExceptionRef> { + let root = Path::new(CERT_DIR); + if !root.is_dir() { + return Err(vm.new_exception_msg( + vm.ctx.exceptions.file_not_found_error.clone(), + CERT_DIR.to_string(), + )); + } + + let entries = match read_dir(root) { + Ok(v) => v, + Err(err) => return Err(vm.new_os_error(format!("read cert root: {}", err))), + }; + + let mut combined_pem = String::new(); + for entry in entries { + let entry = match entry { + Ok(v) => v, + Err(err) => return Err(vm.new_os_error(format!("iter cert root: {}", err))), + }; + + let path = entry.path(); + if !path.is_file() { + continue; + } + + let mut file = match File::open(&path) { + Ok(v) => v, + Err(err) => { + return Err(vm.new_os_error(format!( + "open cert file {}: {}", + path.display(), + err + ))) + } + }; + + if let Err(err) = file.read_to_string(&mut combined_pem) { + return Err(vm.new_os_error(format!("read cert file {}: {}", path.display(), err))); + } + + combined_pem.push('\n'); + } + + let mut store_b = X509StoreBuilder::new().map_err(|err| convert_openssl_error(vm, err))?; + let x509_vec = X509::stack_from_pem(combined_pem.as_bytes()) + .map_err(|err| convert_openssl_error(vm, err))?; + for x509 in x509_vec { + store_b + .add_cert(x509) + .map_err(|err| convert_openssl_error(vm, err))?; + } + b.set_cert_store(store_b.build()); + + Ok(()) + } +} From 728af615ff96efb3403979b6b0384722d1e133ac Mon Sep 17 00:00:00 2001 From: Jeong YunWon Date: Wed, 29 Sep 2021 02:00:13 +0900 Subject: [PATCH 2/3] clean up andorid ssl --- vm/src/stdlib/ssl.rs | 49 +++++++++++++++----------------------------- 1 file changed, 16 insertions(+), 33 deletions(-) diff --git a/vm/src/stdlib/ssl.rs b/vm/src/stdlib/ssl.rs index 07ad8c2b0b..daa2287357 100644 --- a/vm/src/stdlib/ssl.rs +++ b/vm/src/stdlib/ssl.rs @@ -1263,24 +1263,22 @@ impl Write for SocketStream { #[cfg(target_os = "android")] mod droid { + use crate::{ + exceptions::PyBaseExceptionRef, stdlib::ssl::convert_openssl_error, VirtualMachine, + }; + use openssl::{ + ssl::SslContextBuilder, + x509::{store::X509StoreBuilder, X509}, + }; use std::{ fs::{read_dir, File}, io::Read, path::Path, }; - use openssl::{ - ssl::SslContextBuilder, - x509::{store::X509StoreBuilder, X509}, - }; - - use crate::{ - exceptions::PyBaseExceptionRef, stdlib::ssl::convert_openssl_error, VirtualMachine, - }; - static CERT_DIR: &'static str = "/system/etc/security/cacerts"; - pub fn load_client_ca_list( + pub(super) fn load_client_ca_list( vm: &VirtualMachine, b: &mut SslContextBuilder, ) -> Result<(), PyBaseExceptionRef> { @@ -1292,37 +1290,22 @@ mod droid { )); } - let entries = match read_dir(root) { - Ok(v) => v, - Err(err) => return Err(vm.new_os_error(format!("read cert root: {}", err))), - }; - let mut combined_pem = String::new(); + let entries = + read_dir(root).map_err(|err| vm.new_os_error(format!("read cert root: {}", err)))?; for entry in entries { - let entry = match entry { - Ok(v) => v, - Err(err) => return Err(vm.new_os_error(format!("iter cert root: {}", err))), - }; + let entry = entry.map_err(|err| vm.new_os_error(format!("iter cert root: {}", err)))?; let path = entry.path(); if !path.is_file() { continue; } - let mut file = match File::open(&path) { - Ok(v) => v, - Err(err) => { - return Err(vm.new_os_error(format!( - "open cert file {}: {}", - path.display(), - err - ))) - } - }; - - if let Err(err) = file.read_to_string(&mut combined_pem) { - return Err(vm.new_os_error(format!("read cert file {}: {}", path.display(), err))); - } + File::open(&path) + .and_then(|file| file.read_to_string(&mut combined_pem)) + .map_err(|err| { + vm.new_os_error(format!("open cert file {}: {}", path.display(), err)) + })?; combined_pem.push('\n'); } From dee02b4935b8b9ed2109cfa9e13ca44a98388fa7 Mon Sep 17 00:00:00 2001 From: afpro Date: Wed, 29 Sep 2021 11:44:57 +0800 Subject: [PATCH 3/3] fix naming (droid->android); fix compile error --- vm/src/stdlib/ssl.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/vm/src/stdlib/ssl.rs b/vm/src/stdlib/ssl.rs index daa2287357..ec22f15584 100644 --- a/vm/src/stdlib/ssl.rs +++ b/vm/src/stdlib/ssl.rs @@ -286,7 +286,7 @@ impl SlotConstructor for PySslContext { SslContextBuilder::new(method).map_err(|e| convert_openssl_error(vm, e))?; #[cfg(target_os = "android")] - droid::load_client_ca_list(vm, &mut builder)?; + android::load_client_ca_list(vm, &mut builder)?; let check_hostname = proto == SslVersion::TlsClient; builder.set_verify(if check_hostname { @@ -1262,7 +1262,7 @@ impl Write for SocketStream { } #[cfg(target_os = "android")] -mod droid { +mod android { use crate::{ exceptions::PyBaseExceptionRef, stdlib::ssl::convert_openssl_error, VirtualMachine, }; @@ -1302,7 +1302,7 @@ mod droid { } File::open(&path) - .and_then(|file| file.read_to_string(&mut combined_pem)) + .and_then(|mut file| file.read_to_string(&mut combined_pem)) .map_err(|err| { vm.new_os_error(format!("open cert file {}: {}", path.display(), err)) })?;