X-Git-Url: https://git.netwichtig.de/gitweb/?a=blobdiff_plain;f=src%2Fsrc%2Fdk.c;h=9ed82382b98d47ed40b9a4728b5bff03de900ed1;hb=48c7f9e2e3b50cd5548447de62c77c7ddfe21519;hp=c31a1ddb60edf20148391bd7b80cdbcfd3ad8f4d;hpb=fb2274d4a2c4398a497fbec5cacebaab7d20a127;p=user%2Fhenk%2Fcode%2Fexim.git diff --git a/src/src/dk.c b/src/src/dk.c index c31a1ddb6..9ed82382b 100644 --- a/src/src/dk.c +++ b/src/src/dk.c @@ -1,10 +1,10 @@ -/* $Cambridge: exim/src/src/dk.c,v 1.1 2005/03/08 15:32:02 tom Exp $ */ +/* $Cambridge: exim/src/src/dk.c,v 1.11 2006/10/30 22:06:33 tom Exp $ */ /************************************************* * Exim - an Internet mail transport agent * *************************************************/ -/* Copyright (c) University of Cambridge 1995 - 2005 */ +/* Copyright (c) University of Cambridge 1995 - 2006 */ /* See the file NOTICE for conditions of use and distribution. */ /* Code for DomainKeys support. Other DK relevant code is in @@ -34,11 +34,11 @@ int dkbuff[6] = {256,256,256,256,256,256}; int dk_receive_getc(void) { int i; int c = receive_getc(); - + 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)); } @@ -55,7 +55,7 @@ int dk_receive_getc(void) { dkbuff[3] = 256; dkbuff[4] = 256; dkbuff[5] = 256; - } + } if ( (dkbuff[2] == '\r') && (dkbuff[3] == '\n') && (dkbuff[4] == '.') && @@ -80,15 +80,15 @@ int dk_receive_ungetc(int c) { } -void dk_exim_verify_init(void) { +void dk_exim_verify_init(void) { int old_pool = store_pool; store_pool = POOL_PERM; - + /* Reset DK state in any case. */ dk_context = NULL; dk_lib = NULL; dk_verify_block = NULL; - + /* Set up DK context if DK was requested and input is SMTP. */ if (smtp_input && !smtp_batched_input && dk_do_verify) { /* initialize library */ @@ -127,17 +127,24 @@ void dk_exim_verify_finish(void) { /* Bail out if context could not be set up earlier. */ if (dk_context == NULL) return; - + store_pool = POOL_PERM; - + /* 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); if (p != NULL) { @@ -160,17 +167,20 @@ void dk_exim_verify_finish(void) { 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) + if (dk_flags & DK_FLAG_SIGNSALL) dk_verify_block->signsall = TRUE; } @@ -212,14 +222,14 @@ void dk_exim_verify_finish(void) { /* This is missing DK_EXIM_RESULT_NON_PARTICIPANT. The lib does not report such a status. */ } - + /* Set up human readable result string. */ 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; } @@ -229,8 +239,10 @@ uschar *dk_exim_sign(int dk_fd, 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]; @@ -238,7 +250,7 @@ uschar *dk_exim_sign(int dk_fd, int sread; int old_pool = store_pool; store_pool = POOL_PERM; - + dk_lib = dk_init(&dk_internal_status); if (dk_internal_status != DK_STAT_OK) { debug_printf("DK: %s\n", DK_STAT_to_string(dk_internal_status)); @@ -249,52 +261,58 @@ uschar *dk_exim_sign(int dk_fd, /* 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); if (dk_internal_status != DK_STAT_OK) { - debug_printf("DK: %s\n", DK_STAT_to_string(dk_internal_status)); + debug_printf("DK: %s\n", DK_STAT_to_string(dk_internal_status)); dk_context = NULL; goto CLEANUP; } - - while((sread = read(dk_fd,&c,1)) > 0) { - - if ((c == '.') && seen_lfdot) { - /* escaped dot, write "\n.", continue */ - dk_message(dk_context, "\n.", 2); - seen_lf = 0; - seen_lfdot = 0; - continue; - } - - if (seen_lfdot) { - /* EOM, write "\n" and break */ - dk_message(dk_context, "\n", 1); - break; - } - if ((c == '.') && seen_lf) { - seen_lfdot = 1; - continue; - } - - if (seen_lf) { - /* normal lf, just send it */ - dk_message(dk_context, "\n", 1); - seen_lf = 0; - } - - if (c == '\n') { - seen_lf = 1; - continue; + while((sread = read(dk_fd,&buf,4096)) > 0) { + int pos = 0; + char c; + + while (pos < sread) { + c = buf[pos++]; + + if ((c == '.') && seen_lfdot) { + /* escaped dot, write "\n.", continue */ + dk_message(dk_context, CUS "\n.", 2); + seen_lf = 0; + seen_lfdot = 0; + continue; + } + + if (seen_lfdot) { + /* EOM, write "\n" and break */ + dk_message(dk_context, CUS "\n", 1); + break; + } + + if ((c == '.') && seen_lf) { + seen_lfdot = 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, CUS &c, 1); } - - /* write the char */ - dk_message(dk_context, &c, 1); } - + /* Handle failed read above. */ if (sread == -1) { debug_printf("DK: Error reading -K file.\n"); @@ -302,36 +320,36 @@ uschar *dk_exim_sign(int dk_fd, rc = NULL; goto CLEANUP; } - + /* Flag end-of-message. */ dk_internal_status = dk_end(dk_context, NULL); /* TODO: check status */ - - + + /* 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++; p = dk_domain; - while (*p != 0) { *p = tolower(*p); p++; } + while (*p != 0) { *p = tolower(*p); p++; } } break; } if (dk_domain == NULL) { - debug_printf("DK: Could not determine domain to use for signing from message headers.\n"); + debug_printf("DK: Could not determine domain to use for signing from message headers.\n"); /* In this case, we return "OK" by sending up an empty string as the 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; } } @@ -342,10 +360,10 @@ uschar *dk_exim_sign(int dk_fd, debug_printf("DK: Error while expanding dk_domain option.\n"); rc = NULL; goto CLEANUP; - } + } } - - /* Set up $dk_domain expansion variable. */ + + /* Set up $dk_domain expansion variable. */ dk_signing_domain = dk_domain; /* Get selector to use. */ @@ -356,10 +374,10 @@ uschar *dk_exim_sign(int dk_fd, rc = NULL; goto CLEANUP; } - + /* Set up $dk_selector expansion variable. */ dk_signing_selector = dk_selector; - + /* Get private key to use. */ dk_private_key = expand_string(dk_private_key); if (dk_private_key == NULL) { @@ -368,46 +386,50 @@ uschar *dk_exim_sign(int dk_fd, rc = NULL; goto CLEANUP; } - + if ( (Ustrlen(dk_private_key) == 0) || (Ustrcmp(dk_private_key,"0") == 0) || (Ustrcmp(dk_private_key,"false") == 0) ) { /* don't sign, but no error */ - rc = ""; + rc = US""; goto CLEANUP; } - + if (dk_private_key[0] == '/') { 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) { - debug_printf("DK: %s\n", DK_STAT_to_string(dk_internal_status)); + debug_printf("DK: %s\n", DK_STAT_to_string(dk_internal_status)); rc = NULL; 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); - - 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); + (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; 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;