Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Two small breaking API changes before next release #516

Open
wants to merge 2 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 18 additions & 15 deletions librustls/src/rustls.h
Original file line number Diff line number Diff line change
Expand Up @@ -2365,22 +2365,22 @@ rustls_result rustls_server_connection_new(const struct rustls_server_config *co
struct rustls_connection **conn_out);

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

/**
* Register a callback to be invoked when a connection created from this config
Expand Down Expand Up @@ -2428,13 +2428,16 @@ rustls_result rustls_client_hello_select_certified_key(const struct rustls_clien
* keys and values are highly sensitive data, containing enough information
* to break the security of the connections involved.
*
* If `builder`, `get_cb`, or `put_cb` are NULL, this function will return
* immediately without doing anything.
*
* If `userdata` has been set with rustls_connection_set_userdata, it
* will be passed to the callbacks. Otherwise the userdata param passed to
* the callbacks will be NULL.
*/
rustls_result rustls_server_config_builder_set_persistence(struct rustls_server_config_builder *builder,
rustls_session_store_get_callback get_cb,
rustls_session_store_put_callback put_cb);
void rustls_server_config_builder_set_persistence(struct rustls_server_config_builder *builder,
rustls_session_store_get_callback get_cb,
rustls_session_store_put_callback put_cb);

/**
* Free a `rustls_client_cert_verifier` previously returned from
Expand Down
79 changes: 29 additions & 50 deletions librustls/src/server.rs
Original file line number Diff line number Diff line change
Expand Up @@ -443,55 +443,33 @@ impl rustls_server_config {
}
}

/// Copy the server name from the server name indication (SNI) extension to `buf`.
/// Returns a `rustls_str` reference to the server name sent by the client in a server name
/// indication (SNI) extension.
///
/// `buf` can hold up to `count` bytes, and the length of that server name in `out_n`.
/// The returned `rustls_str` is valid until the next mutating function call affecting the
/// connection. A mutating function call is one where the first argument has type
/// `struct rustls_connection *` (as opposed to `const struct rustls_connection *`). The caller
/// does not need to free the `rustls_str`.
///
/// The string is stored in UTF-8 with no terminating NUL byte.
/// Returns a zero-length `rustls_str` if:
///
/// Returns RUSTLS_RESULT_INSUFFICIENT_SIZE if the SNI hostname is longer than `count`.
///
/// Returns Ok with *out_n == 0 if there is no SNI hostname available on this connection
/// because it hasn't been processed yet, or because the client did not send SNI.
/// <https://docs.rs/rustls/latest/rustls/server/struct.ServerConnection.html#method.server_name>
/// - the connection is not a server connection.
/// - the connection is a server connection but the SNI extension in the client hello has not
/// been processed during the handshake yet. Check `rustls_connection_is_handshaking`.
/// - the SNI value contains null bytes.
#[no_mangle]
pub extern "C" fn rustls_server_connection_get_server_name(
conn: *const rustls_connection,
buf: *mut u8,
count: size_t,
out_n: *mut size_t,
) -> rustls_result {
) -> rustls_str<'static> {
ffi_panic_boundary! {
let conn = try_ref_from_ptr!(conn);
if buf.is_null() {
return rustls_result::NullParameter;
}
if out_n.is_null() {
return rustls_result::NullParameter;
}
let server_connection = match conn.as_server() {
Some(s) => s,
_ => return rustls_result::InvalidParameter,
let Some(server_connection) = try_ref_from_ptr!(conn).as_server() else {
return rustls_str::default();
};
let sni_hostname = match server_connection.server_name() {
Some(sni_hostname) => sni_hostname,
None => {
unsafe {
*out_n = 0;
}
return rustls_result::Ok;
}
let Some(sni_hostname) = server_connection.server_name() else {
return rustls_str::default();
};
let len = sni_hostname.len();
if len > count {
unsafe { *out_n = 0 }
return rustls_result::InsufficientSize;
}
unsafe {
std::ptr::copy_nonoverlapping(sni_hostname.as_ptr(), buf, len);
*out_n = len;
}
rustls_result::Ok
let res = rustls_str::try_from(sni_hostname).unwrap_or_default();
unsafe { res.into_static() }
}
}

Expand Down Expand Up @@ -743,6 +721,9 @@ impl rustls_server_config_builder {
/// keys and values are highly sensitive data, containing enough information
/// to break the security of the connections involved.
///
/// If `builder`, `get_cb`, or `put_cb` are NULL, this function will return
/// immediately without doing anything.
///
/// If `userdata` has been set with rustls_connection_set_userdata, it
/// will be passed to the callbacks. Otherwise the userdata param passed to
/// the callbacks will be NULL.
Expand All @@ -751,19 +732,17 @@ impl rustls_server_config_builder {
builder: *mut rustls_server_config_builder,
get_cb: rustls_session_store_get_callback,
put_cb: rustls_session_store_put_callback,
) -> rustls_result {
) {
ffi_panic_boundary! {
let get_cb = match get_cb {
Some(cb) => cb,
None => return rustls_result::NullParameter,
let Some(get_cb) = get_cb else {
return;
};
let put_cb = match put_cb {
Some(cb) => cb,
None => return rustls_result::NullParameter,
let Some(put_cb) = put_cb else {
return;
};
let builder = try_mut_from_ptr!(builder);
builder.session_storage = Some(Arc::new(SessionStoreBroker::new(get_cb, put_cb)));
rustls_result::Ok

try_mut_from_ptr!(builder).session_storage =
Some(Arc::new(SessionStoreBroker::new(get_cb, put_cb)));
}
}
}
Expand Down
8 changes: 8 additions & 0 deletions librustls/tests/common.c
Original file line number Diff line number Diff line change
Expand Up @@ -486,6 +486,14 @@ log_connection_info(const rustls_connection *rconn)
else {
LOG_SIMPLE("negotiated ALPN protocol: none");
}

// We can unconditionally call this function whether we have a server
// or client connection, as it will return an empty rustls_str if it was a
// client connection.
const rustls_str sni = rustls_server_connection_get_server_name(rconn);
if(sni.len > 0) {
LOG("client SNI: '%.*s'", (int)sni.len, sni.data);
}
}

// TLS 1.2 and TLS 1.3, matching Rustls default.
Expand Down
Loading