-/* $Cambridge: exim/src/src/dk.c,v 1.2 2005/03/08 16:57:28 ph10 Exp $ */
+/* $Cambridge: exim/src/src/dk.c,v 1.12 2007/01/08 10:50:18 ph10 Exp $ */
/*************************************************
* Exim - an Internet mail transport agent *
*************************************************/
-/* Copyright (c) University of Cambridge 1995 - 2005 */
+/* Copyright (c) University of Cambridge 1995 - 2007 */
/* See the file NOTICE for conditions of use and distribution. */
/* Code for DomainKeys support. Other DK relevant code is in
if (dk_context != NULL) {
/* Send oldest byte */
if ((dkbuff[0] < 256) && (dk_internal_status == DK_STAT_OK)) {
- dk_internal_status = dk_message(dk_context, (char *)&dkbuff[0], 1);
+ dk_internal_status = dk_message(dk_context, CUS &dkbuff[0], 1);
if (dk_internal_status != DK_STAT_OK)
DEBUG(D_receive) debug_printf("DK: %s\n", DK_STAT_to_string(dk_internal_status));
}
/* Send remaining bytes from input which are still in the buffer. */
for (i=0;i<6;i++)
if (dkbuff[i] < 256)
- dk_internal_status = dk_message(dk_context, (char *)&dkbuff[i], 1);
+ dk_internal_status = dk_message(dk_context, CUS &dkbuff[i], 1);
/* Flag end-of-message. */
- dk_internal_status = dk_end(dk_context, NULL);
+ dk_internal_status = dk_end(dk_context, &dk_flags);
+
+ /* dk_flags now has the selector flags (if there was one).
+ It seems that currently only the "t=" flag is supported
+ in selectors. */
+ if (dk_flags & DK_FLAG_SET)
+ if (dk_flags & DK_FLAG_TESTING)
+ dk_verify_block->testing = TRUE;
/* Grab address/domain information. */
p = dk_address(dk_context);
dk_verify_block->domain = string_copy((uschar *)(q+1));
*q = '\0';
dk_verify_block->local_part = string_copy((uschar *)p);
+ *q = '@';
}
}
}
+ /* Now grab the domain-wide DK policy */
dk_flags = dk_policy(dk_context);
- /* Grab domain policy */
if (dk_flags & DK_FLAG_SET) {
- if (dk_flags & DK_FLAG_TESTING)
+ /* Selector "t=" flag has precedence, don't overwrite it if
+ the selector has set it above. */
+ if ((dk_flags & DK_FLAG_TESTING) && !dk_verify_block->testing)
dk_verify_block->testing = TRUE;
if (dk_flags & DK_FLAG_SIGNSALL)
dk_verify_block->signsall = TRUE;
dk_verify_block->result_string = string_copy((uschar *)DK_STAT_to_string(dk_internal_status));
/* All done, reset dk_context. */
- dk_free(dk_context);
+ dk_free(dk_context,1);
dk_context = NULL;
store_pool = old_pool;
uschar *dk_selector,
uschar *dk_canon) {
uschar *rc = NULL;
+ uschar *headers = NULL;
+ int headers_len;
int dk_canon_int = DK_CANON_SIMPLE;
- char c;
+ char buf[4096];
int seen_lf = 0;
int seen_lfdot = 0;
uschar sig[1024];
/* Figure out what canonicalization to use. Unfortunately
we must do this BEFORE knowing which domain we sign for. */
if ((dk_canon != NULL) && (Ustrcmp(dk_canon, "nofws") == 0)) dk_canon_int = DK_CANON_NOFWS;
- else dk_canon = "simple";
+ else dk_canon = US "simple";
/* Initialize signing context. */
dk_context = dk_sign(dk_lib, &dk_internal_status, dk_canon_int);
goto CLEANUP;
}
- while((sread = read(dk_fd,&c,1)) > 0) {
+ while((sread = read(dk_fd,&buf,4096)) > 0) {
+ int pos = 0;
+ char c;
- if ((c == '.') && seen_lfdot) {
- /* escaped dot, write "\n.", continue */
- dk_message(dk_context, "\n.", 2);
- seen_lf = 0;
- seen_lfdot = 0;
- continue;
- }
+ while (pos < sread) {
+ c = buf[pos++];
- if (seen_lfdot) {
- /* EOM, write "\n" and break */
- dk_message(dk_context, "\n", 1);
- break;
- }
+ if ((c == '.') && seen_lfdot) {
+ /* escaped dot, write "\n.", continue */
+ dk_message(dk_context, CUS "\n.", 2);
+ seen_lf = 0;
+ seen_lfdot = 0;
+ continue;
+ }
- if ((c == '.') && seen_lf) {
- seen_lfdot = 1;
- continue;
- }
+ if (seen_lfdot) {
+ /* EOM, write "\n" and break */
+ dk_message(dk_context, CUS "\n", 1);
+ break;
+ }
- if (seen_lf) {
- /* normal lf, just send it */
- dk_message(dk_context, "\n", 1);
- seen_lf = 0;
- }
+ if ((c == '.') && seen_lf) {
+ seen_lfdot = 1;
+ continue;
+ }
- if (c == '\n') {
- seen_lf = 1;
- continue;
- }
+ if (seen_lf) {
+ /* normal lf, just send it */
+ dk_message(dk_context, CUS "\n", 1);
+ seen_lf = 0;
+ }
+
+ if (c == '\n') {
+ seen_lf = 1;
+ continue;
+ }
- /* write the char */
- dk_message(dk_context, &c, 1);
+ /* write the char */
+ dk_message(dk_context, CUS &c, 1);
+ }
}
/* Handle failed read above. */
/* Get domain to use, unless overridden. */
if (dk_domain == NULL) {
- dk_domain = dk_address(dk_context);
+ dk_domain = US dk_address(dk_context);
switch(dk_domain[0]) {
case 'N': dk_domain = NULL; break;
case 'F':
case 'S':
dk_domain++;
- dk_domain = strrchr(dk_domain,'@');
+ dk_domain = Ustrrchr(dk_domain,'@');
if (dk_domain != NULL) {
uschar *p;
dk_domain++;
DomainKey-Signature header. If there is no domain to sign for, we
can send the message anyway since the recipient has no policy to
apply ... */
- rc = "";
+ rc = US"";
goto CLEANUP;
}
}
(Ustrcmp(dk_private_key,"0") == 0) ||
(Ustrcmp(dk_private_key,"false") == 0) ) {
/* don't sign, but no error */
- rc = "";
+ rc = US"";
goto CLEANUP;
}
int privkey_fd = 0;
/* Looks like a filename, load the private key. */
memset(big_buffer,0,big_buffer_size);
- privkey_fd = open(dk_private_key,O_RDONLY);
- read(privkey_fd,big_buffer,16383);
- close(privkey_fd);
+ privkey_fd = open(CS dk_private_key,O_RDONLY);
+ (void)read(privkey_fd,big_buffer,16383);
+ (void)close(privkey_fd);
dk_private_key = big_buffer;
}
/* Get the signature. */
- dk_internal_status = dk_getsig(dk_context, dk_private_key, sig, 8192);
+ dk_internal_status = dk_getsig(dk_context, dk_private_key, sig, 1024);
/* Check for unuseable key */
if (dk_internal_status != DK_STAT_OK) {
goto CLEANUP;
}
- rc = store_get(1024);
+ headers_len = dk_headers(dk_context, NULL);
+ rc = store_get(1024+256+headers_len);
+ headers = store_malloc(headers_len);
+ dk_headers(dk_context, CS headers);
/* Build DomainKey-Signature header to return. */
- snprintf(rc, 1024, "DomainKey-Signature: a=rsa-sha1; q=dns; c=%s;\r\n"
- "\ts=%s; d=%s;\r\n"
- "\tb=%s;\r\n", dk_canon, dk_selector, dk_domain, sig);
+ (void)string_format(rc, 1024+256+headers_len, "DomainKey-Signature: a=rsa-sha1; q=dns; c=%s; s=%s; d=%s;\r\n"
+ "\th=%s;\r\n"
+ "\tb=%s;\r\n", dk_canon, dk_selector, dk_domain, headers, sig);
- log_write(0, LOG_MAIN, "DK: message signed using a=rsa-sha1; q=dns; c=%s; s=%s; d=%s;", dk_canon, dk_selector, dk_domain);
+ log_write(0, LOG_MAIN, "DK: message signed using a=rsa-sha1; q=dns; c=%s; s=%s; d=%s; h=%s;", dk_canon, dk_selector, dk_domain, headers);
+ store_free(headers);
CLEANUP:
if (dk_context != NULL) {
- dk_free(dk_context);
+ dk_free(dk_context,1);
dk_context = NULL;
}
store_pool = old_pool;