@@ -14,75 +14,73 @@ use rustls::pki_types::{pem::PemObject, CertificateDer, PrivateKeyDer};
1414use rustls:: { ClientConfig , RootCertStore , ServerConfig } ;
1515use webpki_roots:: TLS_SERVER_ROOTS ;
1616
17- /// Options for creating a secure context
18- #[ derive( Default ) ]
19- pub struct SecureContextOptions {
20- pub cert : Option < Vec < u8 > > ,
21- pub key : Option < Vec < u8 > > ,
22- pub ca : Option < Vec < Vec < u8 > > > ,
23- pub ciphers : Option < String > ,
24- pub min_version : Option < String > ,
25- pub max_version : Option < String > ,
26- }
27-
28- impl SecureContextOptions {
29- pub fn from_js_options < ' js > ( ctx : & Ctx < ' js > , opts : & Object < ' js > ) -> Result < Self > {
30- let mut options = Self :: default ( ) ;
31-
32- // Handle certificate
33- if let Some ( cert_value) = opts. get_optional :: < _ , Value > ( "cert" ) ? {
34- if let Some ( s) = cert_value. as_string ( ) {
35- options. cert = Some ( s. to_string ( ) ?. into_bytes ( ) ) ;
36- } else if let Some ( bytes) = get_bytes_from_value ( ctx, & cert_value) ? {
37- options. cert = Some ( bytes) ;
38- }
17+ use crate :: BuildClientConfigOptions ;
18+
19+ /// Parse BuildClientConfigOptions from a JavaScript options object
20+ pub fn options_from_js < ' js > (
21+ ctx : & Ctx < ' js > ,
22+ opts : & Object < ' js > ,
23+ ) -> Result < BuildClientConfigOptions > {
24+ let mut options = BuildClientConfigOptions :: default ( ) ;
25+
26+ // Handle certificate
27+ if let Some ( cert_value) = opts. get_optional :: < _ , Value > ( "cert" ) ? {
28+ if let Some ( s) = cert_value. as_string ( ) {
29+ options. cert = Some ( s. to_string ( ) ?. into_bytes ( ) ) ;
30+ } else if let Some ( bytes) = get_bytes_from_value ( ctx, & cert_value) ? {
31+ options. cert = Some ( bytes) ;
3932 }
33+ }
4034
41- // Handle private key
42- if let Some ( key_value) = opts. get_optional :: < _ , Value > ( "key" ) ? {
43- if let Some ( s) = key_value. as_string ( ) {
44- options. key = Some ( s. to_string ( ) ?. into_bytes ( ) ) ;
45- } else if let Some ( bytes) = get_bytes_from_value ( ctx, & key_value) ? {
46- options. key = Some ( bytes) ;
47- }
35+ // Handle private key
36+ if let Some ( key_value) = opts. get_optional :: < _ , Value > ( "key" ) ? {
37+ if let Some ( s) = key_value. as_string ( ) {
38+ options. key = Some ( s. to_string ( ) ?. into_bytes ( ) ) ;
39+ } else if let Some ( bytes) = get_bytes_from_value ( ctx, & key_value) ? {
40+ options. key = Some ( bytes) ;
4841 }
42+ }
4943
50- // Handle CA certificates
51- if let Some ( ca_value) = opts. get_optional :: < _ , Value > ( "ca" ) ? {
52- let mut ca_certs = Vec :: new ( ) ;
53- if let Some ( ca_array) = ca_value. as_array ( ) {
54- for item in ca_array. iter :: < Value > ( ) {
55- let item = item?;
56- if let Some ( s) = item. as_string ( ) {
57- ca_certs. push ( s. to_string ( ) ?. into_bytes ( ) ) ;
58- } else if let Some ( bytes) = get_bytes_from_value ( ctx, & item) ? {
59- ca_certs. push ( bytes) ;
60- }
44+ // Handle CA certificates
45+ if let Some ( ca_value) = opts. get_optional :: < _ , Value > ( "ca" ) ? {
46+ let mut ca_certs = Vec :: new ( ) ;
47+ if let Some ( ca_array) = ca_value. as_array ( ) {
48+ for item in ca_array. iter :: < Value > ( ) {
49+ let item = item?;
50+ if let Some ( s) = item. as_string ( ) {
51+ ca_certs. push ( s. to_string ( ) ?. into_bytes ( ) ) ;
52+ } else if let Some ( bytes) = get_bytes_from_value ( ctx, & item) ? {
53+ ca_certs. push ( bytes) ;
6154 }
62- } else if let Some ( s) = ca_value. as_string ( ) {
63- ca_certs. push ( s. to_string ( ) ?. into_bytes ( ) ) ;
64- } else if let Some ( bytes) = get_bytes_from_value ( ctx, & ca_value) ? {
65- ca_certs. push ( bytes) ;
66- }
67- if !ca_certs. is_empty ( ) {
68- options. ca = Some ( ca_certs) ;
6955 }
56+ } else if let Some ( s) = ca_value. as_string ( ) {
57+ ca_certs. push ( s. to_string ( ) ?. into_bytes ( ) ) ;
58+ } else if let Some ( bytes) = get_bytes_from_value ( ctx, & ca_value) ? {
59+ ca_certs. push ( bytes) ;
7060 }
71-
72- if let Some ( ciphers) = opts. get_optional :: < _ , String > ( "ciphers" ) ? {
73- options. ciphers = Some ( ciphers) ;
61+ if !ca_certs. is_empty ( ) {
62+ options. ca = Some ( ca_certs) ;
7463 }
64+ }
7565
76- if let Some ( min_version) = opts. get_optional :: < _ , String > ( "minVersion" ) ? {
77- options. min_version = Some ( min_version) ;
78- }
66+ // Handle rejectUnauthorized
67+ if let Some ( reject_unauthorized) = opts. get_optional :: < _ , bool > ( "rejectUnauthorized" ) ? {
68+ options. reject_unauthorized = reject_unauthorized;
69+ }
7970
80- if let Some ( max_version ) = opts. get_optional :: < _ , String > ( "maxVersion " ) ? {
81- options. max_version = Some ( max_version ) ;
82- }
71+ if let Some ( ciphers ) = opts. get_optional :: < _ , String > ( "ciphers " ) ? {
72+ options. ciphers = Some ( ciphers ) ;
73+ }
8374
84- Ok ( options)
75+ if let Some ( min_version) = opts. get_optional :: < _ , String > ( "minVersion" ) ? {
76+ options. min_version = Some ( min_version) ;
8577 }
78+
79+ if let Some ( max_version) = opts. get_optional :: < _ , String > ( "maxVersion" ) ? {
80+ options. max_version = Some ( max_version) ;
81+ }
82+
83+ Ok ( options)
8684}
8785
8886fn get_bytes_from_value < ' js > ( ctx : & Ctx < ' js > , value : & Value < ' js > ) -> Result < Option < Vec < u8 > > > {
@@ -132,7 +130,7 @@ impl SecureContext {
132130
133131impl SecureContext {
134132 /// Create a new SecureContext from options
135- pub fn from_options ( ctx : & Ctx < ' _ > , options : SecureContextOptions ) -> Result < Self > {
133+ pub fn from_options ( ctx : & Ctx < ' _ > , options : BuildClientConfigOptions ) -> Result < Self > {
136134 let mut secure_context = Self :: new ( ) ;
137135
138136 // Build client config if we have CA certs or need default trust
@@ -165,26 +163,32 @@ impl SecureContext {
165163 } ) ?
166164 . with_root_certificates ( root_store) ;
167165
168- let client_config = if let ( Some ( cert_pem) , Some ( key_pem) ) = ( & options. cert , & options. key ) {
169- // Client certificate authentication
170- let certs: Vec < CertificateDer < ' static > > = CertificateDer :: pem_slice_iter ( cert_pem)
171- . collect :: < std:: result:: Result < Vec < _ > , _ > > ( )
172- . map_err ( |e| {
173- Exception :: throw_message ( ctx, & format ! ( "Invalid certificate: {}" , e) )
166+ let mut client_config =
167+ if let ( Some ( cert_pem) , Some ( key_pem) ) = ( & options. cert , & options. key ) {
168+ // Client certificate authentication
169+ let certs: Vec < CertificateDer < ' static > > = CertificateDer :: pem_slice_iter ( cert_pem)
170+ . collect :: < std:: result:: Result < Vec < _ > , _ > > ( )
171+ . map_err ( |e| {
172+ Exception :: throw_message ( ctx, & format ! ( "Invalid certificate: {}" , e) )
173+ } ) ?;
174+
175+ let key = PrivateKeyDer :: from_pem_slice ( key_pem) . map_err ( |e| {
176+ Exception :: throw_message ( ctx, & format ! ( "Invalid private key: {}" , e) )
174177 } ) ?;
175178
176- let key = PrivateKeyDer :: from_pem_slice ( key_pem) . map_err ( |e| {
177- Exception :: throw_message ( ctx, & format ! ( "Invalid private key: {}" , e) )
178- } ) ?;
179-
180- client_builder
181- . with_client_auth_cert ( certs, key)
182- . map_err ( |e| {
183- Exception :: throw_message ( ctx, & format ! ( "Failed to set client auth: {}" , e) )
184- } ) ?
185- } else {
186- client_builder. with_no_client_auth ( )
187- } ;
179+ client_builder
180+ . with_client_auth_cert ( certs, key)
181+ . map_err ( |e| {
182+ Exception :: throw_message ( ctx, & format ! ( "Failed to set client auth: {}" , e) )
183+ } ) ?
184+ } else {
185+ client_builder. with_no_client_auth ( )
186+ } ;
187+
188+ // Set key log if provided
189+ if let Some ( key_log) = options. key_log {
190+ client_config. key_log = key_log;
191+ }
188192
189193 secure_context. client_config = Some ( Arc :: new ( client_config) ) ;
190194
@@ -220,9 +224,9 @@ pub fn create_secure_context<'js>(
220224 options : Option < Object < ' js > > ,
221225) -> Result < Class < ' js , SecureContext > > {
222226 let opts = if let Some ( opts) = options {
223- SecureContextOptions :: from_js_options ( & ctx, & opts) ?
227+ options_from_js ( & ctx, & opts) ?
224228 } else {
225- SecureContextOptions :: default ( )
229+ BuildClientConfigOptions :: default ( )
226230 } ;
227231
228232 let secure_context = SecureContext :: from_options ( & ctx, opts) ?;
0 commit comments