diff --git a/RELEASE_NOTES b/RELEASE_NOTES index b8cc446a..6eda6328 100644 --- a/RELEASE_NOTES +++ b/RELEASE_NOTES @@ -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. @@ -49,8 +51,16 @@ release, and a summary of the changes in that release. oversized input lines. Reported by Mars Peng. LIBOPENDKIM: Fix parsing bug in dkim_mail_parse_multi(), where quotes were not being properly handled. + LIBOPENDKIM: Expose conversion table between internal code already + provided as DKIM_ macros and their literal name in C string. + LIBOPENDKIM: Extend dkim_test_key() to allow testing a ed25519 key, + as dkim_test_key2(). For API compatibility, function interface + of dkim_test_key() is not changed, but it only calls + dkim_test_key2(). Patch from Yasuhito Futatsuki. TOOLS: Feature requrest #187: Add option to match subdomains when generating zone files. Patch from Andreas Schulze. + TOOLS: issue #183: On opendkim-testkey, add support for ed25519 keys. + Patch from Yasuhito Futatsuki. 2.10.3 2015/05/12 LIBOPENDKIM: Make strict header checking non-destructive. The last diff --git a/libopendkim/Makefile.am b/libopendkim/Makefile.am index b105eefa..0e4ca265 100644 --- a/libopendkim/Makefile.am +++ b/libopendkim/Makefile.am @@ -8,7 +8,7 @@ endif LDADD = ./libopendkim.la lib_LTLIBRARIES = libopendkim.la -libopendkim_la_SOURCES = base32.c base64.c dkim-atps.c dkim-cache.c dkim-canon.c dkim-dns.c dkim-keys.c dkim-mailparse.c dkim-report.c dkim-tables.c dkim-test.c dkim-util.c dkim.c util.c base64.h dkim-cache.h dkim-canon.h dkim-dns.h dkim-internal.h dkim-keys.h dkim-mailparse.h dkim-report.h dkim-tables.h dkim-test.h dkim-types.h dkim-util.h dkim.h util.h +libopendkim_la_SOURCES = base32.c base64.c dkim-atps.c dkim-cache.c dkim-canon.c dkim-dns.c dkim-keys.c dkim-mailparse.c dkim-report.c dkim-tables.c dkim-test.c dkim-util.c dkim.c util.c base64.h dkim-cache.h dkim-canon.h dkim-dns.h dkim-internal.h dkim-keys.h dkim-mailparse.h dkim-report.h dkim-test.h dkim-types.h dkim-util.h dkim.h util.h libopendkim_la_CPPFLAGS = $(LIBCRYPTO_CPPFLAGS) libopendkim_la_CFLAGS = $(LIBCRYPTO_INCDIRS) $(LIBOPENDKIM_INC) $(COV_CFLAGS) libopendkim_la_LDFLAGS = -no-undefined $(LIBCRYPTO_LIBDIRS) $(COV_LDFLAGS) -version-info $(LIBOPENDKIM_VERSION_INFO) diff --git a/libopendkim/base32.c b/libopendkim/base32.c index d807c605..f0ca9cd8 100644 --- a/libopendkim/base32.c +++ b/libopendkim/base32.c @@ -158,22 +158,21 @@ dkim_base32_encode(char *buf, size_t *buflen, const void *data, size_t size) #ifdef TEST #include +#include int main(int argc, char **argv) { int x; size_t buflen; - SHA_CTX sha; char buf[128]; unsigned char shaout[SHA_DIGEST_LENGTH]; memset(buf, '\0', sizeof buf); buflen = sizeof buf; - SHA1_Init(&sha); - SHA1_Update(&sha, argv[1], strlen(argv[1])); - SHA1_Final(shaout, &sha); + (void) EVP_Digest(argv[1], strlen(argv[1]), shaout, NULL, EVP_sha1(), + NULL); x = dkim_base32_encode(buf, &buflen, shaout, SHA_DIGEST_LENGTH); diff --git a/libopendkim/dkim-atps.c b/libopendkim/dkim-atps.c index 889f1d47..c38673e3 100644 --- a/libopendkim/dkim-atps.c +++ b/libopendkim/dkim-atps.c @@ -21,7 +21,6 @@ #include "dkim.h" #include "dkim-internal.h" #include "dkim-types.h" -#include "dkim-tables.h" #include "util.h" #ifdef USE_GNUTLS @@ -37,6 +36,7 @@ #else /* USE_GNUTLS */ /* openssl includes */ # include +# include #endif /* USE_GNUTLS */ /* prototypes */ @@ -113,11 +113,6 @@ dkim_atps_check(DKIM *dkim, DKIM_SIGINFO *sig, struct timeval *timeout, u_char *eom; #ifdef USE_GNUTLS gnutls_hash_hd_t ctx; -#else /* USE_GNUTLS */ - SHA_CTX ctx; -# ifdef HAVE_SHA256 - SHA256_CTX ctx2; -# endif /* HAVE_SHA256 */ #endif /* USE_GNUTLS */ struct timeval to; HEADER hdr; @@ -146,7 +141,7 @@ dkim_atps_check(DKIM *dkim, DKIM_SIGINFO *sig, struct timeval *timeout, /* confirm it requested a hash we know how to do */ if (strcasecmp(ahash, "none") != 0) { - hash = dkim_name_to_code(hashes, ahash); + hash = dkim_name_to_code(dkim_table_hashes, ahash); if (hash == -1) return DKIM_STAT_INVALID; } @@ -198,16 +193,14 @@ dkim_atps_check(DKIM *dkim, DKIM_SIGINFO *sig, struct timeval *timeout, switch (hash) { case DKIM_HASHTYPE_SHA1: - SHA1_Init(&ctx); - SHA1_Update(&ctx, sdomain, strlen(sdomain)); - SHA1_Final(digest, &ctx); + (void) EVP_Digest(sdomain, strlen(sdomain), digest, + NULL, EVP_sha1(), NULL); break; # ifdef HAVE_SHA256 case DKIM_HASHTYPE_SHA256: - SHA256_Init(&ctx2); - SHA256_Update(&ctx2, sdomain, strlen(sdomain)); - SHA256_Final(digest, &ctx2); + (void) EVP_Digest(sdomain, strlen(sdomain), digest, + NULL, EVP_sha256(), NULL); break; # endif /* HAVE_SHA256 */ diff --git a/libopendkim/dkim-canon.c b/libopendkim/dkim-canon.c index da98a23c..8e78978b 100644 --- a/libopendkim/dkim-canon.c +++ b/libopendkim/dkim-canon.c @@ -116,38 +116,27 @@ dkim_canon_free(DKIM *dkim, DKIM_CANON *canon) #else /* USE_GNUTLS */ case DKIM_HASHTYPE_SHA1: + case DKIM_HASHTYPE_SHA256: { - struct dkim_sha1 *sha1; + struct dkim_sha *sha; - sha1 = (struct dkim_sha1 *) canon->canon_hash; + sha = (struct dkim_sha *) canon->canon_hash; - if (sha1->sha1_tmpbio != NULL) + if (sha->sha_tmpbio != NULL) { - BIO_free(sha1->sha1_tmpbio); - sha1->sha1_tmpfd = -1; - sha1->sha1_tmpbio = NULL; + BIO_free(sha->sha_tmpbio); + sha->sha_tmpfd = -1; + sha->sha_tmpbio = NULL; } - break; - } - -# ifdef HAVE_SHA256 - case DKIM_HASHTYPE_SHA256: - { - struct dkim_sha256 *sha256; - - sha256 = (struct dkim_sha256 *) canon->canon_hash; - - if (sha256->sha256_tmpbio != NULL) + if (sha->sha_ctx != NULL) { - BIO_free(sha256->sha256_tmpbio); - sha256->sha256_tmpfd = -1; - sha256->sha256_tmpbio = NULL; + EVP_MD_CTX_free(sha->sha_ctx); + sha->sha_ctx = NULL; } break; } -# endif /* HAVE_SHA256 */ #endif /* USE_GNUTLS */ default: @@ -217,32 +206,18 @@ dkim_canon_write(DKIM_CANON *canon, u_char *buf, size_t buflen) } #else /* USE_GNUTLS */ case DKIM_HASHTYPE_SHA1: - { - struct dkim_sha1 *sha1; - - sha1 = (struct dkim_sha1 *) canon->canon_hash; - SHA1_Update(&sha1->sha1_ctx, buf, buflen); - - if (sha1->sha1_tmpbio != NULL) - BIO_write(sha1->sha1_tmpbio, buf, buflen); - - break; - } - -# ifdef HAVE_SHA256 case DKIM_HASHTYPE_SHA256: { - struct dkim_sha256 *sha256; + struct dkim_sha *sha; - sha256 = (struct dkim_sha256 *) canon->canon_hash; - SHA256_Update(&sha256->sha256_ctx, buf, buflen); + sha = (struct dkim_sha *) canon->canon_hash; + EVP_DigestUpdate(sha->sha_ctx, buf, buflen); - if (sha256->sha256_tmpbio != NULL) - BIO_write(sha256->sha256_tmpbio, buf, buflen); + if (sha->sha_tmpbio != NULL) + BIO_write(sha->sha_tmpbio, buf, buflen); break; } -# endif /* HAVE_SHA256 */ #endif /* USE_GNUTLS */ } @@ -700,76 +675,51 @@ dkim_canon_init(DKIM *dkim, _Bool tmp, _Bool keep) } #else /* USE_GNUTLS */ case DKIM_HASHTYPE_SHA1: + case DKIM_HASHTYPE_SHA256: { - struct dkim_sha1 *sha1; + struct dkim_sha *sha; - sha1 = (struct dkim_sha1 *) DKIM_MALLOC(dkim, - sizeof(struct dkim_sha1)); - if (sha1 == NULL) + sha = (struct dkim_sha *) DKIM_MALLOC(dkim, + sizeof(struct dkim_sha)); + if (sha == NULL) { dkim_error(dkim, "unable to allocate %d byte(s)", - sizeof(struct dkim_sha1)); + sizeof(struct dkim_sha)); return DKIM_STAT_NORESOURCE; } - memset(sha1, '\0', sizeof(struct dkim_sha1)); - SHA1_Init(&sha1->sha1_ctx); + memset(sha, '\0', sizeof(struct dkim_sha)); - if (tmp) + sha->sha_ctx = EVP_MD_CTX_new(); + if (cur->canon_hashtype == DKIM_HASHTYPE_SHA1) { - status = dkim_tmpfile(dkim, &fd, keep); - if (status != DKIM_STAT_OK) - { - DKIM_FREE(dkim, sha1); - return status; - } - - sha1->sha1_tmpfd = fd; - sha1->sha1_tmpbio = BIO_new_fd(fd, 1); + (void) EVP_DigestInit_ex(sha->sha_ctx, + EVP_sha1(), NULL); } - - cur->canon_hash = sha1; - - break; - } - -# ifdef HAVE_SHA256 - case DKIM_HASHTYPE_SHA256: - { - struct dkim_sha256 *sha256; - - sha256 = (struct dkim_sha256 *) DKIM_MALLOC(dkim, - sizeof(struct dkim_sha256)); - if (sha256 == NULL) + else { - dkim_error(dkim, - "unable to allocate %d byte(s)", - sizeof(struct dkim_sha256)); - return DKIM_STAT_NORESOURCE; + (void) EVP_DigestInit_ex(sha->sha_ctx, + EVP_sha256(), NULL); } - memset(sha256, '\0', sizeof(struct dkim_sha256)); - SHA256_Init(&sha256->sha256_ctx); - if (tmp) { status = dkim_tmpfile(dkim, &fd, keep); if (status != DKIM_STAT_OK) { - DKIM_FREE(dkim, sha256); + DKIM_FREE(dkim, sha); return status; } - sha256->sha256_tmpfd = fd; - sha256->sha256_tmpbio = BIO_new_fd(fd, 1); + sha->sha_tmpfd = fd; + sha->sha_tmpbio = BIO_new_fd(fd, 1); } - cur->canon_hash = sha256; + cur->canon_hash = sha; break; } -# endif /* HAVE_SHA256 */ #endif /* USE_GNUTLS */ default: @@ -1420,32 +1370,19 @@ dkim_canon_runheaders(DKIM *dkim) #else /* USE_GNUTLS */ case DKIM_HASHTYPE_SHA1: - { - struct dkim_sha1 *sha1; - - sha1 = (struct dkim_sha1 *) cur->canon_hash; - SHA1_Final(sha1->sha1_out, &sha1->sha1_ctx); - - if (sha1->sha1_tmpbio != NULL) - (void) BIO_flush(sha1->sha1_tmpbio); - - break; - } - -# ifdef HAVE_SHA256 case DKIM_HASHTYPE_SHA256: { - struct dkim_sha256 *sha256; + struct dkim_sha *sha; - sha256 = (struct dkim_sha256 *) cur->canon_hash; - SHA256_Final(sha256->sha256_out, &sha256->sha256_ctx); + sha = (struct dkim_sha *) cur->canon_hash; + EVP_DigestFinal_ex(sha->sha_ctx, sha->sha_out, + &sha->sha_outlen); - if (sha256->sha256_tmpbio != NULL) - (void) BIO_flush(sha256->sha256_tmpbio); + if (sha->sha_tmpbio != NULL) + (void) BIO_flush(sha->sha_tmpbio); break; } -# endif /* HAVE_SHA256 */ #endif /* USE_GNUTLS */ default: @@ -1556,34 +1493,22 @@ dkim_canon_signature(DKIM *dkim, struct dkim_header *hdr) break; } + #else /* USE_GNUTLS */ case DKIM_HASHTYPE_SHA1: - { - struct dkim_sha1 *sha1; - - sha1 = (struct dkim_sha1 *) cur->canon_hash; - SHA1_Final(sha1->sha1_out, &sha1->sha1_ctx); - - if (sha1->sha1_tmpbio != NULL) - (void) BIO_flush(sha1->sha1_tmpbio); - - break; - } - -# ifdef HAVE_SHA256 case DKIM_HASHTYPE_SHA256: { - struct dkim_sha256 *sha256; + struct dkim_sha *sha; - sha256 = (struct dkim_sha256 *) cur->canon_hash; - SHA256_Final(sha256->sha256_out, &sha256->sha256_ctx); + sha = (struct dkim_sha *) cur->canon_hash; + EVP_DigestFinal_ex(sha->sha_ctx, sha->sha_out, + &sha->sha_outlen); - if (sha256->sha256_tmpbio != NULL) - (void) BIO_flush(sha256->sha256_tmpbio); + if (sha->sha_tmpbio != NULL) + (void) BIO_flush(sha->sha_tmpbio); break; } -# endif /* HAVE_SHA256 */ #endif /* USE_GNUTLS */ default: @@ -1993,32 +1918,19 @@ dkim_canon_closebody(DKIM *dkim) } #else /* USE_GNUTLS */ case DKIM_HASHTYPE_SHA1: - { - struct dkim_sha1 *sha1; - - sha1 = (struct dkim_sha1 *) cur->canon_hash; - SHA1_Final(sha1->sha1_out, &sha1->sha1_ctx); - - if (sha1->sha1_tmpbio != NULL) - (void) BIO_flush(sha1->sha1_tmpbio); - - break; - } - -# ifdef HAVE_SHA256 case DKIM_HASHTYPE_SHA256: { - struct dkim_sha256 *sha256; + struct dkim_sha *sha; - sha256 = (struct dkim_sha256 *) cur->canon_hash; - SHA256_Final(sha256->sha256_out, &sha256->sha256_ctx); + sha = (struct dkim_sha *) cur->canon_hash; + EVP_DigestFinal_ex(sha->sha_ctx, sha->sha_out, + &sha->sha_outlen); - if (sha256->sha256_tmpbio != NULL) - (void) BIO_flush(sha256->sha256_tmpbio); + if (sha->sha_tmpbio != NULL) + (void) BIO_flush(sha->sha_tmpbio); break; } -# endif /* HAVE_SHA256 */ #endif /* USE_GNUTLS */ default: @@ -2070,28 +1982,16 @@ dkim_canon_getfinal(DKIM_CANON *canon, u_char **digest, size_t *dlen) } #else /* USE_GNUTLS */ case DKIM_HASHTYPE_SHA1: - { - struct dkim_sha1 *sha1; - - sha1 = (struct dkim_sha1 *) canon->canon_hash; - *digest = sha1->sha1_out; - *dlen = sizeof sha1->sha1_out; - - return DKIM_STAT_OK; - } - -# ifdef HAVE_SHA256 case DKIM_HASHTYPE_SHA256: { - struct dkim_sha256 *sha256; + struct dkim_sha *sha; - sha256 = (struct dkim_sha256 *) canon->canon_hash; - *digest = sha256->sha256_out; - *dlen = sizeof sha256->sha256_out; + sha = (struct dkim_sha *) canon->canon_hash; + *digest = sha->sha_out; + *dlen = sha->sha_outlen; return DKIM_STAT_OK; } -# endif /* HAVE_SHA256 */ #endif /* USE_GNUTLS */ default: diff --git a/libopendkim/dkim-internal.h b/libopendkim/dkim-internal.h index 08bdc1e0..c256f265 100644 --- a/libopendkim/dkim-internal.h +++ b/libopendkim/dkim-internal.h @@ -97,6 +97,8 @@ typedef int dkim_key_t; #define DKIM_KEY_SERVICE 5 /* s */ #define DKIM_KEY_FLAGS 6 /* t */ +extern DKIM_NAMETABLE *dkim_table_keyparams; + /* ** DKIM_SETTYPE -- types of sets */ @@ -108,6 +110,8 @@ typedef int dkim_set_t; #define DKIM_SETTYPE_KEY 1 #define DKIM_SETTYPE_SIGREPORT 2 +extern DKIM_NAMETABLE *dkim_table_settypes; + /* ** DKIM_HASHTYPE -- types of hashes */ @@ -116,6 +120,8 @@ typedef int dkim_set_t; #define DKIM_HASHTYPE_SHA1 0 #define DKIM_HASHTYPE_SHA256 1 +extern DKIM_NAMETABLE *dkim_table_hashes; + /* ** DKIM_KEYTYPE -- types of keys */ @@ -124,6 +130,8 @@ typedef int dkim_set_t; #define DKIM_KEYTYPE_RSA 0 #define DKIM_KEYTYPE_ED25519 1 +extern DKIM_NAMETABLE *dkim_table_keytypes; + /* ** DKIM_SET -- a set of parameters and values */ @@ -152,6 +160,15 @@ typedef struct dkim_key DKIM_KEY; struct dkim_canon; typedef struct dkim_canon DKIM_CANON; + +#ifdef _FFR_CONDITIONAL + +/* +** mandatory DKIM tags +*/ +extern DKIM_NAMETABLE *dkim_table_mandatory; +#endif /* _FFR_CONDITIONAL */ + /* prototypes */ extern DKIM_STAT dkim_process_set __P((DKIM *, dkim_set_t, u_char *, size_t, void *, _Bool, const char *)); diff --git a/libopendkim/dkim-report.c b/libopendkim/dkim-report.c index 0fb2a9e0..50dd35e7 100644 --- a/libopendkim/dkim-report.c +++ b/libopendkim/dkim-report.c @@ -22,7 +22,6 @@ #include "dkim-report.h" #include "dkim-internal.h" #include "dkim-types.h" -#include "dkim-tables.h" #include "util.h" /* prototypes */ diff --git a/libopendkim/dkim-tables.c b/libopendkim/dkim-tables.c index 3817a7bf..5a9dcfa9 100644 --- a/libopendkim/dkim-tables.c +++ b/libopendkim/dkim-tables.c @@ -10,15 +10,28 @@ /* system includes */ #include +#include #include #include /* libopendkim includes */ -#include "dkim-tables.h" #include "dkim-internal.h" +/* structures */ +struct dkim_nametable +{ + const char * tbl_name; /* name */ + const int tbl_code; /* code */ +}; + +struct dkim_iter_ctx +{ + DKIM_NAMETABLE *current; /* current table entry */ + _Bool is_eot; /* It is last entry or not */ +}; + /* lookup tables */ -static struct nametable prv_keyparams[] = /* key parameters */ +static struct dkim_nametable prv_keyparams[] = /* key parameters */ { { "a", DKIM_KEY_ALGORITHM }, { "n", DKIM_KEY_NOTES }, @@ -28,17 +41,17 @@ static struct nametable prv_keyparams[] = /* key parameters */ { "v", DKIM_KEY_VERSION }, { NULL, -1 } }; -struct nametable *keyparams = prv_keyparams; +DKIM_NAMETABLE *dkim_table_keyparams = prv_keyparams; -static struct nametable prv_keyflags[] = /* key flags */ +static struct dkim_nametable prv_keyflags[] = /* key flags */ { { "y", DKIM_SIGFLAG_TESTKEY }, { "s", DKIM_SIGFLAG_NOSUBDOMAIN }, { NULL, -1 } }; -struct nametable *keyflags = prv_keyflags; +DKIM_NAMETABLE *dkim_table_keyflags = prv_keyflags; -static struct nametable prv_sigparams[] = /* signature parameters */ +static struct dkim_nametable prv_sigparams[] = /* signature parameters */ { { "a", DKIM_PARAM_SIGNALG }, { "b", DKIM_PARAM_SIGNATURE }, @@ -56,49 +69,49 @@ static struct nametable prv_sigparams[] = /* signature parameters */ { "z", DKIM_PARAM_COPIEDHDRS }, { NULL, -1 } }; -struct nametable *sigparams = prv_sigparams; +DKIM_NAMETABLE *dkim_table_sigparams = prv_sigparams; -static struct nametable prv_algorithms[] = /* signing algorithms */ +static struct dkim_nametable prv_algorithms[] = /* signing algorithms */ { { "rsa-sha1", DKIM_SIGN_RSASHA1 }, { "rsa-sha256", DKIM_SIGN_RSASHA256 }, { "ed25519-sha256", DKIM_SIGN_ED25519SHA256 }, { NULL, -1 }, }; -struct nametable *algorithms = prv_algorithms; +DKIM_NAMETABLE *dkim_table_algorithms = prv_algorithms; -static struct nametable prv_canonicalizations[] = /* canonicalizations */ +static struct dkim_nametable prv_canonicalizations[] = /* canonicalizations */ { { "simple", DKIM_CANON_SIMPLE }, { "relaxed", DKIM_CANON_RELAXED }, { NULL, -1 }, }; -struct nametable *canonicalizations = prv_canonicalizations; +DKIM_NAMETABLE *dkim_table_canonicalizations = prv_canonicalizations; -static struct nametable prv_hashes[] = /* hashes */ +static struct dkim_nametable prv_hashes[] = /* hashes */ { { "sha1", DKIM_HASHTYPE_SHA1 }, { "sha256", DKIM_HASHTYPE_SHA256 }, { NULL, -1 }, }; -struct nametable *hashes = prv_hashes; +DKIM_NAMETABLE *dkim_table_hashes = prv_hashes; -static struct nametable prv_keytypes[] = /* key types */ +static struct dkim_nametable prv_keytypes[] = /* key types */ { { "rsa", DKIM_KEYTYPE_RSA }, { "ed25519", DKIM_KEYTYPE_ED25519 }, { NULL, -1 }, }; -struct nametable *keytypes = prv_keytypes; +DKIM_NAMETABLE *dkim_table_keytypes = prv_keytypes; -static struct nametable prv_querytypes[] = /* query types */ +static struct dkim_nametable prv_querytypes[] = /* query types */ { { "dns", DKIM_QUERY_DNS }, { NULL, -1 }, }; -struct nametable *querytypes = prv_querytypes; +DKIM_NAMETABLE *dkim_table_querytypes = prv_querytypes; -static struct nametable prv_results[] = /* result codes */ +static struct dkim_nametable prv_results[] = /* result codes */ { { "Success", DKIM_STAT_OK }, { "Bad signature", DKIM_STAT_BADSIG }, @@ -116,20 +129,21 @@ static struct nametable prv_results[] = /* result codes */ { "Invalid result", DKIM_STAT_CBINVALID }, { "Try again later", DKIM_STAT_CBTRYAGAIN }, { "Multiple DNS replies", DKIM_STAT_MULTIDNSREPLY }, + { "End of the table", DKIM_STAT_ITER_EOT }, { NULL, -1 }, }; -struct nametable *results = prv_results; +DKIM_NAMETABLE *dkim_table_results = prv_results; -static struct nametable prv_settypes[] = /* set types */ +static struct dkim_nametable prv_settypes[] = /* set types */ { { "key", DKIM_SETTYPE_KEY }, { "signature", DKIM_SETTYPE_SIGNATURE }, { "signature reporting", DKIM_SETTYPE_SIGREPORT }, { NULL, -1 }, }; -struct nametable *settypes = prv_settypes; +DKIM_NAMETABLE *dkim_table_settypes = prv_settypes; -static struct nametable prv_sigerrors[] = /* signature parsing errors */ +static struct dkim_nametable prv_sigerrors[] = /* signature parsing errors */ { { "no signature error", DKIM_SIGERROR_OK }, { "unsupported signature version", DKIM_SIGERROR_VERSION }, @@ -182,15 +196,15 @@ static struct nametable prv_sigerrors[] = /* signature parsing errors */ #endif /* _FFR_CONDITIONAL */ { NULL, -1 }, }; -struct nametable *sigerrors = prv_sigerrors; +DKIM_NAMETABLE *dkim_table_sigerrors = prv_sigerrors; #ifdef _FFR_CONDITIONAL -static struct nametable prv_mandatory[] = /* mandatory DKIM tags */ +static struct dkim_nametable prv_mandatory[] = /* mandatory DKIM tags */ { { "!cd", 0 }, { NULL, -1 }, }; -struct nametable *mandatory = prv_mandatory; +DKIM_NAMETABLE *dkim_table_mandatory = prv_mandatory; #endif /* _FFR_CONDITIONAL */ /* ===================================================================== */ @@ -207,7 +221,7 @@ struct nametable *mandatory = prv_mandatory; */ const char * -dkim_code_to_name(struct nametable *tbl, const int code) +dkim_code_to_name(DKIM_NAMETABLE *tbl, const int code) { int c; @@ -235,7 +249,7 @@ dkim_code_to_name(struct nametable *tbl, const int code) */ const int -dkim_name_to_code(struct nametable *tbl, const char *name) +dkim_name_to_code(DKIM_NAMETABLE *tbl, const char *name) { int c; @@ -250,3 +264,93 @@ dkim_name_to_code(struct nametable *tbl, const char *name) return tbl[c].tbl_code; } } + +/* +** DKIM_NAMETABLE_FIRST -- get the first entry of the table and start iteration +** +** Parameters: +** tbl -- name table +** ctx -- iteration context (returned) +** name -- name in the first item in the table (returned) +** code -- code in the first item in the table (returned) +** +** Return value: +** A DKIM_STAT_OK -- retrieve the first item successfully +** A DKIM_STAT_ITER_EOT -- the table has no item. +** A DKIM_STAT_NORESOURCE -- cannot allocate memory for the +** iteration context +** +*/ +DKIM_STAT +dkim_nametable_first(DKIM_NAMETABLE *tbl, DKIM_ITER_CTX **ctx, + const char **name, int *code) +{ + *ctx = (DKIM_ITER_CTX *) + malloc(sizeof(DKIM_ITER_CTX)); + if (*ctx == NULL) + { + return DKIM_STAT_NORESOURCE; + } + if (tbl->tbl_name == NULL) + { + (*ctx)->current = NULL; + (*ctx)->is_eot = TRUE; + return DKIM_STAT_ITER_EOT; + } + *name = tbl->tbl_name; + *code = tbl->tbl_code; + (*ctx)->current = tbl; + (*ctx)->is_eot = (((*ctx)->current)[1].tbl_name == NULL)? TRUE : FALSE; + return DKIM_STAT_OK; +} + +/* +** DKIM_NAMETABLE_NEXT -- get the next entry on the iteration the table +** +** Parameters: +** ctx -- iteration context (updated) +** name -- name in the first item in the table (returned) +** code -- code in the first item in the table (returned) +** +** Return value: +** A DKIM_STAT_OK -- retrieve the first item successfully +** A DKIM_STAT_ITER_EOT -- the table has no item. +** +*/ +DKIM_STAT +dkim_nametable_next(DKIM_ITER_CTX *ctx, const char **name, int *code) +{ + if (ctx->is_eot) + { + return DKIM_STAT_ITER_EOT; + } + ctx->current++; + *name = ctx->current->tbl_name; + *code = ctx->current->tbl_code; + ctx->is_eot = ((ctx->current)[1].tbl_name == NULL)? TRUE : FALSE; + return DKIM_STAT_OK; +} + +/* +** DKIM_ITER_CTX_FREE -- release resources associated with +** a nametable iteration context +** +** Parameters: +** ctx -- iteration context +** +** Return value: +** DKIM_STAT_OK -- operation was successful +** +** Note: This function is a placeholder to add some operation associated +** with future changes of the structure of the tables. +** +*/ +DKIM_STAT +dkim_iter_ctx_free(DKIM_ITER_CTX *ctx) +{ + if (ctx != NULL) + { + free((void *)ctx); + } + return DKIM_STAT_OK; +} diff --git a/libopendkim/dkim-tables.h b/libopendkim/dkim-tables.h deleted file mode 100644 index 5ee57930..00000000 --- a/libopendkim/dkim-tables.h +++ /dev/null @@ -1,51 +0,0 @@ -/* -** Copyright (c) 2005-2008 Sendmail, Inc. and its suppliers. -** All rights reserved. -** -** Copyright (c) 2009, 2010, 2012, 2014, 2015, The Trusted Domain Project. -** All rights reserved. -*/ - -#ifndef _DKIM_TABLES_H_ -#define _DKIM_TABLES_H_ - -#ifdef __STDC__ -# ifndef __P -# define __P(x) x -# endif /* ! __P */ -#else /* __STDC__ */ -# ifndef __P -# define __P(x) () -# endif /* ! __P */ -#endif /* __STDC__ */ - -/* structures */ -struct nametable -{ - const char * tbl_name; /* name */ - const int tbl_code; /* code */ -}; - -/* tables */ -extern struct nametable *algorithms; -extern struct nametable *canonicalizations; -extern struct nametable *hashes; -extern struct nametable *keyflags; -extern struct nametable *keyparams; -extern struct nametable *keytypes; -extern struct nametable *querytypes; -extern struct nametable *results; -extern struct nametable *settypes; -extern struct nametable *sigerrors; -extern struct nametable *sigparams; -#ifdef _FFR_CONDITIONAL -extern struct nametable *mandatory; -#endif /* _FFR_CONDITIONAL */ - -/* prototypes */ -extern const char *dkim_code_to_name __P((struct nametable *tbl, - const int code)); -extern const int dkim_name_to_code __P((struct nametable *tbl, - const char *name)); - -#endif /* _DKIM_TABLES_H_ */ diff --git a/libopendkim/dkim-test.c b/libopendkim/dkim-test.c index 3985db83..34a45aae 100644 --- a/libopendkim/dkim-test.c +++ b/libopendkim/dkim-test.c @@ -27,6 +27,7 @@ # include # include # include +# include #endif /* USE_GNUTLS */ /* libopendkim includes */ @@ -266,8 +267,8 @@ dkim_test_dns_get(DKIM *dkim, u_char *buf, size_t buflen) } /* -** DKIM_TEST_KEY -- retrieve a public key and verify it against a provided -** private key +** DKIM_TEST_KEY2 -- retrieve a public key and verify it against a provided +** private key ** ** Parameters: ** lib -- DKIM library handle @@ -276,6 +277,7 @@ dkim_test_dns_get(DKIM *dkim, u_char *buf, size_t buflen) ** key -- private key to verify (PEM format) ** keylen -- size of private key ** dnssec -- DNSSEC result (may be NULL) +** alg -- signing algorithm ** err -- error buffer (may be NULL) ** errlen -- size of error buffer ** @@ -286,8 +288,9 @@ dkim_test_dns_get(DKIM *dkim, u_char *buf, size_t buflen) */ int -dkim_test_key(DKIM_LIB *lib, char *selector, char *domain, - char *key, size_t keylen, int *dnssec, char *err, size_t errlen) +dkim_test_key2(DKIM_LIB *lib, char *selector, char *domain, + char *key, size_t keylen, dkim_alg_t alg, + int *dnssec, char *err, size_t errlen) { int status = 0; DKIM_STAT stat; @@ -299,10 +302,12 @@ dkim_test_key(DKIM_LIB *lib, char *selector, char *domain, #else /* USE_GNUTLS */ BIO *keybuf; BIO *outkey; + size_t outkey_len; #endif /* USE_GNUTLS */ void *ptr; struct dkim_crypto *crypto; char buf[BUFRSZ]; + const char *algstr; assert(lib != NULL); assert(selector != NULL); @@ -316,8 +321,10 @@ dkim_test_key(DKIM_LIB *lib, char *selector, char *domain, return -1; } - snprintf(buf, sizeof buf, "v=1; d=%s; s=%s; h=x; b=x; a=x", - domain, selector); + algstr = dkim_code_to_name(dkim_table_algorithms, alg); + + snprintf(buf, sizeof buf, "v=1; d=%s; s=%s; h=x; b=x; a=%s", + domain, selector, algstr); stat = dkim_process_set(dkim, DKIM_SETTYPE_SIGNATURE, (u_char *) buf, strlen(buf), NULL, FALSE, NULL); @@ -407,7 +414,18 @@ dkim_test_key(DKIM_LIB *lib, char *selector, char *domain, #endif /* USE_GNUTLS */ sig->sig_signature = (void *) crypto; - sig->sig_keytype = DKIM_KEYTYPE_RSA; + switch(alg) + { + case DKIM_SIGN_RSASHA1: + case DKIM_SIGN_RSASHA256: + sig->sig_keytype = DKIM_KEYTYPE_RSA; + break; + case DKIM_SIGN_ED25519SHA256: + sig->sig_keytype = DKIM_KEYTYPE_ED25519; + break; + default: + return -1; + } #ifdef USE_GNUTLS if (err != NULL) @@ -431,58 +449,73 @@ dkim_test_key(DKIM_LIB *lib, char *selector, char *domain, return -1; } - crypto->crypto_key = EVP_PKEY_get1_RSA(crypto->crypto_pkey); - if (crypto->crypto_key == NULL) + if (sig->sig_keytype == DKIM_KEYTYPE_ED25519) { - BIO_free(keybuf); - (void) dkim_free(dkim); - if (err != NULL) + outkey_len = sizeof(buf); + if (! EVP_PKEY_get_raw_public_key(crypto->crypto_pkey, + buf, &outkey_len)) { - strlcpy(err, "EVP_PKEY_get1_RSA() failed", + strlcpy(err, + "EVP_PKEY_get_raw_public_key() failed", errlen); + return -1; } - return -1; + ptr = buf; } - - crypto->crypto_keysize = RSA_size(crypto->crypto_key); - crypto->crypto_pad = RSA_PKCS1_PADDING; - - outkey = BIO_new(BIO_s_mem()); - if (outkey == NULL) + else { - BIO_free(keybuf); - (void) dkim_free(dkim); - if (err != NULL) - strlcpy(err, "BIO_new() failed", errlen); - return -1; - } + crypto->crypto_keysize = EVP_PKEY_size(crypto->crypto_pkey); - status = i2d_RSA_PUBKEY_bio(outkey, crypto->crypto_key); - if (status == 0) - { - BIO_free(keybuf); - BIO_free(outkey); - (void) dkim_free(dkim); - if (err != NULL) + outkey = BIO_new(BIO_s_mem()); + if (outkey == NULL) { - strlcpy(err, "i2d_RSA_PUBKEY_bio() failed", - errlen); + BIO_free(keybuf); + (void) dkim_free(dkim); + if (err != NULL) + strlcpy(err, "BIO_new() failed", errlen); + return -1; } - return -1; - } - (void) BIO_get_mem_data(outkey, &ptr); + status = i2d_PUBKEY_bio(outkey, crypto->crypto_pkey); + if (status == 0) + { + BIO_free(keybuf); + BIO_free(outkey); + (void) dkim_free(dkim); + if (err != NULL) + { + strlcpy(err, "i2d_RSA_PUBKEY_bio() failed", + errlen); + } + return -1; + } + (void) BIO_get_mem_data(outkey, &ptr); + + outkey_len = BIO_number_written(outkey); - if (BIO_number_written(outkey) == sig->sig_keylen) + } + + if (outkey_len == sig->sig_keylen) + { status = memcmp(ptr, sig->sig_key, sig->sig_keylen); + if (status != 0) + { + strlcpy(err, "keys do not match", errlen); + } + } else + { status = 1; + snprintf(err, errlen, + "key do not match: local = %zd, remote = %zd", + outkey_len, sig->sig_keylen); + } - if (status != 0) - strlcpy(err, "keys do not match", errlen); - - BIO_free(keybuf); - BIO_free(outkey); + if (sig->sig_keytype != DKIM_KEYTYPE_ED25519) + { + BIO_free(keybuf); + BIO_free(outkey); + } #endif /* USE_GNUTLS */ } @@ -490,3 +523,31 @@ dkim_test_key(DKIM_LIB *lib, char *selector, char *domain, return (status == 0 ? 0 : 1); } + +/* +** DKIM_TEST_KEY -- retrieve a public key and verify it against a provided +** private key +** +** Parameters: +** lib -- DKIM library handle +** selector -- selector +** domain -- domain name +** key -- private key to verify (PEM format) +** keylen -- size of private key +** dnssec -- DNSSEC result (may be NULL) +** err -- error buffer (may be NULL) +** errlen -- size of error buffer +** +** Return value: +** 1 -- keys don't match +** 0 -- keys match (or no key provided) +** -1 -- error +*/ + +int +dkim_test_key(DKIM_LIB *lib, char *selector, char *domain, + char *key, size_t keylen, int *dnssec, char *err, size_t errlen) +{ + return dkim_test_key2(lib, selector, domain, key, keylen, + DKIM_SIGN_RSASHA256, dnssec, err, errlen); +} diff --git a/libopendkim/dkim-types.h b/libopendkim/dkim-types.h index f54800a1..18ee7cae 100644 --- a/libopendkim/dkim-types.h +++ b/libopendkim/dkim-types.h @@ -37,6 +37,7 @@ # include # include # include +# include #endif /* USE_GNUTLS */ #ifdef QUERY_CACHE @@ -151,36 +152,22 @@ struct dkim_siginfo struct dkim_dstring * sig_sslerrbuf; }; -#ifdef USE_GNUTLS /* struct dkim_sha -- stuff needed to do a sha hash */ struct dkim_sha { +#ifdef USE_GNUTLS int sha_tmpfd; u_int sha_outlen; gnutls_hash_hd_t sha_hd; u_char * sha_out; -}; #else /* USE_GNUTLS */ -/* struct dkim_sha1 -- stuff needed to do a sha1 hash */ -struct dkim_sha1 -{ - int sha1_tmpfd; - BIO * sha1_tmpbio; - SHA_CTX sha1_ctx; - u_char sha1_out[SHA_DIGEST_LENGTH]; -}; - -# ifdef HAVE_SHA256 -/* struct dkim_sha256 -- stuff needed to do a sha256 hash */ -struct dkim_sha256 -{ - int sha256_tmpfd; - BIO * sha256_tmpbio; - SHA256_CTX sha256_ctx; - u_char sha256_out[SHA256_DIGEST_LENGTH]; -}; -# endif /* HAVE_SHA256 */ + int sha_tmpfd; + BIO * sha_tmpbio; + EVP_MD_CTX * sha_ctx; + u_char sha_out[EVP_MAX_MD_SIZE]; + u_int sha_outlen; #endif /* USE_GNUTLS */ +}; /* struct dkim_canon -- a canonicalization status handle */ struct dkim_canon @@ -220,12 +207,10 @@ struct dkim_crypto gnutls_datum_t crypto_rsaout; gnutls_datum_t crypto_keydata; #else /* USE_GNUTLS */ - u_char crypto_pad; int crypto_keysize; size_t crypto_inlen; size_t crypto_outlen; EVP_PKEY * crypto_pkey; - void * crypto_key; BIO * crypto_keydata; u_char * crypto_in; u_char * crypto_out; diff --git a/libopendkim/dkim.c b/libopendkim/dkim.c index e429a6fc..ca9a4098 100644 --- a/libopendkim/dkim.c +++ b/libopendkim/dkim.c @@ -75,12 +75,12 @@ # include # include # include +# include #endif /* USE_GNUTLS */ /* libopendkim includes */ #include "dkim-internal.h" #include "dkim-types.h" -#include "dkim-tables.h" #include "dkim-keys.h" #include "dkim-report.h" #include "dkim-util.h" @@ -203,12 +203,6 @@ void dkim_error __P((DKIM *, const char *, ...)); (x) = NULL; \ } -# define RSA_CLOBBER(x) if ((x) != NULL) \ - { \ - RSA_free((x)); \ - (x) = NULL; \ - } - # define EVP_CLOBBER(x) if ((x) != NULL) \ { \ EVP_PKEY_free((x)); \ @@ -519,7 +513,7 @@ dkim_process_set(DKIM *dkim, dkim_set_t type, u_char *str, size_t len, } set->set_type = type; - settype = dkim_code_to_name(settypes, type); + settype = dkim_code_to_name(dkim_table_settypes, type); set->set_name = name; #ifdef _FFR_CONDITIONAL set->set_minv = 1; @@ -836,7 +830,7 @@ dkim_process_set(DKIM *dkim, dkim_set_t type, u_char *str, size_t len, plist != NULL; plist = plist->plist_next) { - if (dkim_name_to_code(mandatory, + if (dkim_name_to_code(dkim_table_mandatory, plist->plist_param) == -1) { dkim_error(dkim, @@ -1270,32 +1264,14 @@ dkim_privkey_load(DKIM *dkim) } } - if (dkim->dkim_signalg == DKIM_SIGN_ED25519SHA256) - { - crypto->crypto_keysize = EVP_PKEY_size(crypto->crypto_pkey) * 8; - } - else - { - crypto->crypto_key = EVP_PKEY_get1_RSA(crypto->crypto_pkey); - if (crypto->crypto_key == NULL) - { - dkim_load_ssl_errors(dkim, 0); - dkim_error(dkim, "EVP_PKEY_get1_RSA() failed"); - BIO_CLOBBER(crypto->crypto_keydata); - return DKIM_STAT_NORESOURCE; - } + crypto->crypto_outlen = EVP_PKEY_size(crypto->crypto_pkey); + crypto->crypto_keysize = crypto->crypto_outlen * 8; - crypto->crypto_keysize = RSA_size(crypto->crypto_key) * 8; - crypto->crypto_pad = RSA_PKCS1_PADDING; - } - - crypto->crypto_outlen = crypto->crypto_keysize / 8; crypto->crypto_out = DKIM_MALLOC(dkim, crypto->crypto_outlen); if (crypto->crypto_out == NULL) { dkim_error(dkim, "unable to allocate %d byte(s)", - crypto->crypto_keysize / 8); - RSA_free(crypto->crypto_key); + crypto->crypto_outlen); BIO_CLOBBER(crypto->crypto_keydata); return DKIM_STAT_NORESOURCE; } @@ -1489,7 +1465,7 @@ dkim_key_hashok(DKIM_SIGINFO *sig, u_char *hashlist) { strlcpy((char *) tmp, (char *) x, sizeof tmp); tmp[y - x] = '\0'; - hashalg = dkim_name_to_code(hashes, + hashalg = dkim_name_to_code(dkim_table_hashes, (char *) tmp); if (hashalg == sig->sig_hashtype) return TRUE; @@ -1548,7 +1524,7 @@ dkim_key_hashesok(DKIM_LIB *lib, u_char *hashlist) strlcpy((char *) tmp, (char *) x, sizeof tmp); tmp[y - x] = '\0'; - hashcode = dkim_name_to_code(hashes, + hashcode = dkim_name_to_code(dkim_table_hashes, (char *) tmp); if (hashcode != -1 && @@ -2089,7 +2065,7 @@ dkim_siglist_setup(DKIM *dkim) if (q != NULL) *q = '\0'; - hdrcanon = dkim_name_to_code(canonicalizations, value); + hdrcanon = dkim_name_to_code(dkim_table_canonicalizations, value); if (hdrcanon == -1) { dkim->dkim_siglist[c]->sig_error = DKIM_SIGERROR_INVALID_HC; @@ -2102,7 +2078,7 @@ dkim_siglist_setup(DKIM *dkim) } else { - bodycanon = dkim_name_to_code(canonicalizations, + bodycanon = dkim_name_to_code(dkim_table_canonicalizations, q + 1); if (bodycanon == -1) @@ -2122,7 +2098,7 @@ dkim_siglist_setup(DKIM *dkim) } else { - signalg = dkim_name_to_code(algorithms, + signalg = dkim_name_to_code(dkim_table_algorithms, (char *) param); if (signalg == -1) @@ -2257,7 +2233,7 @@ dkim_siglist_setup(DKIM *dkim) } /* unknown type */ - q = dkim_name_to_code(querytypes, (char *) p); + q = dkim_name_to_code(dkim_table_querytypes, (char *) p); if (q == (dkim_query_t) -1) continue; @@ -2416,7 +2392,7 @@ dkim_siglist_setup(DKIM *dkim) plist != NULL; plist = plist->plist_next) { - pcode = dkim_name_to_code(sigparams, + pcode = dkim_name_to_code(dkim_table_sigparams, (char *) plist->plist_param); (void) lib->dkiml_sig_tagvalues(user, @@ -2545,12 +2521,12 @@ dkim_gensighdr(DKIM *dkim, DKIM_SIGINFO *sig, struct dkim_dstring *dstr, (void) dkim_dstring_printf(dstr, format, v, delim, - dkim_code_to_name(algorithms, + dkim_code_to_name(dkim_table_algorithms, sig->sig_signalg), delim, - dkim_code_to_name(canonicalizations, + dkim_code_to_name(dkim_table_canonicalizations, sig->sig_hdrcanonalg), - dkim_code_to_name(canonicalizations, + dkim_code_to_name(dkim_table_canonicalizations, sig->sig_bodycanonalg), delim, sig->sig_domain, delim, @@ -3080,7 +3056,7 @@ dkim_get_key(DKIM *dkim, DKIM_SIGINFO *sig, _Bool test) sig->sig_error = DKIM_SIGERROR_KEYTYPEMISSING; return DKIM_STAT_SYNTAX; } - else if (dkim_name_to_code(keytypes, (char *) p) == -1) + else if (dkim_name_to_code(dkim_table_keytypes, (char *) p) == -1) { dkim_error(dkim, "unknown key type '%s'", p); sig->sig_error = DKIM_SIGERROR_KEYTYPEUNKNOWN; @@ -3136,7 +3112,7 @@ dkim_get_key(DKIM *dkim, DKIM_SIGINFO *sig, _Bool test) t != NULL; t = strtok_r(NULL, ":", &last)) { - flag = (u_int) dkim_name_to_code(keyflags, t); + flag = (u_int) dkim_name_to_code(dkim_table_keyflags, t); if (flag != (u_int) -1) sig->sig_flags |= flag; } @@ -3650,7 +3626,7 @@ dkim_eoh_verify(DKIM *dkim) sig->sig_error != DKIM_SIGERROR_OK) { dkim_error(dkim, - dkim_code_to_name(sigerrors, + dkim_code_to_name(dkim_table_sigerrors, sig->sig_error)); } @@ -3675,7 +3651,6 @@ static DKIM_STAT dkim_eom_sign(DKIM *dkim) { int status; - size_t l = 0; size_t diglen; size_t siglen = 0; size_t len; @@ -3811,9 +3786,7 @@ dkim_eom_sign(DKIM *dkim) #ifdef USE_GNUTLS if (crypto->crypto_privkey == NULL) #else /* USE_GNUTLS */ - if (!(crypto->crypto_key != NULL || - (sig->sig_signalg == DKIM_SIGN_ED25519SHA256 && - crypto->crypto_pkey != NULL))) + if (crypto->crypto_pkey == NULL) #endif /* USE_GNUTLS */ { dkim_error(dkim, "private key load failed"); @@ -3949,39 +3922,83 @@ dkim_eom_sign(DKIM *dkim) case DKIM_SIGN_RSASHA1: case DKIM_SIGN_RSASHA256: { - int nid; struct dkim_crypto *crypto; + EVP_PKEY_CTX *pkey_ctx; + const EVP_MD *md; crypto = (struct dkim_crypto *) sig->sig_signature; - nid = NID_sha1; + pkey_ctx = EVP_PKEY_CTX_new(crypto->crypto_pkey, NULL); + + if (pkey_ctx == NULL) + { + dkim_error(dkim, "failed to allocate EVP_PKEY context"); + BIO_CLOBBER(crypto->crypto_keydata); + return DKIM_STAT_NORESOURCE; + } + + if (EVP_PKEY_sign_init(pkey_ctx) <= 0) + { + dkim_load_ssl_errors(dkim, 0); + dkim_error(dkim, + "failed to initialize EVP_PKEY context"); + + EVP_PKEY_CTX_free(pkey_ctx); + BIO_CLOBBER(crypto->crypto_keydata); + + return DKIM_STAT_INTERNAL; + } + + if (EVP_PKEY_CTX_set_rsa_padding(pkey_ctx, RSA_PKCS1_PADDING) <= 0) + { + dkim_load_ssl_errors(dkim, 0); + dkim_error(dkim, "failed to set RSA padding mode"); + + EVP_PKEY_CTX_free(pkey_ctx); + BIO_CLOBBER(crypto->crypto_keydata); + + return DKIM_STAT_INTERNAL; + } + + md = EVP_sha1(); if (dkim_libfeature(dkim->dkim_libhandle, DKIM_FEATURE_SHA256) && sig->sig_hashtype == DKIM_HASHTYPE_SHA256) - nid = NID_sha256; + md = EVP_sha256(); + + if (EVP_PKEY_CTX_set_signature_md(pkey_ctx, md) <= 0) + { + dkim_load_ssl_errors(dkim, 0); + dkim_error(dkim, "failed to set message digest type"); + + EVP_PKEY_CTX_free(pkey_ctx); + BIO_CLOBBER(crypto->crypto_keydata); + + return DKIM_STAT_INTERNAL; + } + + status = EVP_PKEY_sign(pkey_ctx, crypto->crypto_out, + &crypto->crypto_outlen, digest, diglen); - status = RSA_sign(nid, digest, diglen, - crypto->crypto_out, (int *) &l, - crypto->crypto_key); - if (status != 1 || l == 0) + if (status != 1 || crypto->crypto_outlen == 0) { dkim_load_ssl_errors(dkim, 0); dkim_error(dkim, "signature generation failed (status %d, length %d)", - status, l); + status, crypto->crypto_outlen); - RSA_free(crypto->crypto_key); + EVP_PKEY_CTX_free(pkey_ctx); BIO_CLOBBER(crypto->crypto_keydata); return DKIM_STAT_INTERNAL; } - crypto->crypto_outlen = l; - signature = crypto->crypto_out; siglen = crypto->crypto_outlen; + EVP_PKEY_CTX_free(pkey_ctx); + break; } @@ -4000,7 +4017,6 @@ dkim_eom_sign(DKIM *dkim) dkim_error(dkim, "failed to initialize digest context"); - RSA_free(crypto->crypto_key); BIO_CLOBBER(crypto->crypto_keydata); return DKIM_STAT_INTERNAL; @@ -4010,9 +4026,9 @@ dkim_eom_sign(DKIM *dkim) NULL, NULL, crypto->crypto_pkey); if (status == 1) { - l = crypto->crypto_outlen; - status = EVP_DigestSign(md_ctx, crypto->crypto_out, &l, - digest, diglen); + status = EVP_DigestSign(md_ctx, crypto->crypto_out, + &crypto->crypto_outlen, digest, + diglen); } if (status != 1) @@ -4020,16 +4036,14 @@ dkim_eom_sign(DKIM *dkim) /* dkim_load_ssl_errors(dkim, 0); */ dkim_error(dkim, "signature generation failed (status %d, length %d, %s)", - status, l, ERR_error_string(ERR_get_error(), NULL)); + status, crypto->crypto_outlen, + ERR_error_string(ERR_get_error(), NULL)); - RSA_free(crypto->crypto_key); BIO_CLOBBER(crypto->crypto_keydata); return DKIM_STAT_INTERNAL; } - crypto->crypto_outlen = l; - signature = crypto->crypto_out; siglen = crypto->crypto_outlen; @@ -4307,7 +4321,7 @@ dkim_eom_verify(DKIM *dkim, _Bool *testkey) if (dkim->dkim_error == NULL || dkim->dkim_error[0] == '\0') { - dkim_error(dkim, dkim_code_to_name(sigerrors, + dkim_error(dkim, dkim_code_to_name(dkim_table_sigerrors, sig->sig_error)); } @@ -5146,7 +5160,6 @@ dkim_free(DKIM *dkim) #else /* USE_GNUTLS */ BIO_CLOBBER(crypto->crypto_keydata); EVP_CLOBBER(crypto->crypto_pkey); - RSA_CLOBBER(crypto->crypto_key); CLOBBER(crypto->crypto_out); #endif /* USE_GNUTLS */ } @@ -5558,6 +5571,8 @@ dkim_sig_process(DKIM *dkim, DKIM_SIGINFO *sig) # endif /* GNUTLS_VERSION_MAJOR == 3 */ #else /* USE_GNUTLS */ BIO *key; + EVP_PKEY_CTX *pkey_ctx; + const EVP_MD *md; #endif /* USE_GNUTLS */ u_char *digest = NULL; struct dkim_crypto *crypto; @@ -5836,12 +5851,10 @@ dkim_sig_process(DKIM *dkim, DKIM_SIGINFO *sig) else # endif /* HAVE_ED25519 */ { - crypto->crypto_key = EVP_PKEY_get1_RSA(crypto->crypto_pkey); - if (crypto->crypto_key == NULL) + if (EVP_PKEY_base_id(crypto->crypto_pkey) != EVP_PKEY_RSA) { - dkim_sig_load_ssl_errors(dkim, sig, 0); dkim_error(dkim, - "s=%s d=%s: EVP_PKEY_get1_RSA() failed", + "s=%s d=%s: not an RSA key", dkim_sig_getselector(sig), dkim_sig_getdomain(sig)); @@ -5852,23 +5865,69 @@ dkim_sig_process(DKIM *dkim, DKIM_SIGINFO *sig) return DKIM_STAT_OK; } - crypto->crypto_keysize = RSA_size(crypto->crypto_key); - crypto->crypto_pad = RSA_PKCS1_PADDING; + crypto->crypto_keysize = EVP_PKEY_size(crypto->crypto_pkey); crypto->crypto_in = sig->sig_sig; crypto->crypto_inlen = sig->sig_siglen; - nid = NID_sha1; + pkey_ctx = EVP_PKEY_CTX_new(crypto->crypto_pkey, NULL); + + if (pkey_ctx == NULL) + { + dkim_error(dkim, + "failed to allocate EVP_PKEY context"); + BIO_CLOBBER(key); + return DKIM_STAT_NORESOURCE; + } + + if (EVP_PKEY_verify_init(pkey_ctx) <= 0) + { + dkim_sig_load_ssl_errors(dkim, sig, 0); + dkim_error(dkim, + "failed to initialize EVP_PKEY context"); + + EVP_PKEY_CTX_free(pkey_ctx); + BIO_CLOBBER(key); + + return DKIM_STAT_INTERNAL; + } + + if (EVP_PKEY_CTX_set_rsa_padding(pkey_ctx, RSA_PKCS1_PADDING) <= 0) + { + dkim_sig_load_ssl_errors(dkim, sig, 0); + dkim_error(dkim, + "failed to set RSA padding mode"); + + EVP_PKEY_CTX_free(pkey_ctx); + BIO_CLOBBER(key); + + return DKIM_STAT_INTERNAL; + } + + md = EVP_sha1(); if (dkim_libfeature(dkim->dkim_libhandle, DKIM_FEATURE_SHA256) && sig->sig_hashtype == DKIM_HASHTYPE_SHA256) - nid = NID_sha256; + md = EVP_sha256(); + + if (EVP_PKEY_CTX_set_signature_md(pkey_ctx, md) <= 0) + { + dkim_sig_load_ssl_errors(dkim, sig, 0); + dkim_error(dkim, + "failed to set message digest type"); + + EVP_PKEY_CTX_free(pkey_ctx); + BIO_CLOBBER(key); + + return DKIM_STAT_INTERNAL; + } - vstat = RSA_verify(nid, digest, diglen, - crypto->crypto_in, - crypto->crypto_inlen, - crypto->crypto_key); + vstat = EVP_PKEY_verify(pkey_ctx, crypto->crypto_in, + crypto->crypto_inlen, digest, + diglen); + + EVP_PKEY_CTX_free(pkey_ctx); } dkim_sig_load_ssl_errors(dkim, sig, 0); @@ -5876,13 +5935,7 @@ dkim_sig_process(DKIM *dkim, DKIM_SIGINFO *sig) sig->sig_keybits = 8 * crypto->crypto_keysize; BIO_CLOBBER(key); - EVP_PKEY_free(crypto->crypto_pkey); - crypto->crypto_pkey = NULL; - if (crypto->crypto_key != NULL) - { - RSA_free(crypto->crypto_key); - crypto->crypto_key = NULL; - } + EVP_CLOBBER(crypto->crypto_pkey); #endif /* USE_GNUTLS */ if (vstat == 1) @@ -7598,40 +7651,22 @@ dkim_sig_getreportinfo(DKIM *dkim, DKIM_SIGINFO *sig, } #else /* USE_GNUTLS */ case DKIM_HASHTYPE_SHA1: - { - struct dkim_sha1 *sha1; - - sha1 = (struct dkim_sha1 *) sig->sig_hdrcanon->canon_hash; - if (hfd != NULL) - *hfd = sha1->sha1_tmpfd; - - if (bfd != NULL) - { - sha1 = (struct dkim_sha1 *) sig->sig_bodycanon->canon_hash; - *bfd = sha1->sha1_tmpfd; - } - - break; - } - -# ifdef HAVE_SHA256 case DKIM_HASHTYPE_SHA256: { - struct dkim_sha256 *sha256; + struct dkim_sha *sha; - sha256 = (struct dkim_sha256 *) sig->sig_hdrcanon->canon_hash; + sha = (struct dkim_sha *) sig->sig_hdrcanon->canon_hash; if (hfd != NULL) - *hfd = sha256->sha256_tmpfd; + *hfd = sha->sha_tmpfd; if (bfd != NULL) { - sha256 = (struct dkim_sha256 *) sig->sig_bodycanon->canon_hash; - *bfd = sha256->sha256_tmpfd; + sha = (struct dkim_sha *) sig->sig_bodycanon->canon_hash; + *bfd = sha->sha_tmpfd; } break; } -# endif /* HAVE_SHA256 */ #endif /* USE_GNUTLS */ default: @@ -8153,7 +8188,7 @@ dkim_set_margin(DKIM *dkim, int value) const char * dkim_getresultstr(DKIM_STAT result) { - return dkim_code_to_name(results, result); + return dkim_code_to_name(dkim_table_results, result); } /* @@ -8486,7 +8521,7 @@ dkim_sig_getalgorithm(DKIM_SIGINFO *siginfo) { assert(siginfo != NULL); - return (unsigned char *) dkim_code_to_name(algorithms, + return (unsigned char *) dkim_code_to_name(dkim_table_algorithms, siginfo->sig_signalg); } @@ -8546,7 +8581,7 @@ dkim_sig_geterror(DKIM_SIGINFO *siginfo) const char * dkim_sig_geterrorstr(DKIM_SIGERROR sigerr) { - return dkim_code_to_name(sigerrors, sigerr); + return dkim_code_to_name(dkim_table_sigerrors, sigerr); } /* @@ -9460,7 +9495,7 @@ dkim_add_xtag(DKIM *dkim, const char *tag, const char *value) /* check that it's not in sigparams */ if (tag[0] == '\0' || value[0] == '\0') return DKIM_STAT_INVALID; - pcode = dkim_name_to_code(sigparams, tag); + pcode = dkim_name_to_code(dkim_table_sigparams, tag); if (pcode != (dkim_param_t) -1) return DKIM_STAT_INVALID; diff --git a/libopendkim/dkim.h b/libopendkim/dkim.h index 42572595..00db1a7f 100644 --- a/libopendkim/dkim.h +++ b/libopendkim/dkim.h @@ -64,6 +64,13 @@ extern "C" { /* macros */ #define DKIM_SIG_CHECK(x) ((dkim_sig_getflags((x)) & DKIM_SIGFLAG_PASSED) != 0 && dkim_sig_getbh((x)) == DKIM_SIGBH_MATCH) +/* +** DKIM_NAMETABLE -- tables for conversion between code and name +*/ + +struct dkim_nametable; +typedef struct dkim_nametable DKIM_NAMETABLE; + /* ** DKIM_STAT -- status code type */ @@ -88,6 +95,9 @@ typedef int DKIM_STAT; #define DKIM_STAT_CBERROR 15 /* callback error */ #define DKIM_STAT_MULTIDNSREPLY 16 /* multiple DNS replies */ #define DKIM_STAT_SIGGEN 17 /* signature generation failed */ +#define DKIM_STAT_ITER_EOT 18 /* the table has no more item */ + +extern DKIM_NAMETABLE *dkim_table_results; /* ** DKIM_CBSTAT -- callback status code type @@ -159,6 +169,8 @@ typedef int DKIM_SIGERROR; #define DKIM_SIGERROR_CONDITIONAL 47 /* conditional sig error */ #define DKIM_SIGERROR_CONDLOOP 48 /* conditional sig loop */ +extern DKIM_NAMETABLE *dkim_table_sigerrors; + /* generic DNS error codes */ #define DKIM_DNS_ERROR (-1) /* error in transit */ #define DKIM_DNS_SUCCESS 0 /* reply available */ @@ -176,6 +188,8 @@ typedef int dkim_canon_t; #define DKIM_CANON_SIMPLE 0 /* as specified in DKIM spec */ #define DKIM_CANON_RELAXED 1 /* as specified in DKIM spec */ +extern DKIM_NAMETABLE *dkim_table_canonicalizations; + #define DKIM_CANON_DEFAULT DKIM_CANON_SIMPLE /* @@ -190,6 +204,8 @@ typedef int dkim_alg_t; #define DKIM_SIGN_RSASHA256 1 /* an RSA-signed SHA256 digest */ #define DKIM_SIGN_ED25519SHA256 2 /* an ED25519-signed SHA256 digest */ +extern DKIM_NAMETABLE *dkim_table_algorithms; + /* ** DKIM_QUERY -- query method */ @@ -200,6 +216,8 @@ typedef int dkim_query_t; #define DKIM_QUERY_DNS 0 /* DNS query method (per the draft) */ #define DKIM_QUERY_FILE 1 /* text file method (for testing) */ +extern DKIM_NAMETABLE *dkim_table_querytypes; + #define DKIM_QUERY_DEFAULT DKIM_QUERY_DNS /* @@ -224,6 +242,8 @@ typedef int dkim_param_t; #define DKIM_PARAM_BODYHASH 12 /* bh */ #define DKIM_PARAM_BODYLENGTH 13 /* l */ +extern DKIM_NAMETABLE *dkim_table_sigparams; + /* ** DKIM_MODE -- mode of a handle */ @@ -334,6 +354,8 @@ typedef struct dkim_siginfo DKIM_SIGINFO; #define DKIM_SIGFLAG_NOSUBDOMAIN 0x10 #define DKIM_SIGFLAG_KEYLOADED 0x20 +extern DKIM_NAMETABLE *dkim_table_keyflags; + #define DKIM_SIGBH_UNTESTED (-1) #define DKIM_SIGBH_MATCH 0 #define DKIM_SIGBH_MISMATCH 1 @@ -355,6 +377,13 @@ struct dkim_hdrdiff u_char * hd_new; }; +/* +** DKIM_ITER -- iteration on conversion tables +*/ + +struct dkim_iter_ctx; /* table iteration context */ +typedef struct dkim_iter_ctx DKIM_ITER_CTX; + /* ** PROTOTYPES */ @@ -1423,6 +1452,30 @@ extern uint32_t dkim_libversion __P((void)); extern DKIM_STAT dkim_get_sigsubstring __P((DKIM *, DKIM_SIGINFO *, char *, size_t *)); +/* +** DKIM_TEST_KEY2 -- retrieve a public key and verify it against a provided +** private key +** +** Parameters: +** lib -- DKIM library handle +** selector -- selector +** domain -- domain name +** key -- private key to verify (PEM format) +** keylen -- size of private key +** alg -- signing algorithm +** dnssec -- DNSSEC result (may be NULL) +** err -- error buffer (may be NULL) +** errlen -- size of error buffer +** +** Return value: +** 1 -- keys don't match +** 0 -- keys match (or no key provided) +** -1 -- error +*/ + +extern int dkim_test_key2 __P((DKIM_LIB *, char *, char *, char *, size_t, + dkim_alg_t, int *, char *, size_t)); + /* ** DKIM_TEST_KEY -- retrieve a public key and verify it against a provided ** private key @@ -1941,6 +1994,84 @@ extern const u_char *dkim_should_signhdrs[]; /* list of headers that should not be signed, per RFC6376 Section 5.4 */ extern const u_char *dkim_should_not_signhdrs[]; +/* +** DKIM_CODE_TO_NAME -- translate a mnemonic code to its name +** +** Parameters: +** tbl -- name table +** code -- code to translate +** +** Return value: +** Pointer to the name matching the provided code, or NULL if not found. +*/ + +extern const char *dkim_code_to_name __P((DKIM_NAMETABLE *tbl, + const int code)); + +/* +** DKIM_NAME_TO_CODE -- translate a name to a mnemonic code +** +** Parameters: +** tbl -- name table +** name -- name to translate +** +** Return value: +** A mnemonic code matching the provided name, or -1 if not found. +*/ + +extern const int dkim_name_to_code __P((DKIM_NAMETABLE *tbl, + const char *name)); + +/* +** DKIM_NAMETABLE_FIRST -- get the first entry of the table and start iteration +** +** Parameters: +** tbl -- name table +** ctx -- iteration context (returned) +** name -- name in the first item in the table (returned) +** code -- code in the first item in the table (returned) +** +** Return value: +** A DKIM_STAT_OK -- retrieve the first item successfully +** A DKIM_STAT_ITER_EOT -- the table has no item. +** A DKIM_STAT_NORESOURCE -- cannot allocate memory for the +** iteration context +** +*/ +extern DKIM_STAT dkim_nametable_first __P((DKIM_NAMETABLE *tbl, + DKIM_ITER_CTX **ctx, + const char **name, int *code)); + +/* +** DKIM_NAMETABLE_NEXT -- get the next entry on the iteration the table +** +** Parameters: +** ctx -- iteration context (updated) +** name -- name in the first item in the table (returned) +** code -- code in the first item in the table (returned) +** +** Return value: +** A DKIM_STAT_OK -- retrieve the first item successfully +** A DKIM_STAT_ITER_EOT -- the table has no item. +** +*/ +extern DKIM_STAT dkim_nametable_next __P((DKIM_ITER_CTX *ctx, + const char **name, + int *code)); + +/* +** DKIM_ITER_CTX_FREE -- release resources associated with +** a nametable iteration context +** +** Parameters: +** ctx -- iteration context +** +** Return value: +** None. +** +*/ +extern DKIM_STAT dkim_iter_ctx_free __P((DKIM_ITER_CTX *ctx)); + #ifdef __cplusplus } diff --git a/libopendkim/docs/Makefile.am b/libopendkim/docs/Makefile.am index fe468e77..405e5967 100644 --- a/libopendkim/docs/Makefile.am +++ b/libopendkim/docs/Makefile.am @@ -12,6 +12,7 @@ dist_doc_DATA = dkim.html \ dkim_cbstat.html \ dkim_chunk.html \ dkim_close.html \ + dkim_code_to_name.html \ dkim_dns_close.html \ dkim_dns_config.html \ dkim_dns_init.html \ @@ -48,11 +49,17 @@ dist_doc_DATA = dkim.html \ dkim_getuser.html \ dkim_header.html \ dkim_init.html \ + dkim_iter_ctx.html \ + dkim_iter_ctx_free.html \ dkim_key_syntax.html \ dkim_lib.html \ dkim_libfeature.html \ dkim_libversion.html \ dkim_minbody.html \ + dkim_name_to_code.html \ + dkim_nametable.html \ + dkim_nametable_first.html \ + dkim_nametable_next.html \ dkim_ohdrs.html \ dkim_options.html \ dkim_param_t.html \ diff --git a/libopendkim/docs/dkim_code_to_name.html b/libopendkim/docs/dkim_code_to_name.html new file mode 100644 index 00000000..003c73b8 --- /dev/null +++ b/libopendkim/docs/dkim_code_to_name.html @@ -0,0 +1,79 @@ + +dkim_code_to_name() + + +

