rust_rcs_client/
context.rs1extern crate rustls;
16extern crate walkdir;
17
18use std::fs::File;
19use std::io::{BufReader, Read};
20use std::path::PathBuf;
21use std::sync::Arc;
22use std::{iter, panic};
23
24use rustls::pki_types::CertificateDer;
25use rustls::{ClientConfig, RootCertStore};
26use rustls_pemfile::{read_one, Item};
27
28use rust_rcs_core::dns::DnsClient;
29
30use rust_rcs_core::ffi::log::platform_log;
31
32use rust_rcs_core::http::HttpClient;
33
34use rust_rcs_core::security::gba::GbaContext;
35use rust_rcs_core::security::SecurityContext;
36
37use rust_rcs_core::third_gen_pp::{addressing, CountryCode, NetworkCode};
38
39use tokio::runtime::Runtime;
40use tokio::sync::broadcast;
41use walkdir::WalkDir;
42
43const LOG_TAG: &str = "context";
44
45pub struct Context {
46 pub fs_root_dir: String,
47
48 dns_client: Arc<DnsClient>,
49 http_client: Arc<HttpClient>,
50
51 tls_client_config: Arc<ClientConfig>,
52
53 security_context: Arc<SecurityContext>,
54
55 otp_broadcaster: broadcast::Sender<String>,
56}
57
58impl Context {
59 pub fn new(fs_root_dir: &str, rt: Arc<Runtime>) -> Context {
60 let tls_client_config = make_tls_client_config(fs_root_dir);
61 let tls_client_config = Arc::new(tls_client_config);
62
63 let dns_client = DnsClient::new(Arc::clone(&rt));
64 let dns_client = Arc::new(dns_client);
65
66 let http_client =
67 HttpClient::new(Arc::clone(&tls_client_config), Arc::clone(&dns_client), rt);
68 let http_client = Arc::new(http_client);
69
70 let (otp_broadcaster, _) = broadcast::channel(1);
71
72 Context {
73 fs_root_dir: fs_root_dir.to_string(),
74
75 dns_client,
76 http_client,
77
78 tls_client_config,
79
80 security_context: Arc::new(SecurityContext::new()),
81
82 otp_broadcaster,
83 }
84 }
85
86 pub fn get_fs_root_dir(&self) -> &str {
87 &self.fs_root_dir
88 }
89
90 pub fn get_dns_client(&self) -> Arc<DnsClient> {
91 Arc::clone(&self.dns_client)
92 }
93
94 pub fn get_http_client(&self) -> Arc<HttpClient> {
95 Arc::clone(&self.http_client)
96 }
97
98 pub fn get_tls_client_config(&self) -> Arc<ClientConfig> {
99 Arc::clone(&self.tls_client_config)
100 }
101
102 pub fn get_security_context(&self) -> Arc<SecurityContext> {
103 Arc::clone(&self.security_context)
104 }
105
106 pub fn subscribe_otp(&self) -> broadcast::Receiver<String> {
107 self.otp_broadcaster.subscribe()
108 }
109
110 pub fn broadcast_otp(&self, otp: &str) {
111 if let Err(e) = self.otp_broadcaster.send(String::from(otp)) {
112 platform_log(LOG_TAG, format!("broadcast_otp failed with error {}", &e));
113 }
114 }
115
116 pub fn make_gba_context(
117 &self,
118 imsi: &str,
119 mcc: CountryCode,
120 mnc: NetworkCode,
121 subscription_id: i32,
122 ) -> GbaContext {
123 let impi = addressing::impi_from_imsi(imsi, mcc, mnc);
124
125 let bsf_realm = addressing::bsf_address(mcc, mnc);
126 let bsf_url = format! {"{}:8080", bsf_realm}; GbaContext::new(impi, bsf_url, bsf_realm, subscription_id)
129 }
130}
131
132fn make_tls_client_config(root_dir: &str) -> ClientConfig {
133 let mut root_certs = RootCertStore::empty();
134
135 let mut path = PathBuf::from(root_dir);
136 path.push("certs");
137
138 platform_log(
139 LOG_TAG,
140 format!("searching for certificates under path {:?}", path),
141 );
142
143 for entry in WalkDir::new(path)
144 .min_depth(1)
145 .into_iter()
146 .filter_entry(|e| -> bool {
147 platform_log(LOG_TAG, format!("found entry {:?}", e));
148
149 if let Some(file_name) = e.file_name().to_str() {
150 file_name.ends_with(".der") || file_name.ends_with(".pem")
151 } else {
152 false
153 }
154 })
155 {
156 match entry {
157 Ok(e) => {
158 let path = e.path();
159 platform_log(LOG_TAG, format!("init certificate with file {:?}", path));
160 let mut f = File::open(path).unwrap();
161 match path.extension() {
162 Some(ext) => {
163 if ext.eq_ignore_ascii_case("pem") {
164 let mut buf_reader = BufReader::new(f);
165 for item in iter::from_fn(|| read_one(&mut buf_reader).transpose()) {
166 match item {
167 Ok(cert_item) => match cert_item {
168 Item::X509Certificate(cert) => {
169 platform_log(LOG_TAG, "adding X509Certificate");
170 root_certs.add(cert).unwrap();
171 }
172 Item::Pkcs1Key(key) => platform_log(
173 LOG_TAG,
174 format!("rsa pkcs1 key {:?} not handled", key),
175 ),
176 Item::Pkcs8Key(key) => platform_log(
177 LOG_TAG,
178 format!("pkcs8 key {:?} not handled", key),
179 ),
180 Item::Sec1Key(key) => platform_log(
181 LOG_TAG,
182 format!("sec1 ec key {:?} not handled", key),
183 ),
184 _ => platform_log(LOG_TAG, "no certificate found"),
185 },
186
187 Err(e) => platform_log(LOG_TAG, format!("pem error {:?}", e)),
188 }
189 }
190 } else {
191 let mut v = vec![0; 4 * 1024];
192 f.read_to_end(&mut v).unwrap();
193
194 let cert = CertificateDer::from(v);
195 platform_log(LOG_TAG, format!("adding certificate {:?}", cert));
196 root_certs.add(cert).unwrap();
197 }
198 }
199 None => panic!(""),
200 }
201 }
202
203 Err(e) => {}
204 }
205 }
206
207 let client_config = ClientConfig::builder()
208 .with_root_certificates(root_certs)
209 .with_no_client_auth();
210
211 client_config
212}