void DKIMSigner::Sign(boost::shared_ptr<Message> message) { AnsiString senderAddress = message->GetFromAddress(); AnsiString senderDomain = StringParser::ExtractDomain(senderAddress); // Check if signing is enabled for this domain. boost::shared_ptr<const Domain> pDomain = CacheContainer::Instance()->GetDomain(senderDomain); if (!pDomain || !pDomain->GetDKIMEnabled()) return; LOG_DEBUG("Signing message using DKIM..."); AnsiString selector = pDomain->GetDKIMSelector(); AnsiString domain = pDomain->GetName(); AnsiString privateKeyFile = pDomain->GetDKIMPrivateKeyFile(); if (selector.IsEmpty() || privateKeyFile.IsEmpty()) { ErrorManager::Instance()->ReportError(ErrorManager::Medium, 5305, "DKIMSigner::Sign", "Either the selector or private key file was not specified."); return; } Canonicalization::CanonicalizeMethod headerMethod = (Canonicalization::CanonicalizeMethod) pDomain->GetDKIMHeaderCanonicalizationMethod(); Canonicalization::CanonicalizeMethod bodyMethod = (Canonicalization::CanonicalizeMethod) pDomain->GetDKIMBodyCanonicalizationMethod(); HashCreator::HashType algorithm = (HashCreator::HashType) pDomain->GetDKIMSigningAlgorithm(); DKIM dkim; if (!dkim.Sign(message, domain, selector, privateKeyFile, algorithm, headerMethod, bodyMethod)) { ErrorManager::Instance()->ReportError(ErrorManager::Medium, 5306, "DKIMSigner::Sign", "Message signing using DKIM failed."); } }
set<shared_ptr<SpamTestResult> > SpamTestDKIM::RunTest(shared_ptr<SpamTestData> pTestData) { shared_ptr<Message> pMessage = pTestData->GetMessageData()->GetMessage(); set<shared_ptr<SpamTestResult> > setSpamTestResults; const String fileName = PersistentMessage::GetFileName(pMessage); DKIM dkim; DKIM::Result result = dkim.Verify(fileName); if (result == DKIM::PermFail) { // Blocked AntiSpamConfiguration &config= Configuration::Instance()->GetAntiSpamConfiguration(); int iSomeScore = config.GetDKIMVerificationFailureScore(); shared_ptr<SpamTestResult> pResult = shared_ptr<SpamTestResult>(new SpamTestResult(GetName(), SpamTestResult::Fail, iSomeScore, "Rejected by DKIM.")); setSpamTestResults.insert(pResult); } else if (result == DKIM::Pass) { shared_ptr<SpamTestResult> pResult = shared_ptr<SpamTestResult>(new SpamTestResult(GetName(), SpamTestResult::Pass, 0, "")); setSpamTestResults.insert(pResult); } return setSpamTestResults; }
void _SignMailTest(const SignatoryOptions& options, const std::string& mail) { std::string head; std::stringstream fp; std::stringstream fp2; std::string DKIMPublicKey = "v=DKIM1; p=" DKIM_PUBLICKEY "; t=s"; fp.str(mail); CPPUNIT_ASSERT_NO_THROW ( head = Signatory(fp).CreateSignature(options) ); fp2.str(head + "\r\n" + mail); Validatory myValidatory(fp2); const Validatory::SignatureList& siglist = myValidatory.GetSignatures(); CPPUNIT_ASSERT ( siglist.size() == 1 ); DKIM::Signature sig; CPPUNIT_ASSERT_NO_THROW ( myValidatory.GetSignature(siglist.begin(), sig) ); DKIM::PublicKey pub; CPPUNIT_ASSERT_NO_THROW ( pub.Parse(DKIMPublicKey) ); CPPUNIT_ASSERT_NO_THROW ( myValidatory.CheckSignature(siglist.begin(), sig, pub) ); CPPUNIT_ASSERT_NO_THROW ( myValidatory.CheckSignature(*(siglist.begin()), sig, pub) ); }
int main(int argc, char* argv[]) { __progname = argv[0]; bool validate = false; bool doubleDots = false; std::string selector; std::string domain; std::string keyfile; // no arguments if (argc < 2) usage(stderr, 2); // longopts static struct option longopts[] = { { "help", no_argument, NULL, 'h' }, { "doubledots", no_argument, NULL, 'D' }, { "validate", no_argument, NULL, 'v' }, { "selector", required_argument, NULL, 's' }, { "domain", required_argument, NULL, 'd' }, { "keyfile", required_argument, NULL, 'k' }, { NULL, 0, NULL, 0 } }; // fetching arguments.. opterr = 0; optind = 0; int ch; while ((ch = getopt_long(argc, argv, "hvs:d:k:D", longopts, NULL)) != -1) { switch (ch) { case 'D': doubleDots = true; break; case 'v': validate = true; break; case 'h': usage(stdout, 0); break; case 's': selector = optarg; break; case 'd': domain = optarg; break; case 'k': keyfile = optarg; break; case 0: break; default: usage(stderr, 2); break; } } argc -= optind; argv += optind; if (argc < 1) usage(stderr, 2); if (!validate && (selector.empty() || domain.empty() || keyfile.empty())) usage(stderr, 2); // sign the message.. if (!validate) { // readkey std::ifstream kfp(keyfile); if (!kfp) { fprintf(stderr, "keyfile %s could not be open\n", keyfile.c_str()); return 1; } std::string key((std::istreambuf_iterator<char>(kfp)), std::istreambuf_iterator<char>()); std::ifstream fp(argv[0]); try { printf("%s\r\n", Signatory(fp, doubleDots).CreateSignature( SignatoryOptions() .SetPrivateKey(key) .SetDomain(domain) .SetSelector(selector) .SetCanonModeHeader(DKIM::DKIM_C_RELAXED) .SetCanonModeBody(DKIM::DKIM_C_RELAXED) ).c_str() ); } catch (std::runtime_error& e) { fprintf(stderr, "%s\n", e.what()); return 1; } return 0; } // validate messages (0 .. argv) for (int x = 0; x < argc; x++) { std::ifstream fp(argv[x]); Validatory mail(fp, doubleDots); mail.CustomDNSResolver = MyResolver; // first check ADSP status try { std::list<ADSP> adsp; mail.GetADSP(adsp); for (std::list<ADSP>::const_iterator i = adsp.begin(); i != adsp.end(); ++i) { printf("[%s][ADSP][%s] %s/%s\n", argv[x], i->GetDomain().c_str(), i->GetResultAsString().c_str(), i->GetReason().c_str()); } } catch (DKIM::TemporaryError& e) { printf("[%s][ADSP] TEMPERR:%s\n", argv[x], e.what()); } catch (DKIM::PermanentError& e) { printf("[%s][ADSP] PERMERR:%s\n", argv[x], e.what()); } // then list all valid SDID's for (Validatory::SignatureList::const_iterator i = mail.GetSignatures().begin(); i != mail.GetSignatures().end(); ++i) { DKIM::PublicKey pub; DKIM::Signature sig; try { mail.GetSignature(i, sig); mail.GetPublicKey(sig, pub); mail.CheckSignature(i, sig, pub); printf("[%s][%s] OK\n", argv[x], sig.GetDomain().c_str()); } catch (DKIM::TemporaryError& e) { printf("[%s][%s] TEMPERR:%s\n", argv[x], sig.GetDomain().c_str(), e.what()); } catch (DKIM::PermanentError& e) { if (pub.SoftFail()) printf("[%s][%s] SOFT:%s\n", argv[x], sig.GetDomain().c_str(), e.what()); else printf("[%s][%s] = %s\n", argv[x], sig.GetDomain().c_str(), e.what()); } } } return 0; }