dkim_code_to_name()

+

[back to index]

+ + + + + + + + + + + + + + + + + + + + +
SYNOPSIS +
+#include <dkim.h>
+const char *dkim_code_to_name(
+	DKIM_NAMETABLE *tbl,
+	const int *code
+);
+
+Translate a mnemonic code to its name in C string. +
DESCRIPTION + + + + + +
Called Whendkim_code_to_name() can be called at any time.
+ + +
ARGUMENTS + + + + + + +
ArgumentDescription
tblA name table to use for translation. One of values described in + DKIM_NAMETABLE. +
codeA code to translate.
+
RETURN VALUES +
    +
  • Pointer to the name matching the provided code, if found +
  • NULL, if no maching is found +
+
NOTES +
    +
  • None. +
+
+ +
+ +Copyright (c) 2005, 2007 Sendmail, Inc. and its suppliers. +All rights reserved. +
+Copyright (c) 2009-2014, 2024 The Trusted Domain Project. All rights reserved. + +
+By using this file, you agree to the terms and conditions set +forth in the respective licenses. +
+ + diff --git a/libopendkim/docs/dkim_iter_ctx.html b/libopendkim/docs/dkim_iter_ctx.html new file mode 100644 index 00000000..79842d89 --- /dev/null +++ b/libopendkim/docs/dkim_iter_ctx.html @@ -0,0 +1,51 @@ + +DKIM_ITER_CTX + + +

