summaryrefslogtreecommitdiff
path: root/src/qmail-dkim.cpp
diff options
context:
space:
mode:
authorJannis Hoffmann <jannis@fehcom.de>2024-07-08 17:55:05 +0200
committerJannis Hoffmann <jannis@fehcom.de>2024-07-08 17:55:05 +0200
commit1001ed6c2ae98a5b9ed707b7710eb3ae87a0a7ce (patch)
treef30f7780a24fc6143e49658d696ba8f661bdfcdc /src/qmail-dkim.cpp
parente8046bd96422c3bedaa0f0e693cac28d3458d4bd (diff)
Downgraded qmail-dkim from C++ to C. Made DKIMContext opaque.
Added functions DKIMContextNew and DKIMContextFree. Changed fields of DKIMContext.
Diffstat (limited to 'src/qmail-dkim.cpp')
-rw-r--r--src/qmail-dkim.cpp377
1 files changed, 0 insertions, 377 deletions
diff --git a/src/qmail-dkim.cpp b/src/qmail-dkim.cpp
deleted file mode 100644
index 1a05e6c..0000000
--- a/src/qmail-dkim.cpp
+++ /dev/null
@@ -1,377 +0,0 @@
-/*****************************************************************************
-* Copyright 2005 Alt-N Technologies, Ltd.
-*
-* Licensed under the Apache License, Version 2.0 (the "License");
-* you may not use this file except in compliance with the License.
-* You may obtain a copy of the License at
-*
-* http://www.apache.org/licenses/LICENSE-2.0
-*
-* This code incorporates intellectual property owned by Yahoo! and licensed
-* pursuant to the Yahoo! DomainKeys Patent License Agreement.
-*
-* Unless required by applicable law or agreed to in writing, software
-* distributed under the License is distributed on an "AS IS" BASIS,
-* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-* See the License for the specific language governing permissions and
-* limitations under the License.
-*
-* Changes done by ¢feh@fehcom.de obeying the above license
-*
-* Comment: Awful mixture of C and C++ making use of the worst parts of it.
-* Style: Partial Hungarian notation (see Torvalds comments)
-* C++: Obsolete classes, allocators, virtual constructors w/o destructors
-* C: Stdio interface routines
-* OpenSSL: Brain demaged EVP_Digest calls with memory leaks.
-* Network: Sigh, exchanged internal DNS routines by fehQlibs resolver
-*
-*****************************************************************************/
-#include <unistd.h>
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <time.h>
-
-#include "dkim.h"
-
-extern "C" {
-#include "dns.h"
-}
-
-// change these to your selector name, domain name, etc
-#define MYRSASELECTOR "default"
-#define MYECCSELECTOR "eddy"
-#define MYDOMAIN "" //"bardenhagen.com"
-#define MYIDENTITY "" //"dkimtest@bardenhagen.com"
-
-#define strnicmp strncasecmp
-#define FDLOG stderr /* writing to another FD requires a method */
-
-int DKIM_CALL SignThisHeader(const char *szHeader)
-{
- if (strnicmp(szHeader, "X-", 2) == 0) {
- return 0;
- }
- return 1;
-}
-
-int DKIM_CALL SelectorCallback(const char *szFQDN, char *szBuffer, int nBufLen)
-{
- return 0;
-}
-
-void usage()
-{
- char version[] = "1.4.0";
- fprintf(FDLOG, "qmail-dkim %s \n", version);
- fprintf(
- FDLOG,
- "Usage: qmail-dkim [-h|-v|-s] [tags] <msgfile> [<RSAkeyfile> <outfile> <Ed25519keyfile>]\n\n");
- fprintf(FDLOG, "Options:\n\t-h show this help\n");
- fprintf(FDLOG, "\t-s sign the message \n");
- fprintf(FDLOG, "\t-v verify the message\n");
- fprintf(FDLOG, "\t-V verify the message and write result to output file (Pass/Fail)\n\n");
- fprintf(FDLOG, "These tags are available:\n");
- fprintf(
- FDLOG,
- "\t-c<canonicalization> - r=relaxed [DEFAULT], s=simple, t=relaxed/simple, u=simple/relaxed\n");
- fprintf(
- FDLOG,
- "\t-d<sdid> - Signing Domain Identifier (if not provided it will be determined from "
- "the sender/from header)\n");
- fprintf(
- FDLOG,
- "\t-i<auid> - Agent User Identifier, usually the sender's email address "
- "(optional)\n");
- fprintf(FDLOG, "\t-l - include body length tag (optional)\n");
- fprintf(FDLOG, "\t-q - include query method tag\n");
- fprintf(FDLOG, "\t-t - include a timestamp tag (optional)\n");
- fprintf(
- FDLOG,
- "\t-x<expire_time> - the expire time in seconds since epoch (optional, DEFAULT = current "
- "time + 604800)\n");
- fprintf(FDLOG, "\t-y<selector> - set RSA selector (DEFAULT: default)\n");
- fprintf(FDLOG, "\t-Y<selector> - set Ed25519 selector (DEFAULT: default)\n");
- fprintf(
- FDLOG,
- "\t-z<hash> - set signature algorithm type (1=rsa-sha1, 2=rsa-sha256, 3=both, "
- "4=ed25519, 5=hybrid)\n");
-}
-
-int main(int argc, char *argv[])
-{
- int n;
- const char *RSAKeyFile = "rsa.pem";
- const char *ECCKeyFile = "ed25519.pem";
- const char *MsgFile = "test.msg";
- const char *OutFile = "signed.msg";
- int nKeyLen;
- char RSAPrivKey[4196]; // storge for private key FILE including header and DER envelope
- char ECCPrivKey[128];
- char Buffer[1000];
- int BufLen;
- char szSignature[8192];
- time_t t;
- DKIMContext ctxt;
- DKIMSignOptions opts = {0};
-
- opts.nHash = DKIM_HASH_SHA256; // default
-
- time(&t);
-
- opts.nCanon = DKIM_SIGN_RELAXED;
- opts.nIncludeBodyLengthTag = 0;
- opts.nIncludeQueryMethod = 0;
- opts.nIncludeTimeStamp = 0;
- opts.expireTime = t + 604800; // expires in 1 week
- strcpy(opts.szSelector, MYRSASELECTOR);
- strcpy(opts.szSelectorE, MYECCSELECTOR);
- strcpy(opts.szDomain, MYDOMAIN);
- strcpy(opts.szIdentity, MYIDENTITY);
- opts.pfnHeaderCallback = SignThisHeader;
- strcpy(opts.szRequiredHeaders, "NonExistant");
- opts.nIncludeCopiedHeaders = 0;
-
- int nArgParseState = 0;
- bool bSign = true;
- bool bRes = false;
-
- if (argc < 2) {
- usage();
- exit(1);
- }
-
- for (n = 1; n < argc; n++) {
- if (argv[n][0] == '-' && strlen(argv[n]) > 1) {
- switch (argv[n][1]) {
- case 'c': // canonicalization
- if (argv[n][2] == 'r') {
- opts.nCanon = DKIM_SIGN_RELAXED;
- } else if (argv[n][2] == 's') {
- opts.nCanon = DKIM_SIGN_SIMPLE;
- } else if (argv[n][2] == 't') {
- opts.nCanon = DKIM_SIGN_RELAXED_SIMPLE;
- } else if (argv[n][2] == 'u') {
- opts.nCanon = DKIM_SIGN_SIMPLE_RELAXED;
- }
- break;
- case 'd': strncpy(opts.szDomain, (const char *)(argv[n] + 2), sizeof(opts.szDomain) - 1); break;
- case 'l': // body length tag
- opts.nIncludeBodyLengthTag = 1;
- break;
- case 'h': usage(); return 0;
- case 'i': // identity
- if (argv[n][2] == '-') {
- opts.szIdentity[0] = '\0';
- } else {
- strncpy(opts.szIdentity, argv[n] + 2, sizeof(opts.szIdentity) - 1);
- }
- break;
- case 'q': // query method tag
- opts.nIncludeQueryMethod = 1;
- break;
- case 's': // sign with and use potentially Ed25519 private key
- bSign = true;
- break;
- case 't': // timestamp tag
- opts.nIncludeTimeStamp = 1;
- break;
- case 'v': // verify
- bSign = false;
- break;
- case 'V': // verify and write result to OutFile
- bSign = false;
- bRes = true;
- break;
- case 'x': // expire time
- if (argv[n][2] == '-') {
- opts.expireTime = 0;
- } else {
- opts.expireTime = t + atoi(argv[n] + 2);
- }
- break;
- case 'y': strncpy(opts.szSelector, argv[n] + 2, sizeof(opts.szSelector) - 1); break;
- case 'Y': strncpy(opts.szSelectorE, argv[n] + 2, sizeof(opts.szSelectorE) - 1); break;
- case 'z': // sign w/ sha1, sha256, both, ed25519, hybrid
- opts.nHash = atoi(&argv[n][2]);
- }
- } else {
- switch (nArgParseState) {
- case 0: MsgFile = argv[n]; break;
- case 1: RSAKeyFile = argv[n]; break;
- case 2: OutFile = argv[n]; break;
- case 3: ECCKeyFile = argv[n]; break;
- }
- nArgParseState++;
- }
- }
-
- /** Go for DKIM signing ... **/
-
- if (bSign) {
- if (opts.nHash != 4) {
- FILE *RSAPrivKeyFP = fopen(RSAKeyFile, "r");
- if (RSAPrivKeyFP == NULL) {
-#ifdef SHOWLOG
- fprintf(FDLOG, " qmail-dkim: can't open private key file (%s) \n", RSAKeyFile);
-#endif
- exit(1);
- }
- nKeyLen = fread(
- RSAPrivKey,
- 1,
- sizeof(RSAPrivKey),
- RSAPrivKeyFP); // we read sizeof(RSAPrivKey) members with size of 1 byte each; sigh
-#ifdef SHOWLOG
- fprintf(FDLOG, " qmail-dkim: private key file (%s) - length %i \n", RSAKeyFile, nKeyLen);
-#endif
- if (nKeyLen >= sizeof(RSAPrivKey)) { /* (TC9) on return, we get the number of members read! */
-#ifdef SHOWLOG
- fprintf(
- FDLOG,
- " qmail-dkim: private key buffer isn't big enough for private key length %i \n",
- nKeyLen);
-#endif
- exit(1);
- }
- RSAPrivKey[nKeyLen] = '\0';
- fclose(RSAPrivKeyFP);
- }
-
- /** Ed25519 signing **/
-
- if (opts.nHash == 4 || opts.nHash == 5) {
- FILE *ECCPrivKeyFP = fopen(ECCKeyFile, "r");
- if (ECCPrivKeyFP == NULL) {
-#ifdef SHOWLOG
- fprintf(FDLOG, " qmail-dkim: can't open Ed25519 private key file (%s) \n", ECCKeyFile);
-#endif
- exit(1);
- }
- nKeyLen = fread(ECCPrivKey, 1, sizeof(ECCPrivKey), ECCPrivKeyFP);
-#ifdef SHOWLOG
- fprintf(FDLOG, " qmail-dkim: Ed25519 private key file (%s) - length %i \n", ECCKeyFile, nKeyLen);
-#endif
- if (nKeyLen >= sizeof(ECCPrivKey)) {
-#ifdef SHOWLOG
- fprintf(
- FDLOG,
- " qmail-dkim: ECC private key buffer isn't big enough for ECC private key length %i \n",
- nKeyLen);
-#endif
- exit(1);
- }
- ECCPrivKey[nKeyLen] = '\0';
- fclose(ECCPrivKeyFP);
- }
-
- /** Input message for signing **/
-
- FILE *MsgFP = fopen(MsgFile, "rb");
- if (MsgFP == NULL) {
-#ifdef SHOWLOG
- fprintf(FDLOG, " qmail-dkim: can't open msg file (%s) \n", MsgFile);
-#endif
- exit(1);
- }
-
- n = DKIMSignInit(&ctxt, &opts);
-
- while (1) {
- BufLen = fread(Buffer, 1, sizeof(Buffer), MsgFP);
- if (BufLen > 0) {
- DKIMSignProcess(&ctxt, Buffer, BufLen);
- } else {
- break;
- }
- }
- fclose(MsgFP);
-
- char *pSig = NULL;
-
- /** Do the actual signing **/
-
- n = DKIMSignGetSig2(&ctxt, RSAPrivKey, ECCPrivKey, &pSig);
-
- strcpy(szSignature, pSig);
-
- DKIMSignFree(&ctxt);
-
- FILE *in = fopen(MsgFile, "rb");
- FILE *out = fopen(OutFile, "wb+");
-
-#ifdef SHOWLOG
- fprintf(FDLOG, " outfile written %s \n", OutFile);
-#endif
-
- fwrite(szSignature, 1, strlen(szSignature), out);
- fwrite("\r\n", 1, 2, out);
-
- while (1) {
- BufLen = fread(Buffer, 1, sizeof(Buffer), in);
- if (BufLen > 0) {
- fwrite(Buffer, 1, BufLen, out);
- } else {
- break;
- }
- }
- fclose(in);
-
- }
-
- /** Now go for verification **/
-
- else
- {
- FILE *in = fopen(MsgFile, "rb");
- if (in == NULL) {
- //#ifdef SHOWLOG
- fprintf(FDLOG, " qmail-dkim: can't open input file\n");
- //#endif
- return 0; // bad option -- no CTX set up yet
- }
-
- DKIMVerifyOptions vopts = {0};
- vopts.pfnSelectorCallback = NULL; //SelectorCallback;
-
- n = DKIMVerifyInit(&ctxt, &vopts);
-
- while (1) {
- BufLen = fread(Buffer, 1, sizeof(Buffer), in);
- if (BufLen > 0) {
- DKIMVerifyProcess(&ctxt, Buffer, BufLen);
- } else {
- break;
- }
- }
-
- n = DKIMVerifyResults(&ctxt);
-
- int nSigCount = 0;
- DKIMVerifyDetails *pDetails;
- char szPolicy[512];
-
- n = DKIMVerifyGetDetails(&ctxt, &nSigCount, &pDetails, szPolicy);
-
- for (int i = 0; i < nSigCount; i++) {
- const char s[] = "pass";
- const char f[] = "fail";
- const char *error = DKIM_ErrorResult(pDetails[i].nResult);
- if (!bRes) fprintf(FDLOG, " Signature #%d: ", i + 1);
- if (pDetails[i].nResult >= 0) {
- if (bRes) {
- _DKIM_ReportResult(OutFile, s, 0);
- } else
- printf(" Pass\n");
- } else { // fail
- if (bRes) {
- _DKIM_ReportResult(OutFile, f, error);
- } else
- printf(" Fail %s \n", error);
- }
- }
- DKIMVerifyFree(&ctxt);
- }
- return 0;
-}