Skip to content

Commit 0662104

Browse files
committed
Implement SSL_get_servername and SSL_get_servername_type
1 parent 3f710c4 commit 0662104

File tree

6 files changed

+88
-5
lines changed

6 files changed

+88
-5
lines changed

rustls-libssl/MATRIX.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -362,8 +362,8 @@
362362
| `SSL_get_security_level` | | | |
363363
| `SSL_get_selected_srtp_profile` [^srtp] | | | |
364364
| `SSL_get_server_random` | | | |
365-
| `SSL_get_servername` | | :white_check_mark: | |
366-
| `SSL_get_servername_type` | | | |
365+
| `SSL_get_servername` | | :white_check_mark: | :white_check_mark: |
366+
| `SSL_get_servername_type` | | | :white_check_mark: |
367367
| `SSL_get_session` | | :white_check_mark: | :exclamation: [^stub] |
368368
| `SSL_get_shared_ciphers` | | | |
369369
| `SSL_get_shared_sigalgs` | | | |

rustls-libssl/build.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,8 @@ const ENTRYPOINTS: &[&str] = &[
117117
"SSL_get_peer_cert_chain",
118118
"SSL_get_privatekey",
119119
"SSL_get_rbio",
120+
"SSL_get_servername",
121+
"SSL_get_servername_type",
120122
"SSL_get_session",
121123
"SSL_get_shutdown",
122124
"SSL_get_state",

rustls-libssl/src/entry.rs

Lines changed: 37 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,8 @@ use std::sync::Mutex;
1010
use std::{fs, io, path::PathBuf};
1111

1212
use openssl_sys::{
13-
stack_st_X509, OPENSSL_malloc, EVP_PKEY, OPENSSL_NPN_NEGOTIATED, OPENSSL_NPN_NO_OVERLAP, X509,
14-
X509_STORE, X509_STORE_CTX, X509_V_ERR_UNSPECIFIED,
13+
stack_st_X509, OPENSSL_malloc, TLSEXT_NAMETYPE_host_name, EVP_PKEY, OPENSSL_NPN_NEGOTIATED,
14+
OPENSSL_NPN_NO_OVERLAP, X509, X509_STORE, X509_STORE_CTX, X509_V_ERR_UNSPECIFIED,
1515
};
1616
use rustls::pki_types::{CertificateDer, PrivateKeyDer, PrivatePkcs8KeyDer};
1717

@@ -1117,6 +1117,41 @@ entry! {
11171117
}
11181118
}
11191119

