diff options
Diffstat (limited to 'src/qmail-dkim.cpp')
-rw-r--r-- | src/qmail-dkim.cpp | 297 |
1 files changed, 165 insertions, 132 deletions
diff --git a/src/qmail-dkim.cpp b/src/qmail-dkim.cpp index fba94fe..53e1b27 100644 --- a/src/qmail-dkim.cpp +++ b/src/qmail-dkim.cpp @@ -26,32 +26,36 @@ * 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 <stdlib.h> -#include <unistd.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 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 */ +#define strnicmp strncasecmp +#define FDLOG stderr /* writing to another FD requires a method */ -int DKIM_CALL SignThisHeader(const char* szHeader) +int DKIM_CALL SignThisHeader(const char *szHeader) { - if (strnicmp(szHeader,"X-",2) == 0 ) { return 0; } + if (strnicmp(szHeader, "X-", 2) == 0) { + return 0; + } return 1; } -int DKIM_CALL SelectorCallback(const char* szFQDN,char* szBuffer,int nBufLen) +int DKIM_CALL SelectorCallback(const char *szFQDN, char *szBuffer, int nBufLen) { return 0; } @@ -59,34 +63,50 @@ int DKIM_CALL SelectorCallback(const char* szFQDN,char* szBuffer,int nBufLen) 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, "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-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-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"); + 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 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"; + 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 RSAPrivKey[4196]; // storge for private key FILE including header and DER envelope char ECCPrivKey[128]; char Buffer[1000]; int BufLen; @@ -103,20 +123,20 @@ int main(int argc, char* argv[]) 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.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"); + strcpy(opts.szRequiredHeaders, "NonExistant"); opts.nIncludeCopiedHeaders = 0; int nArgParseState = 0; bool bSign = true; bool bRes = false; - if (argc < 2){ + if (argc < 2) { usage(); exit(1); } @@ -124,92 +144,93 @@ int main(int argc, char* argv[]) 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); + 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 'l': // body length tag + 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); } + 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 + case 'q': // query method tag opts.nIncludeQueryMethod = 1; break; - case 's': // sign with and use potentially Ed25519 private key + case 's': // sign with and use potentially Ed25519 private key bSign = true; break; - case 't': // timestamp tag + case 't': // timestamp tag opts.nIncludeTimeStamp = 1; break; - case 'v': // verify + case 'v': // verify bSign = false; break; - case 'V': // verify and write result to OutFile + 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); + case 'x': // expire time + if (argv[n][2] == '-') { + opts.expireTime = 0; + } else { + opts.expireTime = t + atoi(argv[n] + 2); + } break; - case 'Y': - strncpy(opts.szSelectorE,argv[n] + 2,sizeof(opts.szSelectorE) - 1); - break; - case 'z': // sign w/ sha1, sha256, both, ed25519, hybrid + 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 { + } 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; + 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 ... **/ + + /** Go for DKIM signing ... **/ if (bSign) { if (opts.nHash != 4) { - FILE* RSAPrivKeyFP = fopen(RSAKeyFile,"r"); + FILE *RSAPrivKeyFP = fopen(RSAKeyFile, "r"); if (RSAPrivKeyFP == NULL) { #ifdef SHOWLOG - fprintf(FDLOG," qmail-dkim: can't open private key file (%s) \n",RSAKeyFile); + 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 + } + 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); + 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); + fprintf( + FDLOG, + " qmail-dkim: private key buffer isn't big enough for private key length %i \n", + nKeyLen); #endif exit(1); } @@ -217,124 +238,136 @@ int main(int argc, char* argv[]) fclose(RSAPrivKeyFP); } -/** Ed25519 signing **/ + /** Ed25519 signing **/ if (opts.nHash == 4 || opts.nHash == 5) { - FILE* ECCPrivKeyFP = fopen(ECCKeyFile,"r"); + FILE *ECCPrivKeyFP = fopen(ECCKeyFile, "r"); if (ECCPrivKeyFP == NULL) { #ifdef SHOWLOG - fprintf(FDLOG," qmail-dkim: can't open Ed25519 private key file (%s) \n",ECCKeyFile); + fprintf(FDLOG, " qmail-dkim: can't open Ed25519 private key file (%s) \n", ECCKeyFile); #endif exit(1); } - nKeyLen = fread(ECCPrivKey,1,sizeof(ECCPrivKey),ECCPrivKeyFP); + nKeyLen = fread(ECCPrivKey, 1, sizeof(ECCPrivKey), ECCPrivKeyFP); #ifdef SHOWLOG - fprintf(FDLOG," qmail-dkim: Ed25519 private key file (%s) - length %i \n",ECCKeyFile,nKeyLen); + 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); + 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 **/ + /** Input message for signing **/ - FILE* MsgFP = fopen(MsgFile,"rb"); + FILE *MsgFP = fopen(MsgFile, "rb"); if (MsgFP == NULL) { #ifdef SHOWLOG - fprintf(FDLOG," qmail-dkim: can't open msg file (%s) \n",MsgFile); + fprintf(FDLOG, " qmail-dkim: can't open msg file (%s) \n", MsgFile); #endif exit(1); } - n = DKIMSignInit(&ctxt,&opts); + n = DKIMSignInit(&ctxt, &opts); while (1) { - BufLen = fread(Buffer,1,sizeof(Buffer),MsgFP); - if (BufLen > 0) { DKIMSignProcess(&ctxt,Buffer,BufLen); } - else { break; } + BufLen = fread(Buffer, 1, sizeof(Buffer), MsgFP); + if (BufLen > 0) { + DKIMSignProcess(&ctxt, Buffer, BufLen); + } else { + break; + } } fclose(MsgFP); - char* pSig = NULL; + char *pSig = NULL; -/** Do the actual signing **/ + /** Do the actual signing **/ - n = DKIMSignGetSig2(&ctxt,RSAPrivKey,ECCPrivKey,&pSig); + n = DKIMSignGetSig2(&ctxt, RSAPrivKey, ECCPrivKey, &pSig); - strcpy(szSignature,pSig); + strcpy(szSignature, pSig); DKIMSignFree(&ctxt); - FILE* in = fopen(MsgFile,"rb"); - FILE* out = fopen(OutFile,"wb+"); + FILE *in = fopen(MsgFile, "rb"); + FILE *out = fopen(OutFile, "wb+"); #ifdef SHOWLOG - fprintf(FDLOG," outfile written %s \n",OutFile); + fprintf(FDLOG, " outfile written %s \n", OutFile); #endif - fwrite(szSignature,1,strlen(szSignature),out); - fwrite("\r\n",1,2,out); + 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; } + BufLen = fread(Buffer, 1, sizeof(Buffer), in); + if (BufLen > 0) { + fwrite(Buffer, 1, BufLen, out); + } else { + break; + } } fclose(in); } -/** Now go for verification **/ + /** Now go for verification **/ - else { - FILE* in = fopen(MsgFile,"rb"); + 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 + //#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; + vopts.pfnSelectorCallback = NULL; //SelectorCallback; - n = DKIMVerifyInit(&ctxt,&vopts); + n = DKIMVerifyInit(&ctxt, &vopts); while (1) { - BufLen = fread(Buffer,1,sizeof(Buffer),in); - if (BufLen > 0) { DKIMVerifyProcess(&ctxt,Buffer,BufLen); } - else { break; } + BufLen = fread(Buffer, 1, sizeof(Buffer), in); + if (BufLen > 0) { + DKIMVerifyProcess(&ctxt, Buffer, BufLen); + } else { + break; + } } n = DKIMVerifyResults(&ctxt); int nSigCount = 0; - DKIMVerifyDetails* pDetails; + DKIMVerifyDetails *pDetails; char szPolicy[512]; - n = DKIMVerifyGetDetails(&ctxt,&nSigCount,&pDetails,szPolicy); + 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 ) { + 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); + _DKIM_ReportResult(OutFile, s, 0); } else - printf(" Pass\n"); - } else { // fail + printf(" Pass\n"); + } else { // fail if (bRes) { - _DKIM_ReportResult(OutFile,f,error); + _DKIM_ReportResult(OutFile, f, error); } else - printf(" Fail %s \n",error); + printf(" Fail %s \n", error); } } DKIMVerifyFree(&ctxt); |