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