366 static const unsigned char base64_table[256] = {
367 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
368 255,255,255,255,255,255,255,255,255,255,255, 62,255,255,255, 63, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61,255,255,255,255,255,255,
369 255, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25,255,255,255,255,255,
370 255, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51,255,255,255,255,255,
371 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
372 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
373 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
374 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255 };
376 unsigned char* s = (
unsigned char* )ptr;
377 unsigned char*
d = (
unsigned char* )ptr;
378 unsigned b64accum = 0;
379 unsigned char b64shift = 0;
382 unsigned char value = base64_table[*s++];
383 if ((
signed char) value >= 0) {
384 b64accum = (b64accum << 6) | value;
388 *
d++ = (b64accum >> b64shift);
393 return (
char* )
d-ptr;
566 unsigned char *SignMsg;
567 unsigned SuccessCount = 0;
568 int TestingFailures = 0;
569 int RealFailures = 0;
572 list<string> SuccessfulDomains;
576 if (!i->BodyHashData.empty()) {
577 unsigned char md[EVP_MAX_MD_SIZE];
580 res = EVP_DigestFinal_ex(i->m_Bdy_ctx,md,&len);
581 EVP_MD_CTX_reset(i->m_Bdy_ctx);
585 if (!res || len != i->BodyHashData.length() || memcmp(i->BodyHashData.data(),md,len) != 0) {
589 if (i->m_pSelector->Testing) {
605 string sSignedSig = i->Header;
606 string sSigValue = sSignedSig.substr(sSignedSig.find(
':') + 1);
608 static const char* tags[] = {
"b",NULL};
609 char* values[
sizeof(tags)/
sizeof(tags[0])] = {NULL};
611 char* pSigValue = (
char* ) sSigValue.c_str();
613 sSignedSig.erase(15 + values[0] - pSigValue,strlen(values[0]));
622 sSignedSig.replace(0,14,
"dkim-signature",14);
625 i->Hash(sSignedSig.c_str(),sSignedSig.length());
626 assert(i->m_pSelector != NULL);
628 if (EVP_PKEY_base_id(i->m_pSelector->PublicKey) != EVP_PKEY_ED25519)
629 res = EVP_VerifyFinal(i->m_Hdr_ctx,(
unsigned char *)i->SignatureData.data(),i->SignatureData.length(),i->m_pSelector->PublicKey);
630 else if (EVP_PKEY_base_id(i->m_pSelector->PublicKey) == EVP_PKEY_ED25519) {
631 EVP_DigestVerifyInit(i->m_Msg_ctx,NULL,NULL,NULL,i->m_pSelector->PublicKey);
633 SignMsg = (
unsigned char *)
SigHdr.data();
634 res = EVP_DigestVerify(i->m_Msg_ctx,(
unsigned char *)i->SignatureData.data(),(
size_t)i->SignatureData.length(),
639 if (i->UnverifiedBodyCount == 0)
644 SuccessfulDomains.push_back(i->Domain);
647 if (i->m_pSelector->Testing) {
669 if (
_strnicmp(i->c_str(),
"From",4) == 0) {
671 const char* s = i->c_str() + 4;
672 while (*s ==
' ' || *s ==
'\t')
675 vector<string> Addresses;
677 unsigned atpos = Addresses[0].find(
'@');
678 sFromDomain = Addresses[0].substr(atpos + 1);
688 if (SuccessCount > 0 && !sFromDomain.empty()) {
689 for (list<string>::iterator i = SuccessfulDomains.begin(); i != SuccessfulDomains.end(); ++i) {
691 if (i->length() > sFromDomain.length())
693 if (
_stricmp(i->c_str(),sFromDomain.c_str() + sFromDomain.length() - i->length()) != 0)
695 if (i->length() == sFromDomain.length() || sFromDomain.c_str()[sFromDomain.length() - i->length() - 1] ==
'.') {