Lockfile /var/lib/dkim-rotate/
instance/lock
/var/lib/dkim-rotate/
instance/state
Updated with rename(2)
.
Text file, line based, with the these keywords. All of the following entries must appear, in this order:
sel_offset
selectorSelector of first key
entry. (As a number.)
sel_limit
numberValue that selectors are modulo. Indicates the maximum selector that we are currently using, or might use.
Normally this is equal to the max_selector
config key.
last_serial
numberLast DNS serial number used. Each attempt to publish needs to increment this.
status
statusIndicates that subsequent key
entries have this status. status is one of -1
+0
+N
+X
, and, again, one of each status
must appear, once, in order. There must not be more than one key in status -1
or status +0
.
key
selector time_t keyname dkim dns dataDefines a key. Repeated zero or more times after or in between status
.
selector must be the letter corresponding to (key number in list + sel_offset
) % sel_limit
).
time_t is in decimal. It may also be one or more of the two special values DNS
or MTA
, separated by commas. These means that the config update event referred to has not yet been completed.
After all of these has been completed, the value should be replaced with the time of the successful update. Eg, DNS
means “DNS zonefile update is outstanding”; the new DNS zone should be generated and the nameserver reloaded, and then DNS
replaced with the time of that update.
keyname is derived from the public key value.
dkim dns data (starting at the first nonwhitespace) is the combined content of the TXT
strings tbat ought to be published in the DNS to advertise this key.
README.txt
/var/lib/dkim-rotate/INSTANCE/pub/HH/KEYNAME.pem
Here HH is the first two characters of keyname.
keyname is derived from the public key value, as follows:
p=
base64stringEg, base64 -d <contents-of-p-field | md5sum
.
Note that this is not sufficient to use as a key identifier for verification purposes, but it is nicely uniformly distributed (so can’t be pre-guessed) and determinable from the public key (so that if someone could verify a DKIM signature they can know where to try to find the leaked key).
The directory priv/
must be readable by the MTA, but not otherwise accessible. With Exim on Debian that probably means it ought to be group-owned by Debian-exim
.
The directories pub/HH
should all executable but unreadable by the webserver. All of these directories should be created before any work is done. This prevents enumeration of the keys.
The individual private key files in pub/
will all have the fixed mtime with time_t 1000000000
. This prevents a putative verifier from determining when a key first existed.
pub/README.txt
explains the situation and is installed and maintained automatically.
pub/
directories exist.Check if last +X
can be revealed.
dns_lag
elapsed.R
;
pub/
+X
.Check if last +N can be deadvertised.
email_lag
elapsed.+X
.+N
.Check if actual selector limit can be adjusted towards intended. Requirements:
+X
, so that seeing sel_limit
decrease is suffiient to know one can change/remove the “upstream” DNS CNAME
s.)This is fiddly. Instead we use the following conditions:
sel_offset
is zero.Possibly advance -1
key to become newly-in-use +0
.
dns_lag
(for -1
) has elapsed.+0
becomes +N
-1
becomes +0
Possibly create -1
key.
-1
key.+X
is OK) (not used to publish another key).max_selector
(the intended sel_limit
). Again, this condition is fiddely: instead, we check that the proposed new number of keys doesn’t exceed max_selector
.SPDX-License-Identifier: GPL-3.0-or-later