DKIM_NAMETABLE_CTX

+

[back to index]

+ + + + + + + +
DESCRIPTION + + + + + +
PurposeA DKIM_ITER_CTX stores a context in a iteration + over a table (currently support DKIM_NAMETABLE only). + It is created by dkim_nametable_first() function and must be freed by the + caler by using dkim_iter_free() function. +
+ + +
NOTES + +
+ +
+ +Copyright (c) 2008 Sendmail, Inc. and its suppliers. +All rights reserved. +
+Copyright (c) 2009-2014, 2024, The Trusted Domain Project. +All rights reserved. + +
+By using this file, you agree to the terms and conditions set +forth in the respective licenses. +
+ + diff --git a/libopendkim/docs/dkim_iter_ctx_free.html b/libopendkim/docs/dkim_iter_ctx_free.html new file mode 100644 index 00000000..5332483b --- /dev/null +++ b/libopendkim/docs/dkim_iter_ctx_free.html @@ -0,0 +1,85 @@ + +dkim_iter_ctx_free() + + +

dkim_iter_ctx_free()

+

[back to index]

+ + + + + + + + + + + + + + + + + + + + + +
SYNOPSIS +
+#include <dkim.h>
+DKIM_STAT dkim_iter_ctx_free(
+	DKIM_ITER_CTX *ctx
+);
+
+Release resources associated with a nametable iteration context. +
DESCRIPTION + + + + + + + + + +
Called Whendkim_iter_ctx_free() must be passed a table iteration context + returned by + dkim_nametable_first()
EffectsReleases resources that were allocated and assigned to the context + ctx when it was returned by dkim_nametable_first(). + The context ctx may not be reused.
+ + +
ARGUMENTS + + + + +
ArgumentDescription
ctx A DKIM_ITER_CTX context returned by + a previous call to dkim_nametable_first(). +
+
RETURN VALUES +
    +
  • DKIM_STAT_OK -- operation was successful +
