-/* $Cambridge: exim/src/src/dkim.c,v 1.1.2.5 2009/03/17 21:44:10 tom Exp $ */
+/* $Cambridge: exim/src/src/dkim.c,v 1.1.2.9 2009/05/19 09:30:41 tom Exp $ */
/*************************************************
* Exim - an Internet mail transport agent *
#include "pdkim/pdkim.h"
+pdkim_ctx *dkim_verify_ctx = NULL;
+pdkim_signature *dkim_signatures = NULL;
-void dkim_exim_verify_init(void) {
+int dkim_exim_query_dns_txt(char *name, char *answer) {
+ dns_answer dnsa;
+ dns_scan dnss;
+ dns_record *rr;
+
+ if (dns_lookup(&dnsa, (uschar *)name, T_TXT, NULL) != DNS_SUCCEED) return 1;
+
+ /* Search for TXT record */
+ for (rr = dns_next_rr(&dnsa, &dnss, RESET_ANSWERS);
+ rr != NULL;
+ rr = dns_next_rr(&dnsa, &dnss, RESET_NEXT))
+ if (rr->type == T_TXT) break;
+
+ /* Copy record content to the answer buffer */
+ if (rr != NULL) {
+ int rr_offset = 0;
+ int answer_offset = 0;
+ while (rr_offset < rr->size) {
+ uschar len = (rr->data)[rr_offset++];
+ snprintf(answer+(answer_offset),
+ PDKIM_DNS_TXT_MAX_RECLEN-(answer_offset),
+ "%.*s", (int)len, (char *)((rr->data)+rr_offset));
+ rr_offset+=len;
+ answer_offset+=len;
+ }
+ }
+ else return 1;
+
+ return PDKIM_OK;
+}
+
+
+int dkim_exim_verify_init(void) {
+
+ /* Free previous context if there is one */
+ if (dkim_verify_ctx) pdkim_free_ctx(dkim_verify_ctx);
+
+ /* Create new context */
+ dkim_verify_ctx = pdkim_init_verify(PDKIM_INPUT_SMTP,
+ &dkim_exim_query_dns_txt
+ );
+
+ if (dkim_verify_ctx != NULL) {
+ dkim_collect_input = 1;
+ pdkim_set_debug_stream(dkim_verify_ctx,debug_file);
+ return 1;
+ }
+ else {
+ dkim_collect_input = 0;
+ return 0;
+ }
}
-void dkim_exim_verify_finish(void) {
+
+int dkim_exim_verify_feed(uschar *data, int len) {
+ if (pdkim_feed(dkim_verify_ctx,
+ (char *)data,
+ len) != PDKIM_OK) return 0;
+ return 1;
}
+
+int dkim_exim_verify_finish(void) {
+ dkim_signatures = NULL;
+ dkim_collect_input = 0;
+ if (pdkim_feed_finish(dkim_verify_ctx,&dkim_signatures) != PDKIM_OK) return 0;
+
+ while (dkim_signatures != NULL) {
+ int size = 0;
+ int ptr = 0;
+ uschar *logmsg = string_append(NULL, &size, &ptr, 5,
+
+ string_sprintf( "DKIM: v=%u d=%s s=%s c=%s/%s a=%s ",
+ dkim_signatures->version,
+ dkim_signatures->domain,
+ dkim_signatures->selector,
+ (dkim_signatures->canon_headers == PDKIM_CANON_SIMPLE)?"simple":"relaxed",
+ (dkim_signatures->canon_body == PDKIM_CANON_SIMPLE)?"simple":"relaxed",
+ (dkim_signatures->algo == PDKIM_ALGO_RSA_SHA256)?"rsa-sha256":"rsa-sha1"
+ ),
+
+ ((dkim_signatures->identity != NULL)?
+ string_sprintf("i=%s ", dkim_signatures->identity)
+ :
+ US""
+ ),
+ ((dkim_signatures->created > 0)?
+ string_sprintf("t=%lu ", dkim_signatures->created)
+ :
+ US""
+ ),
+ ((dkim_signatures->expires > 0)?
+ string_sprintf("x=%lu ", dkim_signatures->expires)
+ :
+ US""
+ ),
+ ((dkim_signatures->bodylength > -1)?
+ string_sprintf("x=%li ", dkim_signatures->bodylength)
+ :
+ US""
+ )
+ );
+
+ switch(dkim_signatures->verify_status) {
+ case PDKIM_VERIFY_NONE:
+ logmsg = string_append(logmsg, &size, &ptr, 1, "[not verified]");
+ break;
+ case PDKIM_VERIFY_INVALID:
+ logmsg = string_append(logmsg, &size, &ptr, 1, "[invalid - ");
+ switch (dkim_signatures->verify_ext_status) {
+ case PDKIM_VERIFY_INVALID_PUBKEY_UNAVAILABLE:
+ logmsg = string_append(logmsg, &size, &ptr, 1, "public key record (currently?) unavailable]");
+ break;
+ case PDKIM_VERIFY_INVALID_BUFFER_SIZE:
+ logmsg = string_append(logmsg, &size, &ptr, 1, "overlong public key record]");
+ break;
+ case PDKIM_VERIFY_INVALID_PUBKEY_PARSING:
+ logmsg = string_append(logmsg, &size, &ptr, 1, "syntax error in public key record]");
+ break;
+ default:
+ logmsg = string_append(logmsg, &size, &ptr, 1, "unspecified problem]");
+ }
+ break;
+ case PDKIM_VERIFY_FAIL:
+ logmsg = string_append(logmsg, &size, &ptr, 1, "[verification failed - ");
+ switch (dkim_signatures->verify_ext_status) {
+ case PDKIM_VERIFY_FAIL_BODY:
+ logmsg = string_append(logmsg, &size, &ptr, 1, "body hash mismatch (body probably modified in transit)]");
+ break;
+ case PDKIM_VERIFY_FAIL_MESSAGE:
+ logmsg = string_append(logmsg, &size, &ptr, 1, "signature did not verify (headers probably modified in transit)]");
+ break;
+ default:
+ logmsg = string_append(logmsg, &size, &ptr, 1, "unspecified reason]");
+ }
+ break;
+ case PDKIM_VERIFY_PASS:
+ logmsg = string_append(logmsg, &size, &ptr, 1, "[verification succeeded]");
+ break;
+ }
+
+ logmsg[ptr] = '\0';
+ log_write(0, LOG_MAIN, (char *)logmsg);
+
+ /* Try next signature */
+ dkim_signatures = dkim_signatures->next;
+ }
+
+ return dkim_signatures?1:0;
+}
+
+
int dkim_exim_verify_result(uschar *domain, uschar **result, uschar **error) {
+
+ if (dkim_verify_ctx) {
+
+ }
+
return OK;
}
+
uschar *dkim_exim_sign(int dkim_fd,
uschar *dkim_private_key,
uschar *dkim_domain,
NULL,
pdkim_canon,
pdkim_canon,
- 0,
+ -1,
PDKIM_ALGO_RSA_SHA256,
0,
0);