/*
* PDKIM - a RFC4871 (DKIM) implementation
*
- * Copyright (C) 2009 - 2015 Tom Kistner <tom@duncanthrax.net>
+ * Copyright (C) 2009 - 2016 Tom Kistner <tom@duncanthrax.net>
+ * Copyright (C) 2016 Jeremy Harris <jgh@exim.org>
*
* http://duncanthrax.net/pdkim/
*
*/
#include "../exim.h"
-#include "pdkim.h"
-#include "pdkim-rsa.h"
-#include "polarssl/sha1.h"
-#include "polarssl/sha2.h"
-#include "polarssl/rsa.h"
+
+#ifndef DISABLE_DKIM /* entire file */
+
+#ifndef SUPPORT_TLS
+# error Need SUPPORT_TLS for DKIM
+#endif
+
+
+#ifdef USE_GNUTLS
+# include <gnutls/gnutls.h>
+# include <gnutls/x509.h>
+# include <gnutls/abstract.h>
+# include <gnutls/crypto.h>
+#else
+# include <openssl/rsa.h>
+# include <openssl/ssl.h>
+# include <openssl/err.h>
+#endif
+
+#include "pdkim.h"
#define PDKIM_SIGNATURE_VERSION "1"
#define PDKIM_PUB_RECORD_VERSION "DKIM1"
int canon_headers;
int canon_body;
} pdkim_combined_canon_entry;
+
pdkim_combined_canon_entry pdkim_combined_canons[] = {
{ "simple/simple", PDKIM_CANON_SIMPLE, PDKIM_CANON_SIMPLE },
{ "simple/relaxed", PDKIM_CANON_SIMPLE, PDKIM_CANON_RELAXED },
};
-const char *pdkim_verify_status_str(int status) {
+/* -------------------------------------------------------------------------- */
+
+const char *
+pdkim_verify_status_str(int status)
+{
switch(status) {
case PDKIM_VERIFY_NONE: return "PDKIM_VERIFY_NONE";
case PDKIM_VERIFY_INVALID: return "PDKIM_VERIFY_INVALID";
default: return "PDKIM_VERIFY_UNKNOWN";
}
}
-const char *pdkim_verify_ext_status_str(int ext_status) {
+
+const char *
+pdkim_verify_ext_status_str(int ext_status)
+{
switch(ext_status) {
case PDKIM_VERIFY_FAIL_BODY: return "PDKIM_VERIFY_FAIL_BODY";
case PDKIM_VERIFY_FAIL_MESSAGE: return "PDKIM_VERIFY_FAIL_MESSAGE";
}
-/* -------------------------------------------------------------------------- */
-/* Simple string list implementation for convinience */
-pdkim_stringlist *
-pdkim_append_stringlist(pdkim_stringlist *base, char *str)
+
+/* String package: should be replaced by Exim standard ones */
+
+static pdkim_stringlist *
+pdkim_prepend_stringlist(pdkim_stringlist *base, char *str)
{
pdkim_stringlist *new_entry = malloc(sizeof(pdkim_stringlist));
return new_entry;
}
-pdkim_stringlist *
-pdkim_prepend_stringlist(pdkim_stringlist *base, char *str)
-{
-pdkim_stringlist *new_entry = malloc(sizeof(pdkim_stringlist));
-
-if (!new_entry) return NULL;
-memset(new_entry, 0, sizeof(pdkim_stringlist));
-if (!(new_entry->value = strdup(str))) return NULL;
-if (base)
- new_entry->next = base;
-return new_entry;
-}
-
/* -------------------------------------------------------------------------- */
/* A small "growing string" implementation to escape malloc/realloc hell */
-pdkim_str *
+static pdkim_str *
pdkim_strnew (const char *cstr)
{
unsigned int len = cstr ? strlen(cstr) : 0;
return p;
}
-char *
+static char *
pdkim_strncat(pdkim_str *str, const char *data, int len)
{
if ((str->allocated - str->len) < (len+1))
return str->str;
}
-char *
+static char *
pdkim_strcat(pdkim_str *str, const char *cstr)
{
return pdkim_strncat(str, cstr, strlen(cstr));
}
-char *
-pdkim_numcat(pdkim_str *str, unsigned long num)
-{
-char minibuf[20];
-snprintf(minibuf, 20, "%lu", num);
-return pdkim_strcat(str, minibuf);
-}
-
-char *
+static char *
pdkim_strtrim(pdkim_str *str)
{
char *p = str->str;
return str->str;
}
-char *
+static char *
pdkim_strclear(pdkim_str *str)
{
str->str[0] = '\0';
return str->str;
}
-void
+static void
pdkim_strfree(pdkim_str *str)
{
if (!str) return;
/* -------------------------------------------------------------------------- */
-void
+static void
pdkim_free_pubkey(pdkim_pubkey *pub)
{
if (pub)
/* -------------------------------------------------------------------------- */
-void
+static void
pdkim_free_sig(pdkim_signature *sig)
{
if (sig)
free(c);
}
-/* if (sig->sigdata ) free(sig->sigdata); */
-/* if (sig->bodyhash ) free(sig->bodyhash); */
if (sig->selector ) free(sig->selector);
if (sig->domain ) free(sig->domain);
if (sig->identity ) free(sig->identity);
if (sig->rsa_privkey ) free(sig->rsa_privkey);
if (sig->sign_headers ) free(sig->sign_headers);
if (sig->signature_header) free(sig->signature_header);
- if (sig->sha1_body ) free(sig->sha1_body);
- if (sig->sha2_body ) free(sig->sha2_body);
if (sig->pubkey) pdkim_free_pubkey(sig->pubkey);
"start". Returns the position of the header name in
the list. */
-int
+static int
header_name_match(const char *header,
char *tick,
int do_tick)
/* Performs "relaxed" canonicalization of a header. The returned pointer needs
to be free()d. */
-char *
+static char *
pdkim_relax_header (char *header, int crlf)
{
BOOL past_field_name = FALSE;
/* -------------------------------------------------------------------------- */
-char *
+static char *
pdkim_decode_qp(char *str)
{
int nchar = 0;
/* -------------------------------------------------------------------------- */
-char *
+static char *
pdkim_decode_base64(char *str, int *num_decoded)
{
int dlen = 0;
/* -------------------------------------------------------------------------- */
-char *
+static char *
pdkim_encode_base64(char *str, int num)
{
char * ret;
#define PDKIM_HDR_TAG 1
#define PDKIM_HDR_VALUE 2
-pdkim_signature *
+static pdkim_signature *
pdkim_parse_sig_header(pdkim_ctx *ctx, char *raw_hdr)
{
pdkim_signature *sig ;
"PDKIM <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<\n");
}
-if ( !(sig->sha1_body = malloc(sizeof(sha1_context)))
- || !(sig->sha2_body = malloc(sizeof(sha2_context)))
- )
- {
- pdkim_free_sig(sig);
- return NULL;
- }
+#ifdef USE_GNUTLS
+gnutls_hash_init(&sig->sha_body,
+ sig->algo == PDKIM_ALGO_RSA_SHA1 ? GNUTLS_DIG_SHA1 : GNUTLS_DIG_SHA256);
-sha1_starts(sig->sha1_body);
-sha2_starts(sig->sha2_body, 0);
+#else
+SHA1_Init (&sig->sha1_body);
+SHA256_Init(&sig->sha2_body);
+#endif
return sig;
}
/* -------------------------------------------------------------------------- */
-pdkim_pubkey *
+static pdkim_pubkey *
pdkim_parse_pubkey_record(pdkim_ctx *ctx, char *raw_record)
{
pdkim_pubkey *pub;
/* -------------------------------------------------------------------------- */
-int
+static int
pdkim_update_bodyhash(pdkim_ctx *ctx, const char *data, int len)
{
pdkim_signature *sig = ctx->sig;
if (canon_len > 0)
{
+#ifdef USE_GNUTLS
+ gnutls_hash(sig->sha_body, canon_data, canon_len);
+#else
if (sig->algo == PDKIM_ALGO_RSA_SHA1)
- sha1_update(sig->sha1_body, (unsigned char *)canon_data, canon_len);
+ SHA1_Update (&sig->sha1_body, canon_data, canon_len);
else
- sha2_update(sig->sha2_body, (unsigned char *)canon_data, canon_len);
+ SHA256_Update(&sig->sha2_body, canon_data, canon_len);
+#endif
sig->signed_body_bytes += canon_len;
DEBUG(D_acl) pdkim_quoteprint(canon_data, canon_len, 1);
/* -------------------------------------------------------------------------- */
-int
+static int
pdkim_finish_bodyhash(pdkim_ctx *ctx)
{
pdkim_signature *sig;
/* Traverse all signatures */
for (sig = ctx->sig; sig; sig = sig->next)
{ /* Finish hashes */
- unsigned char bh[32]; /* SHA-256 = 32 Bytes, SHA-1 = 20 Bytes */
+ uschar bh[32]; /* SHA-256 = 32 Bytes, SHA-1 = 20 Bytes */
+#ifdef USE_GNUTLS
+ gnutls_hash_output(sig->sha_body, bh);
+#else
if (sig->algo == PDKIM_ALGO_RSA_SHA1)
- sha1_finish(sig->sha1_body, bh);
+ SHA1_Final (bh, &sig->sha1_body);
else
- sha2_finish(sig->sha2_body, bh);
+ SHA256_Final(bh, &sig->sha2_body);
+#endif
DEBUG(D_acl)
{
/* SIGNING -------------------------------------------------------------- */
if (ctx->mode == PDKIM_MODE_SIGN)
{
- sig->bodyhash_len = (sig->algo == PDKIM_ALGO_RSA_SHA1)?20:32;
-
+ sig->bodyhash_len = sig->algo == PDKIM_ALGO_RSA_SHA1 ? 20:32;
sig->bodyhash = string_copyn(US bh, sig->bodyhash_len);
/* If bodylength limit is set, and we have received less bytes
/* Callback from pdkim_feed below for processing complete headers */
#define DKIM_SIGNATURE_HEADERNAME "DKIM-Signature:"
-int
+static int
pdkim_header_complete(pdkim_ctx *ctx)
{
/* Special case: The last header can have an extra \r appended */
* "pad"
*
* no guarantees are made for output given out-of range input. like tag
- * names loinger than 78, or bogus col. Input is assumed to be free of line breaks.
+ * names longer than 78, or bogus col. Input is assumed to be free of line breaks.
*/
static char *
/* -------------------------------------------------------------------------- */
-char *
+static char *
pdkim_create_header(pdkim_signature *sig, int final)
{
char *rc = NULL;
while (sig)
{
- sha1_context sha1_headers;
- sha2_context sha2_headers;
+#ifdef USE_GNUTLS
+ gnutls_hash_hd_t sha_headers;
+ uschar * hdata = NULL;
+ int hdata_alloc = 0;
+ int hdata_size = 0;
+#else
+ SHA_CTX sha1_headers;
+ SHA256_CTX sha2_headers;
+#endif
char *sig_hdr;
char headerhash[32];
+#ifdef USE_GNUTLS
+ gnutls_hash_init(&sha_headers,
+ sig->algo == PDKIM_ALGO_RSA_SHA1 ? GNUTLS_DIG_SHA1 : GNUTLS_DIG_SHA256);
+#else
if (sig->algo == PDKIM_ALGO_RSA_SHA1)
- sha1_starts(&sha1_headers);
+ SHA1_Init(&sha1_headers);
else
- sha2_starts(&sha2_headers, 0);
+ SHA256_Init(&sha2_headers);
+#endif
DEBUG(D_acl) debug_printf(
"PDKIM >> Hashed header data, canonicalized, in sequence >>>>>>>>>>>>>>\n");
return PDKIM_ERR_OOM;
/* Feed header to the hash algorithm */
+#ifdef USE_GNUTLS
+ gnutls_hash(sha_headers, rh, strlen(rh));
+#else
if (sig->algo == PDKIM_ALGO_RSA_SHA1)
- sha1_update(&(sha1_headers), (unsigned char *)rh, strlen(rh));
+ SHA1_Update (&sha1_headers, rh, strlen(rh));
else
- sha2_update(&(sha2_headers), (unsigned char *)rh, strlen(rh));
+ SHA256_Update(&sha2_headers, rh, strlen(rh));
+#endif
+
+#ifdef USE_GNUTLS
+ /* Remember headers block for signing */
+ hdata = string_append(hdata, &hdata_alloc, &hdata_size, 1, rh);
+#endif
DEBUG(D_acl) pdkim_quoteprint(rh, strlen(rh), 1);
free(rh);
return PDKIM_ERR_OOM;
/* Feed header to the hash algorithm */
+#ifdef USE_GNUTLS
+ gnutls_hash(sha_headers, rh, strlen(rh));
+#else
if (sig->algo == PDKIM_ALGO_RSA_SHA1)
- sha1_update(&sha1_headers, (unsigned char *)rh, strlen(rh));
+ SHA1_Update (&sha1_headers, rh, strlen(rh));
else
- sha2_update(&sha2_headers, (unsigned char *)rh, strlen(rh));
+ SHA256_Update(&sha2_headers, rh, strlen(rh));
+#endif
DEBUG(D_acl) pdkim_quoteprint(rh, strlen(rh), 1);
free(rh);
}
/* Finalize header hash */
+#ifdef USE_GNUTLS
+ gnutls_hash(sha_headers, sig_hdr, strlen(sig_hdr));
+ gnutls_hash_output(sha_headers, headerhash);
+#else
if (sig->algo == PDKIM_ALGO_RSA_SHA1)
{
- sha1_update(&sha1_headers, (unsigned char *)sig_hdr, strlen(sig_hdr));
- sha1_finish(&sha1_headers, (unsigned char *)headerhash);
-
- DEBUG(D_acl)
- {
- debug_printf( "PDKIM [%s] hh computed: ", sig->domain);
- pdkim_hexprint(headerhash, 20, 1);
- }
+ SHA1_Update(&sha1_headers, sig_hdr, strlen(sig_hdr));
+ SHA1_Final(US headerhash, &sha1_headers);
}
else
{
- sha2_update(&sha2_headers, (unsigned char *)sig_hdr, strlen(sig_hdr));
- sha2_finish(&sha2_headers, (unsigned char *)headerhash);
+ SHA256_Update(&sha2_headers, sig_hdr, strlen(sig_hdr));
+ SHA256_Final(US headerhash, &sha2_headers);
+ }
+#endif
- DEBUG(D_acl)
- {
- debug_printf("PDKIM [%s] hh computed: ", sig->domain);
- pdkim_hexprint(headerhash, 32, 1);
- }
+ DEBUG(D_acl)
+ {
+ debug_printf("PDKIM [%s] hh computed: ", sig->domain);
+ pdkim_hexprint(headerhash, sig->algo == PDKIM_ALGO_RSA_SHA1 ? 20:32, 1);
}
+#ifdef USE_GNUTLS
+ if (ctx->mode == PDKIM_MODE_SIGN)
+ hdata = string_append(hdata, &hdata_alloc, &hdata_size, 1, sig_hdr);
+#endif
+
free(sig_hdr);
/* SIGNING ---------------------------------------------------------------- */
if (ctx->mode == PDKIM_MODE_SIGN)
{
- rsa_context rsa;
-int perr;
+#ifdef USE_GNUTLS
+ gnutls_x509_privkey_t rsa;
+ gnutls_datum_t k;
+ int rc;
+ size_t sigsize;
+#else
+ RSA * rsa;
+ uschar * p, * q;
+ int len;
+#endif
+
+ /* Import private key */
+#ifdef USE_GNUTLS
+
+ k.data = sig->rsa_privkey;
+ k.size = strlen(sig->rsa_privkey);
+ if ( (rc = gnutls_x509_privkey_init(&rsa)) != GNUTLS_E_SUCCESS
+ || (rc = gnutls_x509_privkey_import2(rsa, &k,
+ GNUTLS_X509_FMT_PEM, NULL, GNUTLS_PKCS_PLAIN)) != GNUTLS_E_SUCCESS
+ )
+ {
+ DEBUG(D_acl) debug_printf("gnutls_x509_privkey_import2: %s\n",
+ gnutls_strerror(rc));
+ return PDKIM_ERR_RSA_PRIVKEY;
+ }
- rsa_init(&rsa, RSA_PKCS_V15, 0);
+#else
- /* Perform private key operation */
- if ((perr = rsa_parse_key(&rsa, (unsigned char *)sig->rsa_privkey,
- strlen(sig->rsa_privkey), NULL, 0)) != 0)
-{
-debug_printf("rsa_parse_key: perr 0x%x\n", perr);
+ if ( !(p = Ustrstr(sig->rsa_privkey, "-----BEGIN RSA PRIVATE KEY-----"))
+ || !(q = Ustrstr(p+=31, "-----END RSA PRIVATE KEY-----"))
+ )
return PDKIM_ERR_RSA_PRIVKEY;
-}
+ *q = '\0';
+ if ( (len = b64decode(p, &p)) < 0
+ || !(rsa = d2i_RSAPrivateKey(NULL, CUSS &p, len))
+ )
+ /*XXX todo: get errstring from library */
+ return PDKIM_ERR_RSA_PRIVKEY;
+
+#endif
+
+
+ /* Allocate mem for signature */
+#ifdef USE_GNUTLS
+ k.data = hdata;
+ k.size = hdata_size;
+ (void) gnutls_x509_privkey_sign_data(rsa,
+ sig->algo == PDKIM_ALGO_RSA_SHA1 ? GNUTLS_DIG_SHA1 : GNUTLS_DIG_SHA256,
+ 0, &k, NULL, &sigsize);
+ sig->sigdata = store_get(sig->sigdata_len = sigsize);
+#else
+ sig->sigdata = store_get(RSA_size(rsa));
+#endif
+
+ /* Do signing */
+#ifdef USE_GNUTLS
- sig->sigdata_len = mpi_size(&(rsa.N));
- sig->sigdata = store_get(sig->sigdata_len);
+ if ((rc = gnutls_x509_privkey_sign_data(rsa,
+ sig->algo == PDKIM_ALGO_RSA_SHA1 ? GNUTLS_DIG_SHA1 : GNUTLS_DIG_SHA256,
+ 0, &k, sig->sigdata, &sigsize)) != GNUTLS_E_SUCCESS
+ )
+ {
+ DEBUG(D_acl) debug_printf("gnutls_x509_privkey_sign_data: %s\n",
+ gnutls_strerror(rc));
+ return PDKIM_ERR_RSA_SIGNING;
+ }
+ gnutls_x509_privkey_deinit(rsa);
+
+#else
- if (rsa_pkcs1_sign( &rsa, RSA_PRIVATE,
- ((sig->algo == PDKIM_ALGO_RSA_SHA1)?
- SIG_RSA_SHA1:SIG_RSA_SHA256),
- 0,
- (unsigned char *)headerhash,
- (unsigned char *)sig->sigdata ) != 0)
+ if (RSA_sign(sig->algo == PDKIM_ALGO_RSA_SHA1 ? NID_sha1 : NID_sha256,
+ CUS headerhash, sig->algo == PDKIM_ALGO_RSA_SHA1 ? 20 : 32,
+ US sig->sigdata, (unsigned int *)&sig->sigdata_len,
+ rsa) != 1)
return PDKIM_ERR_RSA_SIGNING;
+ RSA_free(rsa);
+
+#endif
- rsa_free(&rsa);
DEBUG(D_acl)
{
/* VERIFICATION ----------------------------------------------------------- */
else
{
- rsa_context rsa;
+#ifdef USE_GNUTLS
+ gnutls_pubkey_t rsa;
+ gnutls_datum_t k, s;
+ int rc;
+#else
+ RSA * rsa;
+ const unsigned char * p;
+#endif
char *dns_txt_name, *dns_txt_reply;
- rsa_init(&rsa, RSA_PKCS_V15, 0);
+#ifdef USE_GNUTLS
+ gnutls_pubkey_init(&rsa);
+#endif
+
+ /* Fetch public key for signing domain, from DNS */
if (!(dns_txt_name = malloc(PDKIM_DNS_TXT_MAX_NAMELEN)))
return PDKIM_ERR_OOM;
DEBUG(D_acl) debug_printf(
"PDKIM <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<\n");
- if (rsa_parse_public_key(&rsa,
- (unsigned char *)sig->pubkey->key,
- sig->pubkey->key_len) != 0)
+ /* Import public key */
+#ifdef USE_GNUTLS
+
+ k.data = sig->pubkey->key;
+ k.size = sig->pubkey->key_len;
+ if ((rc = gnutls_pubkey_import(rsa, &k, GNUTLS_X509_FMT_DER))
+ != GNUTLS_E_SUCCESS)
+
+#else
+
+ p = CUS sig->pubkey->key;
+ if (!(rsa = d2i_RSA_PUBKEY(NULL, &p, (long) sig->pubkey->key_len)))
+
+#endif
{
+ DEBUG(D_acl)
+ {
+#ifdef USE_GNUTLS
+ debug_printf("gnutls_pubkey_import: %s\n", gnutls_strerror(rc));
+#else
+ long e;
+ ERR_load_crypto_strings(); /*XXX move to a startup routine */
+ while ((e = ERR_get_error()))
+ debug_printf("Az: %.120s\n", ERR_error_string(e, NULL));
+#endif
+ }
+
sig->verify_status = PDKIM_VERIFY_INVALID;
sig->verify_ext_status = PDKIM_VERIFY_INVALID_PUBKEY_PARSING;
goto NEXT_VERIFY;
}
/* Check the signature */
- if (rsa_pkcs1_verify(&rsa,
- RSA_PUBLIC,
- ((sig->algo == PDKIM_ALGO_RSA_SHA1)?
- SIG_RSA_SHA1:SIG_RSA_SHA256),
- 0,
- (unsigned char *)headerhash,
- (unsigned char *)sig->sigdata) != 0)
+#ifdef USE_GNUTLS
+
+ k.data = headerhash;
+ k.size = sig->algo == PDKIM_ALGO_RSA_SHA1 ? 20 : 32;
+ s.data = sig->sigdata;
+ s.size = sig->sigdata_len;
+ if ((rc = gnutls_pubkey_verify_hash2(rsa,
+ sig->algo == PDKIM_ALGO_RSA_SHA1
+ ? GNUTLS_SIGN_RSA_SHA1 : GNUTLS_SIGN_RSA_SHA256,
+ 0, &k, &s)) < 0)
+
+#else
+
+ if (RSA_verify(sig->algo == PDKIM_ALGO_RSA_SHA1 ? NID_sha1 : NID_sha256,
+ CUS headerhash, sig->algo == PDKIM_ALGO_RSA_SHA1 ? 20 : 32,
+ US sig->sigdata, (unsigned int)sig->sigdata_len,
+ rsa) != 1)
+
+#endif
{
+#ifdef USE_GNUTLS
+ debug_printf("gnutls_pubkey_verify_hash2: %s\n", gnutls_strerror(rc));
+#endif
sig->verify_status = PDKIM_VERIFY_FAIL;
sig->verify_ext_status = PDKIM_VERIFY_FAIL_MESSAGE;
goto NEXT_VERIFY;
debug_printf("\n");
}
- rsa_free(&rsa);
+#ifdef USE_GNUTLS
+ gnutls_pubkey_deinit(rsa);
+#endif
free(dns_txt_name);
free(dns_txt_reply);
}
/* -------------------------------------------------------------------------- */
DLLEXPORT pdkim_ctx *
-pdkim_init_sign(char *domain, char *selector, char *rsa_privkey)
+pdkim_init_sign(char *domain, char *selector, char *rsa_privkey, int algo)
{
pdkim_ctx *ctx;
pdkim_signature *sig;
ctx->sig->domain = strdup(domain);
ctx->sig->selector = strdup(selector);
ctx->sig->rsa_privkey = strdup(rsa_privkey);
+ctx->sig->algo = algo;
if (!ctx->sig->domain || !ctx->sig->selector || !ctx->sig->rsa_privkey)
goto BAIL;
-if (!(ctx->sig->sha1_body = malloc(sizeof(sha1_context))))
- goto BAIL;
-sha1_starts(ctx->sig->sha1_body);
+#ifdef USE_GNUTLS
+gnutls_hash_init(&ctx->sig->sha_body,
+ algo == PDKIM_ALGO_RSA_SHA1 ? GNUTLS_DIG_SHA1 : GNUTLS_DIG_SHA256);
-if (!(ctx->sig->sha2_body = malloc(sizeof(sha2_context))))
- goto BAIL;
-sha2_starts(ctx->sig->sha2_body, 0);
+#else
+SHA1_Init (&ctx->sig->sha1_body);
+SHA256_Init(&ctx->sig->sha2_body);
+
+#endif
return ctx;
return NULL;
}
+
/* -------------------------------------------------------------------------- */
DLLEXPORT int
int canon_headers,
int canon_body,
long bodylength,
- int algo,
unsigned long created,
unsigned long expires)
{
-
if (identity)
if (!(ctx->sig->identity = strdup(identity)))
return PDKIM_ERR_OOM;
ctx->sig->canon_headers = canon_headers;
ctx->sig->canon_body = canon_body;
ctx->sig->bodylength = bodylength;
-ctx->sig->algo = algo;
ctx->sig->created = created;
ctx->sig->expires = expires;
}
+#endif /*DISABLE_DKIM*/