From a1ff1f61816435637d68253c750016f0c0cb1178 Mon Sep 17 00:00:00 2001 From: Rodolphe Breard Date: Thu, 27 Aug 2020 00:02:26 +0200 Subject: [PATCH] Raise a descriptive error for invalid identifier specifications An identifier must have one and only one type field (`dns` or `ip`). Rel #24 --- acmed/src/config.rs | 23 ++++++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) diff --git a/acmed/src/config.rs b/acmed/src/config.rs index 5810905..3bdb201 100644 --- a/acmed/src/config.rs +++ b/acmed/src/config.rs @@ -5,7 +5,7 @@ use acme_common::crypto::{HashFunction, KeyType}; use acme_common::error::Error; use glob::glob; use log::info; -use serde::Deserialize; +use serde::{de, Deserialize, Deserializer}; use std::collections::HashMap; use std::fmt; use std::fs::{self, File}; @@ -421,6 +421,7 @@ impl Certificate { } #[derive(Clone, Debug, Deserialize)] +#[serde(remote = "Self")] #[serde(deny_unknown_fields)] pub struct Identifier { pub challenge: String, @@ -430,6 +431,26 @@ pub struct Identifier { pub env: HashMap, } +impl<'de> Deserialize<'de> for Identifier { + fn deserialize(deserializer: D) -> Result + where + D: Deserializer<'de>, + { + let unchecked = Identifier::deserialize(deserializer)?; + let filled_nb: u8 = [unchecked.dns.is_some(), unchecked.ip.is_some()] + .iter() + .copied() + .map(u8::from) + .sum(); + if filled_nb != 1 { + return Err(de::Error::custom( + "one and only one of `dns` or `ip` must be specified", + )); + } + Ok(unchecked) + } +} + impl fmt::Display for Identifier { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { let s = String::new();