}
+// Get the public key from our DKIM signing pair.
+// Returns a string that must be freed by the caller.
+char *dkim_get_public_key(EVP_PKEY *pkey) {
+ char *b64key = NULL;
+ EVP_PKEY_CTX *ctx;
+ ctx = EVP_PKEY_CTX_new_id(EVP_PKEY_RSA, NULL);
+ if (ctx) {
+ BIO *bio = NULL;
+ bio = BIO_new(BIO_s_mem());
+ if (bio) {
+ PEM_write_bio_PUBKEY(bio, pkey);
+ b64key = malloc(4096);
+ if (b64key) {
+ size_t readbytes;
+ BIO_read_ex(bio, b64key, 4096, &readbytes);
+ b64key[readbytes] = 0;
+
+ // strip the header
+ if (!strncasecmp(b64key, HKEY("-----BEGIN PUBLIC KEY-----\n"))) {
+ strcpy(b64key, &b64key[27]);
+ }
+
+ // strip the footer
+ char *foot = strstr(b64key, "\n-----END PUBLIC KEY-----");
+ if (foot) {
+ *foot = 0;
+ }
+
+ // remove newlines
+ char *nl;
+ while (nl = strchr(b64key, '\n')) {
+ strcpy(nl, nl+1);
+ }
+ }
+ BIO_free(bio);
+ }
+ EVP_PKEY_CTX_free(ctx);
+ }
+ return(b64key);
+}
+
// DKIM-sign an email, supplied as a full RFC2822-compliant message stored in a StrBuf
void dkim_sign(StrBuf *email, char *pkey_in, char *domain, char *selector) {
int i = 0;
#include <libcitadel.h>
#include "../../config.h"
#include "../../msgbase.h"
+#include "smtp_util.h"
// Generate a private key and selector for DKIM if needed. This is called during server startup.
"\r\n"
),0);
- ptr = inetcfg_in;
- while (ptr && *ptr) {
- char *sep = strchr(ptr, '|');
- if (sep && !strncasecmp(sep+1, HKEY("localhost"))) {
- StrBufAppendPrintf(message, "Host name : %s._domainkey.", CtdlGetConfigStr("dkim_selector"));
- StrBufAppendBufPlain(message, ptr, sep-ptr, 0);
- StrBufAppendBufPlain(message, HKEY("\r\n"), 0);
- StrBufAppendPrintf(message, "Record type: TXT\r\n");
- StrBufAppendBufPlain(message, HKEY("Value : v=DKIM1;k=rsa;p="), 0);
-
- // FIXME calculate the public key and add it here
+ char *pubkey = NULL;
+ EVP_PKEY *pkey = dkim_import_key(CtdlGetConfigStr("dkim_private_key"));
+ if (pkey) {
+ pubkey = dkim_get_public_key(pkey);
+ EVP_PKEY_free(pkey);
+ }
- StrBufAppendPrintf(message, "\r\n\r\n");
- }
- ptr = strchr(ptr, '\n');
- if (ptr) {
- ++ptr;
+ if (pubkey) {
+ ptr = inetcfg_in;
+ while (ptr && *ptr) {
+ char *sep = strchr(ptr, '|');
+ if (sep && !strncasecmp(sep+1, HKEY("localhost"))) {
+ StrBufAppendPrintf(message, "Host name : %s._domainkey.", CtdlGetConfigStr("dkim_selector"));
+ StrBufAppendBufPlain(message, ptr, sep-ptr, 0);
+ StrBufAppendBufPlain(message, HKEY("\r\n"), 0);
+ StrBufAppendPrintf(message, "Record type: TXT\r\n");
+ StrBufAppendPrintf(message, "Value : v=DKIM1;k=rsa;p=%s\r\n", pubkey);
+ StrBufAppendPrintf(message, "\r\n");
+ }
+ ptr = strchr(ptr, '\n');
+ if (ptr) {
+ ++ptr;
+ }
}
+ free(pubkey);
+ }
+ else {
+ StrBufAppendBufPlain(message, HKEY("YOW! Something went wrong.\r\n\r\n"), 0);
}
quickie_message("Citadel",