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::mem::forget;
15 
16 use libc::c_int;
17 
18 use crate::util::c_openssl::x509::{X509StoreContextRef, X509};
19 use crate::{ErrorKind, HttpClientError};
20 /// ServerCerts is provided to fetch info from X509
21 pub struct ServerCerts<'a> {
22     inner: &'a X509StoreContextRef,
23 }
24 
25 impl<'a> ServerCerts<'a> {
new(inner: &'a X509StoreContextRef) -> Self26     pub(crate) fn new(inner: &'a X509StoreContextRef) -> Self {
27         Self { inner }
28     }
29 
30     /// Gets cers version.
31     ///
32     ///
33     /// # Examples
34     ///
35     /// ```
36     /// # use ylong_http_client::ServerCerts;
37     ///
38     /// # fn cert_version(certs: &ServerCerts) {
39     /// let version = certs.version();
40     /// # }
41     /// ```
version(&self) -> Result<usize, HttpClientError>42     pub fn version(&self) -> Result<usize, HttpClientError> {
43         let cert = self
44             .inner
45             .get_current_cert()
46             .map_err(|e| HttpClientError::from_error(ErrorKind::Connect, e))?;
47         Ok(cert.get_cert_version() as usize)
48     }
49 
50     /// Gets certs name.
51     ///
52     ///
53     /// # Examples
54     ///
55     /// ```
56     /// # use ylong_http_client::ServerCerts;
57     ///
58     /// # fn cert_name(certs: &ServerCerts) {
59     /// let name = certs.cert_name().unwrap();
60     /// # }
61     /// ```
cert_name(&self) -> Result<String, HttpClientError>62     pub fn cert_name(&self) -> Result<String, HttpClientError> {
63         let cert = self
64             .inner
65             .get_current_cert()
66             .map_err(|e| HttpClientError::from_error(ErrorKind::Connect, e))?;
67         let cert_name = cert
68             .get_cert_name()
69             .map_err(|e| HttpClientError::from_error(ErrorKind::Connect, e))?;
70         let mut buf = [0u8; 128];
71         let size = 128;
72         let res = cert_name.get_x509_name_info(buf.as_mut(), size as c_int);
73         forget(cert_name);
74         Ok(res)
75     }
76 
77     /// Gets certs issuer.
78     ///
79     ///
80     /// # Examples
81     ///
82     /// ```
83     /// # use ylong_http_client::ServerCerts;
84     ///
85     /// # fn cert_issuer(certs: &ServerCerts) {
86     /// let issuer = certs.issuer().unwrap();
87     /// # }
88     /// ```
issuer(&self) -> Result<String, HttpClientError>89     pub fn issuer(&self) -> Result<String, HttpClientError> {
90         let cert = self
91             .inner
92             .get_current_cert()
93             .map_err(|e| HttpClientError::from_error(ErrorKind::Connect, e))?;
94         let cert_issuer = cert
95             .get_issuer_name()
96             .map_err(|e| HttpClientError::from_error(ErrorKind::Connect, e))?;
97         let mut buf = [0u8; 128];
98         let size = 128;
99         let res = cert_issuer.get_x509_name_info(buf.as_mut(), size as c_int);
100         forget(cert_issuer);
101         Ok(res)
102     }
103 
104     /// Compares certs, if they are same, return 1, if they are different,
105     /// return 0.
106     ///
107     ///
108     /// # Examples
109     ///
110     /// ```
111     /// # use ylong_http_client::ServerCerts;
112     /// # use std::io::Read;
113     /// # fn cmp_certs(certs: &ServerCerts) {
114     /// # let mut file = std::fs::File::open("./examples/cert/cert.pem").unwrap();
115     /// # let mut contents = String::new();
116     /// # file.read_to_string(&mut contents).unwrap();
117     /// let res = certs.cmp_pem_cert(contents.as_bytes()).unwrap();
118     /// # }
119     /// ```
cmp_pem_cert(&self, target_pem: &[u8]) -> Result<usize, HttpClientError>120     pub fn cmp_pem_cert(&self, target_pem: &[u8]) -> Result<usize, HttpClientError> {
121         let cert = self
122             .inner
123             .get_current_cert()
124             .map_err(|e| HttpClientError::from_error(ErrorKind::Connect, e))?;
125         let cert_key = cert
126             .get_cert()
127             .map_err(|e| HttpClientError::from_error(ErrorKind::Connect, e))?;
128         let target_cert = X509::from_pem(target_pem)
129             .map_err(|e| HttpClientError::from_error(ErrorKind::Build, e))?;
130         Ok(target_cert.cmp_certs(cert_key) as usize)
131     }
132 }
133 
134 impl AsRef<X509StoreContextRef> for ServerCerts<'_> {
as_ref(&self) -> &X509StoreContextRef135     fn as_ref(&self) -> &X509StoreContextRef {
136         self.inner
137     }
138 }
139