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

Add support for client auth certificates & keys #25

Merged
merged 1 commit into from
Oct 27, 2023
Merged
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
28 changes: 28 additions & 0 deletions native/yaha_native/src/binding.rs
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,34 @@ pub extern "C" fn yaha_client_config_add_root_certificates(ctx: *mut YahaNativeC
valid
}

#[no_mangle]
pub extern "C" fn yaha_client_config_add_client_auth_certificates(ctx: *mut YahaNativeContext, auth_certs: *const StringBuffer) -> usize {
let ctx = YahaNativeContextInternal::from_raw_context(ctx);
let certs: Vec<rustls::Certificate> = unsafe { rustls_pemfile::certs(&mut (*auth_certs).to_bytes()).unwrap().into_iter().map(rustls::Certificate).collect() };

let count = certs.len();

if count > 0 {
ctx.client_auth_certificates.get_or_insert(certs);
}

count
}

#[no_mangle]
pub extern "C" fn yaha_client_config_add_client_auth_key(ctx: *mut YahaNativeContext, auth_key: *const StringBuffer) -> usize {
let ctx = YahaNativeContextInternal::from_raw_context(ctx);
let keys: Vec<rustls::PrivateKey> = unsafe { rustls_pemfile::pkcs8_private_keys(&mut (*auth_key).to_bytes()).unwrap().into_iter().map(rustls::PrivateKey).collect() };

let count = keys.len();

if count > 0 {
ctx.client_auth_key.get_or_insert(keys[0].clone());
}

count
}

