Skip to content

Commit 00e7f75

Browse files
committed
Apply state prefix to a relative "state_path".
Previously, we would prepend NGX_ACME_STATE_PREFIX to default paths and cycle->prefix to explicitly configured paths. This seems inconsistent and unnecesarily confusing. Fixes 131a681.
1 parent 726b9e9 commit 00e7f75

File tree

3 files changed

+63
-5
lines changed

3 files changed

+63
-5
lines changed

src/conf.rs

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -535,10 +535,29 @@ extern "C" fn cmd_issuer_set_state_path(
535535

536536
issuer.state_path = ptr::null_mut();
537537

538-
if cf.args().get(1).map(ngx_str_t::as_bytes) == Some(b"off") {
538+
// NGX_CONF_TAKE1 ensures that args contains 2 elements
539+
let mut path = cf.args()[1];
540+
541+
if path.as_bytes() == b"off" {
539542
return NGX_CONF_OK;
540543
}
541544

545+
// We need to add our prefix before we pass the path to ngx_conf_set_path_slot,
546+
// because otherwise it will be resolved with cycle->prefix.
547+
if let Some(p) = issuer::NGX_ACME_STATE_PREFIX {
548+
let mut p = ngx_str_t {
549+
data: p.as_ptr().cast_mut(),
550+
len: p.len(),
551+
};
552+
553+
// ngx_get_full_name does not modify input buffers.
554+
if !Status(unsafe { nginx_sys::ngx_get_full_name(cf.pool, &mut p, &mut path) }).is_ok() {
555+
return NGX_CONF_ERROR;
556+
}
557+
558+
cf.args_mut()[1] = path;
559+
}
560+
542561
unsafe { nginx_sys::ngx_conf_set_path_slot(cf, cmd, ptr::from_mut(issuer).cast()) }
543562
}
544563

src/conf/ext.rs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ use ngx::ngx_conf_log_error;
1313

1414
pub trait NgxConfExt {
1515
fn args(&self) -> &[ngx_str_t];
16+
fn args_mut(&mut self) -> &mut [ngx_str_t];
1617
fn error(&self, dir: impl AsRef<[u8]>, err: &dyn StdError) -> *mut c_char;
1718
fn pool(&self) -> ngx::core::Pool;
1819
}
@@ -23,6 +24,16 @@ impl NgxConfExt for ngx_conf_t {
2324
unsafe { self.args.as_ref().map(|x| x.as_slice()).unwrap_or_default() }
2425
}
2526

27+
fn args_mut(&mut self) -> &mut [ngx_str_t] {
28+
// SAFETY: we know that cf.args is an array of ngx_str_t
29+
unsafe {
30+
self.args
31+
.as_mut()
32+
.map(|x| x.as_slice_mut())
33+
.unwrap_or_default()
34+
}
35+
}
36+
2637
fn error(&self, dir: impl AsRef<[u8]>, err: &dyn StdError) -> *mut c_char {
2738
// ngx_conf_log_error does not modify the `cf` itself, and the log is mutable due to being a
2839
// pointer.

src/conf/issuer.rs

Lines changed: 32 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ use crate::state::issuer::{IssuerContext, IssuerState};
3434
use crate::time::{Time, TimeRange};
3535

3636
pub const ACCOUNT_URL_FILE: &str = "account.url";
37+
pub const NGX_ACME_STATE_PREFIX: Option<&str> = get_state_prefix();
3738

3839
const ACCOUNT_KEY_FILE: &str = "account.key";
3940
const NGX_ACME_DEFAULT_RESOLVER_TIMEOUT: ngx_msec_t = 30000;
@@ -344,12 +345,10 @@ fn default_state_path(cf: &mut ngx_conf_t, name: &ngx_str_t) -> Result<ngx_str_t
344345
let mut path = Vec::new_in(cf.pool());
345346
let reserve = "acme_".len() + name.len + 1;
346347

347-
if let Some(p) = core::option_env!("NGX_ACME_STATE_PREFIX") {
348-
let p = p.trim_end_matches('/');
349-
path.try_reserve_exact(p.len() + reserve + 1)
348+
if let Some(p) = NGX_ACME_STATE_PREFIX {
349+
path.try_reserve_exact(p.len() + reserve)
350350
.map_err(|_| AllocError)?;
351351
path.extend(p.as_bytes());
352-
path.push(b'/');
353352
}
354353

355354
path.try_reserve_exact(reserve).map_err(|_| AllocError)?;
@@ -450,3 +449,32 @@ impl StateDir {
450449
Ok(cert)
451450
}
452451
}
452+
453+
/// Returns NGX_ACME_STATE_PREFIX value with a trailing '/'.
454+
const fn get_state_prefix() -> Option<&'static str> {
455+
const fn trim_trailing_slashes(x: &str) -> &str {
456+
let mut bytes = x.as_bytes();
457+
while let [rest @ .., last] = bytes {
458+
if *last == b'/' {
459+
bytes = rest;
460+
} else {
461+
break;
462+
}
463+
}
464+
// SAFETY: the transform above cannot produce an invalid UTF-8 sequence.
465+
unsafe { core::str::from_utf8_unchecked(bytes) }
466+
}
467+
468+
const VAL_0: Option<&str> = core::option_env!("NGX_ACME_STATE_PREFIX");
469+
if VAL_0.is_none() {
470+
return None;
471+
}
472+
473+
// Strip all the trailing slashes from the path.
474+
const VAL_1: &str = match VAL_0 {
475+
Some(x) => trim_trailing_slashes(x),
476+
None => "", // unreachable
477+
};
478+
479+
Some(constcat::concat!(VAL_1, "/"))
480+
}

0 commit comments

Comments
 (0)