Skip to content

Commit

Permalink
libopenarc: respect signature expiration
Browse files Browse the repository at this point in the history
  • Loading branch information
flowerysong committed Nov 12, 2024
1 parent a30a200 commit bf943d6
Show file tree
Hide file tree
Showing 12 changed files with 259 additions and 128 deletions.
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ All notable changes to this project will be documented in this file.
## Unreleased

### Added
- libopenarc - `ARC_OPTS_SIGNATURE_TTL`
- milter - `SignatureTTL` configuration option.

### Changed

Expand All @@ -14,6 +16,7 @@ All notable changes to this project will be documented in this file.
- Build issues on FreeBSD.
- libopenarc - `arc_free()` accepts NULL.
- libopenarc - `c` is not a required tag in `ARC-Message-Signature`.
- libopenarc - Expired signatures cause chain validation to fail.

## [1.1.0](https://github.com/flowerysong/OpenARC/releases/tag/v1.1.0) - 2024-11-05

Expand Down
3 changes: 2 additions & 1 deletion libopenarc/arc-types.h
Original file line number Diff line number Diff line change
Expand Up @@ -131,10 +131,10 @@ struct arc_msghandle
unsigned int arc_keybits;
unsigned int arc_keytype;
unsigned int arc_hashtype;
unsigned int arc_sigttl;
unsigned long arc_flags;
arc_query_t arc_query;
time_t arc_timestamp;
time_t arc_sigttl;
size_t arc_siglen;
size_t arc_keylen;
size_t arc_errorlen;
Expand Down Expand Up @@ -181,6 +181,7 @@ struct arc_lib
bool arcl_signre;
bool arcl_dnsinit_done;
unsigned int arcl_flsize;
unsigned int arcl_sigttl;
uint32_t arcl_flags;
time_t arcl_fixedtime;
unsigned int arcl_callback_int;
Expand Down
101 changes: 73 additions & 28 deletions libopenarc/arc.c
Original file line number Diff line number Diff line change
Expand Up @@ -907,6 +907,28 @@ arc_options(ARC_LIB *lib, int op, int arg, void *val, size_t valsz)

return ARC_STAT_OK;

case ARC_OPTS_SIGNATURE_TTL:
if (val == NULL)
{
return ARC_STAT_INVALID;
}

if (valsz != sizeof lib->arcl_sigttl)
{
return ARC_STAT_INVALID;
}

if (op == ARC_OP_GETOPT)
{
memcpy(val, &lib->arcl_sigttl, valsz);
}
else
{
memcpy(&lib->arcl_sigttl, val, valsz);
}

return ARC_STAT_OK;

case ARC_OPTS_TESTKEYS:
if (val == NULL)
{
Expand Down Expand Up @@ -1101,20 +1123,20 @@ arc_getsslbuf(ARC_LIB *lib)
return (const char *) arc_dstring_get(lib->arcl_sslerrbuf);
}

/*
** ARC_CHECK_UINT -- check a parameter for a valid unsigned integer
**
** Parameters:
** value -- value to check
** allow_zero -- if true, allow zero
**
** Return value:
** true iff the input value looks like a properly formed unsigned integer
** that is not zero.
*/
/**
* Check if a string represents a valid unsigned integer and return the value.
*
* Parameters:
* value: string to convert
* out: pointer to store the value
*
* Returns:
* Whether the input value looks like a properly formed non-zero unsigned
* integer.
*/

static bool
arc_check_uint(char *value)
arc_check_uint(char *value, uint64_t *out)
{
uint64_t tmp = 0;
char *end;
Expand All @@ -1138,7 +1160,16 @@ arc_check_uint(char *value)
tmp = strtoll(value, &end, 10);
}

return !(tmp <= 0 || errno != 0 || *end != '\0');
if (tmp <= 0 || errno != 0 || *end != '\0')
{
return false;
}

if (out)
{
*out = tmp;
}
return true;
}

/*
Expand Down Expand Up @@ -1426,6 +1457,7 @@ arc_process_set(ARC_MESSAGE *msg,
bool stop = false;
int state;
int status;
uint64_t uint_val;
char *p;
char *param;
char *value;
Expand Down Expand Up @@ -1720,22 +1752,35 @@ arc_process_set(ARC_MESSAGE *msg,

/* test validity of "t", "x", and "i" */
p = arc_param_get(set, "t");
if (p != NULL && !arc_check_uint(p))
if (p != NULL)
{
arc_error(msg, "invalid \"t\" value in %s data", settype);
set->set_bad = true;
return ARC_STAT_SYNTAX;
if (!arc_check_uint(p, &uint_val))
{
arc_error(msg, "invalid \"t\" value in %s data", settype);
set->set_bad = true;
return ARC_STAT_SYNTAX;
}
}

p = arc_param_get(set, "x");
if (p != NULL && !arc_check_uint(p))
if (p != NULL)
{
arc_error(msg, "invalid \"x\" value in %s data", settype);
set->set_bad = true;
return ARC_STAT_SYNTAX;
if (!arc_check_uint(p, &uint_val))
{
arc_error(msg, "invalid \"x\" value in %s data", settype);
set->set_bad = true;
return ARC_STAT_SYNTAX;
}
if (msg->arc_timestamp > uint_val)
{
arc_error(msg, "signature expired %d seconds ago",
msg->arc_timestamp - uint_val);
set->set_bad = true;
return ARC_STAT_BADSIG;
}
}

