Skip to content

Commit

Permalink
Merge pull request trusteddomainproject#202 from futatuki/per-request…
Browse files Browse the repository at this point in the history
…-sign-algorithm
  • Loading branch information
futatuki committed Apr 9, 2024
2 parents f290f22 + a05fead commit daf493a
Show file tree
Hide file tree
Showing 5 changed files with 81 additions and 9 deletions.
2 changes: 2 additions & 0 deletions RELEASE_NOTES
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ release, and a summary of the changes in that release.
Make odkim.internal_ip() available to all Lua hooks. Problem noted
by Iosif Fettich.
Make bind code DNSSEC-aware. Patch from Jack Bates.
Extend KeyTable to specify signing algorithm.
Patch from Yasuhito Futatsuki.
Fix dkimf_db_nextpunct() so it doesn't incorrectly identify an encoded
hex digit as a value delimiter.
Fix issue #8: The password file critical section isn't big enough.
Expand Down
34 changes: 32 additions & 2 deletions opendkim/opendkim-testkey.c
Original file line number Diff line number Diff line change
Expand Up @@ -236,6 +236,8 @@ main(int argc, char **argv)
char domain[BUFRSZ];
char selector[BUFRSZ];
char keypath[MAXBUFRSZ];
char signalgstr[BUFRSZ];
dkim_alg_t signalg;

progname = (p = strrchr(argv[0], '/')) == NULL ? argv[0] : p + 1;

Expand Down Expand Up @@ -464,7 +466,7 @@ main(int argc, char **argv)
size_t keylen;
DKIMF_DB db;
char keyname[BUFRSZ + 1];
struct dkimf_db_data dbd[3];
struct dkimf_db_data dbd[4];

memset(dbd, '\0', sizeof dbd);

Expand All @@ -491,18 +493,22 @@ main(int argc, char **argv)
memset(domain, '\0', sizeof domain);
memset(selector, '\0', sizeof selector);
memset(keypath, '\0', sizeof keypath);
memset(signalgstr, '\0', sizeof signalgstr);

dbd[0].dbdata_buffer = domain;
dbd[0].dbdata_buflen = sizeof domain;
dbd[1].dbdata_buffer = selector;
dbd[1].dbdata_buflen = sizeof selector;
dbd[2].dbdata_buffer = keypath;
dbd[2].dbdata_buflen = sizeof keypath;
dbd[3].dbdata_buffer = signalgstr;
dbd[3].dbdata_buflen = sizeof signalgstr;
dbd[3].dbdata_flags = DKIMF_DB_DATA_OPTIONAL;

keylen = sizeof keyname;

status = dkimf_db_walk(db, c == 0, keyname, &keylen,
dbd, 3);
dbd, 4);
if (status == -1)
{
fprintf(stderr,
Expand All @@ -524,6 +530,27 @@ main(int argc, char **argv)
progname, c, keyname);
}

if (signalgstr[0] != '\0')
{
signalg = (dkim_alg_t)dkim_name_to_code(dkim_table_algorithms,
signalgstr);
if (signalg == -1)
{
fprintf(stderr,
"%s: unknown sign algorithm "
"'%s' for key '%s'\n",
progname, signalgstr, keyname);
return 1;
}

if (verbose > 1)
{
fprintf(stderr,
"%s: key '%s': sign algorithm is '%s'\n",
progname, keyname, signalgstr);
}
}

if (keypath[0] == '/' ||
strncmp(keypath, "./", 2) == 0 ||
strncmp(keypath, "../", 3) == 0)
Expand Down Expand Up @@ -572,6 +599,9 @@ main(int argc, char **argv)
progname, keyname);
}

/* To do: check consistency of the key and algorithm.
It is needed to extend dkim_test_key() for it */

dnssec = DKIM_DNSSEC_UNKNOWN;