+ +
NOTES + +None. +
+ +
+ +Copyright (c) 2005, 2006 Sendmail, Inc. and its suppliers. +All rights reserved. +
+Copyright (c) 2009-2014, 2024 The Trusted Domain Project. All rights reserved. + +
+By using this file, you agree to the terms and conditions set +forth in the respective licenses. +
+ + diff --git a/libopendkim/docs/dkim_name_to_code.html b/libopendkim/docs/dkim_name_to_code.html new file mode 100644 index 00000000..d7ad7072 --- /dev/null +++ b/libopendkim/docs/dkim_name_to_code.html @@ -0,0 +1,79 @@ + +dkim_name_to_code() + + +

dkim_name_to_code()

+

[back to index]

+ + + + + + + + + + + + + + + + + + + + +
SYNOPSIS +
+#include <dkim.h>
+const int dkim_name_to_code(
+	DKIM_NAMETABLE *tbl,
+	const char *name
+);
+
+Translate a name text in C string into a mnemonic code. +
DESCRIPTION + + + + + +
Called Whendkim_name_to_code() can be called at any time.
+ + +
ARGUMENTS + + + + + + +
ArgumentDescription
tblA name table to use for translation. One of values described in + DKIM_NAMETABLE. +
codeA name C string to translate.
+
RETURN VALUES +
    +
  • A mnemonic code matching the provided name, if found +
  • -1, if no maching is found +
