1 use bitflags::bitflags; 2 use foreign_types::ForeignTypeRef; 3 use libc::{c_int, c_uint, c_ulong, time_t}; 4 use std::net::IpAddr; 5 6 use crate::error::ErrorStack; 7 #[cfg(ossl102)] 8 use crate::x509::X509PurposeId; 9 use crate::{cvt, cvt_p}; 10 use openssl_macros::corresponds; 11 12 bitflags! { 13 /// Flags used to check an `X509` certificate. 14 pub struct X509CheckFlags: c_uint { 15 const ALWAYS_CHECK_SUBJECT = ffi::X509_CHECK_FLAG_ALWAYS_CHECK_SUBJECT; 16 const NO_WILDCARDS = ffi::X509_CHECK_FLAG_NO_WILDCARDS; 17 const NO_PARTIAL_WILDCARDS = ffi::X509_CHECK_FLAG_NO_PARTIAL_WILDCARDS; 18 const MULTI_LABEL_WILDCARDS = ffi::X509_CHECK_FLAG_MULTI_LABEL_WILDCARDS; 19 const SINGLE_LABEL_SUBDOMAINS = ffi::X509_CHECK_FLAG_SINGLE_LABEL_SUBDOMAINS; 20 /// Requires OpenSSL 1.1.0 or newer. 21 #[cfg(any(ossl110))] 22 const NEVER_CHECK_SUBJECT = ffi::X509_CHECK_FLAG_NEVER_CHECK_SUBJECT; 23 24 #[deprecated(since = "0.10.6", note = "renamed to NO_WILDCARDS")] 25 const FLAG_NO_WILDCARDS = ffi::X509_CHECK_FLAG_NO_WILDCARDS; 26 } 27 } 28 29 bitflags! { 30 /// Flags used to verify an `X509` certificate chain. 31 pub struct X509VerifyFlags: c_ulong { 32 const CB_ISSUER_CHECK = ffi::X509_V_FLAG_CB_ISSUER_CHECK; 33 const USE_CHECK_TIME = ffi::X509_V_FLAG_USE_CHECK_TIME; 34 const CRL_CHECK = ffi::X509_V_FLAG_CRL_CHECK; 35 const CRL_CHECK_ALL = ffi::X509_V_FLAG_CRL_CHECK_ALL; 36 const IGNORE_CRITICAL = ffi::X509_V_FLAG_IGNORE_CRITICAL; 37 const X509_STRICT = ffi::X509_V_FLAG_X509_STRICT; 38 const ALLOW_PROXY_CERTS = ffi::X509_V_FLAG_ALLOW_PROXY_CERTS; 39 const POLICY_CHECK = ffi::X509_V_FLAG_POLICY_CHECK; 40 const EXPLICIT_POLICY = ffi::X509_V_FLAG_EXPLICIT_POLICY; 41 const INHIBIT_ANY = ffi::X509_V_FLAG_INHIBIT_ANY; 42 const INHIBIT_MAP = ffi::X509_V_FLAG_INHIBIT_MAP; 43 const NOTIFY_POLICY = ffi::X509_V_FLAG_NOTIFY_POLICY; 44 const EXTENDED_CRL_SUPPORT = ffi::X509_V_FLAG_EXTENDED_CRL_SUPPORT; 45 const USE_DELTAS = ffi::X509_V_FLAG_USE_DELTAS; 46 const CHECK_SS_SIGNATURE = ffi::X509_V_FLAG_CHECK_SS_SIGNATURE; 47 #[cfg(ossl102)] 48 const TRUSTED_FIRST = ffi::X509_V_FLAG_TRUSTED_FIRST; 49 #[cfg(ossl102)] 50 const SUITEB_128_LOS_ONLY = ffi::X509_V_FLAG_SUITEB_128_LOS_ONLY; 51 #[cfg(ossl102)] 52 const SUITEB_192_LOS = ffi::X509_V_FLAG_SUITEB_128_LOS; 53 #[cfg(ossl102)] 54 const SUITEB_128_LOS = ffi::X509_V_FLAG_SUITEB_192_LOS; 55 #[cfg(ossl102)] 56 const PARTIAL_CHAIN = ffi::X509_V_FLAG_PARTIAL_CHAIN; 57 #[cfg(ossl110)] 58 const NO_ALT_CHAINS = ffi::X509_V_FLAG_NO_ALT_CHAINS; 59 #[cfg(ossl110)] 60 const NO_CHECK_TIME = ffi::X509_V_FLAG_NO_CHECK_TIME; 61 } 62 } 63 64 foreign_type_and_impl_send_sync! { 65 type CType = ffi::X509_VERIFY_PARAM; 66 fn drop = ffi::X509_VERIFY_PARAM_free; 67 68 /// Adjust parameters associated with certificate verification. 69 pub struct X509VerifyParam; 70 /// Reference to `X509VerifyParam`. 71 pub struct X509VerifyParamRef; 72 } 73 74 impl X509VerifyParam { 75 /// Create an X509VerifyParam 76 #[corresponds(X509_VERIFY_PARAM_new)] new() -> Result<X509VerifyParam, ErrorStack>77 pub fn new() -> Result<X509VerifyParam, ErrorStack> { 78 unsafe { 79 ffi::init(); 80 cvt_p(ffi::X509_VERIFY_PARAM_new()).map(X509VerifyParam) 81 } 82 } 83 } 84 85 impl X509VerifyParamRef { 86 /// Set the host flags. 87 #[corresponds(X509_VERIFY_PARAM_set_hostflags)] set_hostflags(&mut self, hostflags: X509CheckFlags)88 pub fn set_hostflags(&mut self, hostflags: X509CheckFlags) { 89 unsafe { 90 ffi::X509_VERIFY_PARAM_set_hostflags(self.as_ptr(), hostflags.bits); 91 } 92 } 93 94 /// Set verification flags. 95 #[corresponds(X509_VERIFY_PARAM_set_flags)] set_flags(&mut self, flags: X509VerifyFlags) -> Result<(), ErrorStack>96 pub fn set_flags(&mut self, flags: X509VerifyFlags) -> Result<(), ErrorStack> { 97 unsafe { cvt(ffi::X509_VERIFY_PARAM_set_flags(self.as_ptr(), flags.bits)).map(|_| ()) } 98 } 99 100 /// Clear verification flags. 101 #[corresponds(X509_VERIFY_PARAM_clear_flags)] clear_flags(&mut self, flags: X509VerifyFlags) -> Result<(), ErrorStack>102 pub fn clear_flags(&mut self, flags: X509VerifyFlags) -> Result<(), ErrorStack> { 103 unsafe { 104 cvt(ffi::X509_VERIFY_PARAM_clear_flags( 105 self.as_ptr(), 106 flags.bits, 107 )) 108 .map(|_| ()) 109 } 110 } 111 112 /// Gets verification flags. 113 #[corresponds(X509_VERIFY_PARAM_get_flags)] flags(&mut self) -> X509VerifyFlags114 pub fn flags(&mut self) -> X509VerifyFlags { 115 let bits = unsafe { ffi::X509_VERIFY_PARAM_get_flags(self.as_ptr()) }; 116 X509VerifyFlags { bits } 117 } 118 119 /// Set the expected DNS hostname. 120 #[corresponds(X509_VERIFY_PARAM_set1_host)] set_host(&mut self, host: &str) -> Result<(), ErrorStack>121 pub fn set_host(&mut self, host: &str) -> Result<(), ErrorStack> { 122 unsafe { 123 // len == 0 means "run strlen" :( 124 let raw_host = if host.is_empty() { "\0" } else { host }; 125 cvt(ffi::X509_VERIFY_PARAM_set1_host( 126 self.as_ptr(), 127 raw_host.as_ptr() as *const _, 128 host.len(), 129 )) 130 .map(|_| ()) 131 } 132 } 133 134 /// Set the expected IPv4 or IPv6 address. 135 #[corresponds(X509_VERIFY_PARAM_set1_ip)] set_ip(&mut self, ip: IpAddr) -> Result<(), ErrorStack>136 pub fn set_ip(&mut self, ip: IpAddr) -> Result<(), ErrorStack> { 137 unsafe { 138 let mut buf = [0; 16]; 139 let len = match ip { 140 IpAddr::V4(addr) => { 141 buf[..4].copy_from_slice(&addr.octets()); 142 4 143 } 144 IpAddr::V6(addr) => { 145 buf.copy_from_slice(&addr.octets()); 146 16 147 } 148 }; 149 cvt(ffi::X509_VERIFY_PARAM_set1_ip( 150 self.as_ptr(), 151 buf.as_ptr() as *const _, 152 len, 153 )) 154 .map(|_| ()) 155 } 156 } 157 158 /// Set the verification time, where time is of type time_t, traditionaly defined as seconds since the epoch 159 #[corresponds(X509_VERIFY_PARAM_set_time)] set_time(&mut self, time: time_t)160 pub fn set_time(&mut self, time: time_t) { 161 unsafe { ffi::X509_VERIFY_PARAM_set_time(self.as_ptr(), time) } 162 } 163 164 /// Set the verification depth 165 #[corresponds(X509_VERIFY_PARAM_set_depth)] set_depth(&mut self, depth: c_int)166 pub fn set_depth(&mut self, depth: c_int) { 167 unsafe { ffi::X509_VERIFY_PARAM_set_depth(self.as_ptr(), depth) } 168 } 169 170 /// Sets the authentication security level to auth_level 171 #[corresponds(X509_VERIFY_PARAM_set_auth_level)] 172 #[cfg(ossl110)] set_auth_level(&mut self, lvl: c_int)173 pub fn set_auth_level(&mut self, lvl: c_int) { 174 unsafe { ffi::X509_VERIFY_PARAM_set_auth_level(self.as_ptr(), lvl) } 175 } 176 177 /// Gets the current authentication security level 178 #[corresponds(X509_VERIFY_PARAM_get_auth_level)] 179 #[cfg(ossl110)] auth_level(&self) -> i32180 pub fn auth_level(&self) -> i32 { 181 unsafe { ffi::X509_VERIFY_PARAM_get_auth_level(self.as_ptr()) } 182 } 183 184 /// Sets the verification purpose 185 #[corresponds(X509_VERIFY_PARAM_set_purpose)] 186 #[cfg(ossl102)] set_purpose(&mut self, purpose: X509PurposeId) -> Result<(), ErrorStack>187 pub fn set_purpose(&mut self, purpose: X509PurposeId) -> Result<(), ErrorStack> { 188 unsafe { cvt(ffi::X509_VERIFY_PARAM_set_purpose(self.as_ptr(), purpose.0)).map(|_| ()) } 189 } 190 } 191