23#define _strnicmp strncasecmp
24#define _stricmp strcasecmp
25#define LOWORD(l) ((unsigned)(l) & 0xffff)
26#define HIWORD(l) ((unsigned)(l) >> 16)
122#if ((OPENSSL_VERSION_NUMBER < 0x10100000L) || (LIBRESSL_VERSION_NUMBER > 0 && LIBRESSL_VERSION_NUMBER < 0x20700000L))
140 m_Hdr_ed25519ctx = EVP_MD_CTX_create();
142 m_Edy_sha256ctx = EVP_MD_CTX_create();
143 EVP_DigestInit_ex(m_Edy_sha256ctx,EVP_sha256(),NULL);
149#if ((OPENSSL_VERSION_NUMBER < 0x10100000L) || (LIBRESSL_VERSION_NUMBER > 0 && LIBRESSL_VERSION_NUMBER < 0x20700000L))
157 EVP_MD_CTX_free(m_Hdr_ed25519ctx);
160 EVP_MD_CTX_free(m_Edy_sha256ctx);
216#if ((OPENSSL_VERSION_NUMBER > 0x10101000L))
253#if ((OPENSSL_VERSION_NUMBER < 0x10100000L) || (LIBRESSL_VERSION_NUMBER > 0 && LIBRESSL_VERSION_NUMBER < 0x20700000L))
261#if ((OPENSSL_VERSION_NUMBER < 0x10100000L) || (LIBRESSL_VERSION_NUMBER > 0 && LIBRESSL_VERSION_NUMBER < 0x20700000L))
266#if ((OPENSSL_VERSION_NUMBER > 0x10101000L))
269 SigHdrs.append(szBuffer,nBufLength);
276#if ((OPENSSL_VERSION_NUMBER < 0x10100000L) || (LIBRESSL_VERSION_NUMBER > 0 && LIBRESSL_VERSION_NUMBER < 0x20700000L))
282#if ((OPENSSL_VERSION_NUMBER < 0x10100000L) || (LIBRESSL_VERSION_NUMBER > 0 && LIBRESSL_VERSION_NUMBER < 0x20700000L))
287#if ((OPENSSL_VERSION_NUMBER > 0x10101000L))
290 EVP_DigestUpdate(m_Edy_sha256ctx,szBuffer,nBufLength);
304 if (
_strnicmp(sTag.c_str(),
"X-",2) == 0 ||
305 _stricmp(sTag.c_str(),
"Authentication-Results:") == 0 ||
306 _stricmp(sTag.c_str(),
"Return-Path:") == 0) {
315 bool bConvert =
false;
318 static unsigned char hexchars[16] = {
'0',
'1',
'2',
'3',
'4',
'5',
'6',
'7',
'8',
'9',
'A',
'B',
'C',
'D',
'E',
'F'};
320 unsigned char *
d = (
unsigned char*)dest;
321 for (
const unsigned char *s = (
const unsigned char *)source; *s !=
'\0'; s++)
323 if (*s >= 33 && *s <= 126 && *s !=
'=' && *s !=
':' && *s !=
';' && *s !=
'|') {
328 *
d++ = hexchars[*s >> 4];
329 *
d++ = hexchars[*s & 15];
344 if (
_strnicmp(sHdr.c_str(),
"X",1) == 0)
return;
345 if (
_strnicmp(sHdr.c_str(),
"From:",5) == 0) {
sFrom.assign(sHdr.c_str() + 5); }
346 if (
_strnicmp(sHdr.c_str(),
"Sender:",7) == 0) {
sSender.assign(sHdr.c_str() + 7); }
349 string::size_type pos = sHdr.find(
':');
351 if (pos != string::npos) {
353 char *workBuffer =
new char[sHdr.size() * 3 + 1];
355 sTag.assign(sHdr.substr(0,pos));
356 sValue.assign(sHdr.substr(pos + 1,string::npos));
376 map<string,list<string>::reverse_iterator> IterMap;
377 map<string,list<string>::reverse_iterator>::iterator IterMapIter;
378 list<string>::reverse_iterator riter;
379 list<string>::iterator iter;
381 bool bFromHeaderFound =
false;
388 string::size_type pos = sTag.find(
':');
390 if (pos != string::npos) {
391 int nSignThisTag = 1;
394 sTag.erase(pos + 1,string::npos);
397 if (
_stricmp(sTag.c_str(),
"From:") == 0) {
398 bFromHeaderFound =
true;
417 if (nSignThisTag > 0) {
421 IterMapIter = IterMap.find(sTag);
423 riter = (IterMapIter == IterMap.end()) ?
HeaderList.rbegin() : IterMapIter->second;
427 if (
_strnicmp(riter->c_str(),sTag.c_str(),sTag.size()) == 0) {
432 IterMap[sTag] = riter;
441 if(!bFromHeaderFound) {
442 string sFrom(
"From:");
468 Hash(sHdr.c_str(),sHdr.size(),
true);
477 for (
char *s = (
char*)sTemp.c_str(); *s !=
'\0' && *s !=
':'; s++) {
478 if (*s >=
'A' && *s <=
'Z')
482 Hash(sTemp.c_str(),sTemp.size(),
true);
489 Hash(sTemp.c_str(),sTemp.length(),
true);
500 if (nBufLength > 0) {
502 Hash(
"\r\n",2,
false);
506 Hash(szBuffer,nBufLength,
false);
507 Hash(
"\r\n",2,
false);
512 Hash(
"\r\n",2,
false);
519 if (nBufLength > 0) {
520 Hash(szBuffer,nBufLength,
false);
526 if (nBufLength > 0) {
528 Hash(
"\r\n",2,
false);
532 Hash(szBuffer,nBufLength,
false);
535 Hash(
"\r\n",2,
false);
548 string::size_type pos;
551 if (!
sFrom.empty()) {
552 sAddress.assign(
sFrom);
562 pos = sAddress.find(
'<');
563 if(pos != string::npos)
564 sAddress.erase(0,pos);
567 pos = sAddress.find(
'>');
568 if (pos != string::npos)
569 sAddress.erase(pos,string::npos);
572 pos = sAddress.find(
'@');
573 if (pos == string::npos)
577 sDomain.assign (sAddress.c_str() + pos + 1);
592 m_sSig.assign(
"DKIM-Signature:");
604 int nTagLen = strlen(Tag);
630 sprintf(szValue,
"%lu",nValue);
659 string::size_type pos = 0;
663 while (pos < sValue.size()) {
665 if (len > sValue.size() - pos)
666 len = sValue.size() - pos;
667 m_sSig.append(sValue.substr(pos,len));
671 if (pos < sValue.size()) {
679 while (pos < sValue.size()) {
681 string::size_type brkpos;
683 if (sValue.size() - pos < len) {
684 brkpos = sValue.size();
686 brkpos = sValue.rfind(cbrk,pos + len);
689 if (brkpos == string::npos || brkpos < pos) {
690 brkpos = sValue.find(cbrk,pos);
691 if (brkpos == string::npos) {
692 brkpos = sValue.size();
696 len = brkpos - pos + 1;
698 m_sSig.append(sValue.substr(pos,len));
703 if (pos < sValue.size()) {
719 if (szRSAKey == NULL && szECCKey == NULL) {
723 if (pszSignature == NULL) {
746 string::size_type start = 0;
749 while (end != string::npos) {
830 unsigned char Hash[4096];
831 unsigned int nHashLen = 0;
835#if ((OPENSSL_VERSION_NUMBER < 0x10100000L) || (LIBRESSL_VERSION_NUMBER > 0 && LIBRESSL_VERSION_NUMBER < 0x20700000L))
841#if ((OPENSSL_VERSION_NUMBER < 0x10100000L) || (LIBRESSL_VERSION_NUMBER > 0 && LIBRESSL_VERSION_NUMBER < 0x20700000L))
846#if (OPENSSL_VERSION_NUMBER > 0x10101000L)
848 EVP_DigestFinal_ex(m_Edy_sha256ctx,
Hash,&nHashLen);
break;
852 bio = BIO_new(BIO_s_mem());
855 b64 = BIO_new(BIO_f_base64());
860 BIO_set_flags(b64,BIO_FLAGS_BASE64_NO_NL);
862 if (BIO_write(b64,
Hash,nHashLen) < (
int)nHashLen) {
895 sSignedSig.assign(
m_sSig.c_str());
905 sTemp = sSignedSig.c_str();
912#if ((OPENSSL_VERSION_NUMBER < 0x10100000L) || (LIBRESSL_VERSION_NUMBER > 0 && LIBRESSL_VERSION_NUMBER < 0x20700000L))
913 EVP_SignUpdate(&
m_Hdr_sha1ctx,sTemp.c_str(),sTemp.size());
break;
915 EVP_SignUpdate(
m_Hdr_sha1ctx,sTemp.c_str(),sTemp.size());
break;
918#if ((OPENSSL_VERSION_NUMBER < 0x10100000L) || (LIBRESSL_VERSION_NUMBER > 0 && LIBRESSL_VERSION_NUMBER < 0x20700000L))
923#if ((OPENSSL_VERSION_NUMBER > 0x10101000L))
925 SigHdrs.append(sTemp.c_str(),sTemp.size());
930 bio = BIO_new_mem_buf(szPrivKey, -1);
933 pkey = PEM_read_bio_PrivateKey(bio,NULL,NULL,NULL);
937 siglen = EVP_PKEY_size(pkey);
939 sig = (
unsigned char*) OPENSSL_malloc(siglen);
948 unsigned char* SignMsg;
952#if ((OPENSSL_VERSION_NUMBER < 0x10100000L) || (LIBRESSL_VERSION_NUMBER > 0 && LIBRESSL_VERSION_NUMBER < 0x20700000L))
953 nSignRet = EVP_SignFinal(&
m_Hdr_sha1ctx,sig,&siglen,pkey);
break;
955 nSignRet = EVP_SignFinal(
m_Hdr_sha1ctx,sig,&siglen,pkey);
break;
958#if ((OPENSSL_VERSION_NUMBER < 0x10100000L) || (LIBRESSL_VERSION_NUMBER > 0 && LIBRESSL_VERSION_NUMBER < 0x20700000L))
963#if (OPENSSL_VERSION_NUMBER > 0x10101000L)
965 EVP_DigestSignInit(m_Hdr_ed25519ctx,NULL,NULL,NULL,pkey);
966 SignMsg = (
unsigned char*)
SigHdrs.c_str();
967 EVP_DigestSign(m_Hdr_ed25519ctx,NULL,&sig_len,SignMsg,
m_SigHdrs);
968 sig = (
unsigned char*) OPENSSL_malloc(sig_len);
969 nSignRet = EVP_DigestSign(m_Hdr_ed25519ctx,sig,&sig_len,SignMsg,
m_SigHdrs);
970 siglen = (
unsigned int) sig_len;
break;
980 bio = BIO_new(BIO_s_mem());
985 b64 = BIO_new(BIO_f_base64());
991 BIO_set_flags(b64,BIO_FLAGS_BASE64_NO_NL);
994 if (BIO_write(b64,sig,siglen) < (
int) siglen) {
1003 buf =
new char[len];
1046 string ed25519Sig, sha256Sig, sha1Sig;
1052 ed25519Sig.assign(
m_sSig);
1063 sha256Sig.assign(
m_sSig);
1082 if (!ed25519Sig.empty()) {
1090 if (!sha1Sig.empty()) {
1097 if (!sha256Sig.empty()) {
static string RelaxHeader(const string &sHeader)
static void CompressSWSP(char *pBuffer, int &nBufLength)
static void RemoveSWSP(char *szBuffer)
list< string > HeaderList
DKIMHEADERCALLBACK m_pfnHdrCallback
EVP_MD_CTX m_Bdy_sha256ctx
int GetSig2(char *szRSAPrivKey, char *szECCPrivKey, char **pszSignature)
bool ParseFromAddress(void)
int m_nIncludeCopiedHeaders
void AddInterTagSpace(int nSizeOfNextTag)
void ProcessHeader(const string &sHdr)
bool IsRequiredHeader(const string &sTag)
void GetHeaderParams(const string &sHdr)
bool m_IncludeBodyLengthTag
virtual int ProcessBody(char *szBuffer, int nBufLength, bool bEOF) override
void AddTagToSig(const char *const Tag, const string &sValue, char cbrk, bool bFold)
int ConstructSignature(char *szSignKey, int nSigAlg)
void AddFoldedValueToSig(const string &sValue, char cbrk)
bool m_bReturnedSigAssembled
int AssembleReturnedSig(char *szRSAPrivKey, char *szECCPrivKey)
virtual int ProcessHeaders(void) override
bool SignThisTag(const string &sTag)
void Hash(const char *szBuffer, int nBufLength, bool bHdr)
int m_nIncludeQueryMethod
EVP_MD_CTX m_Hdr_sha256ctx
@ OptimalHeaderLineLength
#define DKIM_BUFFER_TOO_SMALL
#define DKIM_CANON_SIMPLE
#define DKIM_OUT_OF_MEMORY
#define DKIM_CANON_RELAXED
#define DKIM_HASH_RSA256_AND_ED25519
#define DKIM_BAD_PRIVATE_KEY
#define DKIM_SIGN_RELAXED
#define DKIM_HASH_SHA1_AND_SHA256
#define DKIM_SIGN_RELAXED_SIMPLE
#define DKIM_SIGN_SIMPLE_RELAXED
#define DKIM_HASH_ED25519
bool ConvertHeaderToQuotedPrintable(const char *source, char *dest)
int nIncludeBodyLengthTag
DKIMHEADERCALLBACK pfnHeaderCallback
int nIncludeCopiedHeaders