+
NOTES +
    +
  • None. +
+
+ +
+ +Copyright (c) 2005, 2007 Sendmail, Inc. and its suppliers. +All rights reserved. +
+Copyright (c) 2009-2014, 2024 The Trusted Domain Project. All rights reserved. + +
+By using this file, you agree to the terms and conditions set +forth in the respective licenses. +
+ + diff --git a/libopendkim/docs/dkim_nametable.html b/libopendkim/docs/dkim_nametable.html new file mode 100644 index 00000000..6a616fc0 --- /dev/null +++ b/libopendkim/docs/dkim_nametable.html @@ -0,0 +1,68 @@ + +DKIM_NAMETABLE + + +

DKIM_NAMETABLE

+

[back to index]

+ + + + +
DESCRIPTION + + + + + + + + +
PurposeA DKIM_NAMETABLE is a conversion table between an internal code + in libopendkim and its name text in C string. It is passed as + a parameter to the conversion functions + dkim_code_to_name() or + dkim_name_to_code(). + For the purpose to aquire all data in a table, there are functions + to allow us iteration on a table, + dkim_nametable_first(), + dkim_nametable_next(), and + dkim_iter_free(). +
Possible Values +
    +
  • dkim_table_algorithms -- a conversion table for + dkim_alg_t.
  • +
  • dkim_talbe_canonicalizations -- a conversion table for + dkim_canon_t.
  • +
  • dkim_table_keyflags -- a conversion table for + DKIM_SIGFLAG_* constants.
  • +
  • dkim_table_querytypes -- a conversion table for + DKIM_QUERY_* constants.
  • +
  • dkim_table_results -- a conversion table for + DKIM_STAT constants.
  • +
  • dkim_table_sigerrors -- a conversion table for + DKIM_SIGERROR constants.
  • +
  • dkim_table_sigparams -- a conversion table for + DKIM_PARAM_* constants.
  • +
