|
|
|
|
|
|
|
|
MilterContexts->logThisError(ContextName, Code, Message); // Log message.
|
|
|
MilterContexts->logThisError(ContextName, Code, Message); // Log message.
|
|
|
}
|
|
|
}
|
|
|
|
|
|
|
|
|
class ResultActionHandler : public Configurator {
|
|
|
|
|
|
|
|
|
class ResultActionHandler : public codedweller::Configurator {
|
|
|
private:
|
|
|
private:
|
|
|
SNFMilterEngine* Target;
|
|
|
SNFMilterEngine* Target;
|
|
|
|
|
|
|
|
|
public:
|
|
|
public:
|
|
|
ResultActionHandler(SNFMilterEngine* T) : Target(T) {}
|
|
|
ResultActionHandler(SNFMilterEngine* T) : Target(T) {}
|
|
|
void operator()(ConfigurationElement& E, ConfigurationData& D) {
|
|
|
|
|
|
|
|
|
void operator()(codedweller::ConfigurationElement& E, codedweller::ConfigurationData& D) {
|
|
|
Target->setResultAction(
|
|
|
Target->setResultAction(
|
|
|
Code,
|
|
|
Code,
|
|
|
(Action >= Allow && Action <= Quarantine) ?
|
|
|
(Action >= Allow && Action <= Quarantine) ?
|
|
|
|
|
|
|
|
|
NonZeroAction = NoAction; // NoAction if no configuration for
|
|
|
NonZeroAction = NoAction; // NoAction if no configuration for
|
|
|
// non-zero result.
|
|
|
// non-zero result.
|
|
|
ResultActionHandler ResultActionConfigurator(this); // Create a Result/Action handler.
|
|
|
ResultActionHandler ResultActionConfigurator(this); // Create a Result/Action handler.
|
|
|
ConfigurationElement Reader("milter"); // Create a configuration reader.
|
|
|
|
|
|
|
|
|
codedweller::ConfigurationElement Reader("milter"); // Create a configuration reader.
|
|
|
Reader
|
|
|
Reader
|
|
|
.Element("connect")
|
|
|
.Element("connect")
|
|
|
.Element("white")
|
|
|
.Element("white")
|
|
|
|
|
|
|
|
|
.End("nonzero")
|
|
|
.End("nonzero")
|
|
|
.End("scan")
|
|
|
.End("scan")
|
|
|
.End("milter");
|
|
|
.End("milter");
|
|
|
ConfigurationData ConfigurationData( // Convert our configuration string
|
|
|
|
|
|
|
|
|
codedweller::ConfigurationData ConfigurationData( // Convert our configuration string
|
|
|
NewConfiguration.c_str(), // to a configuration data buffer.
|
|
|
NewConfiguration.c_str(), // to a configuration data buffer.
|
|
|
NewConfiguration.length());
|
|
|
NewConfiguration.length());
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
SNFMilterEngine::~SNFMilterEngine() { // Destroy the engine.
|
|
|
SNFMilterEngine::~SNFMilterEngine() { // Destroy the engine.
|
|
|
try {
|
|
|
try {
|
|
|
ScopeMutex EngineLock(ConfigMutex); // Don't die while scanning.
|
|
|
|
|
|
|
|
|
codedweller::ScopeMutex EngineLock(ConfigMutex); // Don't die while scanning.
|
|
|
if(myEngine) { // If we're not dead then die.
|
|
|
if(myEngine) { // If we're not dead then die.
|
|
|
myEngine->close(); // Close the engine.
|
|
|
myEngine->close(); // Close the engine.
|
|
|
delete myEngine; // Delete it.
|
|
|
delete myEngine; // Delete it.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
SNFMilterAction SNFMilterEngine::scanIP(unsigned long int IP) { // Scans an IP.
|
|
|
SNFMilterAction SNFMilterEngine::scanIP(unsigned long int IP) { // Scans an IP.
|
|
|
IPTestRecord Tester(IP); // Make up a test record for this IP.
|
|
|
IPTestRecord Tester(IP); // Make up a test record for this IP.
|
|
|
ScopeMutex ConfigurationLock(ConfigMutex); // Lock our configuration.
|
|
|
|
|
|
|
|
|
codedweller::ScopeMutex ConfigurationLock(ConfigMutex); // Lock our configuration.
|
|
|
if(0 == myEngine) throw runtime_error("Null engine when scanning IP"); // Skip safely if we're down.
|
|
|
if(0 == myEngine) throw runtime_error("Null engine when scanning IP"); // Skip safely if we're down.
|
|
|
checkConfiguration(); // Re-read our config if it is old.
|
|
|
checkConfiguration(); // Re-read our config if it is old.
|
|
|
myRulebase->performIPTest(Tester); // Tun it past the engine.
|
|
|
myRulebase->performIPTest(Tester); // Tun it past the engine.
|
|
|
SNFMilterAction TestResult = Allow; // Allow by default.
|
|
|
SNFMilterAction TestResult = Allow; // Allow by default.
|
|
|
switch(Tester.R) { // Convert the result to an action.
|
|
|
switch(Tester.R) { // Convert the result to an action.
|
|
|
case White: { TestResult = WhiteAction; break; } // If the IP scan range is recognized
|
|
|
|
|
|
case Caution: { TestResult = CautionAction; break; } // in our configuration then we will
|
|
|
|
|
|
case Black: { TestResult = BlackAction; break; } // return the action code that is
|
|
|
|
|
|
case Truncate: { TestResult = TruncateAction; break; } // configured. Otherwise we will return
|
|
|
|
|
|
|
|
|
case snfIPRange::White: { TestResult = WhiteAction; break; } // If the IP scan range is recognized
|
|
|
|
|
|
case snfIPRange::Caution: { TestResult = CautionAction; break; } // in our configuration then we will
|
|
|
|
|
|
case snfIPRange::Black: { TestResult = BlackAction; break; } // return the action code that is
|
|
|
|
|
|
case snfIPRange::Truncate: { TestResult = TruncateAction; break; } // configured. Otherwise we will return
|
|
|
default: break;
|
|
|
default: break;
|
|
|
} // the default "Allow" action.
|
|
|
} // the default "Allow" action.
|
|
|
return TestResult; // Tell them what we've got.
|
|
|
return TestResult; // Tell them what we've got.
|
|
|
|
|
|
|
|
|
SNFMilterAction SNFMilterEngine::scanMessage( // Scans a message.
|
|
|
SNFMilterAction SNFMilterEngine::scanMessage( // Scans a message.
|
|
|
const unsigned char* bfr, // Requires a pointer to the buffer.
|
|
|
const unsigned char* bfr, // Requires a pointer to the buffer.
|
|
|
int length) { // Requires the buffer length.
|
|
|
int length) { // Requires the buffer length.
|
|
|
ScopeMutex ConfigurationLock(ConfigMutex); // Lock the configuration.
|
|
|
|
|
|
|
|
|
codedweller::ScopeMutex ConfigurationLock(ConfigMutex); // Lock the configuration.
|
|
|
if(0 == myEngine) throw runtime_error("Null engine when scanning message"); // Skip safely if we're down.
|
|
|
if(0 == myEngine) throw runtime_error("Null engine when scanning message"); // Skip safely if we're down.
|
|
|
checkConfiguration(); // Re-read our config if it is old.
|
|
|
checkConfiguration(); // Re-read our config if it is old.
|
|
|
int R = myEngine->scanMessage(bfr, length, "", 0); // Scan the message & get the result.
|
|
|
int R = myEngine->scanMessage(bfr, length, "", 0); // Scan the message & get the result.
|
|
|
|
|
|
|
|
|
}
|
|
|
}
|
|
|
|
|
|
|
|
|
string SNFMilterEngine::XHeaders() { // Return X headers from last scan.
|
|
|
string SNFMilterEngine::XHeaders() { // Return X headers from last scan.
|
|
|
ScopeMutex EngineLock(ConfigMutex); // Use myEngine safely.
|
|
|
|
|
|
|
|
|
codedweller::ScopeMutex EngineLock(ConfigMutex); // Use myEngine safely.
|
|
|
if(0 == myEngine) return ""; // Return no headers if dead.
|
|
|
if(0 == myEngine) return ""; // Return no headers if dead.
|
|
|
return myEngine->getXHDRs(); // Simply return them.
|
|
|
return myEngine->getXHDRs(); // Simply return them.
|
|
|
}
|
|
|
}
|
|
|
|
|
|
|
|
|
MilterSocketPort(0) {
|
|
|
MilterSocketPort(0) {
|
|
|
|
|
|
|
|
|
string NewConfiguration = myRulebase->PlatformConfiguration(); // Get the latest configuration.
|
|
|
string NewConfiguration = myRulebase->PlatformConfiguration(); // Get the latest configuration.
|
|
|
ConfigurationElement Reader("milter"); // Create a configuration reader.
|
|
|
|
|
|
|
|
|
codedweller::ConfigurationElement Reader("milter"); // Create a configuration reader.
|
|
|
Reader
|
|
|
Reader
|
|
|
.Element("socket")
|
|
|
.Element("socket")
|
|
|
.Attribute("type", reinterpret_cast<int&>(MilterSocketType), static_cast<int>(NOMilterSocket))
|
|
|
.Attribute("type", reinterpret_cast<int&>(MilterSocketType), static_cast<int>(NOMilterSocket))
|
|
|
|
|
|
|
|
|
.End("socket")
|
|
|
.End("socket")
|
|
|
.End("milter");
|
|
|
.End("milter");
|
|
|
|
|
|
|
|
|
ConfigurationData ConfigurationData( // Convert our configuration string
|
|
|
|
|
|
NewConfiguration.c_str(), // to a configuration data buffer.
|
|
|
|
|
|
NewConfiguration.length());
|
|
|
|
|
|
|
|
|
codedweller::ConfigurationData ConfigurationData( // Convert our configuration string
|
|
|
|
|
|
NewConfiguration.c_str(), // to a configuration data buffer.
|
|
|
|
|
|
NewConfiguration.length());
|
|
|
|
|
|
|
|
|
Reader.initialize(); // Initialize the defaults.
|
|
|
Reader.initialize(); // Initialize the defaults.
|
|
|
Reader.interpret(ConfigurationData); // Read the new configuration.
|
|
|
Reader.interpret(ConfigurationData); // Read the new configuration.
|
|
|
|
|
|
|
|
|
int SNFMilterContextPool::getSocketPort() { return MilterSocketPort; }
|
|
|
int SNFMilterContextPool::getSocketPort() { return MilterSocketPort; }
|
|
|
|
|
|
|
|
|
SNFMilterContextPool::~SNFMilterContextPool() { // Dtor gracefully discards contexts.
|
|
|
SNFMilterContextPool::~SNFMilterContextPool() { // Dtor gracefully discards contexts.
|
|
|
ScopeMutex ContextPoolLock(ContextAllocationControl); // Lock the context allocation system.
|
|
|
|
|
|
|
|
|
codedweller::ScopeMutex ContextPoolLock(ContextAllocationControl); // Lock the context allocation system.
|
|
|
myRulebase = 0; // Forget our rulebase. We're dead.
|
|
|
myRulebase = 0; // Forget our rulebase. We're dead.
|
|
|
for( // Loop through the context pool
|
|
|
for( // Loop through the context pool
|
|
|
vector<SNFMilterContext*>::iterator iC = ContextPool.begin(); // and delete any contexts we have
|
|
|
vector<SNFMilterContext*>::iterator iC = ContextPool.begin(); // and delete any contexts we have
|
|
|
|
|
|
|
|
|
}
|
|
|
}
|
|
|
|
|
|
|
|
|
SNFMilterContext* SNFMilterContextPool::grab() { // Get a context to use.
|
|
|
SNFMilterContext* SNFMilterContextPool::grab() { // Get a context to use.
|
|
|
ScopeMutex ContextPoolLock(ContextAllocationControl); // Lock the context allocation system.
|
|
|
|
|
|
|
|
|
codedweller::ScopeMutex ContextPoolLock(ContextAllocationControl); // Lock the context allocation system.
|
|
|
if(0 == myRulebase) return 0; // No contexts left if we're dead.
|
|
|
if(0 == myRulebase) return 0; // No contexts left if we're dead.
|
|
|
if(1 > AvailableContexts.size()) { // If we need more contexts then
|
|
|
if(1 > AvailableContexts.size()) { // If we need more contexts then
|
|
|
SNFMilterContext* N = new SNFMilterContext(myRulebase); // Create a new context,
|
|
|
SNFMilterContext* N = new SNFMilterContext(myRulebase); // Create a new context,
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
logInfo(ContextName, InfoCode, "Shutdown command received. Waiting for message processing to complete...");
|
|
|
logInfo(ContextName, InfoCode, "Shutdown command received. Waiting for message processing to complete...");
|
|
|
|
|
|
|
|
|
Sleeper WaitATic;
|
|
|
|
|
|
|
|
|
codedweller::Sleeper WaitATic;
|
|
|
|
|
|
|
|
|
try {
|
|
|
try {
|
|
|
|
|
|
|