status = dkim_test_key(lib, selector, domain,
Expand Down
42 changes: 37 additions & 5 deletions opendkim/opendkim.c
Original file line number Diff line number Diff line change
Expand Up @@ -4919,10 +4919,12 @@ dkimf_add_signrequest(struct msgctx *dfc, DKIMF_DB keytable, char *keyname,
_Bool found = FALSE;
size_t keydatasz = 0;
struct signreq *new;
struct dkimf_db_data dbd[3];
struct dkimf_db_data dbd[4];
char keydata[MAXBUFRSZ + 1];
char domain[DKIM_MAXHOSTNAMELEN + 1];
char selector[BUFRSZ + 1];
char signalgstr[BUFRSZ + 1];
dkim_alg_t signalg = DKIM_SIGN_DEFAULT;
char err[BUFRSZ + 1];

assert(dfc != NULL);
Expand All @@ -4948,6 +4950,7 @@ dkimf_add_signrequest(struct msgctx *dfc, DKIMF_DB keytable, char *keyname,
memset(domain, '\0', sizeof domain);
memset(selector, '\0', sizeof selector);
memset(keydata, '\0', sizeof keydata);
memset(signalgstr, '\0', sizeof signalgstr);

dbd[0].dbdata_buffer = domain;
dbd[0].dbdata_buflen = sizeof domain - 1;
Expand All @@ -4958,9 +4961,12 @@ dkimf_add_signrequest(struct msgctx *dfc, DKIMF_DB keytable, char *keyname,
dbd[2].dbdata_buffer = keydata;
dbd[2].dbdata_buflen = sizeof keydata - 1;
dbd[2].dbdata_flags = DKIMF_DB_DATA_OPTIONAL;
dbd[3].dbdata_buffer = signalgstr;
dbd[3].dbdata_buflen = sizeof signalgstr - 1;
dbd[3].dbdata_flags = DKIMF_DB_DATA_OPTIONAL;

if (dkimf_db_get(keytable, keyname, strlen(keyname),
dbd, 3, &found) != 0)
dbd, 4, &found) != 0)
{
memset(err, '\0', sizeof err);
(void) dkimf_db_strerror(keytable, err, sizeof err);
Expand Down Expand Up @@ -5064,6 +5070,24 @@ dkimf_add_signrequest(struct msgctx *dfc, DKIMF_DB keytable, char *keyname,
if (curconf->conf_safekeys)
return 2;
}

if (dbd[3].dbdata_buflen > 0 && signalgstr[0] != '\0')
{
signalg = (dkim_alg_t)dkim_name_to_code(dkim_table_algorithms,
signalgstr);
if (signalg == -1)
{
if (dolog)
{
syslog(LOG_ERR,
"KeyTable entry for '%s' corrupt:"
" invalid sign algorithm %s",
keyname, signalgstr);
}

return 2;
}
}
}

new = malloc(sizeof *new);
Expand All @@ -5076,6 +5100,7 @@ dkimf_add_signrequest(struct msgctx *dfc, DKIMF_DB keytable, char *keyname,
new->srq_selector = NULL;
new->srq_keydata = NULL;
new->srq_signlen = signlen;
new->srq_signalg = signalg;
if (signer != NULL && signer[0] != '\0')
new->srq_signer = (u_char *) strdup(signer);
else
Expand Down Expand Up @@ -8312,11 +8337,12 @@ dkimf_config_load(struct config *data, struct dkimf_config *conf,
{
_Bool first = TRUE;
_Bool found;
struct dkimf_db_data dbd[3];
struct dkimf_db_data dbd[4];
char keyname[BUFRSZ + 1];
char domain[BUFRSZ + 1];
char selector[BUFRSZ + 1];
char keydata[BUFRSZ + 1];
char signalgstr[BUFRSZ + 1];
char signer[BUFRSZ + 1];

dbd[0].dbdata_flags = 0;
Expand Down Expand Up @@ -8344,10 +8370,13 @@ dkimf_config_load(struct config *data, struct dkimf_config *conf,
dbd[2].dbdata_buffer = keydata;
dbd[2].dbdata_buflen = sizeof keydata - 1;
dbd[2].dbdata_flags = DKIMF_DB_DATA_BINARY;
dbd[3].dbdata_buffer = signalgstr;
dbd[3].dbdata_buflen = sizeof signalgstr - 1;
dbd[3].dbdata_flags = DKIMF_DB_DATA_OPTIONAL;

if (dkimf_db_get(conf->conf_keytabledb,
keyname, strlen(keyname),
dbd, 3, &found) != 0 ||
dbd, 4, &found) != 0 ||
!found ||
dbd[0].dbdata_buflen == 0 ||
dbd[1].dbdata_buflen == 0 ||
Expand Down Expand Up @@ -12604,6 +12633,7 @@ mlfi_eoh(SMFICTX *ctx)

for (sr = dfc->mctx_srhead; sr != NULL; sr = sr->srq_next)
{
dkim_alg_t signalg;
#ifdef _FFR_CONDITIONAL
if (sr->srq_dkim != NULL)
continue;
Expand All @@ -12630,13 +12660,15 @@ mlfi_eoh(SMFICTX *ctx)
selector = conf->conf_selector;
}

signalg = (sr->srq_signalg == DKIM_SIGN_DEFAULT)?
dfc->mctx_signalg:sr->srq_signalg;
sr->srq_dkim = dkim_sign(conf->conf_libopendkim,
dfc->mctx_jobid,
NULL, keydata, selector,
sdomain,
dfc->mctx_hdrcanon,
dfc->mctx_bodycanon,
dfc->mctx_signalg,
signalg,
signlen, &status);

if (sr->srq_dkim == NULL || status != DKIM_STAT_OK)
Expand Down
11 changes: 9 additions & 2 deletions opendkim/opendkim.conf.5.in
Original file line number Diff line number Diff line change
Expand Up @@ -349,15 +349,22 @@ If present, overrides any
setting in the configuration file. The data set named here maps each key
name to three values: (a) the name of the domain to use in the signature's
"d=" value; (b) the name of the selector to use in the signature's "s=" value;
and (c) either a private key or a path to a file containing a private key.
and (c) either a private key or a path to a file containing a private key;
(d) (optional) signing algorithm to use with this key.
If the first value consists solely of a percent sign ("%") character,
it will be replaced by the apparent domain of the sender when generating
a signature.
If the third value starts with a slash ("/") character, or "./" or "../",
then it is presumed to refer to a file from which the private key should
be read, otherwise it is itself a PEM-encoded private key or a base64-encoded
DER private key; a "%" in the third value in this case will be replaced by
the apparent domain name of the sender. The
the apparent domain name of the sender. The fourth field should be one
of supported siginig algorithms (see
.I SignatureAlgorithm
below).
If it is omited, the algorithm specified in
.I SignatureAlgorithm
is used for the key.
.I SigningTable
(see below) is used to select records from this table to be used to add
signatures based on the message sender.
Expand Down
1 change: 1 addition & 0 deletions opendkim/opendkim.h
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,7 @@ struct signreq
u_char * srq_domain;
u_char * srq_selector;
u_char * srq_signer;
dkim_alg_t srq_signalg;
DKIM * srq_dkim;
struct signreq * srq_next;
};
Expand Down

0 comments on commit daf493a

Please sign in to comment.