* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
-/* $Cambridge: exim/src/src/pdkim/pdkim.c,v 1.6 2009/10/29 11:08:01 tom Exp $ */
+/* $Cambridge: exim/src/src/pdkim/pdkim.c,v 1.12 2009/12/07 13:05:07 tom Exp $ */
#include <stdlib.h>
#include <stdio.h>
};
+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";
+ case PDKIM_VERIFY_FAIL: return "PDKIM_VERIFY_FAIL";
+ case PDKIM_VERIFY_PASS: return "PDKIM_VERIFY_PASS";
+ default: return "PDKIM_VERIFY_UNKNOWN";
+ }
+}
+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";
+ case PDKIM_VERIFY_INVALID_PUBKEY_UNAVAILABLE: return "PDKIM_VERIFY_INVALID_PUBKEY_UNAVAILABLE";
+ case PDKIM_VERIFY_INVALID_BUFFER_SIZE: return "PDKIM_VERIFY_INVALID_BUFFER_SIZE";
+ case PDKIM_VERIFY_INVALID_PUBKEY_PARSING: return "PDKIM_VERIFY_INVALID_PUBKEY_PARSING";
+ default: return "PDKIM_VERIFY_UNKNOWN";
+ }
+}
+
+
/* -------------------------------------------------------------------------- */
/* Print debugging functions */
#ifdef PDKIM_DEBUG
if (new_entry->value == NULL) return NULL;
if (base != NULL) {
pdkim_stringlist *last = base;
- while (last->next != NULL) { last = last->next; };
+ while (last->next != NULL) { last = last->next; }
last->next = new_entry;
return base;
}
else return new_entry;
-};
+}
pdkim_stringlist *pdkim_prepend_stringlist(pdkim_stringlist *base, char *str) {
pdkim_stringlist *new_entry = malloc(sizeof(pdkim_stringlist));
if (new_entry == NULL) return NULL;
new_entry->next = base;
}
return new_entry;
-};
+}
/* -------------------------------------------------------------------------- */
p->len=len;
if (cstr) strcpy(p->str,cstr);
return p;
-};
+}
char *pdkim_strncat(pdkim_str *str, char *data, int len) {
if ((str->allocated - str->len) < (len+1)) {
/* Extend the buffer */
str->len+=len;
str->str[str->len] = '\0';
return str->str;
-};
+}
char *pdkim_strcat(pdkim_str *str, 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 *pdkim_strtrim(pdkim_str *str) {
char *p = str->str;
char *q = str->str;
while ( (*p != '\0') && ((*p == '\t') || (*p == ' ')) ) p++;
- while (*p != '\0') {*q = *p; q++; p++;};
+ while (*p != '\0') {*q = *p; q++; p++;}
*q = '\0';
while ( (q != str->str) && ( (*q == '\0') || (*q == '\t') || (*q == ' ') ) ) {
*q = '\0';
}
str->len = strlen(str->str);
return str->str;
-};
+}
char *pdkim_strclear(pdkim_str *str) {
str->str[0] = '\0';
str->len = 0;
return str->str;
-};
+}
void pdkim_strfree(pdkim_str *str) {
if (str == NULL) return;
if (str->str != NULL) free(str->str);
free(str);
-};
+}
free(sig);
if (next != NULL) pdkim_free_sig(next);
}
-};
+}
/* -------------------------------------------------------------------------- */
pdkim_strfree(ctx->cur_header);
free(ctx);
}
-};
+}
/* -------------------------------------------------------------------------- */
*q = '\0';
if (crlf) strcat(relaxed,"\r\n");
return relaxed;
-};
+}
/* -------------------------------------------------------------------------- */
if (isxdigit(*qp_p) && isxdigit(qp_p[1])) {
/* Do hex conversion */
if (isdigit(*qp_p)) {*c = *qp_p - '0';}
- else {*c = toupper(*qp_p) - 'A' + 10;};
+ else {*c = toupper(*qp_p) - 'A' + 10;}
*c <<= 4;
if (isdigit(qp_p[1])) {*c |= qp_p[1] - '0';}
- else {*c |= toupper(qp_p[1]) - 'A' + 10;};
+ else {*c |= toupper(qp_p[1]) - 'A' + 10;}
return qp_p + 2;
- };
+ }
/* Illegal char here */
*c = PDKIM_QP_ERROR_DECODE;
pub->srvtype = strdup(cur_val->str);
break;
case 't':
- if (strchr(cur_val->str,'t') != NULL) pub->testing = 1;
+ if (strchr(cur_val->str,'y') != NULL) pub->testing = 1;
if (strchr(cur_val->str,'s') != NULL) pub->no_subdomaining = 1;
break;
default:
if (relaxed_data != NULL) free(relaxed_data);
return PDKIM_OK;
-};
+}
/* -------------------------------------------------------------------------- */
}
return PDKIM_OK;
-};
+}
ctx->sig = new_sig;
}
else {
- while (last_sig->next != NULL) { last_sig = last_sig->next; };
+ while (last_sig->next != NULL) { last_sig = last_sig->next; }
last_sig->next = new_sig;
}
}
BAIL:
pdkim_strclear(ctx->cur_header); /* Re-use existing pdkim_str */
return PDKIM_OK;
-};
+}
}
}
return PDKIM_OK;
-};
+}
/* -------------------------------------------------------------------------- */
/* Check if we must still flush a (partial) header. If that is the
case, the message has no body, and we must compute a body hash
out of '<CR><LF>' */
- if (ctx->cur_header->len) {
+ if (ctx->cur_header && ctx->cur_header->len) {
int rc = pdkim_header_complete(ctx);
if (rc != PDKIM_OK) return rc;
pdkim_update_bodyhash(ctx,"\r\n",2);
if (rsa_pkcs1_sign( &rsa, RSA_PRIVATE,
((sig->algo == PDKIM_ALGO_RSA_SHA1)?
- RSA_SHA1:RSA_SHA256),
+ SIG_RSA_SHA1:SIG_RSA_SHA256),
0,
(unsigned char *)headerhash,
(unsigned char *)sig->sigdata ) != 0) {
sig->verify_status = PDKIM_VERIFY_INVALID;
sig->verify_ext_status = PDKIM_VERIFY_INVALID_BUFFER_SIZE;
goto NEXT_VERIFY;
- };
+ }
if ((ctx->dns_txt_callback(dns_txt_name, dns_txt_reply) != PDKIM_OK) ||
(dns_txt_reply[0] == '\0')) {
if (rsa_pkcs1_verify(&rsa,
RSA_PUBLIC,
((sig->algo == PDKIM_ALGO_RSA_SHA1)?
- RSA_SHA1:RSA_SHA256),
+ SIG_RSA_SHA1:SIG_RSA_SHA256),
0,
(unsigned char *)headerhash,
(unsigned char *)sig->sigdata) != 0) {
sig->verify_status = PDKIM_VERIFY_FAIL;
sig->verify_ext_status = PDKIM_VERIFY_FAIL_MESSAGE;
- #ifdef PDKIM_DEBUG
- if (ctx->debug_stream) {
- fprintf(ctx->debug_stream, "PDKIM [%s] signature did NOT verify OK\n",
- sig->domain);
- }
- #endif
goto NEXT_VERIFY;
}
- /* We have a winner! */
- sig->verify_status = PDKIM_VERIFY_PASS;
+ /* We have a winner! (if bodydhash was correct earlier) */
+ if (sig->verify_status == PDKIM_VERIFY_NONE) {
+ sig->verify_status = PDKIM_VERIFY_PASS;
+ }
+
+ NEXT_VERIFY:
#ifdef PDKIM_DEBUG
if (ctx->debug_stream) {
- fprintf(ctx->debug_stream, "PDKIM [%s] signature verified OK\n",
- sig->domain);
+ fprintf(ctx->debug_stream, "PDKIM [%s] signature status: %s",
+ sig->domain, pdkim_verify_status_str(sig->verify_status));
+ if (sig->verify_ext_status > 0) {
+ fprintf(ctx->debug_stream, " (%s)\n",
+ pdkim_verify_ext_status_str(sig->verify_ext_status));
+ }
+ else {
+ fprintf(ctx->debug_stream, "\n");
+ }
}
#endif
- NEXT_VERIFY:
rsa_free(&rsa);
free(dns_txt_name);
free(dns_txt_reply);
sha2_starts(ctx->sig->sha2_body,0);
return ctx;
-};
+}
#ifdef PDKIM_DEBUG
/* -------------------------------------------------------------------------- */
DLLEXPORT void pdkim_set_debug_stream(pdkim_ctx *ctx,
FILE *debug_stream) {
ctx->debug_stream = debug_stream;
-};
+}
#endif
/* -------------------------------------------------------------------------- */
ctx->sig->expires = expires;
return PDKIM_OK;
-};
+}