Skip to content

Commit daf493a

Browse files
committed
Merge pull request trusteddomainproject#202 from futatuki/per-request-sign-algorithm
2 parents f290f22 + a05fead commit daf493a

File tree

5 files changed

+81
-9
lines changed

5 files changed

+81
-9
lines changed

RELEASE_NOTES

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@ release, and a summary of the changes in that release.
1313
Make odkim.internal_ip() available to all Lua hooks. Problem noted
1414
by Iosif Fettich.
1515
Make bind code DNSSEC-aware. Patch from Jack Bates.
16+
Extend KeyTable to specify signing algorithm.
17+
Patch from Yasuhito Futatsuki.
1618
Fix dkimf_db_nextpunct() so it doesn't incorrectly identify an encoded
1719
hex digit as a value delimiter.
1820
Fix issue #8: The password file critical section isn't big enough.

opendkim/opendkim-testkey.c

Lines changed: 32 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -236,6 +236,8 @@ main(int argc, char **argv)
236236
char domain[BUFRSZ];
237237
char selector[BUFRSZ];
238238
char keypath[MAXBUFRSZ];
239+
char signalgstr[BUFRSZ];
240+
dkim_alg_t signalg;
239241

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

@@ -464,7 +466,7 @@ main(int argc, char **argv)
464466
size_t keylen;
465467
DKIMF_DB db;
466468
char keyname[BUFRSZ + 1];
467-
struct dkimf_db_data dbd[3];
469+
struct dkimf_db_data dbd[4];
468470

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

@@ -491,18 +493,22 @@ main(int argc, char **argv)
491493
memset(domain, '\0', sizeof domain);
492494
memset(selector, '\0', sizeof selector);
493495
memset(keypath, '\0', sizeof keypath);
496+
memset(signalgstr, '\0', sizeof signalgstr);
494497

495498
dbd[0].dbdata_buffer = domain;
496499
dbd[0].dbdata_buflen = sizeof domain;
497500
dbd[1].dbdata_buffer = selector;
498501
dbd[1].dbdata_buflen = sizeof selector;
499502
dbd[2].dbdata_buffer = keypath;
500503
dbd[2].dbdata_buflen = sizeof keypath;
504+
dbd[3].dbdata_buffer = signalgstr;
505+
dbd[3].dbdata_buflen = sizeof signalgstr;
506+
dbd[3].dbdata_flags = DKIMF_DB_DATA_OPTIONAL;
501507

502508
keylen = sizeof keyname;
503509

504510
status = dkimf_db_walk(db, c == 0, keyname, &keylen,
505-
dbd, 3);
511+
dbd, 4);
506512
if (status == -1)
507513
{
508514
fprintf(stderr,
@@ -524,6 +530,27 @@ main(int argc, char **argv)
524530
progname, c, keyname);
525531
}
526532

533+
if (signalgstr[0] != '\0')
534+
{
535+
signalg = (dkim_alg_t)dkim_name_to_code(dkim_table_algorithms,
536+
signalgstr);
537+
if (signalg == -1)
538+
{
539+
fprintf(stderr,
540+
"%s: unknown sign algorithm "
541+
"'%s' for key '%s'\n",
542+
progname, signalgstr, keyname);
543+
return 1;
544+
}
545+
546+
if (verbose > 1)
547+
{
548+
fprintf(stderr,
549+
"%s: key '%s': sign algorithm is '%s'\n",
550+
progname, keyname, signalgstr);
551+
}
552+
}
553+
527554
if (keypath[0] == '/' ||
528555
strncmp(keypath, "./", 2) == 0 ||
529556
strncmp(keypath, "../", 3) == 0)
@@ -572,6 +599,9 @@ main(int argc, char **argv)
572599
progname, keyname);
573600
}
574601

602+
/* To do: check consistency of the key and algorithm.
603+
It is needed to extend dkim_test_key() for it */
604+
575605
dnssec = DKIM_DNSSEC_UNKNOWN;
576606

