// DKIM signature creation
// https://www.rfc-editor.org/rfc/rfc6376.html
//
-// Trim code borrowed from firm-dkim (C) 2012 by Timothy E. Johansson
+// Body canonicalization code (C) 2012 by Timothy E. Johansson
// The rest is written for Citadel and OpenSSL 3.0 (C) 2024 by Art Cancro
//
// This program is open source software. Use, duplication, or disclosure is subject to the GNU General Public License v3.
}
-// Convert binary to base64 using openssl library function. We should replace this with the encoder from libcitadel.
-char *dkim_base64_encode(const unsigned char *input, int length) {
- BIO *bmem, *b64;
- BUF_MEM *bptr;
-
- b64 = BIO_new(BIO_f_base64());
- bmem = BIO_new(BIO_s_mem());
- b64 = BIO_push(b64, bmem);
-
- BIO_write(b64, input, length);
- BIO_flush(b64);
- BIO_get_mem_ptr(b64, &bptr);
-
- char *buf = malloc(bptr->length);
- memcpy(buf, bptr->data, bptr->length-1);
- buf[bptr->length-1] = '\0';
-
- BIO_free_all(b64);
-
- // remove line breaks
- int buf_len = strlen(buf);
- int i, cur = 0;
- for (i = 0; i < buf_len; ++i) {
- if (buf[i] != '\r' && buf[i] != '\n') {
- buf[cur++] = buf[i];
- }
- }
- buf[cur] = '\0';
- return buf;
-}
-
-
// Canonicalize one line of the message body as per the "relaxed" algorithm
char *dkim_canonicalize_body_line(char *line) {
int line_len = 0;
// Ignores all whitespace at the end of lines. Implementations MUST NOT remove the CRLF at the end of the line.
dkim_rtrim(line);
- // Reduces all sequences of whitespace within a line to a single SP character.
+ // Reduces all sequences of whitespace within a line to a single space character.
line_len = strlen(line);
int new_len = 0;
relaxed_body = NULL;
// base64 encode the body hash
- char *encoded_body_hash = dkim_base64_encode(body_hash, SHA256_DIGEST_LENGTH);
+ char *encoded_body_hash = malloc(SHA256_DIGEST_LENGTH * 2);
+ CtdlEncodeBase64(encoded_body_hash, body_hash, SHA256_DIGEST_LENGTH, BASE64_NO_LINEBREAKS);
free(body_hash); // all we need now is the encoded hash
// "relaxed" header canonicalization, step 1 : unfold the headers
FreeStrBuf(&unfolded_headers);
// base64 encode the signature
- char *encoded_signature = dkim_base64_encode(sig, signature_len);
- int encoded_signature_len = strlen(encoded_signature);
+ char *encoded_signature = malloc(signature_len * 2);
+ int encoded_signature_len = CtdlEncodeBase64(encoded_signature, sig, signature_len, BASE64_NO_LINEBREAKS);
free(sig); // Free the raw signature, keep the b64-encoded one.
StrBufAppendPrintf(dkim_header, "%s", encoded_signature); // Make the final header.
free(encoded_signature);