1120+
entry! {
1121+
pub fn _SSL_get_servername(ssl: *const SSL, ty: c_int) -> *const c_char {
1122+
let ssl = try_clone_arc!(ssl);
1123+
1124+
if ty != TLSEXT_NAMETYPE_host_name {
1125+
return ptr::null();
1126+
}
1127+
1128+
let ret = if let Ok(mut inner) = ssl.lock() {
1129+
inner.server_name_pointer()
1130+
} else {
1131+
ptr::null()
1132+
};
1133+
ret
1134+
}
1135+
}
1136+
1137+
entry! {
1138+
pub fn _SSL_get_servername_type(ssl: *const SSL) -> c_int {
1139+
let ssl = try_clone_arc!(ssl);
1140+
1141+
let any_server_name = if let Ok(mut inner) = ssl.lock() {
1142+
!inner.server_name_pointer().is_null()
1143+
} else {
1144+
false
1145+
};
1146+
1147+
if any_server_name {
1148+
TLSEXT_NAMETYPE_host_name
1149+
} else {
1150+
-1
1151+
}
1152+
}
1153+
}
1154+
11201155
impl Castable for SSL {
11211156
type Ownership = OwnershipArc;
11221157
type RustType = Mutex<SSL>;

rustls-libssl/src/lib.rs

Lines changed: 36 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
1-
use core::ffi::{c_int, c_uint, c_void, CStr};
1+
use core::ffi::{c_char, c_int, c_uint, c_void, CStr};
22
use core::{mem, ptr};
3+
use std::ffi::CString;
34
use std::io::{ErrorKind, Read, Write};
45
use std::sync::{Arc, Mutex};
56

@@ -360,6 +361,7 @@ struct Ssl {
360361
alpn_callback: callbacks::AlpnCallbackConfig,
361362
cert_callback: callbacks::CertCallbackConfig,
362363
sni_server_name: Option<ServerName<'static>>,
364+
server_name: Option<CString>,
363365
bio: Option<bio::Bio>,
364366
conn: ConnState,
365367
peer_cert: Option<x509::OwnedX509>,
@@ -390,6 +392,7 @@ impl Ssl {
390392
alpn_callback: inner.alpn_callback.clone(),
391393
cert_callback: inner.cert_callback.clone(),
392394
sni_server_name: None,
395+
server_name: None,
393396
bio: None,
394397
conn: ConnState::Nothing,
395398
peer_cert: None,
@@ -472,6 +475,33 @@ impl Ssl {
472475
}
473476
}
474477

478+
fn server_name_pointer(&mut self) -> *const c_char {
479+
// This does double duty (see `SSL_get_servername`):
480+
//
481+
// for clients, it is just `sni_server_name`
482+
// (filled in here, lazily)
483+
//
484+
// for servers, it is the client's offered SNI name
485+
// (filled in below in `prepare_accepted_callbacks`)
486+
//
487+
// the remaining annoyance is that the returned pointer has to NUL-terminated.
488+
489+
match self.mode {
490+
ConnMode::Server => self.server_name.as_ref().map(|cstr| cstr.as_ptr()),
491+
ConnMode::Client | ConnMode::Unknown => match &self.server_name {
492+
Some(existing) => Some(existing.as_ptr()),
493+
None => {
494+
self.server_name = self
495+
.sni_server_name
496+
.as_ref()
497+
.and_then(|name| CString::new(name.to_str().as_bytes()).ok());
498+
self.server_name.as_ref().map(|cstr| cstr.as_ptr())
499+
}
500+
},
501+
}
502+
.unwrap_or_else(ptr::null)
503+
}
504+
475505
fn set_bio(&mut self, bio: bio::Bio) {
476506
self.bio = Some(bio);
477507
}
@@ -573,6 +603,11 @@ impl Ssl {
573603
_ => unreachable!(),
574604
};
575605

606+
self.server_name = accepted
607+
.client_hello()
608+
.server_name()
609+
.and_then(|sni| CString::new(sni.as_bytes()).ok());
610+
576611
if let Some(alpn_iter) = accepted.client_hello().alpn() {
577612
let offer = encode_alpn(alpn_iter);
578613
callbacks.add(Box::new(callbacks::AlpnPendingCallback {

rustls-libssl/tests/client.c

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,14 @@ int main(int argc, char **argv) {
101101
printf("SSL_new: SSL_get_certificate %s SSL_CTX_get0_certificate\n",
102102
SSL_get_certificate(ssl) == client_cert ? "same as" : "differs to");
103103
state(ssl);
104+
printf("SSL_get_servername: %s (%d)\n",
105+
SSL_get_servername(ssl, TLSEXT_NAMETYPE_host_name),
106+
SSL_get_servername_type(ssl));
107+
TRACE(SSL_set_tlsext_host_name(ssl, "localhost"));
108+
dump_openssl_error_stack();
109+
printf("SSL_get_servername: %s (%d)\n",
110+
SSL_get_servername(ssl, TLSEXT_NAMETYPE_host_name),
111+
SSL_get_servername_type(ssl));
104112
TRACE(SSL_set1_host(ssl, host));
105113
dump_openssl_error_stack();
106114
TRACE(SSL_set_fd(ssl, sock));

rustls-libssl/tests/server.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -151,6 +151,9 @@ int main(int argc, char **argv) {
151151
printf("version: %s\n", SSL_get_version(ssl));
152152
printf("verify-result: %ld\n", SSL_get_verify_result(ssl));
153153
printf("cipher: %s\n", SSL_CIPHER_standard_name(SSL_get_current_cipher(ssl)));
154+
printf("SSL_get_servername: %s (%d)\n",
155+
SSL_get_servername(ssl, TLSEXT_NAMETYPE_host_name),
156+
SSL_get_servername_type(ssl));
154157

155158
// check the peer certificate and chain
156159
X509 *cert = SSL_get1_peer_certificate(ssl);

0 commit comments

Comments
 (0)