if (!arc_check_uint(arc_param_get(set, "i")))
if (!arc_check_uint(arc_param_get(set, "i"), NULL))
{
arc_error(msg, "invalid \"i\" value in %s data", settype);
set->set_bad = true;
Expand Down Expand Up @@ -1778,7 +1823,7 @@ arc_process_set(ARC_MESSAGE *msg,

/* test validity of "i" */
p = arc_param_get(set, "i");
if (p != NULL && !arc_check_uint(p))
if (p != NULL && !arc_check_uint(p, NULL))
{
arc_error(msg, "invalid \"i\" value in %s data", settype);
set->set_bad = true;
Expand Down Expand Up @@ -1809,7 +1854,7 @@ arc_process_set(ARC_MESSAGE *msg,

/* test validity of "i" */
p = arc_param_get(set, "i");
if (p != NULL && !arc_check_uint(p))
if (p != NULL && !arc_check_uint(p, NULL))
{
arc_error(msg, "invalid \"i\" value in %s data", settype);
set->set_bad = true;
Expand Down Expand Up @@ -2367,6 +2412,8 @@ arc_message(ARC_LIB *lib,
time(&msg->arc_timestamp);
}

msg->arc_sigttl = lib->arcl_sigttl;

msg->arc_canonhdr = canonhdr;
msg->arc_canonbody = canonbody;
msg->arc_signalg = signalg;
Expand Down Expand Up @@ -2860,12 +2907,11 @@ arc_eoh(ARC_MESSAGE *msg)
{
bool keep;
unsigned int c;
unsigned int n;
uint64_t n;
unsigned int nsets = 0;
arc_kvsettype_t type;
ARC_STAT status;
char *inst;
char *p;
struct arc_hdrfield *h;
ARC_KVSET *set;

Expand Down Expand Up @@ -2955,11 +3001,10 @@ arc_eoh(ARC_MESSAGE *msg)

/* if i= is missing or bogus, just skip it */
inst = arc_param_get(set, "i");
if (inst == NULL || !arc_check_uint(inst))
if (inst == NULL || !arc_check_uint(inst, &n))
{
continue;
}
n = strtoul(inst, &p, 10);

switch (type)
{
Expand Down
1 change: 1 addition & 0 deletions libopenarc/arc.h
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,7 @@ typedef int arc_opts_t;
#define ARC_OPTS_OVERSIGNHDRS 4
#define ARC_OPTS_MINKEYSIZE 5
#define ARC_OPTS_TESTKEYS 6
#define ARC_OPTS_SIGNATURE_TTL 7

/* flags */
#define ARC_LIBFLAGS_NONE 0x00000000
Expand Down
1 change: 1 addition & 0 deletions openarc/openarc-config.h
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ struct configdef arcf_config[] = {
{"SealHeaderChecks", CONFIG_TYPE_STRING, false},
{"Selector", CONFIG_TYPE_STRING, false},
{"SignatureAlgorithm", CONFIG_TYPE_STRING, false},
{"SignatureTTL", CONFIG_TYPE_INTEGER, false},
{"SignHeaders", CONFIG_TYPE_STRING, false},
{"Socket", CONFIG_TYPE_STRING, false},
{"SoftwareHeader", CONFIG_TYPE_BOOLEAN, false},
Expand Down
20 changes: 20 additions & 0 deletions openarc/openarc.c
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,7 @@ struct arcf_config
size_t conf_keylen; /* key length */
int conf_maxhdrsz; /* max. header size */
int conf_minkeysz; /* min. key size */
int conf_sigttl; /* signature TTL */
int conf_ret_disabled; /* configured not to process */
int conf_ret_unable; /* internal error */
int conf_ret_unwilling; /* badly formed message */
Expand Down Expand Up @@ -1557,6 +1558,9 @@ arcf_config_load(struct config *data,
conf->conf_fixedtime = strtoul(str, &end, 10);
}

config_get(data, "SignatureTTL", &conf->conf_sigttl,
sizeof conf->conf_sigttl);

str = NULL;
config_get(data, "ResponseDisabled", &str, sizeof str);
if (str)
Expand Down Expand Up @@ -1947,6 +1951,22 @@ arcf_config_setlib(struct arcf_config *conf, char **err)
return false;
}

if (conf->conf_sigttl != 0)
{
arc_options(conf->conf_libopenarc, ARC_OP_SETOPT,
ARC_OPTS_SIGNATURE_TTL, &conf->conf_sigttl,
sizeof conf->conf_sigttl);
}

if (status != ARC_STAT_OK)
{
if (err != NULL)
{
*err = "failed to set ARC library options";
}
return false;
}

if (conf->conf_minkeysz > 0)
{
status = arc_options(conf->conf_libopenarc, ARC_OP_SETOPT,
Expand Down
9 changes: 9 additions & 0 deletions openarc/openarc.conf.5.in
Original file line number Diff line number Diff line change
Expand Up @@ -308,6 +308,15 @@ The default is
Other values are not useful if you are intending to interoperate with other
implementers of the ARC protocol.

.It Cm SignatureTTL Pq integer
Specifies the amount of time (in seconds) before generated signatures expire.
The default is
.Cm 0 ,
for no expiration.
You probably should not set this below
.Cm 604800
in production deployments.

.It Cm SignHeaders Pq string
Specifies the set of header fields that should be included when generating
signatures.
Expand Down
2 changes: 2 additions & 0 deletions openarc/openarc.conf.sample
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,8 @@ Selector my-selector-name

# SignatureAlgorithm rsa-sha256

# SignatureTTL 1209600

# SignHeaders Subject,From,Date,Message-ID,Sender

Socket /run/openarc/openarc.socket
Expand Down
Loading

0 comments on commit bf943d6

Please sign in to comment.