]> code.citadel.org Git - citadel.git/commitdiff
Complete: post Aide message when DKIM records need to be updated
authorArt Cancro <ajc@citadel.org>
Thu, 16 May 2024 03:44:55 +0000 (03:44 +0000)
committerArt Cancro <ajc@citadel.org>
Thu, 16 May 2024 03:44:55 +0000 (03:44 +0000)
citadel/server/modules/smtp/dkim.c
citadel/server/modules/smtp/dkim_bindings.c
citadel/server/modules/smtp/smtp_util.h

index 4099e0ea6ffcea371426b00533ae84be2bcfb34f..76a7a61122f1a55f77938df50cf0f4edf532cda8 100644 (file)
@@ -406,6 +406,47 @@ EVP_PKEY *dkim_import_key(char *pkey_in) {
 }
 
 
+// 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;
index e7491c15468c52da4897802eb747e822fc47d505..340e574b669a21c52672986cea1b890afff63c62 100644 (file)
@@ -29,6 +29,7 @@
 #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.
@@ -144,24 +145,34 @@ void dkim_check_advisory(char *inetcfg_in) {
                        "\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",
index 041fa4dacc580f729b7ff19d452fff7e78295a68..cdaea243aa45acc671308bf9a98cd3e24adda5ca 100644 (file)
@@ -32,3 +32,5 @@ char *smtpstatus(int code);
 void dkim_sign(StrBuf *email, char *pkey_in, char *domain, char *selector);
 void dkim_init(void);
 void dkim_check_advisory(char *inetcfg_in);
+EVP_PKEY *dkim_import_key(char *pkey_in);
+char *dkim_get_public_key(EVP_PKEY *pkey);