+
+ +
+ +
+ +Copyright (c) 2008 Sendmail, Inc. and its suppliers. +All rights reserved. +
+Copyright (c) 2009-2014, 2024, The Trusted Domain Project. +All rights reserved. + +
+By using this file, you agree to the terms and conditions set +forth in the respective licenses. +
+ + diff --git a/libopendkim/docs/dkim_nametable_first.html b/libopendkim/docs/dkim_nametable_first.html new file mode 100644 index 00000000..8a850e4d --- /dev/null +++ b/libopendkim/docs/dkim_nametable_first.html @@ -0,0 +1,107 @@ + +dkim_nametable_first() + + +

dkim_nametable_first()

+

[back to index]

+ + + + + + + + + + + + + + + + + +
SYNOPSIS +
+#include <dkim.h>
+DKIM_STAT dkim_nametable_first(
+	DKIM_NAMETABLE *tbl,
+	DKIM_ITER_CTX **ctx,
+	const char **name,
+	int *code
+);
+
+Get the first entry from the table and start iteration. +
DESCRIPTION + + + + + +
Called Whendkim_nametable_first() can be called at any time.
+ + +
ARGUMENTS + + + + + + + + + + +
ArgumentDescription
tblA name table to use for iteration. One of values described in + DKIM_NAMETABLE. +
ctxPointer to a variable of type + (DKIM_ITER_CTX **) which will be set to + point to an iteration context of the table. +
namePointer to a variable of type (char **) which will be + set to point to the name in the first entry of the table. +
codePointer to a variable of type (int *) which will be + set to the mnemonic code in the first entry of the table. +
+
RETURN VALUES + + + + + + + + +
Return ValueDescription
DKIM_STAT_OKThe first entry of the table is retrieved successfully. +
DKIM_STAT_ITER_EOTThe iteration has reached to the end of the table, + i.e. the table has no item. + (name and code are not set) +
DKIM_STAT_NORESOURCEThe library was unable to create an iteration context. +
+
NOTES +
    +
  • Pointer arguments name and code would be set only if + DKIM_STAT_OK is returned. +
  • The iteration context *ctx would be set except + DKIM_STAT_NORESOURCE is returned. +
  • The iteration context *ctx should be released by the caller + by using dkim_iter_ctx_free() when the iteration is no + longer needed. +