#[no_mangle]
pub extern "C" fn yaha_client_config_skip_certificate_verification(ctx: *mut YahaNativeContext, val: bool) {
let ctx = YahaNativeContextInternal::from_raw_context(ctx);
Expand Down
25 changes: 19 additions & 6 deletions native/yaha_native/src/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@ pub struct YahaNativeContextInternal {
pub client_builder: Option<client::Builder>,
pub skip_certificate_verification: Option<bool>,
pub root_certificates: Option<rustls::RootCertStore>,
pub client_auth_certificates: Option<Vec<rustls::Certificate>>,
pub client_auth_key: Option<rustls::PrivateKey>,
pub client: Option<Client<HttpsConnector<HttpConnector>, hyper::Body>>,
pub on_status_code_and_headers_receive: OnStatusCodeAndHeadersReceive,
pub on_receive: OnReceive,
Expand All @@ -42,6 +44,8 @@ impl YahaNativeContextInternal {
client_builder: Some(Client::builder()),
skip_certificate_verification: None,
root_certificates: None,
client_auth_certificates: None,
client_auth_key: None,
on_status_code_and_headers_receive,
on_receive,
on_complete,
Expand All @@ -66,14 +70,23 @@ impl YahaNativeContextInternal {
.with_custom_certificate_verifier(Arc::new(danger::NoCertificateVerification {}))
.with_no_client_auth();
} else {
let tls_config_builder_root: rustls::ConfigBuilder<rustls::ClientConfig, rustls::client::WantsTransparencyPolicyOrClientCert>;
if let Some(root_certificates) = &self.root_certificates {
tls_config = tls_config_builder
.with_root_certificates(root_certificates.to_owned())
.with_no_client_auth();
tls_config_builder_root = tls_config_builder.with_root_certificates(root_certificates.to_owned());
} else {
tls_config = tls_config_builder
.with_webpki_roots()
.with_no_client_auth();
tls_config_builder_root = tls_config_builder.with_webpki_roots();
}

tls_config = if let Some(client_auth_certificates) = &self.client_auth_certificates {
if let Some(client_auth_key) = &self.client_auth_key {
tls_config_builder_root.clone()
.with_client_auth_cert(client_auth_certificates.to_owned(), client_auth_key.to_owned())
.unwrap_or(tls_config_builder_root.with_no_client_auth())
} else {
tls_config_builder_root.with_no_client_auth()
}
} else {
tls_config_builder_root.with_no_client_auth()
}
}

Expand Down
6 changes: 6 additions & 0 deletions src/YetAnotherHttpHandler/NativeMethods.g.cs
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,12 @@ internal static unsafe partial class NativeMethods
[DllImport(__DllName, EntryPoint = "yaha_client_config_add_root_certificates", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
public static extern nuint yaha_client_config_add_root_certificates(YahaNativeContext* ctx, StringBuffer* root_certs);

[DllImport(__DllName, EntryPoint = "yaha_client_config_add_client_auth_certificates", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
public static extern nuint yaha_client_config_add_client_auth_certificates(YahaNativeContext* ctx, StringBuffer* auth_certs);

[DllImport(__DllName, EntryPoint = "yaha_client_config_add_client_auth_key", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
public static extern nuint yaha_client_config_add_client_auth_key(YahaNativeContext* ctx, StringBuffer* auth_key);

[DllImport(__DllName, EntryPoint = "yaha_client_config_skip_certificate_verification", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
public static extern void yaha_client_config_skip_certificate_verification(YahaNativeContext* ctx, [MarshalAs(UnmanagedType.U1)] bool val);

Expand Down
6 changes: 6 additions & 0 deletions src/YetAnotherHttpHandler/NativeMethodsFuncPtr.g.cs
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,12 @@ internal static unsafe partial class NativeMethodsFuncPtr
[DllImport(__DllName, EntryPoint = "yaha_client_config_add_root_certificates", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
public static extern nuint yaha_client_config_add_root_certificates(YahaNativeContext* ctx, StringBuffer* root_certs);

[DllImport(__DllName, EntryPoint = "yaha_client_config_add_client_auth_certificates", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
public static extern nuint yaha_client_config_add_client_auth_certificates(YahaNativeContext* ctx, StringBuffer* auth_certs);

[DllImport(__DllName, EntryPoint = "yaha_client_config_add_client_auth_key", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
public static extern nuint yaha_client_config_add_client_auth_key(YahaNativeContext* ctx, StringBuffer* auth_key);

[DllImport(__DllName, EntryPoint = "yaha_client_config_skip_certificate_verification", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
public static extern void yaha_client_config_skip_certificate_verification(YahaNativeContext* ctx, [MarshalAs(UnmanagedType.U1)] bool val);

Expand Down
14 changes: 14 additions & 0 deletions src/YetAnotherHttpHandler/YetAnotherHttpHandler.cs
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,16 @@ public class YetAnotherHttpHandler : HttpMessageHandler
/// </summary>
public string? RootCertificates { get => _settings.RootCertificates; set => _settings.RootCertificates = value; }

/// <summary>
/// Gets or sets a custom client auth certificates.
/// </summary>
public string? ClientAuthCertificates { get => _settings.ClientAuthCertificates; set => _settings.ClientAuthCertificates = value; }

/// <summary>
/// Gets or sets a custom client auth key.
/// </summary>
public string? ClientAuthKey { get => _settings.ClientAuthKey; set => _settings.ClientAuthKey = value; }

/// <summary>
/// Gets or sets the SETTINGS_INITIAL_WINDOW_SIZE option for HTTP2 stream-level flow control.
/// </summary>
Expand Down Expand Up @@ -174,6 +184,8 @@ internal class NativeClientSettings
public bool? Http2Only { get; set; }
public bool? SkipCertificateVerification { get; set; }
public string? RootCertificates { get; set; }
public string? ClientAuthCertificates { get; set; }
public string? ClientAuthKey { get; set; }
public uint? Http2InitialStreamWindowSize { get; set; }
public uint? Http2InitialConnectionWindowSize { get; set; }
public bool? Http2AdaptiveWindow { get; set; }
Expand All @@ -193,6 +205,8 @@ public NativeClientSettings Clone()
Http2Only = this.Http2Only,
SkipCertificateVerification = this.SkipCertificateVerification,
RootCertificates = this.RootCertificates,
ClientAuthCertificates = this.ClientAuthCertificates,
ClientAuthKey = this.ClientAuthKey,
Http2InitialStreamWindowSize = this.Http2InitialStreamWindowSize,
Http2InitialConnectionWindowSize = this.Http2InitialConnectionWindowSize,
Http2AdaptiveWindow = this.Http2AdaptiveWindow,
Expand Down