1use std::mem;
4use std::slice;
5
6use windows_sys::Win32::Security::Cryptography;
7
8use crate::cert_context::CertContext;
9use crate::Inner;
10
11pub struct CertChainContext(pub(crate) *mut Cryptography::CERT_CHAIN_CONTEXT);
13inner!(CertChainContext, *mut Cryptography::CERT_CHAIN_CONTEXT);
14
15unsafe impl Sync for CertChainContext {}
16unsafe impl Send for CertChainContext {}
17
18impl Clone for CertChainContext {
19 fn clone(&self) -> Self {
20 let rced = unsafe { Cryptography::CertDuplicateCertificateChain(self.0) };
21 CertChainContext(rced)
22 }
23}
24
25impl Drop for CertChainContext {
26 fn drop(&mut self) {
27 unsafe {
28 Cryptography::CertFreeCertificateChain(self.0);
29 }
30 }
31}
32
33impl CertChainContext {
34 pub fn final_chain(&self) -> Option<CertChain> {
39 if let Some(chain) = self.chains().last() {
40 return Some(CertChain(chain.0, self.clone()));
41 }
42 None
43 }
44
45 pub fn get_chain(&self, index: usize) -> Option<CertChain> {
47 let cert_chain = unsafe {
48 let cert_chain = *self.0;
49 if index >= cert_chain.cChain as usize {
50 None
51 } else {
52 let chain_slice =
53 slice::from_raw_parts(cert_chain.rgpChain, cert_chain.cChain as usize);
54 Some(CertChain(chain_slice[index], self.clone()))
55 }
56 };
57 cert_chain
58 }
59
60 pub fn chains(&self) -> CertificateChains {
62 CertificateChains {
63 context: self,
64 idx: 0,
65 }
66 }
67}
68
69pub struct CertChain(*mut Cryptography::CERT_SIMPLE_CHAIN, CertChainContext);
71
72impl CertChain {
73 pub fn len(&self) -> usize {
75 unsafe { (*self.0).cElement as usize }
76 }
77
78 pub fn is_empty(&self) -> bool {
80 unsafe { (*self.0).cElement == 0 }
81 }
82
83 pub fn get(&self, idx: usize) -> Option<CertContext> {
85 let elements = unsafe {
86 let cert_chain = *self.0;
87 slice::from_raw_parts(
88 cert_chain.rgpElement as *mut &mut Cryptography::CERT_CHAIN_ELEMENT,
89 cert_chain.cElement as usize,
90 )
91 };
92 elements.get(idx).map(|el| {
93 let cert = unsafe { CertContext::from_inner(el.pCertContext) };
94 let rc_cert = cert.clone();
95 mem::forget(cert);
96 rc_cert
97 })
98 }
99
100 pub fn certificates(&self) -> Certificates {
102 Certificates {
103 chain: self,
104 idx: 0,
105 }
106 }
107}
108
109pub struct CertificateChains<'a> {
111 context: &'a CertChainContext,
112 idx: usize,
113}
114
115impl<'a> Iterator for CertificateChains<'a> {
116 type Item = CertChain;
117
118 fn next(&mut self) -> Option<CertChain> {
119 let idx = self.idx;
120 self.idx += 1;
121 self.context.get_chain(idx)
122 }
123}
124
125pub struct Certificates<'a> {
127 chain: &'a CertChain,
128 idx: usize,
129}
130
131impl<'a> Iterator for Certificates<'a> {
132 type Item = CertContext;
133
134 fn next(&mut self) -> Option<CertContext> {
135 let idx = self.idx;
136 self.idx += 1;
137 self.chain.get(idx)
138 }
139}