commit 365862b1aca901a83b87bede4b5a8cb4a8fdd5fc from: Martijn van Duren date: Thu May 2 07:16:36 2019 UTC Move signing component to own function for clearer reading commit - fa9e6602825788fc07b246142c7c60edf465119f commit + 365862b1aca901a83b87bede4b5a8cb4a8fdd5fc blob - 114f8a073d4f1621114bf39d96bab128e9b40cd0 blob + 2f830049280838b6e1a1a5aa4302bc079e1f51f2 --- main.c +++ main.c @@ -112,6 +112,7 @@ void dkim_session_free(struct dkim_session *); int dkim_session_cmp(struct dkim_session *, struct dkim_session *); void dkim_parse_header(struct dkim_session *, char *, int); void dkim_parse_body(struct dkim_session *, char *); +void dkim_sign(struct dkim_session *); int dkim_signature_printf(struct dkim_session *, char *, ...) __attribute__((__format__ (printf, 2, 3))); int dkim_signature_normalize(struct dkim_session *); @@ -220,15 +221,7 @@ dkim_dataline(char *type, int version, struct timespec char *phase, uint64_t reqid, uint64_t token, char *line) { struct dkim_session *session, search; - struct dkim_signature sig; - /* Use largest hash size her */ - char bbh[EVP_MAX_MD_SIZE]; - char bh[(((sizeof(bbh) + 2) / 3) * 4) + 1]; - char *b; - ssize_t i, j; size_t linelen; - char *tmp, *tmp2; - char tmpchar; search.reqid = reqid; session = RB_FIND(dkim_sessions, &dkim_sessions, &search); @@ -246,94 +239,7 @@ dkim_dataline(char *type, int version, struct timespec dkim_err(session, "Couldn't write to tempfile"); if (line[0] == '.' && line[1] =='\0') { - /* This entire section needs an error handling revamp */ - if (canonbody == CANON_SIMPLE && !session->has_body) { - if (EVP_DigestUpdate(session->bh, "\r\n", 2) <= 0) { - dkim_err(session, "Can't update hash context"); - return; - } - } - if (EVP_DigestFinal_ex(session->bh, bbh, NULL) == 0) { - dkim_err(session, "Can't finalize hash context"); - return; - } - EVP_EncodeBlock(bh, bbh, EVP_MD_CTX_size(session->bh)); - if (!dkim_signature_printf(session, "bh=%s; h=", bh)) - return; - /* Reverse order for ease of use of RFC6367 section 5.4.2 */ - for (i = 0; session->headers[i] != NULL; i++) - continue; - for (i--; i >= 0; i--) { - if (EVP_DigestSignUpdate(session->b, - session->headers[i], - strlen(session->headers[i])) <= 0 || - EVP_DigestSignUpdate(session->b, - "\r\n", 2) <= 0) { - dkim_errx(session, - "Failed to update digest context"); - return; - } - /* We're done with the cashed header after hashing */ - for (tmp = session->headers[i]; tmp[0] != ':'; tmp++) { - if (tmp[0] == ' ' || tmp[0] == '\t') - break; - tmp[0] = tolower(tmp[0]); - } - tmp[0] = '\0'; - if (!dkim_signature_printf(session, "%s%s", - session->headers[i + 1] == NULL ? "" : ":", - session->headers[i])) - return; - tmp[0] = tmpchar; - } - dkim_signature_printf(session, "; b="); - if (!dkim_signature_normalize(session)) - return; - if ((tmp = strdup(session->signature.signature)) == NULL) { - dkim_err(session, "Can't create DKIM signature"); - return; - } - dkim_parse_header(session, tmp, 1); - if (EVP_DigestSignUpdate(session->b, tmp, - strlen(tmp)) <= 0) { - dkim_err(session, "Failed to update digest context"); - return; - } - free(tmp); - if (EVP_DigestSignFinal(session->b, NULL, &linelen) <= 0) { - dkim_err(session, "Failed to finalize digest"); - return; - } - if ((tmp = malloc(linelen)) == NULL) { - dkim_err(session, "Can't allocate space for digest"); - return; - } - if (EVP_DigestSignFinal(session->b, tmp, &linelen) <= 0) { - dkim_err(session, "Failed to finalize digest"); - return; - } - /* Lines are unlikely to overflow */ - b = malloc((((linelen + 2) / 3) * 4) + 1); - EVP_EncodeBlock(b, tmp, linelen); - free(tmp); - dkim_signature_printf(session, "%s\r\n", b); - free(b); - dkim_signature_normalize(session); - tmp = session->signature.signature; - while ((tmp2 = strchr(tmp, '\r')) != NULL) { - tmp2[0] = '\0'; - smtp_filter_dataline(session->reqid, session->token, - "%s", tmp); - tmp = tmp2 + 2; - } - tmp = NULL; - linelen = 0; - rewind(session->origf); - while ((i = getline(&tmp, &linelen, session->origf)) != -1) { - tmp[i - 1] = '\0'; - smtp_filter_dataline(session->reqid, session->token, - "%s", tmp); - } + dkim_sign(session); } else if (linelen != 0 && session->parsing_headers) { if (line[0] == '.') line++; @@ -638,6 +544,105 @@ dkim_parse_body(struct dkim_session *session, char *li } } +void +dkim_sign(struct dkim_session *session) +{ + /* Use largest hash size here */ + char bbh[EVP_MAX_MD_SIZE]; + char bh[(((sizeof(bbh) + 2) / 3) * 4) + 1]; + char *b; + ssize_t i, j; + size_t linelen; + char *tmp, *tmp2; + char tmpchar; + + if (canonbody == CANON_SIMPLE && !session->has_body) { + if (EVP_DigestUpdate(session->bh, "\r\n", 2) <= 0) { + dkim_err(session, "Can't update hash context"); + return; + } + } + if (EVP_DigestFinal_ex(session->bh, bbh, NULL) == 0) { + dkim_err(session, "Can't finalize hash context"); + return; + } + EVP_EncodeBlock(bh, bbh, EVP_MD_CTX_size(session->bh)); + if (!dkim_signature_printf(session, "bh=%s; h=", bh)) + return; + /* Reverse order for ease of use of RFC6367 section 5.4.2 */ + for (i = 0; session->headers[i] != NULL; i++) + continue; + for (i--; i >= 0; i--) { + if (EVP_DigestSignUpdate(session->b, + session->headers[i], + strlen(session->headers[i])) <= 0 || + EVP_DigestSignUpdate(session->b, "\r\n", 2) <= 0) { + dkim_errx(session, "Failed to update digest context"); + return; + } + /* We're done with the cached header after hashing */ + for (tmp = session->headers[i]; tmp[0] != ':'; tmp++) { + if (tmp[0] == ' ' || tmp[0] == '\t') + break; + tmp[0] = tolower(tmp[0]); + } + tmp[0] = '\0'; + if (!dkim_signature_printf(session, "%s%s", + session->headers[i + 1] == NULL ? "" : ":", + session->headers[i])) + return; + tmp[0] = tmpchar; + } + dkim_signature_printf(session, "; b="); + if (!dkim_signature_normalize(session)) + return; + if ((tmp = strdup(session->signature.signature)) == NULL) { + dkim_err(session, "Can't create DKIM signature"); + return; + } + dkim_parse_header(session, tmp, 1); + if (EVP_DigestSignUpdate(session->b, tmp, strlen(tmp)) <= 0) { + dkim_err(session, "Failed to update digest context"); + return; + } + free(tmp); + if (EVP_DigestSignFinal(session->b, NULL, &linelen) <= 0) { + dkim_err(session, "Failed to finalize digest"); + return; + } + if ((tmp = malloc(linelen)) == NULL) { + dkim_err(session, "Can't allocate space for digest"); + return; + } + if (EVP_DigestSignFinal(session->b, tmp, &linelen) <= 0) { + dkim_err(session, "Failed to finalize digest"); + return; + } + if ((b = malloc((((linelen + 2) / 3) * 4) + 1)) == NULL) { + dkim_err(session, "Can't create DKIM signature"); + return; + } + EVP_EncodeBlock(b, tmp, linelen); + free(tmp); + dkim_signature_printf(session, "%s\r\n", b); + free(b); + dkim_signature_normalize(session); + tmp = session->signature.signature; + while ((tmp2 = strchr(tmp, '\r')) != NULL) { + tmp2[0] = '\0'; + smtp_filter_dataline(session->reqid, session->token, + "%s", tmp); + tmp = tmp2 + 2; + } + tmp = NULL; + linelen = 0; + rewind(session->origf); + while ((i = getline(&tmp, &linelen, session->origf)) != -1) { + tmp[i - 1] = '\0'; + smtp_filter_dataline(session->reqid, session->token, "%s", tmp); + } +} + int dkim_signature_normalize(struct dkim_session *session) {