• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright (C) 2023 Huawei Device Co., Ltd.
2 // Licensed under the Apache License, Version 2.0 (the "License");
3 // you may not use this file except in compliance with the License.
4 // You may obtain a copy of the License at
5 //
6 //     http://www.apache.org/licenses/LICENSE-2.0
7 //
8 // Unless required by applicable law or agreed to in writing, software
9 // distributed under the License is distributed on an "AS IS" BASIS,
10 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11 // See the License for the specific language governing permissions and
12 // limitations under the License.
13 
14 use std::sync::{Arc, RwLock};
15 use std::time::Duration;
16 
17 use ylong_http_client::Certificate;
18 
19 use crate::utils::runtime_spawn;
20 
21 const UPDATE_SYSTEM_CERT_INTERVAL_IN_SECS: u64 = 60 * 60;
22 
23 #[derive(Clone)]
24 pub(crate) struct CertManager {
25     info: Arc<RwLock<CertInfo>>,
26 }
27 
28 impl CertManager {
init() -> Self29     pub(crate) fn init() -> Self {
30         let info = Arc::new(RwLock::new(CertInfo::default()));
31         runtime_spawn(run(info.clone()));
32         Self { info }
33     }
34 
certificate(&self) -> Option<Vec<Certificate>>35     pub(crate) fn certificate(&self) -> Option<Vec<Certificate>> {
36         self.info.read().unwrap().cert.clone()
37     }
38 
force_update(&self)39     pub(crate) fn force_update(&self) {
40         update_system_cert(&self.info);
41     }
42 }
43 
44 #[derive(Default)]
45 struct CertInfo {
46     cert: Option<Vec<Certificate>>,
47 }
48 
run(info: Arc<RwLock<CertInfo>>)49 async fn run(info: Arc<RwLock<CertInfo>>) {
50     loop {
51         update_system_cert(&info);
52         ylong_runtime::time::sleep(Duration::from_secs(UPDATE_SYSTEM_CERT_INTERVAL_IN_SECS)).await;
53     }
54 }
55 
56 // Try use `async` func to read file.
update_system_cert(info: &Arc<RwLock<CertInfo>>)57 fn update_system_cert(info: &Arc<RwLock<CertInfo>>) {
58     let mut info = info.write().unwrap();
59 
60     let mut certificates = Vec::new();
61 
62     let c_certs_ptr = unsafe { GetUserCertsData() };
63     if !c_certs_ptr.is_null() {
64         info!("GetUserCertsData valid");
65         let certs = unsafe { &*c_certs_ptr };
66         let c_cert_list_ptr =
67             unsafe { std::slice::from_raw_parts(certs.cert_data_list, certs.len as usize) };
68         for item in c_cert_list_ptr.iter() {
69             let cert = unsafe { &**item };
70             let cert_slice = unsafe { std::slice::from_raw_parts(cert.data, cert.size as usize) };
71             match Certificate::from_pem(cert_slice) {
72                 Ok(cert) => {
73                     certificates.push(cert);
74                 }
75                 Err(e) => {
76                     error!("parse security cert path failed, error is {:?}", e);
77                     return;
78                 }
79             };
80         }
81         unsafe { FreeCertDataList(c_certs_ptr) };
82     }
83 
84     match Certificate::from_path("/system/etc/security/certificates/") {
85         Ok(cert) => {
86             certificates.push(cert);
87         }
88         Err(e) => {
89             error!("parse security cert path failed, error is {:?}", e);
90             return;
91         }
92     };
93 
94     *info = CertInfo {
95         cert: Some(certificates),
96     };
97 }
98 
99 #[cfg(feature = "oh")]
100 extern "C" {
GetUserCertsData() -> *const CRequestCerts101     pub(crate) fn GetUserCertsData() -> *const CRequestCerts;
FreeCertDataList(certs: *const CRequestCerts)102     pub(crate) fn FreeCertDataList(certs: *const CRequestCerts);
103 }
104 
105 #[repr(C)]
106 pub(crate) struct CRequestCert {
107     pub(crate) size: u32,
108     pub(crate) data: *const u8,
109 }
110 
111 #[repr(C)]
112 pub(crate) struct CRequestCerts {
113     pub(crate) cert_data_list: *const *const CRequestCert,
114     pub(crate) len: u32,
115 }
116 
117 #[cfg(feature = "oh")]
118 #[cfg(test)]
119 mod test {
120     use super::*;
121     use crate::tests::test_init;
122 
123     #[test]
test_cert_manager()124     fn test_cert_manager() {
125         test_init();
126         let cert_manager = CertManager::init();
127         let cert = cert_manager.certificate();
128         if cert.is_none() {
129             cert_manager.force_update();
130         }
131         assert!(cert_manager.certificate().is_some());
132     }
133 }
134