+
+ +
+ +Copyright (c) 2005, 2007 Sendmail, Inc. and its suppliers. +All rights reserved. +
+Copyright (c) 2009-2014, 2024 The Trusted Domain Project. All rights reserved. + +
+By using this file, you agree to the terms and conditions set +forth in the respective licenses. +
+ + diff --git a/libopendkim/docs/dkim_nametable_next.html b/libopendkim/docs/dkim_nametable_next.html new file mode 100644 index 00000000..2b41a303 --- /dev/null +++ b/libopendkim/docs/dkim_nametable_next.html @@ -0,0 +1,96 @@ + +dkim_nametable_next() + + +

dkim_nametable_next()

+

[back to index]

+ + + + + + + + + + + + + + + + + +
SYNOPSIS +
+#include <dkim.h>
+DKIM_STAT dkim_nametable_next(
+	DKIM_ITER_CTX *ctx,
+	const char **name,
+	int *code
+);
+
+Get the next entry on the iteration over the table. +
DESCRIPTION + + + + +
Called Whendkim_nametable_next() can be called with valid +DKIM_ITER_CTX. +
+ + +
ARGUMENTS + + + + + + + + +
ArgumentDescription
ctxPointer to a valid + DKIM_ITER_CTX. +
namePointer to a variable of type (char **) which will be + set to point to the name in the next entry of the iteration conext. +
codePointer to a variable of type (int *) which will be + set to the mnemonic code in the next entry of the iteration context. +
+
RETURN VALUES + + + + + + +
Return ValueDescription
DKIM_STAT_OKThe next entry of the table is retrieved successfully. +
DKIM_STAT_ITER_EOTThe iteration has reached to the end of the table. + (name and code are not set) +
+
NOTES +
    +
  • Pointer arguments name and code would be set only if + DKIM_STAT_OK is returned. +
  • The iteration context ctx should be released by the caller + by using dkim_iter_ctx_free() when the iteration is no + longer needed. +
+
+ +
+ +Copyright (c) 2005, 2007 Sendmail, Inc. and its suppliers. +All rights reserved. +
+Copyright (c) 2009-2014, 2024 The Trusted Domain Project. All rights reserved. + +
+By using this file, you agree to the terms and conditions set +forth in the respective licenses. +
+ + diff --git a/libopendkim/docs/dkim_stat.html b/libopendkim/docs/dkim_stat.html index a447b2ec..4f786bda 100644 --- a/libopendkim/docs/dkim_stat.html +++ b/libopendkim/docs/dkim_stat.html @@ -35,6 +35,7 @@

