#include <openssl/err.h>
#include <openssl/evp.h>
#include <libcitadel.h>
+#include "../../config.h"
// This utility function is used by the body canonicalizer
// And we're done!
}
+
+
+// Generate a private key and selector for DKIM if needed. This is called during server startup.
+void dkim_init(void) {
+
+ char *dkim_private_key = CtdlGetConfigStr("dkim_private_key");
+ if (dkim_private_key) {
+ syslog(LOG_DEBUG, "dkim: private key exists and will continue to be used.");
+ }
+ else {
+ EVP_PKEY_CTX *ctx;
+ EVP_PKEY *pkey = NULL;
+ BIO *bio = NULL;
+ ctx = EVP_PKEY_CTX_new_id(EVP_PKEY_RSA, NULL);
+ if (ctx) {
+ if (
+ (EVP_PKEY_keygen_init(ctx) == 1)
+ && (EVP_PKEY_CTX_set_rsa_keygen_bits(ctx, 2048) == 1)
+ && (EVP_PKEY_keygen(ctx, &pkey) == 1)
+ ) {
+ syslog(LOG_DEBUG, "dkim: generated private key");
+ bio = BIO_new(BIO_s_mem());
+ if (bio) {
+ PEM_write_bio_PrivateKey(bio, pkey, NULL, NULL, 0, NULL, NULL);
+ char *b64key = malloc(4096);
+ if (b64key) {
+ size_t readbytes;
+ BIO_read_ex(bio, b64key, 4096, &readbytes);
+ b64key[readbytes] = 0;
+ char *nl = NULL;
+ while (nl=strchr(b64key, '\n'), nl) { // convert newlines to underscores
+ *nl = '_';
+ }
+ CtdlSetConfigStr("dkim_private_key", b64key);
+ free(b64key);
+ }
+ free(bio);
+ }
+ }
+ EVP_PKEY_CTX_free(ctx);
+ }
+ }
+
+ char *dkim_selector = CtdlGetConfigStr("dkim_selector");
+ if (dkim_selector) {
+ syslog(LOG_DEBUG, "dkim: selector exists: %s", dkim_selector);
+ }
+ else {
+ // Quick and dirty algorithm to make up a five letter nonsense word as a selector
+ char new_selector[6];
+ int i;
+ for (i=0; i<5; ++i) {
+ new_selector[i] = (rand() % 26) + 'a';
+ }
+ new_selector[5] = 0;
+ syslog(LOG_DEBUG, "dkim: selector created: %s", new_selector);
+ CtdlSetConfigStr("dkim_selector", new_selector);
+ }
+ abort();
+}