577607
status = dkim_test_key(lib, selector, domain,

opendkim/opendkim.c

Lines changed: 37 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4919,10 +4919,12 @@ dkimf_add_signrequest(struct msgctx *dfc, DKIMF_DB keytable, char *keyname,
49194919
_Bool found = FALSE;
49204920
size_t keydatasz = 0;
49214921
struct signreq *new;
4922-
struct dkimf_db_data dbd[3];
4922+
struct dkimf_db_data dbd[4];
49234923
char keydata[MAXBUFRSZ + 1];
49244924
char domain[DKIM_MAXHOSTNAMELEN + 1];
49254925
char selector[BUFRSZ + 1];
4926+
char signalgstr[BUFRSZ + 1];
4927+
dkim_alg_t signalg = DKIM_SIGN_DEFAULT;
49264928
char err[BUFRSZ + 1];
49274929

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

49524955
dbd[0].dbdata_buffer = domain;
49534956
dbd[0].dbdata_buflen = sizeof domain - 1;
@@ -4958,9 +4961,12 @@ dkimf_add_signrequest(struct msgctx *dfc, DKIMF_DB keytable, char *keyname,
49584961
dbd[2].dbdata_buffer = keydata;
49594962
dbd[2].dbdata_buflen = sizeof keydata - 1;
49604963
dbd[2].dbdata_flags = DKIMF_DB_DATA_OPTIONAL;
4964+
dbd[3].dbdata_buffer = signalgstr;
4965+
dbd[3].dbdata_buflen = sizeof signalgstr - 1;
4966+
dbd[3].dbdata_flags = DKIMF_DB_DATA_OPTIONAL;
49614967

49624968
if (dkimf_db_get(keytable, keyname, strlen(keyname),
4963-
dbd, 3, &found) != 0)
4969+
dbd, 4, &found) != 0)
49644970
{
49654971
memset(err, '\0', sizeof err);
49664972
(void) dkimf_db_strerror(keytable, err, sizeof err);
@@ -5064,6 +5070,24 @@ dkimf_add_signrequest(struct msgctx *dfc, DKIMF_DB keytable, char *keyname,
50645070
if (curconf->conf_safekeys)
50655071
return 2;
50665072
}
5073+
5074+
if (dbd[3].dbdata_buflen > 0 && signalgstr[0] != '\0')
5075+
{
5076+
signalg = (dkim_alg_t)dkim_name_to_code(dkim_table_algorithms,
5077+
signalgstr);
5078+
if (signalg == -1)
5079+
{
5080+
if (dolog)
5081+
{
5082+
syslog(LOG_ERR,
5083+
"KeyTable entry for '%s' corrupt:"
5084+
" invalid sign algorithm %s",
5085+
keyname, signalgstr);
5086+
}
5087+
5088+
return 2;
5089+
}
5090+
}
50675091
}
50685092

50695093
new = malloc(sizeof *new);
@@ -5076,6 +5100,7 @@ dkimf_add_signrequest(struct msgctx *dfc, DKIMF_DB keytable, char *keyname,
50765100
new->srq_selector = NULL;
50775101
new->srq_keydata = NULL;
50785102
new->srq_signlen = signlen;
5103+
new->srq_signalg = signalg;
50795104
if (signer != NULL && signer[0] != '\0')
50805105
new->srq_signer = (u_char *) strdup(signer);
50815106
else
@@ -8312,11 +8337,12 @@ dkimf_config_load(struct config *data, struct dkimf_config *conf,
83128337
{
83138338
_Bool first = TRUE;
83148339
_Bool found;
8315-
struct dkimf_db_data dbd[3];
8340+
struct dkimf_db_data dbd[4];
83168341
char keyname[BUFRSZ + 1];
83178342
char domain[BUFRSZ + 1];
83188343
char selector[BUFRSZ + 1];
83198344
char keydata[BUFRSZ + 1];
8345+
char signalgstr[BUFRSZ + 1];
83208346
char signer[BUFRSZ + 1];
83218347

83228348
dbd[0].dbdata_flags = 0;
@@ -8344,10 +8370,13 @@ dkimf_config_load(struct config *data, struct dkimf_config *conf,
83448370
dbd[2].dbdata_buffer = keydata;
83458371
dbd[2].dbdata_buflen = sizeof keydata - 1;
83468372
dbd[2].dbdata_flags = DKIMF_DB_DATA_BINARY;
8373+
dbd[3].dbdata_buffer = signalgstr;
8374+
dbd[3].dbdata_buflen = sizeof signalgstr - 1;
8375+
dbd[3].dbdata_flags = DKIMF_DB_DATA_OPTIONAL;
83478376

83488377
if (dkimf_db_get(conf->conf_keytabledb,
83498378
keyname, strlen(keyname),
8350-
dbd, 3, &found) != 0 ||
8379+
dbd, 4, &found) != 0 ||
83518380
!found ||
83528381
dbd[0].dbdata_buflen == 0 ||
83538382
dbd[1].dbdata_buflen == 0 ||
@@ -12604,6 +12633,7 @@ mlfi_eoh(SMFICTX *ctx)
1260412633

1260512634
for (sr = dfc->mctx_srhead; sr != NULL; sr = sr->srq_next)
1260612635
{
12636+
dkim_alg_t signalg;
1260712637
#ifdef _FFR_CONDITIONAL
1260812638
if (sr->srq_dkim != NULL)
1260912639
continue;
@@ -12630,13 +12660,15 @@ mlfi_eoh(SMFICTX *ctx)
1263012660
selector = conf->conf_selector;
1263112661
}
1263212662

12663+
signalg = (sr->srq_signalg == DKIM_SIGN_DEFAULT)?
12664+
dfc->mctx_signalg:sr->srq_signalg;
1263312665
sr->srq_dkim = dkim_sign(conf->conf_libopendkim,
1263412666
dfc->mctx_jobid,
1263512667
NULL, keydata, selector,
1263612668
sdomain,
1263712669
dfc->mctx_hdrcanon,
1263812670
dfc->mctx_bodycanon,
12639-
dfc->mctx_signalg,
12671+
signalg,
1264012672
signlen, &status);
1264112673

1264212674
if (sr->srq_dkim == NULL || status != DKIM_STAT_OK)

opendkim/opendkim.conf.5.in

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -349,15 +349,22 @@ If present, overrides any
349349
setting in the configuration file. The data set named here maps each key
350350
name to three values: (a) the name of the domain to use in the signature's
351351
"d=" value; (b) the name of the selector to use in the signature's "s=" value;
352-
and (c) either a private key or a path to a file containing a private key.
352+
and (c) either a private key or a path to a file containing a private key;
353+
(d) (optional) signing algorithm to use with this key.
353354
If the first value consists solely of a percent sign ("%") character,
354355
it will be replaced by the apparent domain of the sender when generating
355356
a signature.
356357
If the third value starts with a slash ("/") character, or "./" or "../",
357358
then it is presumed to refer to a file from which the private key should
358359
be read, otherwise it is itself a PEM-encoded private key or a base64-encoded
359360
DER private key; a "%" in the third value in this case will be replaced by
360-
the apparent domain name of the sender. The
361+
the apparent domain name of the sender. The fourth field should be one
362+
of supported siginig algorithms (see
363+
.I SignatureAlgorithm
364+
below).
365+
If it is omited, the algorithm specified in
366+
.I SignatureAlgorithm
367+
is used for the key.
361368
.I SigningTable
362369
(see below) is used to select records from this table to be used to add
363370
signatures based on the message sender.

opendkim/opendkim.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,7 @@ struct signreq
120120
u_char * srq_domain;
121121
u_char * srq_selector;
122122
u_char * srq_signer;
123+
dkim_alg_t srq_signalg;
123124
DKIM * srq_dkim;
124125
struct signreq * srq_next;
125126
};

0 commit comments

Comments
 (0)