Skip to content

Commit e8053a0

Browse files
committed
Expose minimum key size in the milter, add tests
Cleans up a couple of FIXMEs
1 parent f48fe9e commit e8053a0

9 files changed

+70
-19
lines changed

CHANGELOG.md

+1
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ All notable changes to this project will be documented in this file.
99
- libopenarc - `arc_chain_oldest_pass()`
1010
- milter - `AuthResIP` configuration option.
1111
- milter - `RequireSafeKeys` configuration option.
12+
- milter - `MinimumKeySizeRSA` configuration option.
1213

1314
### Changed
1415
- Custom OpenSSL locations must be configured using `OPENSSL_CFLAGS`

libopenarc/arc.c

+3-19
Original file line numberDiff line numberDiff line change
@@ -2160,15 +2160,12 @@ arc_verify_hash(ARC_MESSAGE *msg, char *b64sig, void *h, size_t hlen)
21602160
goto error;
21612161
}
21622162

2163-
keysize = EVP_PKEY_size(pkey);
2164-
/* FIXME: what is this actually measuring? Should this be
2165-
* EVP_PKEY_bits() or EVP_PKEY_securitybits()?
2166-
*/
2167-
if (keysize * 8 < msg->arc_library->arcl_minkeysize)
2163+
keysize = EVP_PKEY_bits(pkey);
2164+
if (keysize < msg->arc_library->arcl_minkeysize)
21682165
{
21692166
arc_error(msg, "key size (%u) below minimum (%u)", keysize,
21702167
msg->arc_library->arcl_minkeysize);
2171-
status = ARC_STAT_CANTVRFY;
2168+
status = ARC_STAT_BADSIG;
21722169
goto error;
21732170
}
21742171

