Create any config files that don't exist from the sample files. SNFMilterConfig is responsible for saving and restoring all config files. SNFIdentity is deprecated. git-svn-id: https://svn.microneil.com/svn/SNFUtility/trunk@8 aa37657e-1934-4a5f-aa6d-2d8eab27ff7cmaster
// This file implements the common functionality for the configuration | // This file implements the common functionality for the configuration | ||||
// utilities. | // utilities. | ||||
#include <sstream> | |||||
#include <stdexcept> | |||||
#include <fstream> | |||||
#include <cerrno> | #include <cerrno> | ||||
#include <cstring> | #include <cstring> | ||||
#include <cstdio> | #include <cstdio> | ||||
#include <sstream> | |||||
#include <stdexcept> | |||||
#include <fstream> | |||||
#include "FileBackup.hpp" | #include "FileBackup.hpp" | ||||
////////////////////////////////////////////////////////////////////////////////////////////////////////// | ////////////////////////////////////////////////////////////////////////////////////////////////////////// | ||||
void | void | ||||
FileBackup::CreateBackupFile(std::string File) { | FileBackup::CreateBackupFile(std::string File) { | ||||
if (OriginalFileExists[File] = FileExists(File)) { // Back up if the file exists. | |||||
bool ThisFileExists = FileExists(File); | |||||
if (ThisFileExists) { // Back up if the file exists. | |||||
try { | try { | ||||
} | } | ||||
OriginalFileExists[File] = ThisFileExists; | |||||
} | } | ||||
void | void | ||||
iFile++) { | iFile++) { | ||||
std::string BackupFileName; | std::string BackupFileName; | ||||
if (iFile->second) { // Original file existed? | if (iFile->second) { // Original file existed? | ||||
try { // Yes. | try { // Yes. | ||||
} else { // No. | } else { // No. | ||||
if (0 != remove(iFile->first.c_str())) { | |||||
if (FileExists(iFile->first)) { | |||||
ErrorMessage << "Unable to remove backup file " << BackupFileName | |||||
<< ": " << strerror(errno) << "\n"; | |||||
if (0 != remove(iFile->first.c_str())) { | |||||
ErrorOccurred = true; | |||||
ErrorMessage << "Unable to remove backup file " << BackupFileName | |||||
<< ": " << strerror(errno) << "\n"; | |||||
ErrorOccurred = true; | |||||
} | |||||
} | } | ||||
// | // | ||||
/////////////////////////////////////////////////////////////////////////////////////////////////// | /////////////////////////////////////////////////////////////////////////////////////////////////// | ||||
#include <iostream> | |||||
#include "MtaIntegrate.hpp" | #include "MtaIntegrate.hpp" | ||||
MtaIntegrate::MtaIntegrate() { | MtaIntegrate::MtaIntegrate() { |
// | // | ||||
virtual void Unintegrate(FileBackup *SaveFile) = 0; | virtual void Unintegrate(FileBackup *SaveFile) = 0; | ||||
/// Check whether the MTA is determined to be running. | |||||
// | |||||
// \return true if the MTA is determined to be running. If the | |||||
// MTA is not running, or the running status cannot be determined, | |||||
// the return value is false. | |||||
// | |||||
virtual bool MtaIsRunningDetected() = 0; | |||||
/// Reload the MTA configuration. | |||||
// | |||||
// This method causes the MTA to reload its configuration. | |||||
// | |||||
// \return true if the MTA successfully reloaded its | |||||
// configuration, false otherwise. | |||||
// | |||||
virtual bool ReloadMta() = 0; | |||||
private: | private: | ||||
/// Determine whether the MTA is integrated. | /// Determine whether the MTA is integrated. |
// End of configuration. ///////////////////////////////////////////////////////////////////////////////// | // End of configuration. ///////////////////////////////////////////////////////////////////////////////// | ||||
////////////////////////////////////////////////////////////////////////////////////////////////////////// | ////////////////////////////////////////////////////////////////////////////////////////////////////////// | ||||
Utility::Utility() { | |||||
} | |||||
bool | bool | ||||
Utility::FileExists(const std::string File) { | Utility::FileExists(const std::string File) { | ||||
void | void | ||||
Utility::SetOwnerGroup(std::string &File) { | |||||
Utility::SetOwnerGroup(std::string File) { | |||||
struct passwd *SNFPasswd; | struct passwd *SNFPasswd; | ||||
uid_t SNFUid; | uid_t SNFUid; | ||||
} | } | ||||
void | void | ||||
Utility::SetMode(std::string &File, mode_t mode) { | |||||
Utility::SetMode(std::string File, mode_t mode) { | |||||
if (Verbose()) { | if (Verbose()) { | ||||
} | } | ||||
std::string | |||||
Utility::Trim(std::string String) { | |||||
std::string Whitespace(" \n\r\t"); | |||||
std::string::size_type End = String.find_last_not_of(Whitespace); | |||||
if (End == std::string::npos) { | |||||
return std::string(); | |||||
} | |||||
std::string::size_type Start = String.find_first_not_of(Whitespace); | |||||
if (Start == std::string::npos) { | |||||
Start = 0; | |||||
} | |||||
return String.substr(Start, (End - Start) + 1); | |||||
} | |||||
void | void | ||||
Utility::SetVerbose(bool Mode) { | Utility::SetVerbose(bool Mode) { | ||||
// | // | ||||
// \see SNFGroupName. | // \see SNFGroupName. | ||||
// | // | ||||
void SetOwnerGroup(std::string &File); | |||||
void SetOwnerGroup(std::string File); | |||||
/// Set the mode of a file. | /// Set the mode of a file. | ||||
// | // | ||||
// | // | ||||
// \param[in] is the mode. | // \param[in] is the mode. | ||||
// | // | ||||
void SetMode(std::string &File, mode_t mode); | |||||
void SetMode(std::string File, mode_t mode); | |||||
/// Create a directory. | /// Create a directory. | ||||
// | // | ||||
// | // | ||||
static bool CheckForString(std::string Line, std::string SearchString); | static bool CheckForString(std::string Line, std::string SearchString); | ||||
/// Trim whitespace from a string. | |||||
// | |||||
// This method removes leading " ", "\t", "\r", and "\n" from the specified string. | |||||
// | |||||
// \param[in] String is the string to trim. | |||||
// | |||||
// \returns String with the leading and trailing whitespace removed. | |||||
static std::string Trim(std::string String); | |||||
/// Store the Verbose mode. | /// Store the Verbose mode. | ||||
// | // | ||||
// \param[in] Mode stores the Verbose mode. | // \param[in] Mode stores the Verbose mode. | ||||
/// Directory separator. | /// Directory separator. | ||||
static const std::string DirectorySeparator; | static const std::string DirectorySeparator; | ||||
/// Trim whitespace from a string. | |||||
private: | private: | ||||
bool VerboseRequested; ///< User requested verbose processing. | bool VerboseRequested; ///< User requested verbose processing. |
// Configuration. //////////////////////////////////////////////////////////////////////////////////////// | // Configuration. //////////////////////////////////////////////////////////////////////////////////////// | ||||
////////////////////////////////////////////////////////////////////////////////////////////////////////// | ////////////////////////////////////////////////////////////////////////////////////////////////////////// | ||||
// Initialize sample ignore list file path. | |||||
// Initialize OS-dependent constants. | |||||
#ifdef WIN | #ifdef WIN | ||||
// Windows OS. | // Windows OS. | ||||
const std::string UtilityConfig::SampleIgnoreListFile("C:\\SNF\\GBUdbIgnoreList.txt.sample"); | const std::string UtilityConfig::SampleIgnoreListFile("C:\\SNF\\GBUdbIgnoreList.txt.sample"); | ||||
const std::string UtilityConfig::RulebaseDownloadCommand("FIX THIS"); | |||||
const std::string ScriptNameKey("FIX THIS"); ///< Text to replace with script name. | |||||
const std::string SnifferPathKey("FIX THIS"); ///< Text to replace with directory of the rulebase. | |||||
const std::string UtilityConfig::SampleRulebaseScriptFile("C:\\SNF\\getRulebase.sample"); | |||||
const std::string UtilityConfig::OperatingSystemType("Windows"); | |||||
#else | #else | ||||
// *nix OS. | |||||
// SCRIPT is replaced with the full path of the script run, | |||||
// SNIFFER_PATH is replaced with the path of the rulebase. | |||||
const std::string UtilityConfig::RulebaseDownloadCommand | |||||
("(cd SNIFFER_PATH; touch UpdateReady.txt; chown snfuser UpdateReady.txt; su -m snfuser -c SCRIPT)"); | |||||
const std::string ScriptNameKey("SCRIPT"); ///< Text to replace with script name. | |||||
const std::string SnifferPathKey("SNIFFER_PATH"); ///< Text to replace with directory of the rulebase. | |||||
#ifdef DEFAULT_DATA_DIR | #ifdef DEFAULT_DATA_DIR | ||||
// *nix, DEFAULT_DATA_DIR is specified on the compile command line. | // *nix, DEFAULT_DATA_DIR is specified on the compile command line. | ||||
const std::string UtilityConfig::SampleIgnoreListFile(DEFAULT_DATA_DIR "/GBUdbIgnoreList.txt.sample"); | const std::string UtilityConfig::SampleIgnoreListFile(DEFAULT_DATA_DIR "/GBUdbIgnoreList.txt.sample"); | ||||
#error DEFAULT_DATA_DIR must be defined by -DDEFAULT_DATA_DIR="..." when compiling. | #error DEFAULT_DATA_DIR must be defined by -DDEFAULT_DATA_DIR="..." when compiling. | ||||
#endif | #endif | ||||
#endif | |||||
// Initialize sample rulebase script file. | |||||
#ifdef WIN | |||||
// Windows OS. | |||||
const std::string UtilityConfig::SampleRulebaseScriptFile("C:\\SNF\\getRulebase.sample"); | |||||
#else | |||||
#ifdef SBIN_DIR | #ifdef SBIN_DIR | ||||
// *nix, SBIN_DIR is specified on the compile command line. | // *nix, SBIN_DIR is specified on the compile command line. | ||||
const std::string UtilityConfig::SampleRulebaseScriptFile(SBIN_DIR "/getRulebase.sample"); | const std::string UtilityConfig::SampleRulebaseScriptFile(SBIN_DIR "/getRulebase.sample"); | ||||
#error SBIN_DIR must be defined by -DSBIN_DIR="..." when compiling. | #error SBIN_DIR must be defined by -DSBIN_DIR="..." when compiling. | ||||
#endif | #endif | ||||
#endif | |||||
// Initialize OS-specific values. | |||||
#ifdef WIN | |||||
// Windows OS. | |||||
const std::string UtilityConfig::OperatingSystemType("Windows"); | |||||
#else | |||||
#ifdef SNF_OSTYPE | #ifdef SNF_OSTYPE | ||||
// *nix, SNF_OSTYPE is specified on the compile command line. | // *nix, SNF_OSTYPE is specified on the compile command line. | ||||
const std::string UtilityConfig::OperatingSystemType(SNF_OSTYPE); | const std::string UtilityConfig::OperatingSystemType(SNF_OSTYPE); | ||||
// line. In this case, we don't know the operating system. | // line. In this case, we don't know the operating system. | ||||
#error SNF_OSTYPE must be defined by -DSNF_OSTYPE="..." when compiling. | #error SNF_OSTYPE must be defined by -DSNF_OSTYPE="..." when compiling. | ||||
#endif | #endif | ||||
#endif | #endif | ||||
/// Verbose command-line input. | /// Verbose command-line input. | ||||
/// Help command-line input. | /// Help command-line input. | ||||
const string HelpKey("-h"); | const string HelpKey("-h"); | ||||
/// Configuration file command-line input. | |||||
const string ConfigFileKey("-config="); | |||||
/// License ID command-line input. | |||||
const string LicenseIdKey("-id="); | |||||
/// Authentication command-line input. | |||||
const string AuthenticationKey("-auth="); | |||||
const string LicenseSearchString = "LICENSE_ID="; | |||||
const string AuthSearchString = "AUTHENTICATION="; | |||||
////////////////////////////////////////////////////////////////////////////////////////////////////////// | ////////////////////////////////////////////////////////////////////////////////////////////////////////// | ||||
// End of configuration. ///////////////////////////////////////////////////////////////////////////////// | // End of configuration. ///////////////////////////////////////////////////////////////////////////////// | ||||
////////////////////////////////////////////////////////////////////////////////////////////////////////// | ////////////////////////////////////////////////////////////////////////////////////////////////////////// | ||||
UtilityConfig::UtilityConfig() { | |||||
UtilityConfig::UtilityConfig() : | |||||
LicenseIdIsSpecified(false), AuthenticationIsSpecified(false), ConfigFileExists(true) | |||||
{ | |||||
SetExplain(false); | SetExplain(false); | ||||
SetVerbose(false); | SetVerbose(false); | ||||
} | } | ||||
void | void | ||||
UtilityConfig::CheckAndLoadConfigFile(const std::string DefaultFile[], int NumDefaultFiles) { | |||||
UtilityConfig::CheckAndSetConfigFileName(const std::string DefaultFile[], int NumDefaultFiles) { | |||||
string ProvisionalConfigFile = ConfigFile; | |||||
string ProvisionalConfigFile = ConfigFileName; | |||||
if (ProvisionalConfigFile.length() == 0) { | if (ProvisionalConfigFile.length() == 0) { | ||||
if (0 == FoundFile.size()) { // No default file found. | if (0 == FoundFile.size()) { // No default file found. | ||||
string Temp; | |||||
if (NumDefaultFiles > 0) { | |||||
Temp = "Configuration file was not specified, and no default configuration file was found. "; | |||||
Temp += "Checked:\n\n"; | |||||
ProvisionalConfigFile = DefaultFile[0]; // Use the first default file. | |||||
ConfigFileExists = false; | |||||
for (i = 0; i < NumDefaultFiles; i++) { | |||||
} else { // No default config file was specified. | |||||
Temp += " "; | |||||
Temp += DefaultFile[i] + "\n"; | |||||
ostringstream Temp; | |||||
} | |||||
Temp << "Internal error: NumDefaultFiles <= 0 at " << __FILE__ << ":" << __LINE__; | |||||
throw runtime_error(Temp); | |||||
throw runtime_error(Temp.str()); | |||||
} | |||||
} | |||||
if (FoundFile.size() > 1) { // No default file found. | |||||
} else if (FoundFile.size() > 1) { // Multiple default files found. | |||||
string Temp; | string Temp; | ||||
throw runtime_error(Temp); | throw runtime_error(Temp); | ||||
} else { | |||||
ConfigFileExists = true; // Config file was found. | |||||
} | } | ||||
} else { | |||||
ConfigFileExists = FileExists(ProvisionalConfigFile); | |||||
} | } | ||||
LoadConfigFile(ProvisionalConfigFile); | |||||
SetConfigFileName(ProvisionalConfigFile); | |||||
} | |||||
void | |||||
UtilityConfig::CreateDefaultConfigFile(std::string SampleConfigFile) { | |||||
std::string File = GetConfigFileName(); | |||||
if (!ConfigFileExists) { | |||||
// Create the config file. | |||||
Copy(SampleConfigFile, File); | |||||
} | |||||
} | } | ||||
void | void | ||||
UtilityConfig::LoadConfigFile(std::string Name) { | |||||
UtilityConfig::CreateDefaultIdentityFile(std::string SampleIdentityFile) { | |||||
std::string File = GetIdentityFileName(); | |||||
if (!FileExists(File)) { | |||||
// Create the config file. | |||||
Copy(SampleIdentityFile, File); | |||||
} | |||||
} | |||||
SetConfigFileName(Name); | |||||
void | |||||
UtilityConfig::LoadConfig() { | |||||
if (Verbose()) { | if (Verbose()) { | ||||
cout << "Using configuration file " << ConfigFile << ".\n"; | |||||
cout << "Using configuration file " << GetConfigFileName() << ".\n"; | |||||
} | } | ||||
string | string | ||||
UtilityConfig::GetConfigFileName(void) { | UtilityConfig::GetConfigFileName(void) { | ||||
return ConfigFile; | |||||
return ConfigFileName; | |||||
} | } | ||||
void | void | ||||
UtilityConfig::SetConfigFileName(string Name) { | UtilityConfig::SetConfigFileName(string Name) { | ||||
ConfigFile = Name; | |||||
ConfigFileName = Name; | |||||
} | } | ||||
} | } | ||||
void | |||||
UtilityConfig::StartOrRestartMta(std::string Mta) { | |||||
string | |||||
UtilityConfig::GetIgnoreListFileName(void) { | |||||
if (Verbose()) { | |||||
return GetWorkspacePath() + "GBUdbIgnoreList.txt"; | |||||
cout << "Restarting the " << Mta << " MTA..."; | |||||
} | |||||
} | |||||
string | |||||
UtilityConfig::GetRulebaseFileName(void) { | |||||
if (!Explain()) { | |||||
std::string Name; | |||||
cout << "restarting the MTA is not implemented..."; | |||||
Name = GetRulebasePath(); | |||||
Name += LicenseId + ".snf"; | |||||
} | |||||
return Name; | |||||
OutputVerboseEnd(); | |||||
} | |||||
string | |||||
UtilityConfig::GetOperatingSystemType(void) { | |||||
return OperatingSystemType; | |||||
} | } | ||||
if ("OpenBSD" == OperatingSystemType) { | if ("OpenBSD" == OperatingSystemType) { | ||||
OsSpec = OpenBSD; | |||||
PostfixMainCfPath = "/usr/local/etc/postfix/main.cf"; | PostfixMainCfPath = "/usr/local/etc/postfix/main.cf"; | ||||
PostfixMasterCfPath = "/usr/local/etc/postfix/master.cf"; | PostfixMasterCfPath = "/usr/local/etc/postfix/master.cf"; | ||||
} else if ("FreeBSD" == OperatingSystemType) { | } else if ("FreeBSD" == OperatingSystemType) { | ||||
OsSpec = FreeBSD; | |||||
PostfixMainCfPath = "/etc/postfix/main.cf"; | PostfixMainCfPath = "/etc/postfix/main.cf"; | ||||
PostfixMasterCfPath = "/etc/postfix/master.cf"; | PostfixMasterCfPath = "/etc/postfix/master.cf"; | ||||
} else if ("Ubuntu" == OperatingSystemType) { | } else if ("Ubuntu" == OperatingSystemType) { | ||||
OsSpec = Ubuntu; | |||||
PostfixMainCfPath = "/etc/postfix/main.cf"; | PostfixMainCfPath = "/etc/postfix/main.cf"; | ||||
PostfixMasterCfPath = "/etc/postfix/master.cf"; | PostfixMasterCfPath = "/etc/postfix/master.cf"; | ||||
} else if ("RedHat" == OperatingSystemType) { | } else if ("RedHat" == OperatingSystemType) { | ||||
OsSpec = RedHat; | |||||
PostfixMainCfPath = "/etc/postfix/main.cf"; | PostfixMainCfPath = "/etc/postfix/main.cf"; | ||||
PostfixMasterCfPath = "/etc/postfix/master.cf"; | PostfixMasterCfPath = "/etc/postfix/master.cf"; | ||||
} else if ("Suse" == OperatingSystemType) { | } else if ("Suse" == OperatingSystemType) { | ||||
OsSpec = Suse; | |||||
PostfixMainCfPath = "/etc/postfix/main.cf"; | PostfixMainCfPath = "/etc/postfix/main.cf"; | ||||
PostfixMasterCfPath = "/etc/postfix/master.cf"; | PostfixMasterCfPath = "/etc/postfix/master.cf"; | ||||
ostringstream Temp; | ostringstream Temp; | ||||
Temp << "Internal error in UtilityConfig::GetOsSpec: Invalid value of OperatingSystemType: " | |||||
Temp << "Internal error in UtilityConfig::LoadInfo: Invalid value of OperatingSystemType: " | |||||
<< OperatingSystemType; | << OperatingSystemType; | ||||
throw runtime_error(Temp.str()); | throw runtime_error(Temp.str()); | ||||
void | void | ||||
UtilityConfig::UpdateIgnoreListFile() { | UtilityConfig::UpdateIgnoreListFile() { | ||||
string IgnoreListPath = GetWorkspacePath(); | |||||
string IgnoreListFile; | |||||
IgnoreListFile = IgnoreListPath + DirectorySeparator; | |||||
IgnoreListFile += "GBUdbIgnoreList.txt"; | |||||
SaveFile.CreateBackupFile(IgnoreListFile); // Save any existing file. | |||||
string IgnoreListFile = GetIgnoreListFileName(); | |||||
if (!FileExists(IgnoreListFile)) { | if (!FileExists(IgnoreListFile)) { | ||||
Copy(SampleIgnoreListFile, IgnoreListFile); // Use SNFMilter.xml.sample. | |||||
Copy(SampleIgnoreListFile, IgnoreListFile); | |||||
} | } | ||||
} | } | ||||
bool | |||||
UtilityConfig::UpdateCredentialsSpecified() { | |||||
return ( (LicenseId.length() > 0) && (Authentication.length() > 0) ); | |||||
} | |||||
void | |||||
UtilityConfig::CreateUpdateRulebaseScript() { | |||||
std::string File = GetRulebaseScriptName(); | |||||
if (!FileExists(File)) { | |||||
Copy(SampleRulebaseScriptFile, File); // Copy if !Explain(). | |||||
} | |||||
if (UpdateCredentialsSpecified()) { | |||||
UpdateRulebaseScriptCredentials(); | |||||
} | |||||
SetMode(File, S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH); // Set permissions. | |||||
} | |||||
void | |||||
UtilityConfig::UpdateRulebaseScriptCredentials() { | |||||
std::string File = GetRulebaseScriptName(); | |||||
if (Verbose()) { | |||||
cout << "Update authentication and license ID in the rulebase download script file " << File << "--\n"; | |||||
} | |||||
ifstream Input; | |||||
Input.open(File.c_str()); // Read the contents. | |||||
if (!Input) { | |||||
string Temp; | |||||
Temp = "Error opening rulebase download script file " + File; | |||||
Temp += " for reading: "; | |||||
Temp += strerror(errno); | |||||
throw runtime_error(Temp); | |||||
} | |||||
string Content; | |||||
string Line; | |||||
bool FoundLicense = false; | |||||
bool FoundAuth = false; | |||||
while (getline(Input, Line)) { | |||||
if (CheckForString(Line, LicenseSearchString)) { // Check for license line. | |||||
if (FoundLicense) { // Second license line found? | |||||
string Temp; | |||||
Temp = "Rulebase sownload script file " + File; | |||||
Temp += " has the wrong format: Found two lines beginning with " + LicenseSearchString; | |||||
throw runtime_error(Temp); | |||||
} | |||||
if (Verbose()) { | |||||
cout << " Modify line: '" << Line << "'...\n"; | |||||
} | |||||
FoundLicense = true; | |||||
Line = LicenseSearchString + LicenseId; // Add license line. | |||||
Line += " # Added by SNFSetup"; | |||||
} | |||||
if (CheckForString(Line, AuthSearchString)) { // Check for authentication line. | |||||
if (FoundAuth) { // Second authentication line found? | |||||
string Temp; | |||||
Temp = "Rulebase download script file " + File; | |||||
Temp += " has the wrong format: Found two lines beginning with " + AuthSearchString; | |||||
throw runtime_error(Temp); | |||||
} | |||||
if (Verbose()) { | |||||
cout << " Modify line: '" << Line << "'...\n"; | |||||
} | |||||
FoundAuth = true; | |||||
Line = AuthSearchString + Authentication; // Add authentication line. | |||||
Line += " # Added by SNFSetup"; | |||||
} | |||||
Content += Line + "\n"; | |||||
} | |||||
if (!FoundLicense || !FoundAuth) { | |||||
string Temp; | |||||
Temp = "Rulebase download script file " + File; | |||||
Temp += " has the wrong format: Missing required line beginning with '" + LicenseSearchString; | |||||
Temp += "' or '" + AuthSearchString; | |||||
Temp += "'"; | |||||
throw runtime_error(Temp); | |||||
} | |||||
if (!Input.eof()) { // Should be at end-of-file. | |||||
string Temp; | |||||
Temp = "Error reading the rulebase download script file " + File; | |||||
Temp += ": "; | |||||
Temp += strerror(errno); | |||||
throw runtime_error(Temp); | |||||
} | |||||
Input.close(); | |||||
if (Input.bad()) { | |||||
string Temp; | |||||
Temp = "Error closing the rulebase download script file " + File; | |||||
Temp += " after reading: "; | |||||
Temp += strerror(errno); | |||||
throw runtime_error(Temp); | |||||
} | |||||
if (!Explain()) { | |||||
ofstream Output; // Write the updated contents. | |||||
Output.open(File.c_str(), ios::trunc); | |||||
if (!Output) { | |||||
string Temp; | |||||
Temp = "Error opening rulebase download script file " + File; | |||||
Temp += " for writing: "; | |||||
Temp += strerror(errno); | |||||
throw runtime_error(Temp); | |||||
} | |||||
Output << Content; | |||||
if (!Output) { | |||||
string Temp; | |||||
Temp = "Error writing the rulebase download script file " + File; | |||||
Temp += ": "; | |||||
Temp += strerror(errno); | |||||
throw runtime_error(Temp); | |||||
} | |||||
Output.close(); | |||||
if (!Output) { | |||||
string Temp; | |||||
Temp = "Error closing the rulebase download script file " + File; | |||||
Temp += " after writing: "; | |||||
Temp += strerror(errno); | |||||
throw runtime_error(Temp); | |||||
} | |||||
} | |||||
OutputVerboseEnd(); | |||||
} | |||||
void | |||||
UtilityConfig::DownloadRulebase() { | |||||
if (!UpdateCredentialsSpecified()) { | |||||
return; | |||||
} | |||||
if (Verbose()) { | |||||
std::cout << "Downloading the rulebase..."; | |||||
} | |||||
std::string Command; | |||||
Command = RulebaseDownloadCommand; | |||||
std::string::size_type ScriptIndex = Command.find(ScriptNameKey); | |||||
if (ScriptIndex != std::string::npos) { // Insert script full path? | |||||
Command.replace(ScriptIndex, ScriptNameKey.length(), GetRulebaseScriptName()); | |||||
} | |||||
std::string::size_type SnifferPathIndex = Command.find(SnifferPathKey); | |||||
if (SnifferPathIndex != std::string::npos) { // Insert rulebase location? | |||||
Command.replace(SnifferPathIndex, SnifferPathKey.length(), GetRulebasePath()); | |||||
} | |||||
if (!Explain()) { | |||||
if (std::system(Command.c_str()) != 0) { | |||||
string Temp; | |||||
Temp = "Error running the command '" + Command; | |||||
Temp += "'."; | |||||
throw runtime_error(Temp); | |||||
} | |||||
} | |||||
OutputVerboseEnd(); | |||||
} | |||||
void | |||||
UtilityConfig::UpdateIdentityFile() { | |||||
std::string File = GetIdentityFileName(); | |||||
if (UpdateCredentialsSpecified()) { | |||||
ofstream Output; | |||||
if (Verbose()) { | |||||
cout << "Create identity file " << File << "..."; | |||||
} | |||||
if (!Explain()) { | |||||
Output.open(File.c_str()); | |||||
if (!Output) { | |||||
string Temp; | |||||
Temp = "Error opening identity file " + File; | |||||
Temp += ": "; | |||||
Temp += strerror(errno); | |||||
throw runtime_error(Temp); | |||||
} | |||||
Output << "<!-- License file created by SNFIdentity-->\n" | |||||
<< "<snf>\n" | |||||
<< " <identity licenseid='" << LicenseId << "' authentication='" | |||||
<< Authentication << "'/>\n" | |||||
<< "</snf>\n"; | |||||
if (!Output) { | |||||
string Temp; | |||||
Temp = "Error writing identity file " + File; | |||||
Temp += ": "; | |||||
Temp += strerror(errno); | |||||
throw runtime_error(Temp); | |||||
} | |||||
Output.close(); | |||||
if (!Output) { | |||||
string Temp; | |||||
Temp = "Error closing identity file " + File; | |||||
Temp += ": "; | |||||
Temp += strerror(errno); | |||||
throw runtime_error(Temp); | |||||
} | |||||
} | |||||
OutputVerboseEnd(); | |||||
} | |||||
SetOwnerGroup(File); // Set the user and group. | |||||
SetMode(File, S_IRUSR); // Set to readonly by owner. | |||||
} | |||||
bool | bool | ||||
UtilityConfig::ProcessCommandLineItem(std::string OneInput) { | UtilityConfig::ProcessCommandLineItem(std::string OneInput) { | ||||
bool ValidCommand = false; | |||||
bool ValidCommand = true; | |||||
std::string TempString; | |||||
if (OneInput == VerboseKey) { | if (OneInput == VerboseKey) { | ||||
SetVerbose(true); | SetVerbose(true); | ||||
ValidCommand = true; | |||||
} else if (OneInput == ExplainKey) { | } else if (OneInput == ExplainKey) { | ||||
SetExplain(true); | SetExplain(true); | ||||
ValidCommand = true; | |||||
} else if (OneInput == HelpKey) { | } else if (OneInput == HelpKey) { | ||||
SetHelp(true); | SetHelp(true); | ||||
ValidCommand = true; | |||||
} else if (OneInput == ConfigFileKey) { | |||||
SetConfigFileName(OneInput.substr(ConfigFileKey.length())); | |||||
} else if (0 == OneInput.find(LicenseIdKey)) { | |||||
TempString = Trim(OneInput.substr(LicenseIdKey.length())); // Copy only if not null after trimming. | |||||
if (!TempString.empty()) { | |||||
LicenseId = TempString; | |||||
LicenseIdIsSpecified = true; | |||||
} else { | |||||
ValidCommand = false; | |||||
} | |||||
} else if (0 == OneInput.find(AuthenticationKey)) { | |||||
Authentication = Trim(OneInput.substr(AuthenticationKey.length())); | |||||
AuthenticationIsSpecified = true; | |||||
} else { | |||||
ValidCommand = false; | |||||
} | } | ||||
} | } | ||||
bool | |||||
UtilityConfig::CommandLineIsOkay() { | |||||
return (AuthenticationIsSpecified == LicenseIdIsSpecified); | |||||
} | |||||
std::string | std::string | ||||
UtilityConfig::HelpCommandLine() { | UtilityConfig::HelpCommandLine() { | ||||
std::string Help; | std::string Help; | ||||
Help = "[ " + VerboseKey + " | " + ExplainKey + " ]"; | |||||
Help = "[" + ConfigFileKey + "snf-config-file] "; | |||||
Help += "[" + LicenseIdKey + "licenseid " + AuthenticationKey + "authentication] "; | |||||
Help += "[ " + VerboseKey + " " + ExplainKey + " ]"; | |||||
return Help; | return Help; | ||||
std::string Desc; | std::string Desc; | ||||
Desc = " -v Provide verbose output\n"; | |||||
Desc = " -config=snf-config-file Specifies the configuration file\n"; | |||||
Desc += " -id=licenseid Specifies the license ID\n"; | |||||
Desc += " -auth=authentication Specifies the Authentication\n"; | |||||
Desc += " -v Provide verbose output\n"; | |||||
Desc += " -explain Provide an explaination of the actions\n"; | Desc += " -explain Provide an explaination of the actions\n"; | ||||
Desc += " without executing any commands\n"; | Desc += " without executing any commands\n"; | ||||
/// Object to back up and restore files. | /// Object to back up and restore files. | ||||
FileBackup SaveFile; | FileBackup SaveFile; | ||||
/// Load the specified or default config file. | |||||
/// Set the config file name to the default if it wasn't specified. | |||||
// | // | ||||
// This function loads (or reloads) the config file specified in | |||||
// the most recent call to LoadConfigFile. If LoadConfigFile has | |||||
// not been called, then this method searches for a unique default | |||||
// config file in the specified list, and loads that config file. | |||||
// If the configuration file wasn't specified by | |||||
// SetConfigFileName() on the command line, then this method sets | |||||
// the config file to the default. The default is the unique file | |||||
// that exists in the specified list. If more than one file in | |||||
// the specified list exists, an exception is thrown. | |||||
// | |||||
// If the configuration file was specified by SetConfigFileName() | |||||
// or on the command line, then this method does nothing. | |||||
// | // | ||||
// \param[in] DefaultFile is the list of default locations of the file. | // \param[in] DefaultFile is the list of default locations of the file. | ||||
// | // | ||||
// \param[in] NumDefaultFiles is the number of defaultlocations. | // \param[in] NumDefaultFiles is the number of defaultlocations. | ||||
// | // | ||||
// If the local data member ConfigFile has a value of "" on input, | |||||
// then this function checks for the existence (but not | |||||
// readability) of a configuration file in several locations. If | |||||
// exactly one file exists, then that file is loaded and | |||||
// ConfigFile is set to that name. Otherwise, an exception is | |||||
// thrown. | |||||
void CheckAndSetConfigFileName(const std::string DefaultFile[], int NumDefaultFiles); | |||||
/// If the configuration file doesn't exist, create it from the | |||||
/// sample file. | |||||
// | |||||
// This method creates the default configuration file if the | |||||
// specified configuration file doesn't exist. | |||||
// | // | ||||
void CheckAndLoadConfigFile(const std::string DefaultFile[], int NumDefaultFiles); | |||||
// The method CheckAndSetConfigFileName must be called before this | |||||
// method. | |||||
// | |||||
// \param[in] SampleConfigFile is the name of the sample | |||||
// configuration file. | |||||
// | |||||
void CreateDefaultConfigFile(std::string SampleConfigFile); | |||||
/// Load the specified configuration file. | |||||
/// If the identity file doesn't exist, create it from the sample | |||||
/// file. | |||||
// | // | ||||
// \param[in] Name is the name of the configuration file. | |||||
// This method creates the default identity file if the identity | |||||
// file specified in the configuration file doesn't exist. | |||||
// | // | ||||
void LoadConfigFile(std::string Name); | |||||
// The method CheckAndSetConfigFileName must be called before this | |||||
// method. | |||||
// | |||||
// \param[in] SampleIdentityFile is the name of the sample | |||||
// identity file. | |||||
// | |||||
void CreateDefaultIdentityFile(std::string SampleIdentityFile); | |||||
/// Load the configuration from the file specified by SetConfigFileName. | |||||
// | |||||
void LoadConfig(void); | |||||
/// Set the configuration file name. | /// Set the configuration file name. | ||||
// | // | ||||
// \returns the rulebase script file name. | // \returns the rulebase script file name. | ||||
std::string GetRulebaseScriptName(void); | std::string GetRulebaseScriptName(void); | ||||
/// Restart the MTA. | |||||
/// Get the ignore list file name. | |||||
// | |||||
// \returns the ignore list file name. | |||||
// | // | ||||
// This function starts or restarts the MTA. | |||||
std::string GetIgnoreListFileName(void); | |||||
/// Return the rulebase file name. | |||||
// | // | ||||
// \param[in] Mta specifies the MTA. The acceptable values are | |||||
// "postfix" and "sendmail". | |||||
// \returns the name of the rulebase file, including the path. | |||||
// | // | ||||
void StartOrRestartMta(std::string Mta); | |||||
std::string GetRulebaseFileName(); | |||||
/// Operating system specification. | |||||
enum OperatingSystemSpecEnum { | |||||
OpenBSD, ///< OpenBSD OS. | |||||
FreeBSD, ///< FreeBSD OS. | |||||
Ubuntu, ///< Ubuntu and variants. | |||||
RedHat, ///< RedHat and variants. | |||||
Suse ///< Suse and variants. | |||||
}; | |||||
/// Get the operating system type. | |||||
// | |||||
// \returns the operating system type. This is the value of | |||||
// SNF_OSTYPE specified on the compile commandline. For *nix, it | |||||
// is identical to the value of the --enable-os-type command-line | |||||
// input to ./configure: | |||||
// | |||||
// <ol> | |||||
// <li>OpenBSD</li> | |||||
// <li>FreeBSD</li> | |||||
// <li>Suse</li> | |||||
// <li>RedHat</li> | |||||
// <li>Ubuntu</li> | |||||
// </ol> | |||||
// | |||||
std::string GetOperatingSystemType(void); | |||||
/// Load the operating-system-dependent info (file locations, etc). | /// Load the operating-system-dependent info (file locations, etc). | ||||
// | // | ||||
// | // | ||||
void LoadInfo(); | void LoadInfo(); | ||||
/// OS specification. | |||||
OperatingSystemSpecEnum OsSpec; | |||||
/// Postfix main.cf file path. | /// Postfix main.cf file path. | ||||
std::string PostfixMainCfPath; | std::string PostfixMainCfPath; | ||||
// owner. | // owner. | ||||
void UpdateLogDir(); | void UpdateLogDir(); | ||||
/// Create or update the rulebase script. | |||||
// | |||||
// If the rulebase script doesn't exist, this method creates the | |||||
// rulebase script from the sample rulebase script. | |||||
// | |||||
// If the credentials were supplied, this method updates the | |||||
// rulebase with the supplied credentials. | |||||
// | |||||
// In either case, the permissions of the rulebase script are | |||||
// updated. | |||||
// | |||||
void CreateUpdateRulebaseScript(); | |||||
/// Download the rulebase. | |||||
// | |||||
void DownloadRulebase(); | |||||
/// Update the identity file. | |||||
// | |||||
// If the credentials were supplied, this method updates the | |||||
// identity file with the supplied credentials. | |||||
// | |||||
// In any case, the owner/group is changed by SetOwnerGroup(), and | |||||
// the permissions are changed to readonly for the owner. | |||||
// | |||||
// \pre Either the identity file must exist, or the credentials | |||||
// must be supplied so that the identity file is created. | |||||
// | |||||
// \see SetOwnerGroup(). | |||||
// | |||||
void UpdateIdentityFile(void); | |||||
/// Process one command-line item. | /// Process one command-line item. | ||||
// | // | ||||
// \param[in] OneInput is the command-line item to process. | // \param[in] OneInput is the command-line item to process. | ||||
// | // | ||||
bool ProcessCommandLineItem(std::string OneInput); | bool ProcessCommandLineItem(std::string OneInput); | ||||
/// Check whether the command-line parameters were specified | |||||
/// correctly. | |||||
// | |||||
// This function check that either both the LicenseID and | |||||
// Authentication were specified, or neither were. | |||||
// | |||||
// \returns if the command-line parameters were specified | |||||
// correctly, false otherwise. | |||||
bool CommandLineIsOkay(); | |||||
/// Output the legal command-line input. | /// Output the legal command-line input. | ||||
std::string HelpCommandLine(); | std::string HelpCommandLine(); | ||||
private: | private: | ||||
std::string ConfigFile; ///< Configuration file name. | |||||
/// Determine whether the credentials should be updated. | |||||
// | |||||
// This method determines whether the credentials should be | |||||
// updated. If the user specified both the License ID and | |||||
// Authentication, then the credentials should be updated. | |||||
// | |||||
// \returns true if the credentials should be updated. | |||||
// | |||||
bool UpdateCredentialsSpecified(); | |||||
/// Update the credentials of an existing rulebase script. | |||||
// | |||||
// This method does the actual work of updating the credentials of | |||||
// the rulebase script. | |||||
// | |||||
// \pre The rulebase script file must exist. | |||||
// | |||||
// Side effect: The rulebase script is updated. | |||||
// | |||||
void UpdateRulebaseScriptCredentials(); | |||||
std::string ConfigFileName; ///< Configuration file name. | |||||
bool ConfigFileExists; ///< True if the configuration file exists. | |||||
std::string LicenseId; ///< License ID string. | |||||
bool LicenseIdIsSpecified; ///< true if the License ID was specified on the command line. | |||||
std::string Authentication; ///< Authentication string. | |||||
bool AuthenticationIsSpecified; ///< true if the Authentication was specified on the command line. | |||||
static const std::string RulebaseDownloadCommand; ///< Command to download the rulebase. | |||||
static const std::string SampleIgnoreListFile; ///< Sample ignore list file. | static const std::string SampleIgnoreListFile; ///< Sample ignore list file. | ||||
static const std::string SampleRulebaseScriptFile; ///< Sample rulebase script file. | static const std::string SampleRulebaseScriptFile; ///< Sample rulebase script file. | ||||
FileName.push_back("File4.txt"); | FileName.push_back("File4.txt"); | ||||
FileSize.push_back(203043); | FileSize.push_back(203043); | ||||
const char *CharPtr = RandomChar.data(); | |||||
std::vector<int>::iterator iSize = FileSize.begin(); | std::vector<int>::iterator iSize = FileSize.begin(); | ||||
for (StringContainer::iterator iFile = FileName.begin(); // Create random data. | for (StringContainer::iterator iFile = FileName.begin(); // Create random data. | ||||
} | } | ||||
bool | |||||
TestBackupRestoreWithNoFiles() { | |||||
/// Unit under test. | |||||
FileBackup TestNoFileBackup; | |||||
for (int i = 0; i < NoFileName.size(); i++) { // Backup and overwrite files that don't exist. | |||||
TestNoFileBackup.CreateBackupFile(NoFileName[i]); | |||||
OverwriteFile(NoFileName[i]); | |||||
} | |||||
TestNoFileBackup.RestoreAllFilesFromBackup(); | |||||
bool ResultIsPass = true; | |||||
for (int i = 0; i < NoFileName.size(); i++) { // Check that files don't exist. | |||||
if (FileBackup::FileExists(NoFileName[i])) { | |||||
std::string Temp; | |||||
Temp = "TestBackupRestoreWithNoFiles: File " + NoFileName[i]; | |||||
Temp += " was supposed to be deleted by RestoreAllFilesFromBackup, "; | |||||
Temp += "but was determined to exist.\n"; | |||||
throw std::runtime_error(Temp); | |||||
} | |||||
} | |||||
return ResultIsPass; | |||||
} | |||||
bool | |||||
TestBackupRestoreWithNoFilesNoOverwrite() { | |||||
/// Unit under test. | |||||
FileBackup TestNoFileBackup; | |||||
for (int i = 0; i < NoFileName.size(); i++) { // Backup and overwrite files that don't exist. | |||||
TestNoFileBackup.CreateBackupFile(NoFileName[i]); | |||||
} | |||||
TestNoFileBackup.RestoreAllFilesFromBackup(); | |||||
bool ResultIsPass = true; | |||||
for (int i = 0; i < NoFileName.size(); i++) { // Check that files don't exist. | |||||
if (FileBackup::FileExists(NoFileName[i])) { | |||||
std::string Temp; | |||||
Temp = "TestBackupRestoreWithNoFilesNoOverwrite: File " + NoFileName[i]; | |||||
Temp += " was supposed to be deleted by RestoreAllFilesFromBackup, "; | |||||
Temp += "but was determined to exist.\n"; | |||||
throw std::runtime_error(Temp); | |||||
} | |||||
} | |||||
return ResultIsPass; | |||||
} | |||||
void | void | ||||
Finalize() { | Finalize() { | ||||
Finalize(); // Remove test files. | Finalize(); // Remove test files. | ||||
// Test backup/restore with no files. | |||||
if (!TestBackupRestoreWithNoFiles()) { | |||||
ErrorExit("TestBackupRestoreWithNoFiles() failure.\n"); | |||||
} | |||||
// Test backup/restore with no files and no overwriting of files. | |||||
if (!TestBackupRestoreWithNoFilesNoOverwrite()) { | |||||
ErrorExit("TestBackupRestoreWithNoFilesNoOverwrite() failure.\n"); | |||||
} | |||||
} // That's all folks. | } // That's all folks. | ||||
catch(std::exception& e) { // Report any normal exceptions. | catch(std::exception& e) { // Report any normal exceptions. |
// Configuration. //////////////////////////////////////////////////////////////////////////////////////// | // Configuration. //////////////////////////////////////////////////////////////////////////////////////// | ||||
////////////////////////////////////////////////////////////////////////////////////////////////////////// | ////////////////////////////////////////////////////////////////////////////////////////////////////////// | ||||
// Initialize command to download the rulebase. | |||||
#ifdef WIN | |||||
// Windows OS. | |||||
const std::string SNFIdentityConfig::RulebaseDownloadCommand("FIX THIS"); | |||||
#else | |||||
// *nix OS. SCRIPT is replaced with the full path of the script run, | |||||
// SNIFFER_PATH is replaced with the path of the rulebase. | |||||
const std::string SNFIdentityConfig::RulebaseDownloadCommand | |||||
("(cd SNIFFER_PATH; touch UpdateReady.txt; chown snfuser UpdateReady.txt; su -m snfuser -c SCRIPT)"); | |||||
#endif | |||||
const std::string ScriptNameKey("SCRIPT"); ///< Text to replace with script name. | |||||
const std::string SnifferPathKey("SNIFFER_PATH"); ///< Text to replace with directory of the rulebase. | |||||
const string LicenseSearchString = "LICENSE_ID="; | const string LicenseSearchString = "LICENSE_ID="; | ||||
const string AuthSearchString = "AUTHENTICATION="; | const string AuthSearchString = "AUTHENTICATION="; | ||||
} | } | ||||
void | |||||
SNFIdentityConfig::CreateIdentityFile() { | |||||
ofstream Output; | |||||
std::string File = GetIdentityFileName(); | |||||
if (Verbose()) { | |||||
cout << "Create identity file " << File << "..."; | |||||
} | |||||
if (!Explain()) { | |||||
Output.open(File.c_str()); | |||||
if (!Output) { | |||||
string Temp; | |||||
Temp = "Error opening identity file " + File; | |||||
Temp += ": "; | |||||
Temp += strerror(errno); | |||||
throw runtime_error(Temp); | |||||
} | |||||
Output << "<!-- License file created by SNFIdentity-->\n" | |||||
<< "<snf>\n" | |||||
<< " <identity licenseid='" << LicenseID << "' authentication='" | |||||
<< Authentication << "'/>\n" | |||||
<< "</snf>\n"; | |||||
if (!Output) { | |||||
string Temp; | |||||
Temp = "Error writing identity file " + File; | |||||
Temp += ": "; | |||||
Temp += strerror(errno); | |||||
throw runtime_error(Temp); | |||||
} | |||||
Output.close(); | |||||
if (!Output) { | |||||
string Temp; | |||||
Temp = "Error closing identity file " + File; | |||||
Temp += ": "; | |||||
Temp += strerror(errno); | |||||
throw runtime_error(Temp); | |||||
} | |||||
} | |||||
OutputVerboseEnd(); | |||||
SetOwnerGroup(File); // Set the user and group. | |||||
SetMode(File, S_IRUSR); // Set to readonly by owner. | |||||
} | |||||
void | void | ||||
SNFIdentityConfig::UpdateRulebaseScriptCredentials() { | SNFIdentityConfig::UpdateRulebaseScriptCredentials() { | ||||
if (Verbose()) { | if (Verbose()) { | ||||
cout << "Update authentication and license ID in the rulebase file " << File << "--\n"; | |||||
cout << "Update authentication and license ID in the rulebase download script file " << File << "--\n"; | |||||
} | } | ||||
if (!Input) { | if (!Input) { | ||||
string Temp; | string Temp; | ||||
Temp = "Error opening rulebase file " + File; | |||||
Temp = "Error opening rulebase download script file " + File; | |||||
Temp += " for reading: "; | Temp += " for reading: "; | ||||
Temp += strerror(errno); | Temp += strerror(errno); | ||||
throw runtime_error(Temp); | throw runtime_error(Temp); | ||||
if (FoundLicense) { // Second license line found? | if (FoundLicense) { // Second license line found? | ||||
string Temp; | string Temp; | ||||
Temp = "Rulebase file " + File; | |||||
Temp = "Rulebase sownload script file " + File; | |||||
Temp += " has the wrong format: Found two lines beginning with " + LicenseSearchString; | Temp += " has the wrong format: Found two lines beginning with " + LicenseSearchString; | ||||
throw runtime_error(Temp); | throw runtime_error(Temp); | ||||
if (FoundAuth) { // Second authentication line found? | if (FoundAuth) { // Second authentication line found? | ||||
string Temp; | string Temp; | ||||
Temp = "Rulebase file " + File; | |||||
Temp = "Rulebase download script file " + File; | |||||
Temp += " has the wrong format: Found two lines beginning with " + AuthSearchString; | Temp += " has the wrong format: Found two lines beginning with " + AuthSearchString; | ||||
throw runtime_error(Temp); | throw runtime_error(Temp); | ||||
} | } | ||||
if (!FoundLicense || !FoundAuth) { | if (!FoundLicense || !FoundAuth) { | ||||
string Temp; | string Temp; | ||||
Temp = "Rulebase file " + File; | |||||
Temp = "Rulebase download script file " + File; | |||||
Temp += " has the wrong format: Missing required line beginning with '" + LicenseSearchString; | Temp += " has the wrong format: Missing required line beginning with '" + LicenseSearchString; | ||||
Temp += "' or '" + AuthSearchString; | Temp += "' or '" + AuthSearchString; | ||||
Temp += "'"; | Temp += "'"; | ||||
if (!Input.eof()) { // Should be at end-of-file. | if (!Input.eof()) { // Should be at end-of-file. | ||||
string Temp; | string Temp; | ||||
Temp = "Error reading the rulebase file " + File; | |||||
Temp = "Error reading the rulebase download script file " + File; | |||||
Temp += ": "; | Temp += ": "; | ||||
Temp += strerror(errno); | Temp += strerror(errno); | ||||
throw runtime_error(Temp); | throw runtime_error(Temp); | ||||
if (Input.bad()) { | if (Input.bad()) { | ||||
string Temp; | string Temp; | ||||
Temp = "Error closing the rulebase file " + File; | |||||
Temp = "Error closing the rulebase download script file " + File; | |||||
Temp += " after reading: "; | Temp += " after reading: "; | ||||
Temp += strerror(errno); | Temp += strerror(errno); | ||||
throw runtime_error(Temp); | throw runtime_error(Temp); | ||||
if (!Explain()) { | if (!Explain()) { | ||||
SaveFile.CreateBackupFile(File); // Save the existing file. | |||||
ofstream Output; // Write the updated contents. | ofstream Output; // Write the updated contents. | ||||
Output.open(File.c_str(), ios::trunc); | Output.open(File.c_str(), ios::trunc); | ||||
if (!Output) { | if (!Output) { | ||||
string Temp; | string Temp; | ||||
Temp = "Error opening rulebase file " + File; | |||||
Temp = "Error opening rulebase download script file " + File; | |||||
Temp += " for writing: "; | Temp += " for writing: "; | ||||
Temp += strerror(errno); | Temp += strerror(errno); | ||||
throw runtime_error(Temp); | throw runtime_error(Temp); | ||||
if (!Output) { | if (!Output) { | ||||
string Temp; | string Temp; | ||||
Temp = "Error writing the rulebase file " + File; | |||||
Temp = "Error writing the rulebase download script file " + File; | |||||
Temp += ": "; | Temp += ": "; | ||||
Temp += strerror(errno); | Temp += strerror(errno); | ||||
throw runtime_error(Temp); | throw runtime_error(Temp); | ||||
if (!Output) { | if (!Output) { | ||||
string Temp; | string Temp; | ||||
Temp = "Error closing the rulebase file " + File; | |||||
Temp = "Error closing the rulebase download script file " + File; | |||||
Temp += " after writing: "; | Temp += " after writing: "; | ||||
Temp += strerror(errno); | Temp += strerror(errno); | ||||
throw runtime_error(Temp); | throw runtime_error(Temp); | ||||
SetMode(File, S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH); // Set permissions. | SetMode(File, S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH); // Set permissions. | ||||
} | } | ||||
void | |||||
SNFIdentityConfig::DownloadRulebase() { | |||||
if (Verbose()) { | |||||
std::cout << "Downloading the rulebase..."; | |||||
} | |||||
std::string Command; | |||||
Command = RulebaseDownloadCommand; | |||||
std::string::size_type ScriptIndex = Command.find(ScriptNameKey); | |||||
if (ScriptIndex != std::string::npos) { // Insert script full path? | |||||
Command.replace(ScriptIndex, ScriptNameKey.length(), GetRulebaseScriptName()); | |||||
} | |||||
std::string::size_type SnifferPathIndex = Command.find(SnifferPathKey); | |||||
if (SnifferPathIndex != std::string::npos) { // Insert rulebase location? | |||||
Command.replace(SnifferPathIndex, SnifferPathKey.length(), GetRulebasePath()); | |||||
} | |||||
if (!Explain()) { | |||||
SaveFile.CreateBackupFile(GetRulebaseFileName()); | |||||
if (std::system(Command.c_str()) != 0) { | |||||
string Temp; | |||||
Temp = "Error running the command '" + Command; | |||||
Temp += "'."; | |||||
throw runtime_error(Temp); | |||||
} | |||||
} | |||||
OutputVerboseEnd(); | |||||
} | |||||
void | |||||
SNFIdentityConfig::CreateIdentityFile() { | |||||
ofstream Output; | |||||
std::string File = GetIdentityFileName(); | |||||
if (Verbose()) { | |||||
cout << "Create identity file " << File << "..."; | |||||
} | |||||
if (!Explain()) { | |||||
SaveFile.CreateBackupFile(File); | |||||
Output.open(File.c_str()); | |||||
if (!Output) { | |||||
string Temp; | |||||
Temp = "Error opening identity file " + File; | |||||
Temp += ": "; | |||||
Temp += strerror(errno); | |||||
throw runtime_error(Temp); | |||||
} | |||||
Output << "<!-- License file created by SNFIdentity-->\n" | |||||
<< "<snf>\n" | |||||
<< " <identity licenseid='" << LicenseID << "' authentication='" | |||||
<< Authentication << "'/>\n" | |||||
<< "</snf>\n"; | |||||
if (!Output) { | |||||
string Temp; | |||||
Temp = "Error writing identity file " + File; | |||||
Temp += ": "; | |||||
Temp += strerror(errno); | |||||
throw runtime_error(Temp); | |||||
} | |||||
Output.close(); | |||||
if (!Output) { | |||||
string Temp; | |||||
Temp = "Error closing identity file " + File; | |||||
Temp += ": "; | |||||
Temp += strerror(errno); | |||||
throw runtime_error(Temp); | |||||
} | |||||
} | |||||
OutputVerboseEnd(); | |||||
SetOwnerGroup(File); // Set the user and group. | |||||
SetMode(File, S_IRUSR); // Set to readonly by owner. | |||||
} | |||||
string | |||||
SNFIdentityConfig::GetRulebaseFileName(void) { | |||||
std::string Name; | |||||
Name = GetRulebasePath(); | |||||
Name += LicenseID + ".snf"; | |||||
return Name; | |||||
} |
// | // | ||||
bool GetCommandLineInput(int argc, char* argv[]); | bool GetCommandLineInput(int argc, char* argv[]); | ||||
#if 0 | |||||
/// Update the rulebase script with the credentials. | |||||
// | |||||
void UpdateRulebaseScriptCredentials(); | |||||
/// Download the rulebase. | |||||
// | |||||
void DownloadRulebase(); | |||||
/// Create the identity file. | /// Create the identity file. | ||||
// | // | ||||
// The file is created, the owner/group is changed by SetOwnerGroup(), | // The file is created, the owner/group is changed by SetOwnerGroup(), | ||||
// | // | ||||
void CreateIdentityFile(); | void CreateIdentityFile(); | ||||
/// Update the rulebase script with the credentials. | |||||
// | |||||
void UpdateRulebaseScriptCredentials(); | |||||
private: | private: | ||||
/// Return the rulebase file name. | |||||
// | |||||
// \returns the name of the rulebase file, including the path. | |||||
// | |||||
std::string GetRulebaseFileName(); | |||||
std::string LicenseID; ///< License ID string. | std::string LicenseID; ///< License ID string. | ||||
std::string Authentication; ///< Authentication string. | std::string Authentication; ///< Authentication string. | ||||
static const std::string RulebaseDownloadCommand; ///< Command to download the rulebase. | |||||
#endif | |||||
}; | }; | ||||
#endif | #endif |
// End of configuration. ///////////////////////////////////////////////////////////////////////////////// | // End of configuration. ///////////////////////////////////////////////////////////////////////////////// | ||||
////////////////////////////////////////////////////////////////////////////////////////////////////////// | ////////////////////////////////////////////////////////////////////////////////////////////////////////// | ||||
void RestoreFiles(SNFIdentityConfig *Config) { | |||||
try { | |||||
cerr << "Restoring all configuration files..."; | |||||
Config->SaveFile.RestoreAllFilesFromBackup(); | |||||
cerr << "done.\n"; | |||||
} | |||||
catch(exception& e) { | |||||
cerr << "SNFIdentityConfig::SaveFile Exception: " << e.what() << endl; | |||||
} | |||||
} | |||||
int main(int argc, char* argv[]) { | int main(int argc, char* argv[]) { | ||||
SNFIdentityConfig SnfIdentityConfig; | SNFIdentityConfig SnfIdentityConfig; | ||||
DefaultConfigFileSize); // config file specified on the | DefaultConfigFileSize); // config file specified on the | ||||
// command line, or the default file. | // command line, or the default file. | ||||
SnfIdentityConfig.CreateIdentityFile(); | |||||
SnfIdentityConfig.UpdateRulebaseScriptCredentials(); | SnfIdentityConfig.UpdateRulebaseScriptCredentials(); | ||||
SnfIdentityConfig.DownloadRulebase(); | |||||
SnfIdentityConfig.CreateIdentityFile(); | |||||
} // That's all folks. | } // That's all folks. | ||||
catch(exception& e) { // Report any normal exceptions. | catch(exception& e) { // Report any normal exceptions. | ||||
cerr << "SNFIdentity Exception: " << e.what() << endl; | cerr << "SNFIdentity Exception: " << e.what() << endl; | ||||
RestoreFiles(&SnfIdentityConfig); | |||||
} | } | ||||
catch (snfCFGmgr::LoadFailure) { // Error loading configuration file. | catch (snfCFGmgr::LoadFailure) { // Error loading configuration file. | ||||
cerr << "snfCFGmgr Exception: Unable to load the configuration file " | cerr << "snfCFGmgr Exception: Unable to load the configuration file " | ||||
<< SnfIdentityConfig.GetConfigFileName() << endl; | << SnfIdentityConfig.GetConfigFileName() << endl; | ||||
RestoreFiles(&SnfIdentityConfig); | |||||
} | } | ||||
catch(...) { // Report any unexpected exceptions. | catch(...) { // Report any unexpected exceptions. | ||||
cerr << "SNFIdentity Panic! Unknown Exception!" << endl; | cerr << "SNFIdentity Panic! Unknown Exception!" << endl; | ||||
RestoreFiles(&SnfIdentityConfig); | |||||
} | } | ||||
return 0; // Normally we return zero. | return 0; // Normally we return zero. |
// | // | ||||
/////////////////////////////////////////////////////////////////////////////////////////////////// | /////////////////////////////////////////////////////////////////////////////////////////////////// | ||||
#include <errno.h> | |||||
#include <string.h> | |||||
#include <unistd.h> | |||||
#include <sys/types.h> | |||||
#include <pwd.h> | |||||
#include <sys/types.h> | |||||
#include <sys/stat.h> | |||||
#include <unistd.h> | |||||
#include <cstdlib> | |||||
#include <cerrno> | |||||
#include <cstring> | |||||
#include <iostream> | #include <iostream> | ||||
#include <exception> | #include <exception> | ||||
#include <stdexcept> | #include <stdexcept> | ||||
#include <sstream> | #include <sstream> | ||||
#include <fstream> | #include <fstream> | ||||
#include <vector> | |||||
#include "PostfixIntegrate.hpp" | #include "PostfixIntegrate.hpp" | ||||
void | void | ||||
PostfixIntegrate::SetOperatingSystem(std::string OperatingSystemType) { | PostfixIntegrate::SetOperatingSystem(std::string OperatingSystemType) { | ||||
MtaIsRunningCommand = "ps -axl root | grep -v grep | grep -q 'postfix/master'"; | |||||
if ("OpenBSD" == OperatingSystemType) { | if ("OpenBSD" == OperatingSystemType) { | ||||
PostfixMainCfPath = "/usr/local/etc/postfix/main.cf"; | PostfixMainCfPath = "/usr/local/etc/postfix/main.cf"; | ||||
PostfixMasterCfPath = "/usr/local/etc/postfix/master.cf"; | PostfixMasterCfPath = "/usr/local/etc/postfix/master.cf"; | ||||
ReloadMtaCommand = "/usr/local/sbin/postfix reload"; | |||||
} else if ("FreeBSD" == OperatingSystemType) { | } else if ("FreeBSD" == OperatingSystemType) { | ||||
PostfixMainCfPath = "/etc/postfix/main.cf"; | PostfixMainCfPath = "/etc/postfix/main.cf"; | ||||
PostfixMasterCfPath = "/etc/postfix/master.cf"; | PostfixMasterCfPath = "/etc/postfix/master.cf"; | ||||
ReloadMtaCommand = "/usr/local/sbin/postfix reload"; | |||||
} else if ("Ubuntu" == OperatingSystemType) { | } else if ("Ubuntu" == OperatingSystemType) { | ||||
PostfixMainCfPath = "/etc/postfix/main.cf"; | PostfixMainCfPath = "/etc/postfix/main.cf"; | ||||
PostfixMasterCfPath = "/etc/postfix/master.cf"; | PostfixMasterCfPath = "/etc/postfix/master.cf"; | ||||
ReloadMtaCommand = "/usr/sbin/postfix reload"; | |||||
} else if ("RedHat" == OperatingSystemType) { | } else if ("RedHat" == OperatingSystemType) { | ||||
PostfixMainCfPath = "/etc/postfix/main.cf"; | PostfixMainCfPath = "/etc/postfix/main.cf"; | ||||
PostfixMasterCfPath = "/etc/postfix/master.cf"; | PostfixMasterCfPath = "/etc/postfix/master.cf"; | ||||
ReloadMtaCommand = "/usr/sbin/postfix reload"; | |||||
} else if ("Suse" == OperatingSystemType) { | } else if ("Suse" == OperatingSystemType) { | ||||
PostfixMainCfPath = "/etc/postfix/main.cf"; | PostfixMainCfPath = "/etc/postfix/main.cf"; | ||||
PostfixMasterCfPath = "/etc/postfix/master.cf"; | PostfixMasterCfPath = "/etc/postfix/master.cf"; | ||||
ReloadMtaCommand = "/usr/sbin/postfix reload"; | |||||
} else { | } else { | ||||
if (!Explain()) { | if (!Explain()) { | ||||
SaveFile->CreateBackupFile(PostfixMainCfPath); // Save any existing file. | |||||
std::ofstream Output; // Append the configuration. | std::ofstream Output; // Append the configuration. | ||||
Output.open(PostfixMainCfPath.c_str(), std::ios::app); | Output.open(PostfixMainCfPath.c_str(), std::ios::app); | ||||
} | } | ||||
Input.open(PostfixMainCfPath.c_str()); // Read the contents. | |||||
if (!Input) { | |||||
std::string Temp; | |||||
Temp = "Error opening the postfix configuration file " + PostfixMainCfPath; | |||||
Temp += " for reading: "; | |||||
Temp += strerror(errno); | |||||
throw std::runtime_error(Temp); | |||||
} | |||||
std::string Content; | |||||
std::string Line; | |||||
while (getline(Input, Line)) { | |||||
if (std::string::npos != Line.find(SnfMilterMainCfSearchString)) { // Check for integration line. | |||||
if (Verbose()) { | |||||
if (!Explain()) { | |||||
std::cout << " Remove '" << Line << "'...\n"; | |||||
SaveFile->CreateBackupFile(PostfixMainCfPath); // Save any existing file. | |||||
} | |||||
continue; // Do not copy this line. | |||||
Input.open(PostfixMainCfPath.c_str()); // Read the contents. | |||||
if (!Input) { | |||||
std::string Temp; | |||||
Temp = "Error opening the postfix configuration file " + PostfixMainCfPath; | |||||
Temp += " for reading: "; | |||||
Temp += strerror(errno); | |||||
throw std::runtime_error(Temp); | |||||
} | } | ||||
Content += Line + "\n"; // Copy this line. | |||||
} | |||||
std::string Content; | |||||
std::string Line; | |||||
if (!Input.eof()) { // Should be at end-of-file. | |||||
std::string Temp; | |||||
while (getline(Input, Line)) { | |||||
Temp = "Error reading the postfix configuration file " + PostfixMainCfPath; | |||||
Temp += ": "; | |||||
Temp += strerror(errno); | |||||
throw std::runtime_error(Temp); | |||||
} | |||||
if (std::string::npos != Line.find(SnfMilterMainCfSearchString)) { // Check for integration line. | |||||
Input.close(); | |||||
if (Input.bad()) { | |||||
std::string Temp; | |||||
if (Verbose()) { | |||||
Temp = "Error closing the postfix configuration file " + PostfixMainCfPath; | |||||
Temp += " after reading: "; | |||||
Temp += strerror(errno); | |||||
throw std::runtime_error(Temp); | |||||
} | |||||
std::cout << " Remove '" << Line << "'...\n"; | |||||
if (!Explain()) { | |||||
} | |||||
continue; // Do not copy this line. | |||||
std::ofstream Output; // Write the updated contents. | |||||
} | |||||
Output.open(PostfixMainCfPath.c_str(), std::ios::trunc); | |||||
if (!Output) { | |||||
std::string Temp; | |||||
Content += Line + "\n"; // Copy this line. | |||||
Temp = "Error opening the postfix configuration file " + PostfixMainCfPath; | |||||
Temp += " for writing: "; | |||||
Temp += strerror(errno); | |||||
throw std::runtime_error(Temp); | |||||
} | } | ||||
Output << Content; | |||||
if (!Output) { | |||||
if (!Input.eof()) { // Should be at end-of-file. | |||||
std::string Temp; | std::string Temp; | ||||
Temp = "Error writing the postfix configuration file " + PostfixMainCfPath; | |||||
Temp = "Error reading the postfix configuration file " + PostfixMainCfPath; | |||||
Temp += ": "; | Temp += ": "; | ||||
Temp += strerror(errno); | Temp += strerror(errno); | ||||
throw std::runtime_error(Temp); | throw std::runtime_error(Temp); | ||||
} | } | ||||
Output.close(); | |||||
if (!Output) { | |||||
Input.close(); | |||||
if (Input.bad()) { | |||||
std::string Temp; | std::string Temp; | ||||
Temp = "Error closing the postfix configuration file " + PostfixMainCfPath; | Temp = "Error closing the postfix configuration file " + PostfixMainCfPath; | ||||
Temp += " after writing: "; | |||||
Temp += " after reading: "; | |||||
Temp += strerror(errno); | Temp += strerror(errno); | ||||
throw std::runtime_error(Temp); | throw std::runtime_error(Temp); | ||||
} | } | ||||
if (!Explain()) { | |||||
std::ofstream Output; // Write the updated contents. | |||||
Output.open(PostfixMainCfPath.c_str(), std::ios::trunc); | |||||
if (!Output) { | |||||
std::string Temp; | |||||
Temp = "Error opening the postfix configuration file " + PostfixMainCfPath; | |||||
Temp += " for writing: "; | |||||
Temp += strerror(errno); | |||||
throw std::runtime_error(Temp); | |||||
} | |||||
Output << Content; | |||||
if (!Output) { | |||||
std::string Temp; | |||||
Temp = "Error writing the postfix configuration file " + PostfixMainCfPath; | |||||
Temp += ": "; | |||||
Temp += strerror(errno); | |||||
throw std::runtime_error(Temp); | |||||
} | |||||
Output.close(); | |||||
if (!Output) { | |||||
std::string Temp; | |||||
Temp = "Error closing the postfix configuration file " + PostfixMainCfPath; | |||||
Temp += " after writing: "; | |||||
Temp += strerror(errno); | |||||
throw std::runtime_error(Temp); | |||||
} | |||||
} | |||||
} | } | ||||
OutputVerboseEnd(); | OutputVerboseEnd(); | ||||
} | } | ||||
bool | |||||
PostfixIntegrate::MtaIsRunningDetected() { | |||||
if (Verbose()) { | |||||
std::cout << "Checking whether postfix is detected to be running..."; | |||||
} | |||||
bool IsRunningDetected; | |||||
IsRunningDetected = (std::system(MtaIsRunningCommand.c_str()) == 0); | |||||
if (Verbose()) { | |||||
std::cout << (IsRunningDetected ? "yes" : "no"); | |||||
} | |||||
OutputVerboseEnd(); | |||||
return IsRunningDetected; | |||||
} | |||||
bool | |||||
PostfixIntegrate::ReloadMta() { | |||||
if (Verbose()) { | |||||
std::cout << "Reloading postfix..."; | |||||
} | |||||
bool Succeeded; | |||||
if (!Explain()) { | |||||
Succeeded = (std::system(ReloadMtaCommand.c_str()) == 0); | |||||
if (Verbose()) { | |||||
std::cout << (Succeeded ? "succeeded" : "failed"); | |||||
} | |||||
} | |||||
OutputVerboseEnd(); | |||||
return Succeeded; | |||||
} | |||||
bool | bool | ||||
PostfixIntegrate::IsIntegrated() { | PostfixIntegrate::IsIntegrated() { | ||||
virtual void Unintegrate(FileBackup *SaveFile); | virtual void Unintegrate(FileBackup *SaveFile); | ||||
virtual bool MtaIsRunningDetected(); | |||||
virtual bool ReloadMta(); | |||||
private: | private: | ||||
virtual bool IsIntegrated(); | virtual bool IsIntegrated(); | ||||
/// Postfix master.cf file path. | /// Postfix master.cf file path. | ||||
std::string PostfixMasterCfPath; | std::string PostfixMasterCfPath; | ||||
/// Command to determine whether postfix is running. | |||||
std::string MtaIsRunningCommand; | |||||
/// Command to reload postfix. | |||||
std::string ReloadMtaCommand; | |||||
}; | }; | ||||
#endif | #endif |
// Windows OS. | // Windows OS. | ||||
const std::string SNFMilterConfig::DefaultConfigFile("C:\\SNF\\SNFMilter.xml"); | const std::string SNFMilterConfig::DefaultConfigFile("C:\\SNF\\SNFMilter.xml"); | ||||
const std::string SNFMilterConfig::DefaultSampleConfigFile("C:\\SNF\\SNFMilter.xml.sample"); | |||||
const std::string SNFMilterConfig::SampleConfigFile("C:\\SNF\\SNFMilter.xml.sample"); | |||||
const std::string SNFMilterConfig::SampleIdentityFile("C:\\SNF\\identity.xml.sample"); | |||||
#else | #else | ||||
#ifdef DEFAULT_CONFIG_DIR | #ifdef DEFAULT_CONFIG_DIR | ||||
// *nix, DEFAULT_CONFIG_DIR is specified on the compile command line. | // *nix, DEFAULT_CONFIG_DIR is specified on the compile command line. | ||||
const std::string SNFMilterConfig::DefaultConfigFile(DEFAULT_CONFIG_DIR "/snf-milter/SNFMilter.xml"); | const std::string SNFMilterConfig::DefaultConfigFile(DEFAULT_CONFIG_DIR "/snf-milter/SNFMilter.xml"); | ||||
const std::string SNFMilterConfig::DefaultSampleConfigFile(DEFAULT_CONFIG_DIR "/snf-milter/SNFMilter.xml.sample"); | |||||
const std::string SNFMilterConfig::SampleConfigFile(DEFAULT_CONFIG_DIR "/snf-milter/SNFMilter.xml.sample"); | |||||
const std::string SNFMilterConfig::SampleIdentityFile(DEFAULT_CONFIG_DIR "/snf-milter/identity.xml.sample"); | |||||
#else | #else | ||||
// Not Windows, and DEFAULT_CONFIG_DIR is not specified on the compile | // Not Windows, and DEFAULT_CONFIG_DIR is not specified on the compile | ||||
// command line. In this case, we don't know the default path for the | // command line. In this case, we don't know the default path for the | ||||
// configuration file. | // configuration file. | ||||
const std::string SNFMilterConfig::DefaultConfigFile(""); | const std::string SNFMilterConfig::DefaultConfigFile(""); | ||||
const std::string SNFMilterConfig::DefaultSampleConfigFile(""); | |||||
const std::string SNFMilterConfig::SampleConfigFile(""); | |||||
const std::string SNFMilterConfig::SampleIdentityFile(""); | |||||
#endif | #endif | ||||
#endif | #endif | ||||
const string ConfigFileKey("-config="); | |||||
const string IntegrateWithNoneKey("-mta=none"); | const string IntegrateWithNoneKey("-mta=none"); | ||||
const string IntegrateWithPostfixKey("-mta=postfix"); | const string IntegrateWithPostfixKey("-mta=postfix"); | ||||
const string IntegrateWithSendmailKey("-mta=sendmail"); | const string IntegrateWithSendmailKey("-mta=sendmail"); | ||||
<< Version << endl | << Version << endl | ||||
<< "Copyright (C) 2012, ARM Research Labs, LLC (www.armresearch.com)\n\n" | << "Copyright (C) 2012, ARM Research Labs, LLC (www.armresearch.com)\n\n" | ||||
<< "Usage:\n\n" | << "Usage:\n\n" | ||||
<< "SNFMilterConfig [" << ConfigFileKey << "snf-config-file] " | |||||
<< "SNFMilterConfig " | |||||
<< IntegrateWithPostfixKey << " | " | << IntegrateWithPostfixKey << " | " | ||||
<< IntegrateWithSendmailKey << " | " | << IntegrateWithSendmailKey << " | " | ||||
<< IntegrateWithNoneKey << " " | << IntegrateWithNoneKey << " " | ||||
<< UtilityConfig::HelpCommandLine() << "\n\n" | << UtilityConfig::HelpCommandLine() << "\n\n" | ||||
<< "SNFMilterConfig creates the configuration files (snf-config-file and the ignore list file) and the\n" | |||||
<< "rulebase download script (default: getRulebase) if they don't exist.\n\n" | |||||
<< " -config=snf-config-file Specifies the configuration file\n" | |||||
<< "SNFMilterConfig creates the configuration files (snf-config-file and the\n" | |||||
<< "ignore list file), the rulebase download script (default: getRulebase) if\n" | |||||
<< "they don't exist, and also the identity file.\n\n" | |||||
<< " -mta=postfix Integrate with postfix\n" | << " -mta=postfix Integrate with postfix\n" | ||||
<< " -mta=sendmail Integrate with sendmail\n" | << " -mta=sendmail Integrate with sendmail\n" | ||||
<< " -mta=none Remove any integration with all supported MTAs\n" | << " -mta=none Remove any integration with all supported MTAs\n" | ||||
<< UtilityConfig::HelpDescription() << "\n" | << UtilityConfig::HelpDescription() << "\n" | ||||
<< "If snf-config-file is not specified, then the following file is used:\n\n" | |||||
<< " " << DefaultConfigFile << "\n\n"; | |||||
<< "If snf-config-file is not specified, then the following file is used if it exists:\n\n" | |||||
<< " " << DefaultConfigFile << "\n\n" | |||||
<< "If snf-config-file is not specified and the above file doesn't exist, then it is\n" | |||||
<< "copied from the following file:\n\n" | |||||
<< " " << SampleConfigFile << "\n\n"; | |||||
}; | }; | ||||
int i; | int i; | ||||
int NumCommandsFound = 0; | int NumCommandsFound = 0; | ||||
string OneInput; | string OneInput; | ||||
string ConfigFile; | |||||
MtaCommand = NoCommand; // Default is to do nothing. | |||||
for (i = 1; i < argc; i++) { // Check each input. | for (i = 1; i < argc; i++) { // Check each input. | ||||
OneInput = argv[i]; | OneInput = argv[i]; | ||||
if (0 == OneInput.find(ConfigFileKey)) { | |||||
ConfigFile = OneInput.substr(ConfigFileKey.length()); | |||||
if (OneInput == IntegrateWithNoneKey) { | |||||
} else if (OneInput == IntegrateWithNoneKey) { | |||||
Command = IntegrateWithNoneCmd; | |||||
MtaCommand = IntegrateWithNoneCmd; | |||||
NumCommandsFound++; | NumCommandsFound++; | ||||
} else if (OneInput == IntegrateWithPostfixKey) { | } else if (OneInput == IntegrateWithPostfixKey) { | ||||
Command = IntegrateWithPostfixCmd; | |||||
MtaCommand = IntegrateWithPostfixCmd; | |||||
NumCommandsFound++; | NumCommandsFound++; | ||||
} else if (0 == OneInput.find(IntegrateWithSendmailKey)) { | } else if (0 == OneInput.find(IntegrateWithSendmailKey)) { | ||||
Command = IntegrateWithSendmailCmd; | |||||
MtaCommand = IntegrateWithSendmailCmd; | |||||
NumCommandsFound++; | NumCommandsFound++; | ||||
} else { | } else { | ||||
} | } | ||||
if (0 == ConfigFile.length()) { // Load default config file name. | |||||
ConfigFile = DefaultConfigFile; | |||||
} | |||||
LoadConfigFile(ConfigFile); | |||||
LoadInfo(); // Load the file paths. | |||||
LoadSocketInfo(); // Load the socket path. | |||||
return (NumCommandsFound == 1); | return (NumCommandsFound == 1); | ||||
} | } | ||||
} | } | ||||
void | void | ||||
SNFMilterConfig::UpdateConfigFiles() { | |||||
SNFMilterConfig::CreateLoadConfig() { | |||||
CheckAndSetConfigFileName(&DefaultConfigFile, 1); // Load the config file name. | |||||
if (!Explain()) { | |||||
std::string ConfigFileName = GetConfigFileName(); | |||||
SaveFile.CreateBackupFile(GetConfigFileName()); | |||||
SaveFile.CreateBackupFile(ConfigFileName); // Save any existing file. | |||||
} | |||||
CreateDefaultConfigFile(SampleConfigFile); // Create the file if it doesn't exist. | |||||
LoadConfig(); | |||||
LoadInfo(); // Load the file paths. | |||||
LoadSocketInfo(); // Load the socket path. | |||||
if (!FileExists(ConfigFileName)) { | |||||
} | |||||
Copy(DefaultSampleConfigFile, ConfigFileName); // Use SNFMilter.xml.sample. | |||||
void | |||||
SNFMilterConfig::SaveFileState() { | |||||
if (!Explain()) { | |||||
SaveFile.CreateBackupFile(GetRulebaseScriptName()); | |||||
SaveFile.CreateBackupFile(GetRulebaseFileName()); | |||||
SaveFile.CreateBackupFile(GetIdentityFileName()); | |||||
SaveFile.CreateBackupFile(GetIgnoreListFileName()); | |||||
} | } | ||||
SetMode(ConfigFileName, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH); // Set permissions. | |||||
SetOwnerGroup(ConfigFileName); // Set to sniffer user. | |||||
} | |||||
void | |||||
SNFMilterConfig::UpdateConfigFiles() { | |||||
SetMode(GetConfigFileName(), S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH); // Set permissions. | |||||
SetOwnerGroup(GetConfigFileName()); // Set to sniffer user. | |||||
CreateDefaultIdentityFile(SampleIdentityFile); | |||||
CreateUpdateRulebaseScript(); | |||||
UpdateLogDir(); | UpdateLogDir(); | ||||
UpdateIgnoreListFile(); | UpdateIgnoreListFile(); | ||||
void | void | ||||
SNFMilterConfig::DoIntegrationCommand() { | SNFMilterConfig::DoIntegrationCommand() { | ||||
switch (Command) { | |||||
switch (MtaCommand) { | |||||
case NoCommand: | |||||
break; | |||||
case IntegrateWithNoneCmd: | case IntegrateWithNoneCmd: | ||||
UnintegrateWithAllExcept(); | UnintegrateWithAllExcept(); | ||||
ostringstream Temp; | ostringstream Temp; | ||||
Temp << "Internal error in SNFMilterConfig::DoIntegrationCommand: Invalid value of command: " | Temp << "Internal error in SNFMilterConfig::DoIntegrationCommand: Invalid value of command: " | ||||
<< Command; | |||||
<< MtaCommand; | |||||
throw runtime_error(Temp.str()); | throw runtime_error(Temp.str()); | ||||
#endif | #endif | ||||
} | } | ||||
void | |||||
SNFMilterConfig::IntegrateWithPostfix() { | |||||
// UnintegrateWithAll(); // Remove any existing integration. | |||||
if (Verbose()) { | |||||
cout << "Add to postfix file " << PostfixMainCfPath << ": '" | |||||
<< SnfMilterMainCfIntegrationString << "'..."; | |||||
} | |||||
if (!Explain()) { | |||||
ofstream Output; // Append the configuration. | |||||
Output.open(PostfixMainCfPath.c_str(), ios::app); | |||||
if (!Output) { | |||||
string Temp; | |||||
Temp = "Error opening the postfix configuration file " + PostfixMainCfPath; | |||||
Temp += " for writing: "; | |||||
Temp += strerror(errno); | |||||
throw runtime_error(Temp); | |||||
} | |||||
Output << SnfMilterMainCfIntegrationString << "\n"; | |||||
if (!Output) { | |||||
string Temp; | |||||
Temp = "Error appending to the postfix configuration file " + PostfixMainCfPath; | |||||
Temp += ": "; | |||||
Temp += strerror(errno); | |||||
throw runtime_error(Temp); | |||||
} | |||||
Output.close(); | |||||
if (!Output) { | |||||
string Temp; | |||||
Temp = "Error closing the postfix configuration file " + PostfixMainCfPath; | |||||
Temp += " after appending: "; | |||||
Temp += strerror(errno); | |||||
throw runtime_error(Temp); | |||||
} | |||||
} | |||||
OutputVerboseEnd(); | |||||
CreateSocketDir(); | |||||
StartOrRestartMta("postfix"); | |||||
} | |||||
void | |||||
SNFMilterConfig::UnintegrateWithPostfix() { | |||||
ifstream Input; | |||||
if (Verbose()) { | |||||
cout << "Remove any integration in postfix file " << PostfixMainCfPath << "--\n"; | |||||
} | |||||
Input.open(PostfixMainCfPath.c_str()); // Read the contents. | |||||
if (!Input) { | |||||
string Temp; | |||||
Temp = "Error opening the postfix configuration file " + PostfixMainCfPath; | |||||
Temp += " for reading: "; | |||||
Temp += strerror(errno); | |||||
throw runtime_error(Temp); | |||||
} | |||||
string Content; | |||||
string Line; | |||||
while (getline(Input, Line)) { | |||||
if (string::npos != Line.find(SnfMilterMainCfSearchString)) { // Check for integration line. | |||||
if (Verbose()) { | |||||
cout << " Remove '" << Line << "'...\n"; | |||||
} | |||||
continue; // Do not copy this line. | |||||
} | |||||
Content += Line + "\n"; // Copy this line. | |||||
} | |||||
if (!Input.eof()) { // Should be at end-of-file. | |||||
string Temp; | |||||
Temp = "Error reading the postfix configuration file " + PostfixMainCfPath; | |||||
Temp += ": "; | |||||
Temp += strerror(errno); | |||||
throw runtime_error(Temp); | |||||
} | |||||
Input.close(); | |||||
if (Input.bad()) { | |||||
string Temp; | |||||
Temp = "Error closing the postfix configuration file " + PostfixMainCfPath; | |||||
Temp += " after reading: "; | |||||
Temp += strerror(errno); | |||||
throw runtime_error(Temp); | |||||
} | |||||
if (!Explain()) { | |||||
ofstream Output; // Write the updated contents. | |||||
Output.open(PostfixMainCfPath.c_str(), ios::trunc); | |||||
if (!Output) { | |||||
string Temp; | |||||
Temp = "Error opening the postfix configuration file " + PostfixMainCfPath; | |||||
Temp += " for writing: "; | |||||
Temp += strerror(errno); | |||||
throw runtime_error(Temp); | |||||
} | |||||
Output << Content; | |||||
if (!Output) { | |||||
string Temp; | |||||
Temp = "Error writing the postfix configuration file " + PostfixMainCfPath; | |||||
Temp += ": "; | |||||
Temp += strerror(errno); | |||||
throw runtime_error(Temp); | |||||
} | |||||
Output.close(); | |||||
if (!Output) { | |||||
string Temp; | |||||
Temp = "Error closing the postfix configuration file " + PostfixMainCfPath; | |||||
Temp += " after writing: "; | |||||
Temp += strerror(errno); | |||||
throw runtime_error(Temp); | |||||
} | |||||
} | |||||
OutputVerboseEnd(); | |||||
} | |||||
void | |||||
SNFMilterConfig::IntegrateWithSendmail() { | |||||
throw runtime_error("Integration with sendmail is not implemented"); | |||||
} | |||||
void | |||||
SNFMilterConfig::UnintegrateWithSendmail() { | |||||
std::cerr << "Unintegration with sendmail is not implemented" << "\n"; | |||||
} |
public: | public: | ||||
/// Command. | /// Command. | ||||
enum CommandEnum { | |||||
enum MtaCommandEnum { | |||||
NoCommand, ///< Take no MTA integration/unintegration action. | |||||
IntegrateWithNoneCmd, ///< Remove integration with all MTAs. | IntegrateWithNoneCmd, ///< Remove integration with all MTAs. | ||||
IntegrateWithPostfixCmd, ///< Integrate with postfix. | IntegrateWithPostfixCmd, ///< Integrate with postfix. | ||||
IntegrateWithSendmailCmd ///< Integrate with sendmail. | IntegrateWithSendmailCmd ///< Integrate with sendmail. | ||||
// | // | ||||
bool GetCommandLineInput(int argc, char* argv[]); | bool GetCommandLineInput(int argc, char* argv[]); | ||||
/// Load the configuration, creating default configuration if necessary. | |||||
// | |||||
// This method load the configuration specified in the command | |||||
// line, or the default config file. If the config file to load | |||||
// doesn't exit, the config file is created by copying from the | |||||
// sample config file. | |||||
// | |||||
// Side effect: The state of the config file is saved. | |||||
// | |||||
// Side effect: If the config file doesn't exist, a new config | |||||
// file is created. | |||||
// | |||||
void CreateLoadConfig(void); | |||||
/// Save the state of all files that might be changed, except the | |||||
/// config file. | |||||
// | |||||
void SaveFileState(void); | |||||
/// Create or update the configuration files. | /// Create or update the configuration files. | ||||
// | // | ||||
// The SNFMilter.xml and GBUdbIgnoreList.txt files are created if | // The SNFMilter.xml and GBUdbIgnoreList.txt files are created if | ||||
PostfixIntegrate Postfix; ///< Postfix integration object. | PostfixIntegrate Postfix; ///< Postfix integration object. | ||||
void IntegrateWithPostfix(); ///< Integrate with postfix. | |||||
void UnintegrateWithPostfix(); ///< Unintegrate with postfix. | |||||
void IntegrateWithSendmail(); ///< Integrate with sendmail. | |||||
void UnintegrateWithSendmail(); ///< Unintegrate with sendmail. | |||||
///< Unintegrate with MTAs. | |||||
/// Unintegrate with MTAs. | |||||
// | // | ||||
// Unintegrate with all MTAs except the specified MTA. | // Unintegrate with all MTAs except the specified MTA. | ||||
// | // | ||||
// | // | ||||
void UnintegrateWithAllExcept(std::string Except = ""); | void UnintegrateWithAllExcept(std::string Except = ""); | ||||
CommandEnum Command; ///< Specified command. | |||||
MtaCommandEnum MtaCommand; ///< Specified MTA integration/unintegration command. | |||||
static const std::string DefaultConfigFile; ///< Default config file. | static const std::string DefaultConfigFile; ///< Default config file. | ||||
static const std::string DefaultSampleConfigFile; ///< Sample config file. | |||||
static const std::string SampleConfigFile; ///< Sample config file. | |||||
static const std::string SampleIdentityFile; ///< Sample identity file. | |||||
std::string SocketFileName; | std::string SocketFileName; | ||||
// End of configuration. ///////////////////////////////////////////////////////////////////////////////// | // End of configuration. ///////////////////////////////////////////////////////////////////////////////// | ||||
////////////////////////////////////////////////////////////////////////////////////////////////////////// | ////////////////////////////////////////////////////////////////////////////////////////////////////////// | ||||
void RestoreFiles(SNFMilterConfig *Config) { | |||||
try { | |||||
cerr << "Restoring all configuration files..."; | |||||
Config->SaveFile.RestoreAllFilesFromBackup(); | |||||
cerr << "done.\n"; | |||||
} | |||||
catch(exception& e) { | |||||
cerr << "SNFMilterConfig::SaveFile Exception: " << e.what() << endl; | |||||
} | |||||
} | |||||
int main(int argc, char* argv[]) { | int main(int argc, char* argv[]) { | ||||
SNFMilterConfig SnfMilterConfig; | SNFMilterConfig SnfMilterConfig; | ||||
try { // Catch anything that breaks loose. | try { // Catch anything that breaks loose. | ||||
SnfMilterConfig.UpdateConfigFiles(); // Create config files if they don't | |||||
// exist, or update config files. | |||||
SnfMilterConfig.CreateLoadConfig(); // Save config file state and load config. | |||||
// Load the default if necessary. | |||||
SnfMilterConfig.SaveFileState(); // Save state of all other files. | |||||
SnfMilterConfig.UpdateConfigFiles(); // Create/update config files | |||||
SnfMilterConfig.CreateUpdateRulebaseScript(); // Create/update GetRulebase. | |||||
SnfMilterConfig.DownloadRulebase(); // Download rulebase. | |||||
SnfMilterConfig.UpdateIdentityFile(); // Update Identity file with credentials, | |||||
// if credentials were specified. | |||||
SnfMilterConfig.DoIntegrationCommand(); // Integrate/unintegrate. | SnfMilterConfig.DoIntegrationCommand(); // Integrate/unintegrate. | ||||
catch(exception& e) { // Report any normal exceptions. | catch(exception& e) { // Report any normal exceptions. | ||||
cerr << "SNFMilterConfig Exception: " << e.what() << endl; | cerr << "SNFMilterConfig Exception: " << e.what() << endl; | ||||
RestoreFiles(&SnfMilterConfig); | |||||
} | } | ||||
catch (snfCFGmgr::LoadFailure) { // Error loading configuration file. | catch (snfCFGmgr::LoadFailure) { // Error loading configuration file. | ||||
cerr << "snfCFGmgr Exception: Unable to load the configuration file " | cerr << "snfCFGmgr Exception: Unable to load the configuration file " | ||||
<< SnfMilterConfig.GetConfigFileName() << endl; | << SnfMilterConfig.GetConfigFileName() << endl; | ||||
RestoreFiles(&SnfMilterConfig); | |||||
} | } | ||||
catch(...) { // Report any unexpected exceptions. | catch(...) { // Report any unexpected exceptions. | ||||
cerr << "SNFMilterConfig Panic! Unknown Exception!" << endl; | cerr << "SNFMilterConfig Panic! Unknown Exception!" << endl; | ||||
RestoreFiles(&SnfMilterConfig); | |||||
} | } | ||||
return 0; // Normally we return zero. | return 0; // Normally we return zero. | ||||
} | } |