DKIM_STAT

  • DKIM_STAT_CBREJECT -- callback requested message rejection
  • DKIM_STAT_CBTRYAGAIN -- callback can't complete (try again later)
  • DKIM_STAT_CBERROR -- unspecified callback error +
  • DKIM_STAT_ITER_EOT -- the table has no more item @@ -86,6 +87,8 @@

    DKIM_STAT

  • DKIM_STAT_CBERROR is returned when a library function used a user-provided callback function which returned DKIM_CBSTAT_ERROR, which indicates the callback failed +
  • DKIM_STAT_ITER_EOT is returned when the iteration on a table + has reached to the end of the table and the table has no more entry @@ -96,7 +99,7 @@

    DKIM_STAT

    Copyright (c) 2005-2007 Sendmail, Inc. and its suppliers. All rights reserved.
    -Copyright (c) 2009, 2010, 2013, 2014, The Trusted Domain Project. +Copyright (c) 2009, 2010, 2013, 2014, 2024, The Trusted Domain Project. All rights reserved.
    diff --git a/libopendkim/docs/index.html b/libopendkim/docs/index.html index 229d607a..bc0a4e1b 100644 --- a/libopendkim/docs/index.html +++ b/libopendkim/docs/index.html @@ -68,11 +68,24 @@

    Data Types

    Key record security evaluation codes. + + DKIM_ITER_CTX + + An iteration context over some table (currently, only support + DKIM_NAMETABLE). + + DKIM_LIB An instance of the libopendkim service. + + DKIM_NAMETABLE + Look up tables for conversion between mnemonic codes and its name + text as C strings + + dkim_param_t A signature parameter. @@ -515,6 +528,11 @@

    Functions

    Utility + + dkim_code_to_name() + Translate a mnemonic code to its name. + + dkim_getid() Retrieve "id" string from handle. @@ -532,6 +550,11 @@

    Functions

    signatures. + + dkim_iter_ctx_free() + Release resources associated with a DKIM_ITER_CTX context. + + dkim_key_syntax() Check the syntax of a key record. @@ -549,6 +572,21 @@

    Functions

    users and domains. + + dkim_name_to_code() + Translate a name to a mnemonic code. + + + + dkim_nametable_first() + Get first table item and start iteration. + + + + dkim_nametable_next() + Get next table item on the iteration. + + dkim_options() Get or set library options. diff --git a/libopendkim/tests/Makefile.am b/libopendkim/tests/Makefile.am index 293a9227..817eb2da 100644 --- a/libopendkim/tests/Makefile.am +++ b/libopendkim/tests/Makefile.am @@ -41,7 +41,7 @@ check_PROGRAMS = t-setup t-test00 t-test01 t-test02 t-test03 t-test04 \ t-test139 t-test140 t-test141 t-test142 t-test143 t-test144 \ t-test145 t-test146 t-test147 t-test148 t-test149 t-test150 \ t-test151 t-test152 t-test153 t-test154 t-test155 t-test156 \ - t-test157 t-test158 t-test159 \ + t-test157 t-test158 t-test159 t-test160\ t-signperf t-verifyperf check_SCRIPTS = t-signperf-sha1 t-signperf-relaxed-relaxed \ t-signperf-simple-simple @@ -219,6 +219,7 @@ t_test156_SOURCES = t-test156.c t-testdata.h t_test157_SOURCES = t-test157.c t-testdata.h t_test158_SOURCES = t-test158.c t-testdata.h t_test159_SOURCES = t-test159.c t-testdata.h +t_test160_SOURCES = t-test160.c t-testdata.h MOSTLYCLEANFILES= diff --git a/libopendkim/tests/t-test160.c b/libopendkim/tests/t-test160.c new file mode 100644 index 00000000..11df277e --- /dev/null +++ b/libopendkim/tests/t-test160.c @@ -0,0 +1,92 @@ +/* +** Copyright (c) 2005-2008 Sendmail, Inc. and its suppliers. +** All rights reserved. +** +** Copyright (c) 2010-2014,2024 The Trusted Domain Project. +** All rights reserved. +*/ + +#include "build-config.h" + +/* system includes */ +#include +#include +#include + +#ifdef USE_GNUTLS +# include +#endif /* USE_GNUTLS */ + +/* libopendkim includes */ +#include "../dkim.h" + +/* +** MAIN -- program mainline +** +** Parameters: +** The usual. +** +** Return value: +** Exit status. +*/ + +int +main(int argc, char **argv) +{ + DKIM_STAT status; + DKIM_ITER_CTX *ctx; + const char *name_iter; + int code_iter; + const char *name_lookup; + int code_lookup; + + printf("*** testing DKIM_NAMETABLE routines\n"); + + /* assuming dkim_table_canonicalizations had only 2 entries */ + status = dkim_nametable_first(dkim_table_canonicalizations, + &ctx, &name_iter, &code_iter); + + assert(status == DKIM_STAT_OK); + + code_lookup = dkim_name_to_code(dkim_table_canonicalizations, + name_iter); + + assert(code_lookup == code_iter); + + name_lookup = dkim_code_to_name(dkim_table_canonicalizations, + code_iter); + + assert(name_lookup == name_iter); + + status = dkim_nametable_next(ctx, &name_iter, &code_iter); + + assert(status == DKIM_STAT_OK); + + code_lookup = dkim_name_to_code(dkim_table_canonicalizations, + name_iter); + + assert(code_lookup == code_iter); + + name_lookup = dkim_code_to_name(dkim_table_canonicalizations, + code_iter); + + assert(name_lookup == name_iter); + + status = dkim_nametable_next(ctx, &name_iter, &code_iter); + + assert(status == DKIM_STAT_ITER_EOT); + assert(code_lookup == code_iter); + assert(name_lookup == name_iter); + + status = dkim_nametable_next(ctx, &name_iter, &code_iter); + + assert(status == DKIM_STAT_ITER_EOT); + assert(code_lookup == code_iter); + assert(name_lookup == name_iter); + + status = dkim_iter_ctx_free(ctx); + + assert(status == DKIM_STAT_OK); + + return 0; +} diff --git a/libopendkim/tests/t-verifyperf.c b/libopendkim/tests/t-verifyperf.c index a9e7a340..3a7a023f 100644 --- a/libopendkim/tests/t-verifyperf.c +++ b/libopendkim/tests/t-verifyperf.c @@ -23,7 +23,6 @@ /* libopendkim includes */ #include "../dkim.h" -#include "../dkim-tables.h" #include "t-testdata.h" #define DEFMSGSIZE 1024 diff --git a/opendkim/opendkim-atpszone.c b/opendkim/opendkim-atpszone.c index 02276ed0..e29555a3 100644 --- a/opendkim/opendkim-atpszone.c +++ b/opendkim/opendkim-atpszone.c @@ -144,11 +144,6 @@ main(int argc, char **argv) DKIMF_DB db; #ifdef USE_GNUTLS gnutls_hash_hd_t sha; -#else /* USE_GNUTLS */ - SHA_CTX sha; -# ifdef HAVE_SHA256 - SHA256_CTX sha256; -# endif /* HAVE_SHA256 */ #endif /* USE_GNUTLS */ char domain[DKIM_MAXHOSTNAMELEN + 1]; char hostname[DKIM_MAXHOSTNAMELEN + 1]; @@ -443,20 +438,19 @@ main(int argc, char **argv) # ifdef HAVE_SHA256 if (hash == NULL || strcasecmp(hash, "sha256") == 0) { - SHA256_Init(&sha256); - SHA256_Update(&sha256, domain, strlen(domain)); - SHA256_Final(shaout, &sha256); + (void) EVP_Digest(domain, strlen(domain), + shaout, NULL, EVP_sha256(), + NULL); } else { - SHA1_Init(&sha); - SHA1_Update(&sha, domain, strlen(domain)); - SHA1_Final(shaout, &sha); + (void) EVP_Digest(domain, strlen(domain), + shaout, NULL, EVP_sha1(), + NULL); } # else /* HAVE_SHA256 */ - SHA1_Init(&sha); - SHA1_Update(&sha, domain, strlen(domain)); - SHA1_Final(shaout, &sha); + (void) EVP_Digest(domain, strlen(domain), shaout, NULL, + EVP_sha1(), NULL); # endif /* HAVE_SHA256 */ #endif /* USE_GNUTLS */ diff --git a/opendkim/opendkim-genzone.c b/opendkim/opendkim-genzone.c index e1c53d53..48c9523b 100644 --- a/opendkim/opendkim-genzone.c +++ b/opendkim/opendkim-genzone.c @@ -26,7 +26,6 @@ # include # include #else /* USE_GNUTLS */ -# include # include # include # include @@ -264,7 +263,6 @@ main(int argc, char **argv) BIO *private; BIO *outbio = NULL; EVP_PKEY *pkey; - RSA *rsa; #endif /* USE_GNUTLS */ DKIMF_DB db; char keyname[BUFRSZ + 1]; @@ -837,12 +835,9 @@ main(int argc, char **argv) } } - rsa = EVP_PKEY_get1_RSA(pkey); - if (rsa == NULL) + if (EVP_PKEY_base_id(pkey) != EVP_PKEY_RSA) { - fprintf(stderr, - "%s: EVP_PKEY_get1_RSA() failed\n", - progname); + fprintf(stderr, "%s: not an RSA key\n", progname); (void) dkimf_db_close(db); (void) BIO_free(private); (void) EVP_PKEY_free(pkey); @@ -851,11 +846,11 @@ main(int argc, char **argv) } /* convert private to public */ - status = PEM_write_bio_RSA_PUBKEY(outbio, rsa); + status = PEM_write_bio_PUBKEY(outbio, pkey); if (status == 0) { fprintf(stderr, - "%s: PEM_write_bio_RSA_PUBKEY() failed\n", + "%s: PEM_write_bio_PUBKEY() failed\n", progname); (void) dkimf_db_close(db); (void) BIO_free(private); diff --git a/opendkim/opendkim-testkey.c b/opendkim/opendkim-testkey.c index fc1df4af..6be9bd08 100644 --- a/opendkim/opendkim-testkey.c +++ b/opendkim/opendkim-testkey.c @@ -236,6 +236,9 @@ main(int argc, char **argv) char domain[BUFRSZ]; char selector[BUFRSZ]; char keypath[MAXBUFRSZ]; + char signalgstr[BUFRSZ]; + dkim_alg_t default_signalg; + dkim_alg_t signalg; progname = (p = strrchr(argv[0], '/')) == NULL ? argv[0] : p + 1; @@ -342,6 +345,26 @@ main(int argc, char **argv) strlcpy(keypath, p, sizeof keypath); } + p = NULL; + (void) config_get(cfg, "SignatureAlgorithm", &p, sizeof p); + if (p != NULL) + { + default_signalg = (dkim_alg_t) + dkim_name_to_code(dkim_table_algorithms, + p); + if (default_signalg == -1) + { + fprintf(stderr, + "%s: %s: Unknown SignatureAlgorithm %s\n", + progname, path, p); + return EX_CONFIG; + } + } + else + { + default_signalg = DKIM_SIGN_RSASHA256; + } + #ifdef USE_LDAP (void) config_get(cfg, "LDAPUseTLS", &ldap_usetls, sizeof ldap_usetls); @@ -464,7 +487,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); @@ -491,6 +514,7 @@ 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; @@ -498,11 +522,14 @@ main(int argc, char **argv) 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, @@ -524,6 +551,31 @@ 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); + } + } + else + { + signalg = default_signalg; + } + if (keypath[0] == '/' || strncmp(keypath, "./", 2) == 0 || strncmp(keypath, "../", 3) == 0) @@ -574,9 +626,9 @@ main(int argc, char **argv) dnssec = DKIM_DNSSEC_UNKNOWN; - status = dkim_test_key(lib, selector, domain, - keypath, keylen, &dnssec, - err, sizeof err); + status = dkim_test_key2(lib, selector, domain, + keypath, keylen, signalg, + &dnssec, err, sizeof err); switch (status) { diff --git a/opendkim/opendkim.c b/opendkim/opendkim.c index 803f37b0..2ac108af 100644 --- a/opendkim/opendkim.c +++ b/opendkim/opendkim.c @@ -622,21 +622,6 @@ struct lookup dkimf_values[] = { NULL, -1 }, }; -struct lookup dkimf_canon[] = -{ - { "relaxed", DKIM_CANON_RELAXED }, - { "simple", DKIM_CANON_SIMPLE }, - { NULL, -1 }, -}; - -struct lookup dkimf_sign[] = -{ - { "rsa-sha1", DKIM_SIGN_RSASHA1 }, - { "rsa-sha256", DKIM_SIGN_RSASHA256 }, - { "ed25519-sha256", DKIM_SIGN_ED25519SHA256 }, - { NULL, -1 }, -}; - struct lookup dkimf_atpshash[] = { #ifdef HAVE_SHA256 @@ -4934,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); @@ -4963,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; @@ -4973,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); @@ -5079,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); @@ -5091,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 @@ -7697,8 +7707,8 @@ dkimf_config_load(struct config *data, struct dkimf_config *conf, if (conf->conf_signalgstr != NULL) { - conf->conf_signalg = dkimf_lookup_strtoint(conf->conf_signalgstr, - dkimf_sign); + conf->conf_signalg = dkim_name_to_code(dkim_table_algorithms, + conf->conf_signalgstr); if (conf->conf_signalg == -1) { snprintf(err, errlen, @@ -7719,8 +7729,8 @@ dkimf_config_load(struct config *data, struct dkimf_config *conf, p = strchr(conf->conf_canonstr, '/'); if (p == NULL) { - conf->conf_hdrcanon = dkimf_lookup_strtoint(conf->conf_canonstr, - dkimf_canon); + conf->conf_hdrcanon = dkim_name_to_code(dkim_table_canonicalizations, + conf->conf_canonstr); if (conf->conf_hdrcanon == -1) { snprintf(err, errlen, @@ -7735,8 +7745,8 @@ dkimf_config_load(struct config *data, struct dkimf_config *conf, { *p = '\0'; - conf->conf_hdrcanon = dkimf_lookup_strtoint(conf->conf_canonstr, - dkimf_canon); + conf->conf_hdrcanon = dkim_name_to_code(dkim_table_canonicalizations, + conf->conf_canonstr); if (conf->conf_hdrcanon == -1) { snprintf(err, errlen, @@ -7745,8 +7755,8 @@ dkimf_config_load(struct config *data, struct dkimf_config *conf, return -1; } - conf->conf_bodycanon = dkimf_lookup_strtoint(p + 1, - dkimf_canon); + conf->conf_bodycanon = dkim_name_to_code(dkim_table_canonicalizations, + p + 1); if (conf->conf_bodycanon == -1) { snprintf(err, errlen, @@ -8327,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; @@ -8359,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 || @@ -11718,10 +11732,10 @@ mlfi_header(SMFICTX *ctx, char *headerf, char *headerv) { *slash = '\0'; - c = dkimf_lookup_strtoint(headerv, dkimf_canon); + c = dkim_name_to_code(dkim_table_canonicalizations, headerv); if (c != -1) dfc->mctx_hdrcanon = (dkim_canon_t) c; - c = dkimf_lookup_strtoint(slash + 1, dkimf_canon); + c = dkim_name_to_code(dkim_table_canonicalizations, slash + 1); if (c != -1) dfc->mctx_bodycanon = (dkim_canon_t) c; @@ -11729,7 +11743,7 @@ mlfi_header(SMFICTX *ctx, char *headerf, char *headerv) } else { - c = dkimf_lookup_strtoint(headerv, dkimf_canon); + c = dkim_name_to_code(dkim_table_canonicalizations, headerv); if (c != -1) dfc->mctx_hdrcanon = (dkim_canon_t) c; } @@ -12619,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; @@ -12645,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) @@ -15544,6 +15561,10 @@ main(int argc, char **argv) char *end; char argstr[MAXARGV]; char err[BUFRSZ + 1]; + DKIM_STAT dkim_stat; + DKIM_ITER_CTX *iter_ctx; + int entry_code; + char *entry_name; /* initialize */ reload = FALSE; @@ -15771,17 +15792,55 @@ main(int argc, char **argv) printf("\tlibmilter version %d.%d.%d\n", mvmajor, mvminor, mvrelease); #endif /* HAVE_SMFI_VERSION */ + dkim_stat = dkim_nametable_first(dkim_table_algorithms, + &iter_ctx, &entry_name, + &entry_code); printf("\tSupported signing algorithms:\n"); - for (c = 0; dkimf_sign[c].str != NULL; c++) + if (dkim_stat == DKIM_STAT_NORESOURCE) + { + printf("\twarn: list of algorithms is not " + "available\n"); + } + else { - if (dkimf_sign[c].code != DKIM_SIGN_RSASHA256 || - dkim_libfeature(curconf->conf_libopendkim, - DKIM_FEATURE_SHA256)) - printf("\t\t%s\n", dkimf_sign[c].str); + while(dkim_stat == DKIM_STAT_OK) + { + if (entry_code != DKIM_SIGN_RSASHA256 || + dkim_libfeature(curconf->conf_libopendkim, + DKIM_FEATURE_SHA256)) + { + printf("\t\t%s\n", entry_name); + } + dkim_stat = dkim_nametable_next(iter_ctx, + &entry_name, + &entry_code); + } + dkim_stat = dkim_iter_ctx_free(iter_ctx); + /* we can do nothing eveif dkim_stat is not + DKIM_STAT_OK ... */ } printf("\tSupported canonicalization algorithms:\n"); - for (c = 0; dkimf_canon[c].str != NULL; c++) - printf("\t\t%s\n", dkimf_canon[c].str); + dkim_stat = dkim_nametable_first(dkim_table_canonicalizations, + &iter_ctx, &entry_name, + &entry_code); + if (dkim_stat == DKIM_STAT_NORESOURCE) + { + printf("\twarn: list of canonicalizations " + "is not available\n"); + } + else + { + while(dkim_stat == DKIM_STAT_OK) + { + printf("\t\t%s\n", entry_name); + dkim_stat = dkim_nametable_next(iter_ctx, + &entry_name, + &entry_code); + } + dkim_stat = dkim_iter_ctx_free(iter_ctx); + /* we can do nothing eveif dkim_stat is not + DKIM_STAT_OK ... */ + } dkimf_optlist(stdout); return EX_OK; diff --git a/opendkim/opendkim.conf.5.in b/opendkim/opendkim.conf.5.in index 21da18f5..0bd6f0f1 100644 --- a/opendkim/opendkim.conf.5.in +++ b/opendkim/opendkim.conf.5.in @@ -349,7 +349,8 @@ 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. @@ -357,7 +358,13 @@ 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. diff --git a/opendkim/opendkim.h b/opendkim/opendkim.h index e3637b10..437ec946 100644 --- a/opendkim/opendkim.h +++ b/opendkim/opendkim.h @@ -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; };