@@ -3340,7 +3337,6 @@ arc_getseal(ARC_MESSAGE *msg,
33403337
size_t siglen;
33413338
ARC_STAT status = ARC_STAT_INTERNAL;
33423339
size_t diglen;
3343-
size_t keysize;
33443340
size_t len;
33453341
size_t b64siglen;
33463342
char *sighdr = NULL;
@@ -3465,18 +3461,6 @@ arc_getseal(ARC_MESSAGE *msg,
34653461
goto error;
34663462
}
34673463

3468-
/* FIXME: what is this actually measuring? Should this be
3469-
* EVP_PKEY_bits() or EVP_PKEY_securitybits()?
3470-
*/
3471-
keysize = EVP_PKEY_size(pkey);
3472-
if (keysize * 8 < msg->arc_library->arcl_minkeysize)
3473-
{
3474-
arc_error(msg, "key size (%u) below minimum (%u)", keysize,
3475-
msg->arc_library->arcl_minkeysize);
3476-
status = ARC_STAT_CANTVRFY;
3477-
goto error;
3478-
}
3479-
34803464
dstr = arc_dstring_new(ARC_MAXHEADER, 0, msg, &arc_error_cb);
34813465

34823466
/*

openarc/openarc-config.h

+1
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ struct configdef arcf_config[] = {
3232
{"KeyFile", CONFIG_TYPE_STRING, false},
3333
{"MaximumHeaders", CONFIG_TYPE_INTEGER, false},
3434
{"MilterDebug", CONFIG_TYPE_INTEGER, false},
35+
{"MinimumKeySizeRSA", CONFIG_TYPE_INTEGER, false},
3536
{"Mode", CONFIG_TYPE_STRING, false},
3637
{"PeerList", CONFIG_TYPE_STRING, false},
3738
{"PermitAuthenticationOverrides", CONFIG_TYPE_BOOLEAN, false},

openarc/openarc.c

+20
Original file line numberDiff line numberDiff line change
@@ -133,6 +133,7 @@ struct arcf_config
133133
unsigned char *conf_keydata; /* binary key data */
134134
size_t conf_keylen; /* key length */
135135
int conf_maxhdrsz; /* max. header size */
136+
int conf_minkeysz; /* min. key size */
136137
struct config *conf_data; /* configuration data */
137138
ARC_LIB *conf_libopenarc; /* shared library instance */
138139
struct conflist conf_peers; /* peers hosts */
@@ -1545,6 +1546,9 @@ arcf_config_load(struct config *data,
15451546
(void) config_get(data, "MaximumHeaders", &conf->conf_maxhdrsz,
15461547
sizeof conf->conf_maxhdrsz);
15471548

1549+
config_get(data, "MinimumKeySizeRSA", &conf->conf_minkeysz,
1550+
sizeof conf->conf_minkeysz);
1551+
15481552
(void) config_get(data, "SignHeaders", &conf->conf_signhdrs_raw,
15491553
sizeof conf->conf_signhdrs_raw);
15501554

@@ -1919,6 +1923,22 @@ arcf_config_setlib(struct arcf_config *conf, char **err)
19191923
return false;
19201924
}
19211925

1926+
if (conf->conf_minkeysz > 0)
1927+
{
1928+
status = arc_options(conf->conf_libopenarc, ARC_OP_SETOPT,
1929+
ARC_OPTS_MINKEYSIZE, &conf->conf_minkeysz,
1930+
sizeof conf->conf_minkeysz);
1931+
}
1932+
1933+
if (status != ARC_STAT_OK)
1934+
{
1935+
if (err != NULL)
1936+
{
1937+
*err = "failed to set ARC library options";
1938+
}
1939+
return false;
1940+
}
1941+
19221942
if (conf->conf_testkeys)
19231943
{
19241944
status = arc_options(conf->conf_libopenarc, ARC_OP_SETOPT,

openarc/openarc.conf.5.in

+6
Original file line numberDiff line numberDiff line change
@@ -130,6 +130,12 @@ provided, "127.0.0.1" is added to the list by default.
130130
Sets the debug level to be requested from the milter library. The
131131
default is 0.
132132

133+
.TP
134+
.I MinimumKeySizeRSA (integer)
135+
Disallows signatures whose keys are smaller than the specified size,
136+
regardless of whether they would otherwise be valid. If this is not
137+
set the library's default (which is currently 1024) will be used.
138+
133139
.TP
134140
.I Mode (string)
135141
Selects the operating mode(s) for this filter. If the string contains

openarc/openarc.conf.sample

+9
Original file line numberDiff line numberDiff line change
@@ -152,6 +152,15 @@ KeyFile /var/db/dkim/example.private
152152

153153
# MilterDebug 0
154154

155+
## MinimumKeySizeRSA n
156+
## default (none)
157+
##
158+
## Disallows signatures whose keys are smaller than the specified size,
159+
## regardless of whether they would otherwise be valid. If this is not set
160+
## the library's default (which is currently 1024) will be used.
161+
162+
# MinimumKeySizeRSA 2048
163+
155164
## Mode modes
156165
## default (none)
157166
##
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
Domain example.com
2+
AuthservID example.com
3+
KeyFile private.key
4+
TestKeys public.key
5+
Selector elpmaxe
6+
Mode s
7+
FixedTimestamp 1234567890
8+
MinimumKeySizeRSA 2048
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
Domain example.com
2+
AuthservID example.com
3+
KeyFile private.key
4+
TestKeys public.key
5+
Selector elpmaxe
6+
Mode s
7+
FixedTimestamp 1234567890
8+
MinimumKeySizeRSA 2049

test/test_milter.py

+14
Original file line numberDiff line numberDiff line change
@@ -561,6 +561,20 @@ def test_milter_finalreceiver(run_miltertest):
561561
assert res['headers'][0][1] == ' example.com; arc=pass header.oldest-pass=0 smtp.remote-ip=127.0.0.1 arc.chain="example.com:example.com"'
562562

563563

564+
def test_milter_minimum_key_bits(run_miltertest):
565+
"""A 2048-bit key passes when that is the minimum"""
566+
res = run_miltertest()
567+
res = run_miltertest(res['headers'])
568+
assert 'cv=pass' in res['headers'][0][1]
569+
570+
571+
def test_milter_minimum_key_bits_fail(run_miltertest):
572+
"""A 2048-bit key fails when the minimum is 2049"""
573+
res = run_miltertest()
574+
res = run_miltertest(res['headers'])
575+
assert 'cv=fail' in res['headers'][0][1]
576+
577+
564578
def test_milter_peerlist(run_miltertest):
565579
"""Connections from peers just get `accept` back immediately"""
566580
with pytest.raises(miltertest.MilterError, match='unexpected response: a'):

0 commit comments

Comments
 (0)