Skip to content

Commit c5ff8e1

Browse files
committed
server: SNI rustls_connection getter ret rustls_str
The `rustls_server_connection_get_server_name()` API function previously wrote the SNI value to a caller-provided buffer as it predates the `rustls_str` pattern. This commit updates it to return a `rustls_str`. Invalid parameters or incomplete connection state are returned as empty strs. The documented lifetime matches that of other `rustls_connection` accessors based on a "set-once" property we assume from upstream.
1 parent b67a4a6 commit c5ff8e1

File tree

3 files changed

+39
-52
lines changed

3 files changed

+39
-52
lines changed

librustls/src/rustls.h

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -2365,22 +2365,22 @@ rustls_result rustls_server_connection_new(const struct rustls_server_config *co
23652365
struct rustls_connection **conn_out);
23662366

23672367
/**
2368-
* Copy the server name from the server name indication (SNI) extension to `buf`.
2368+
* Returns a `rustls_str` reference to the server name sent by the client in a server name
2369+
* indication (SNI) extension.
23692370
*
2370-
* `buf` can hold up to `count` bytes, and the length of that server name in `out_n`.
2371+
* The returned `rustls_str` is valid until the next mutating function call affecting the
2372+
* connection. A mutating function call is one where the first argument has type
2373+
* `struct rustls_connection *` (as opposed to `const struct rustls_connection *`). The caller
2374+
* does not need to free the `rustls_str`.
23712375
*
2372-
* The string is stored in UTF-8 with no terminating NUL byte.
2376+
* Returns a zero-length `rustls_str` if:
23732377
*
2374-
* Returns RUSTLS_RESULT_INSUFFICIENT_SIZE if the SNI hostname is longer than `count`.
2375-
*
2376-
* Returns Ok with *out_n == 0 if there is no SNI hostname available on this connection
2377-
* because it hasn't been processed yet, or because the client did not send SNI.
2378-
* <https://docs.rs/rustls/latest/rustls/server/struct.ServerConnection.html#method.server_name>
2378+
* - the connection is not a server connection.
2379+
* - the connection is a server connection but the SNI extension in the client hello has not
2380+
* been processed during the handshake yet. Check `rustls_connection_is_handshaking`.
2381+
* - the SNI value contains null bytes.
23792382
*/
2380-
rustls_result rustls_server_connection_get_server_name(const struct rustls_connection *conn,
2381-
uint8_t *buf,
2382-
size_t count,
2383-
size_t *out_n);
2383+
struct rustls_str rustls_server_connection_get_server_name(const struct rustls_connection *conn);
23842384

23852385
/**
23862386
* Register a callback to be invoked when a connection created from this config

librustls/src/server.rs

Lines changed: 19 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -443,55 +443,34 @@ impl rustls_server_config {
443443
}
444444
}
445445

446-
/// Copy the server name from the server name indication (SNI) extension to `buf`.
447-
///
448-
/// `buf` can hold up to `count` bytes, and the length of that server name in `out_n`.
446+
447+
/// Returns a `rustls_str` reference to the server name sent by the client in a server name
448+
/// indication (SNI) extension.
449449
///
450-
/// The string is stored in UTF-8 with no terminating NUL byte.
450+
/// The returned `rustls_str` is valid until the next mutating function call affecting the
451+
/// connection. A mutating function call is one where the first argument has type
452+
/// `struct rustls_connection *` (as opposed to `const struct rustls_connection *`). The caller
453+
/// does not need to free the `rustls_str`.
451454
///
452-
/// Returns RUSTLS_RESULT_INSUFFICIENT_SIZE if the SNI hostname is longer than `count`.
455+
/// Returns a zero-length `rustls_str` if:
453456
///
454-
/// Returns Ok with *out_n == 0 if there is no SNI hostname available on this connection
455-
/// because it hasn't been processed yet, or because the client did not send SNI.
456-
/// <https://docs.rs/rustls/latest/rustls/server/struct.ServerConnection.html#method.server_name>
457+
/// - the connection is not a server connection.
458+
/// - the connection is a server connection but the SNI extension in the client hello has not
459+
/// been processed during the handshake yet. Check `rustls_connection_is_handshaking`.
460+
/// - the SNI value contains null bytes.
457461
#[no_mangle]
458462
pub extern "C" fn rustls_server_connection_get_server_name(
459463
conn: *const rustls_connection,
460-
buf: *mut u8,
461-
count: size_t,
462-
out_n: *mut size_t,
463-
) -> rustls_result {
464+
) -> rustls_str<'static> {
464465
ffi_panic_boundary! {
465-
let conn = try_ref_from_ptr!(conn);
466-
if buf.is_null() {
467-
return rustls_result::NullParameter;
468-
}
469-
if out_n.is_null() {
470-
return rustls_result::NullParameter;
471-
}
472-
let server_connection = match conn.as_server() {
473-
Some(s) => s,
474-
_ => return rustls_result::InvalidParameter,
466+
let Some(server_connection) = try_ref_from_ptr!(conn).as_server() else {
467+
return rustls_str::default();
475468
};
476-
let sni_hostname = match server_connection.server_name() {
477-
Some(sni_hostname) => sni_hostname,
478-
None => {
479-
unsafe {
480-
*out_n = 0;
481-
}
482-
return rustls_result::Ok;
483-
}
469+
let Some(sni_hostname) = server_connection.server_name() else {
470+
return rustls_str::default();
484471
};
485-
let len = sni_hostname.len();
486-
if len > count {
487-
unsafe { *out_n = 0 }
488-
return rustls_result::InsufficientSize;
489-
}
490-
unsafe {
491-
std::ptr::copy_nonoverlapping(sni_hostname.as_ptr(), buf, len);
492-
*out_n = len;
493-
}
494-
rustls_result::Ok
472+
let res = rustls_str::try_from(sni_hostname).unwrap_or_default();
473+
unsafe { res.into_static() }
495474
}
496475
}
497476

librustls/tests/common.c

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -486,6 +486,14 @@ log_connection_info(const rustls_connection *rconn)
486486
else {
487487
LOG_SIMPLE("negotiated ALPN protocol: none");
488488
}
489+
490+
// We can unconditionally call this function whether we have a server
491+
// or client connection, as it will return an empty rustls_str if it was a
492+
// client connection.
493+
const rustls_str sni = rustls_server_connection_get_server_name(rconn);
494+
if(sni.len > 0) {
495+
LOG("client SNI: '%.*s'", (int)sni.len, sni.data);
496+
}
489497
}
490498

491499
// TLS 1.2 and TLS 1.3, matching Rustls default.

0 commit comments

Comments
 (0)