1use foreign_types::ForeignTypeRef;
16use libc::*;
17use openssl::error::ErrorStack;
18use openssl::pkey::{HasPrivate, PKeyRef};
19use openssl::ssl::{Ssl, SslAcceptor, SslRef};
20use openssl::x509::store::X509StoreRef;
21use openssl::x509::verify::X509VerifyParamRef;
22use openssl::x509::X509Ref;
23use openssl_sys::{
24 SSL_ctrl, EVP_PKEY, SSL, SSL_CTRL_SET_GROUPS_LIST, SSL_CTRL_SET_VERIFY_CERT_STORE, X509,
25 X509_VERIFY_PARAM,
26};
27use std::ffi::CString;
28use std::os::raw;
29
30fn cvt(r: c_long) -> Result<c_long, ErrorStack> {
31 if r != 1 {
32 Err(ErrorStack::get())
33 } else {
34 Ok(r)
35 }
36}
37
38extern "C" {
39 pub fn X509_VERIFY_PARAM_add1_host(
40 param: *mut X509_VERIFY_PARAM,
41 name: *const c_char,
42 namelen: size_t,
43 ) -> c_int;
44
45 pub fn SSL_use_certificate(ssl: *mut SSL, cert: *mut X509) -> c_int;
46 pub fn SSL_use_PrivateKey(ssl: *mut SSL, key: *mut EVP_PKEY) -> c_int;
47
48 pub fn SSL_set_cert_cb(
49 ssl: *mut SSL,
50 cb: ::std::option::Option<
51 unsafe extern "C" fn(ssl: *mut SSL, arg: *mut raw::c_void) -> raw::c_int,
52 >,
53 arg: *mut raw::c_void,
54 );
55}
56
57pub fn add_host(verify_param: &mut X509VerifyParamRef, host: &str) -> Result<(), ErrorStack> {
61 if host.is_empty() {
62 return Ok(());
63 }
64 unsafe {
65 cvt(X509_VERIFY_PARAM_add1_host(
66 verify_param.as_ptr(),
67 host.as_ptr() as *const c_char,
68 host.len(),
69 ) as c_long)
70 .map(|_| ())
71 }
72}
73
74pub fn ssl_set_verify_cert_store(
78 ssl: &mut SslRef,
79 cert_store: &X509StoreRef,
80) -> Result<(), ErrorStack> {
81 unsafe {
82 cvt(SSL_ctrl(
83 ssl.as_ptr(),
84 SSL_CTRL_SET_VERIFY_CERT_STORE,
85 1, cert_store.as_ptr() as *mut c_void,
87 ))?;
88 }
89 Ok(())
90}
91
92pub fn ssl_use_certificate(ssl: &mut SslRef, cert: &X509Ref) -> Result<(), ErrorStack> {
96 unsafe {
97 cvt(SSL_use_certificate(ssl.as_ptr(), cert.as_ptr()) as c_long)?;
98 }
99 Ok(())
100}
101
102pub fn ssl_use_private_key<T>(ssl: &mut SslRef, key: &PKeyRef<T>) -> Result<(), ErrorStack>
106where
107 T: HasPrivate,
108{
109 unsafe {
110 cvt(SSL_use_PrivateKey(ssl.as_ptr(), key.as_ptr()) as c_long)?;
111 }
112 Ok(())
113}
114
115pub fn ssl_add_chain_cert(ssl: &mut SslRef, cert: &X509Ref) -> Result<(), ErrorStack> {
119 const SSL_CTRL_CHAIN_CERT: i32 = 89;
120 unsafe {
121 cvt(SSL_ctrl(
122 ssl.as_ptr(),
123 SSL_CTRL_CHAIN_CERT,
124 1, cert.as_ptr() as *mut c_void,
126 ))?;
127 }
128 Ok(())
129}
130
131pub fn ssl_set_renegotiate_mode_freely(_ssl: &mut SslRef) {}
135
136pub fn ssl_set_groups_list(ssl: &mut SslRef, groups: &str) -> Result<(), ErrorStack> {
140 if groups.contains('\0') {
141 return Err(ErrorStack::get());
142 }
143 let groups = CString::new(groups).map_err(|_| ErrorStack::get())?;
144 unsafe {
145 cvt(SSL_ctrl(
146 ssl.as_ptr(),
147 SSL_CTRL_SET_GROUPS_LIST,
148 0,
149 groups.as_ptr() as *mut c_void,
150 ))?;
151 }
152 Ok(())
153}
154
155pub fn ssl_use_second_key_share(_ssl: &mut SslRef, _enabled: bool) {}
159
160pub fn clear_error_stack() {
166 let _ = ErrorStack::get();
167}
168
169pub fn ssl_from_acceptor(acceptor: &SslAcceptor) -> Result<Ssl, ErrorStack> {
173 Ssl::new(acceptor.context())
174}
175
176pub fn suspend_when_need_ssl_cert(ssl: &mut SslRef) {
182 unsafe {
183 SSL_set_cert_cb(ssl.as_ptr(), Some(raw_cert_block), std::ptr::null_mut());
184 }
185}
186
187pub fn unblock_ssl_cert(ssl: &mut SslRef) {
191 unsafe {
192 SSL_set_cert_cb(ssl.as_ptr(), None, std::ptr::null_mut());
193 }
194}
195
196extern "C" fn raw_cert_block(_ssl: *mut openssl_sys::SSL, _arg: *mut c_void) -> c_int {
198 -1
199}
200
201pub fn is_suspended_for_cert(error: &openssl::ssl::Error) -> bool {
203 error.code().as_raw() == openssl_sys::SSL_ERROR_WANT_X509_LOOKUP
204}
205
206#[allow(clippy::mut_from_ref)]
207pub unsafe fn ssl_mut(ssl: &SslRef) -> &mut SslRef {
211 SslRef::from_ptr_mut(ssl.as_ptr())
212}
213
214#[cfg(test)]
215mod tests {
216 use super::*;
217 use openssl::ssl::{SslContextBuilder, SslMethod};
218
219 #[test]
220 fn test_ssl_set_groups_list() {
221 let ctx_builder = SslContextBuilder::new(SslMethod::tls()).unwrap();
222 let ssl = Ssl::new(&ctx_builder.build()).unwrap();
223 let ssl_ref = unsafe { ssl_mut(&ssl) };
224
225 assert!(ssl_set_groups_list(ssl_ref, "P-256:P-384").is_ok());
227
228 assert!(ssl_set_groups_list(ssl_ref, "P-256\0P-384").is_err());
230 }
231}