@@ -7,10 +7,10 @@ use core::ffi::{c_char, c_void, CStr};
77use core:: { mem, ptr} ;
88
99use nginx_sys:: {
10- ngx_command_t, ngx_conf_parse, ngx_conf_t, ngx_http_core_srv_conf_t , ngx_str_t , ngx_uint_t ,
11- NGX_CONF_1MORE , NGX_CONF_BLOCK , NGX_CONF_FLAG , NGX_CONF_NOARGS , NGX_CONF_TAKE1 ,
12- NGX_HTTP_MAIN_CONF , NGX_HTTP_MAIN_CONF_OFFSET , NGX_HTTP_SRV_CONF , NGX_HTTP_SRV_CONF_OFFSET ,
13- NGX_LOG_EMERG ,
10+ ngx_command_t, ngx_conf_parse, ngx_conf_t, ngx_decode_base64url , ngx_http_core_srv_conf_t ,
11+ ngx_str_t , ngx_uint_t , NGX_CONF_1MORE , NGX_CONF_BLOCK , NGX_CONF_FLAG , NGX_CONF_NOARGS ,
12+ NGX_CONF_TAKE1 , NGX_CONF_TAKE2 , NGX_HTTP_MAIN_CONF , NGX_HTTP_MAIN_CONF_OFFSET ,
13+ NGX_HTTP_SRV_CONF , NGX_HTTP_SRV_CONF_OFFSET , NGX_LOG_EMERG ,
1414} ;
1515use ngx:: collections:: Vec ;
1616use ngx:: core:: { Pool , Status , NGX_CONF_ERROR , NGX_CONF_OK } ;
@@ -80,7 +80,7 @@ pub static mut NGX_HTTP_ACME_COMMANDS: [ngx_command_t; 4] = [
8080 ngx_command_t:: empty ( ) ,
8181] ;
8282
83- static mut NGX_HTTP_ACME_ISSUER_COMMANDS : [ ngx_command_t ; 8 ] = [
83+ static mut NGX_HTTP_ACME_ISSUER_COMMANDS : [ ngx_command_t ; 9 ] = [
8484 ngx_command_t {
8585 name : ngx_string ! ( "uri" ) ,
8686 type_ : NGX_CONF_TAKE1 as ngx_uint_t ,
@@ -105,6 +105,14 @@ static mut NGX_HTTP_ACME_ISSUER_COMMANDS: [ngx_command_t; 8] = [
105105 offset : 0 ,
106106 post : ptr:: null_mut ( ) ,
107107 } ,
108+ ngx_command_t {
109+ name : ngx_string ! ( "external_account_key" ) ,
110+ type_ : NGX_CONF_TAKE2 as ngx_uint_t ,
111+ set : Some ( cmd_issuer_set_external_account_key) ,
112+ conf : 0 ,
113+ offset : 0 ,
114+ post : ptr:: null_mut ( ) ,
115+ } ,
108116 ngx_command_t {
109117 name : ngx_string ! ( "ssl_trusted_certificate" ) ,
110118 type_ : NGX_CONF_TAKE1 as ngx_uint_t ,
@@ -391,6 +399,62 @@ extern "C" fn cmd_issuer_set_account_key(
391399 NGX_CONF_OK
392400}
393401
402+ extern "C" fn cmd_issuer_set_external_account_key (
403+ cf : * mut ngx_conf_t ,
404+ _cmd : * mut ngx_command_t ,
405+ conf : * mut c_void ,
406+ ) -> * mut c_char {
407+ let cf = unsafe { cf. as_mut ( ) . expect ( "cf" ) } ;
408+ let issuer = unsafe { conf. cast :: < Issuer > ( ) . as_mut ( ) . expect ( "issuer conf" ) } ;
409+
410+ if issuer. eab_key . is_some ( ) {
411+ return NGX_CONF_DUPLICATE ;
412+ }
413+
414+ let mut pool = cf. pool ( ) ;
415+ // NGX_CONF_TAKE2 ensures that args contains 3 elements
416+ let args = cf. args ( ) ;
417+
418+ if args. len ( ) != 3 || args[ 1 ] . len == 0 || args[ 2 ] . len == 0 {
419+ return NGX_CONF_INVALID_VALUE ;
420+ }
421+
422+ // SAFETY: the value is not empty, well aligned, and the conversion result is assigned to an
423+ // object in the same pool.
424+ let Ok ( kid) = ( unsafe { conf_value_to_str ( & args[ 1 ] ) } ) else {
425+ return NGX_CONF_INVALID_VALUE ;
426+ } ;
427+
428+ let mut encoded = if let Some ( arg) = args[ 2 ] . strip_prefix ( b"data:" ) {
429+ arg
430+ } else {
431+ match crate :: util:: read_to_ngx_str ( cf, & args[ 2 ] ) {
432+ Ok ( x) => x,
433+ Err ( e) => return cf. error ( args[ 0 ] , & e) ,
434+ }
435+ } ;
436+
437+ crate :: util:: ngx_str_trim ( & mut encoded) ;
438+
439+ let len = encoded. len . div_ceil ( 4 ) * 3 ;
440+ let mut key = ngx_str_t {
441+ data : pool. alloc_unaligned ( len) . cast ( ) ,
442+ len,
443+ } ;
444+
445+ if key. data . is_null ( ) {
446+ return NGX_CONF_ERROR ;
447+ }
448+
449+ if !Status ( unsafe { ngx_decode_base64url ( & mut key, & mut encoded) } ) . is_ok ( ) {
450+ return c"invalid base64url encoded value" . as_ptr ( ) . cast_mut ( ) ;
451+ }
452+
453+ issuer. eab_key = Some ( issuer:: ExternalAccountKey { kid, key } ) ;
454+
455+ NGX_CONF_OK
456+ }
457+
394458extern "C" fn cmd_issuer_set_uri (
395459 cf : * mut ngx_conf_t ,
396460 _cmd : * mut ngx_command_t ,
0 commit comments