Просмотр исходного кода

Moved SNFIdentity functionality to SNFMilterConfig.

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-2d8eab27ff7c
master
adeniz 12 лет назад
Родитель
Сommit
06b2ca5907

+ 17
- 10
Common/FileBackup.cpp Просмотреть файл

@@ -6,14 +6,14 @@
// This file implements the common functionality for the configuration
// utilities.
#include <sstream>
#include <stdexcept>
#include <fstream>
#include <cerrno>
#include <cstring>
#include <cstdio>
#include <sstream>
#include <stdexcept>
#include <fstream>
#include "FileBackup.hpp"
//////////////////////////////////////////////////////////////////////////////////////////////////////////
@@ -126,7 +126,9 @@ FileBackup::FileExists(std::string File) {
void
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 {
@@ -144,6 +146,8 @@ FileBackup::CreateBackupFile(std::string File) {
}
OriginalFileExists[File] = ThisFileExists;
}
void
@@ -193,7 +197,6 @@ FileBackup::RestoreAllFilesFromBackup() {
iFile++) {
std::string BackupFileName;
if (iFile->second) { // Original file existed?
try { // Yes.
@@ -213,12 +216,16 @@ FileBackup::RestoreAllFilesFromBackup() {
} 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;
}
}

+ 0
- 2
Common/MtaIntegrate.cpp Просмотреть файл

@@ -9,8 +9,6 @@
//
///////////////////////////////////////////////////////////////////////////////////////////////////
#include <iostream>
#include "MtaIntegrate.hpp"
MtaIntegrate::MtaIntegrate() {

+ 17
- 0
Common/MtaIntegrate.hpp Просмотреть файл

@@ -54,6 +54,23 @@ public:
//
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:
/// Determine whether the MTA is integrated.

+ 30
- 2
Common/Utility.cpp Просмотреть файл

@@ -39,6 +39,10 @@ const string SNFGroupName = "snfuser";
// End of configuration. /////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////////////////////
Utility::Utility() {
}
bool
Utility::FileExists(const std::string File) {
@@ -151,7 +155,7 @@ Utility::Copy(std::string From, std::string To) {
void
Utility::SetOwnerGroup(std::string &File) {
Utility::SetOwnerGroup(std::string File) {
struct passwd *SNFPasswd;
uid_t SNFUid;
@@ -196,7 +200,7 @@ Utility::SetOwnerGroup(std::string &File) {
}
void
Utility::SetMode(std::string &File, mode_t mode) {
Utility::SetMode(std::string File, mode_t mode) {
if (Verbose()) {
@@ -267,6 +271,30 @@ Utility::CheckForString(std::string Line, std::string SearchString) {
}
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
Utility::SetVerbose(bool Mode) {

+ 13
- 2
Common/Utility.hpp Просмотреть файл

@@ -50,7 +50,7 @@ public:
//
// \see SNFGroupName.
//
void SetOwnerGroup(std::string &File);
void SetOwnerGroup(std::string File);
/// Set the mode of a file.
//
@@ -61,7 +61,7 @@ public:
//
// \param[in] is the mode.
//
void SetMode(std::string &File, mode_t mode);
void SetMode(std::string File, mode_t mode);
/// Create a directory.
//
@@ -83,6 +83,15 @@ public:
//
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.
//
// \param[in] Mode stores the Verbose mode.
@@ -126,6 +135,8 @@ public:
/// Directory separator.
static const std::string DirectorySeparator;
/// Trim whitespace from a string.
private:
bool VerboseRequested; ///< User requested verbose processing.

+ 440
- 67
Common/UtilityConfig.cpp Просмотреть файл

@@ -27,14 +27,33 @@ using namespace std;
// Configuration. ////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////////////////////
// Initialize sample ignore list file path.
// Initialize OS-dependent constants.
#ifdef WIN
// Windows OS.
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
// *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
// *nix, DEFAULT_DATA_DIR is specified on the compile command line.
const std::string UtilityConfig::SampleIgnoreListFile(DEFAULT_DATA_DIR "/GBUdbIgnoreList.txt.sample");
@@ -45,16 +64,6 @@ const std::string UtilityConfig::SampleIgnoreListFile(DEFAULT_DATA_DIR "/GBUdbIg
#error DEFAULT_DATA_DIR must be defined by -DDEFAULT_DATA_DIR="..." when compiling.
#endif
#endif
// Initialize sample rulebase script file.
#ifdef WIN
// Windows OS.
const std::string UtilityConfig::SampleRulebaseScriptFile("C:\\SNF\\getRulebase.sample");
#else
#ifdef SBIN_DIR
// *nix, SBIN_DIR is specified on the compile command line.
const std::string UtilityConfig::SampleRulebaseScriptFile(SBIN_DIR "/getRulebase.sample");
@@ -65,13 +74,6 @@ const std::string UtilityConfig::SampleRulebaseScriptFile(SBIN_DIR "/getRulebase
#error SBIN_DIR must be defined by -DSBIN_DIR="..." when compiling.
#endif
#endif
// Initialize OS-specific values.
#ifdef WIN
// Windows OS.
const std::string UtilityConfig::OperatingSystemType("Windows");
#else
#ifdef SNF_OSTYPE
// *nix, SNF_OSTYPE is specified on the compile command line.
const std::string UtilityConfig::OperatingSystemType(SNF_OSTYPE);
@@ -80,6 +82,7 @@ const std::string UtilityConfig::OperatingSystemType(SNF_OSTYPE);
// line. In this case, we don't know the operating system.
#error SNF_OSTYPE must be defined by -DSNF_OSTYPE="..." when compiling.
#endif
#endif
/// Verbose command-line input.
@@ -91,11 +94,25 @@ const string ExplainKey("-explain");
/// Help command-line input.
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. /////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////////////////////
UtilityConfig::UtilityConfig() {
UtilityConfig::UtilityConfig() :
LicenseIdIsSpecified(false), AuthenticationIsSpecified(false), ConfigFileExists(true)
{
SetExplain(false);
SetVerbose(false);
@@ -104,9 +121,9 @@ UtilityConfig::UtilityConfig() {
}
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) {
@@ -128,23 +145,22 @@ UtilityConfig::CheckAndLoadConfigFile(const std::string DefaultFile[], int NumDe
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;
@@ -159,22 +175,56 @@ UtilityConfig::CheckAndLoadConfigFile(const std::string DefaultFile[], int NumDe
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
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()) {
cout << "Using configuration file " << ConfigFile << ".\n";
cout << "Using configuration file " << GetConfigFileName() << ".\n";
}
@@ -224,14 +274,14 @@ UtilityConfig::GetPlatformContents(void) {
string
UtilityConfig::GetConfigFileName(void) {
return ConfigFile;
return ConfigFileName;
}
void
UtilityConfig::SetConfigFileName(string Name) {
ConfigFile = Name;
ConfigFileName = Name;
}
@@ -270,22 +320,29 @@ UtilityConfig::GetRulebaseScriptName(void) {
}
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;
}
@@ -294,31 +351,26 @@ UtilityConfig::LoadInfo(){
if ("OpenBSD" == OperatingSystemType) {
OsSpec = OpenBSD;
PostfixMainCfPath = "/usr/local/etc/postfix/main.cf";
PostfixMasterCfPath = "/usr/local/etc/postfix/master.cf";
} else if ("FreeBSD" == OperatingSystemType) {
OsSpec = FreeBSD;
PostfixMainCfPath = "/etc/postfix/main.cf";
PostfixMasterCfPath = "/etc/postfix/master.cf";
} else if ("Ubuntu" == OperatingSystemType) {
OsSpec = Ubuntu;
PostfixMainCfPath = "/etc/postfix/main.cf";
PostfixMasterCfPath = "/etc/postfix/master.cf";
} else if ("RedHat" == OperatingSystemType) {
OsSpec = RedHat;
PostfixMainCfPath = "/etc/postfix/main.cf";
PostfixMasterCfPath = "/etc/postfix/master.cf";
} else if ("Suse" == OperatingSystemType) {
OsSpec = Suse;
PostfixMainCfPath = "/etc/postfix/main.cf";
PostfixMasterCfPath = "/etc/postfix/master.cf";
@@ -326,7 +378,7 @@ UtilityConfig::LoadInfo(){
ostringstream Temp;
Temp << "Internal error in UtilityConfig::GetOsSpec: Invalid value of OperatingSystemType: "
Temp << "Internal error in UtilityConfig::LoadInfo: Invalid value of OperatingSystemType: "
<< OperatingSystemType;
throw runtime_error(Temp.str());
@@ -338,18 +390,11 @@ UtilityConfig::LoadInfo(){
void
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)) {
Copy(SampleIgnoreListFile, IgnoreListFile); // Use SNFMilter.xml.sample.
Copy(SampleIgnoreListFile, IgnoreListFile);
}
@@ -374,25 +419,341 @@ UtilityConfig::UpdateLogDir() {
}
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
UtilityConfig::ProcessCommandLineItem(std::string OneInput) {
bool ValidCommand = false;
bool ValidCommand = true;
std::string TempString;
if (OneInput == VerboseKey) {
SetVerbose(true);
ValidCommand = true;
} else if (OneInput == ExplainKey) {
SetExplain(true);
ValidCommand = true;
} else if (OneInput == HelpKey) {
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;
}
@@ -400,12 +761,21 @@ UtilityConfig::ProcessCommandLineItem(std::string OneInput) {
}
bool
UtilityConfig::CommandLineIsOkay() {
return (AuthenticationIsSpecified == LicenseIdIsSpecified);
}
std::string
UtilityConfig::HelpCommandLine() {
std::string Help;
Help = "[ " + VerboseKey + " | " + ExplainKey + " ]";
Help = "[" + ConfigFileKey + "snf-config-file] ";
Help += "[" + LicenseIdKey + "licenseid " + AuthenticationKey + "authentication] ";
Help += "[ " + VerboseKey + " " + ExplainKey + " ]";
return Help;
@@ -416,7 +786,10 @@ UtilityConfig::HelpDescription() {
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 += " without executing any commands\n";

+ 134
- 32
Common/UtilityConfig.hpp Просмотреть файл

@@ -30,31 +30,54 @@ public:
/// Object to back up and restore files.
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] 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.
//
@@ -100,23 +123,34 @@ public:
// \returns the rulebase script file name.
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).
//
@@ -125,9 +159,6 @@ public:
//
void LoadInfo();
/// OS specification.
OperatingSystemSpecEnum OsSpec;
/// Postfix main.cf file path.
std::string PostfixMainCfPath;
@@ -150,12 +181,54 @@ public:
// owner.
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.
//
// \param[in] OneInput is the command-line item to process.
//
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.
std::string HelpCommandLine();
@@ -164,7 +237,36 @@ public:
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 SampleRulebaseScriptFile; ///< Sample rulebase script file.

+ 77
- 2
CommonTests/TestFileBackup.cpp Просмотреть файл

@@ -82,8 +82,6 @@ Initialize() {
FileName.push_back("File4.txt");
FileSize.push_back(203043);
const char *CharPtr = RandomChar.data();
std::vector<int>::iterator iSize = FileSize.begin();
for (StringContainer::iterator iFile = FileName.begin(); // Create random data.
@@ -337,6 +335,73 @@ TestFileExists() {
}
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
Finalize() {
@@ -377,6 +442,16 @@ int main(int argc, char* argv[]) {
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.
catch(std::exception& e) { // Report any normal exceptions.

+ 150
- 67
SNFIdentity/SNFIdentityConfig.cpp Просмотреть файл

@@ -33,6 +33,24 @@ using namespace std;
// 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 AuthSearchString = "AUTHENTICATION=";
@@ -110,63 +128,6 @@ SNFIdentityConfig::GetCommandLineInput(int argc, char* argv[]) {
}
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
SNFIdentityConfig::UpdateRulebaseScriptCredentials() {
@@ -174,7 +135,7 @@ SNFIdentityConfig::UpdateRulebaseScriptCredentials() {
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";
}
@@ -184,7 +145,7 @@ SNFIdentityConfig::UpdateRulebaseScriptCredentials() {
if (!Input) {
string Temp;
Temp = "Error opening rulebase file " + File;
Temp = "Error opening rulebase download script file " + File;
Temp += " for reading: ";
Temp += strerror(errno);
throw runtime_error(Temp);
@@ -202,7 +163,7 @@ SNFIdentityConfig::UpdateRulebaseScriptCredentials() {
if (FoundLicense) { // Second license line found?
string Temp;
Temp = "Rulebase file " + File;
Temp = "Rulebase sownload script file " + File;
Temp += " has the wrong format: Found two lines beginning with " + LicenseSearchString;
throw runtime_error(Temp);
@@ -224,7 +185,7 @@ SNFIdentityConfig::UpdateRulebaseScriptCredentials() {
if (FoundAuth) { // Second authentication line found?
string Temp;
Temp = "Rulebase file " + File;
Temp = "Rulebase download script file " + File;
Temp += " has the wrong format: Found two lines beginning with " + AuthSearchString;
throw runtime_error(Temp);
}
@@ -247,7 +208,7 @@ SNFIdentityConfig::UpdateRulebaseScriptCredentials() {
if (!FoundLicense || !FoundAuth) {
string Temp;
Temp = "Rulebase file " + File;
Temp = "Rulebase download script file " + File;
Temp += " has the wrong format: Missing required line beginning with '" + LicenseSearchString;
Temp += "' or '" + AuthSearchString;
Temp += "'";
@@ -257,7 +218,7 @@ SNFIdentityConfig::UpdateRulebaseScriptCredentials() {
if (!Input.eof()) { // Should be at end-of-file.
string Temp;
Temp = "Error reading the rulebase file " + File;
Temp = "Error reading the rulebase download script file " + File;
Temp += ": ";
Temp += strerror(errno);
throw runtime_error(Temp);
@@ -267,7 +228,7 @@ SNFIdentityConfig::UpdateRulebaseScriptCredentials() {
if (Input.bad()) {
string Temp;
Temp = "Error closing the rulebase file " + File;
Temp = "Error closing the rulebase download script file " + File;
Temp += " after reading: ";
Temp += strerror(errno);
throw runtime_error(Temp);
@@ -276,13 +237,15 @@ SNFIdentityConfig::UpdateRulebaseScriptCredentials() {
if (!Explain()) {
SaveFile.CreateBackupFile(File); // Save the existing file.
ofstream Output; // Write the updated contents.
Output.open(File.c_str(), ios::trunc);
if (!Output) {
string Temp;
Temp = "Error opening rulebase file " + File;
Temp = "Error opening rulebase download script file " + File;
Temp += " for writing: ";
Temp += strerror(errno);
throw runtime_error(Temp);
@@ -292,7 +255,7 @@ SNFIdentityConfig::UpdateRulebaseScriptCredentials() {
if (!Output) {
string Temp;
Temp = "Error writing the rulebase file " + File;
Temp = "Error writing the rulebase download script file " + File;
Temp += ": ";
Temp += strerror(errno);
throw runtime_error(Temp);
@@ -302,7 +265,7 @@ SNFIdentityConfig::UpdateRulebaseScriptCredentials() {
if (!Output) {
string Temp;
Temp = "Error closing the rulebase file " + File;
Temp = "Error closing the rulebase download script file " + File;
Temp += " after writing: ";
Temp += strerror(errno);
throw runtime_error(Temp);
@@ -315,3 +278,123 @@ SNFIdentityConfig::UpdateRulebaseScriptCredentials() {
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;
}

+ 18
- 4
SNFIdentity/SNFIdentityConfig.hpp Просмотреть файл

@@ -58,6 +58,15 @@ public:
//
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.
//
// The file is created, the owner/group is changed by SetOwnerGroup(),
@@ -67,15 +76,20 @@ public:
//
void CreateIdentityFile();
/// Update the rulebase script with the credentials.
//
void UpdateRulebaseScriptCredentials();
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 Authentication; ///< Authentication string.
static const std::string RulebaseDownloadCommand; ///< Command to download the rulebase.
#endif
};
#endif

+ 23
- 2
SNFIdentity/main.cpp Просмотреть файл

@@ -51,6 +51,22 @@ const size_t DefaultConfigFileSize = sizeof DefaultConfigFile / sizeof DefaultCo
// 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[]) {
SNFIdentityConfig SnfIdentityConfig;
@@ -82,21 +98,26 @@ int main(int argc, char* argv[]) {
DefaultConfigFileSize); // config file specified on the
// command line, or the default file.
SnfIdentityConfig.CreateIdentityFile();
SnfIdentityConfig.UpdateRulebaseScriptCredentials();
SnfIdentityConfig.DownloadRulebase();
SnfIdentityConfig.CreateIdentityFile();
} // That's all folks.
catch(exception& e) { // Report any normal exceptions.
cerr << "SNFIdentity Exception: " << e.what() << endl;
RestoreFiles(&SnfIdentityConfig);
}
catch (snfCFGmgr::LoadFailure) { // Error loading configuration file.
cerr << "snfCFGmgr Exception: Unable to load the configuration file "
<< SnfIdentityConfig.GetConfigFileName() << endl;
RestoreFiles(&SnfIdentityConfig);
}
catch(...) { // Report any unexpected exceptions.
cerr << "SNFIdentity Panic! Unknown Exception!" << endl;
RestoreFiles(&SnfIdentityConfig);
}
return 0; // Normally we return zero.

+ 126
- 64
SNFMilterConfig/PostfixIntegrate.cpp Просмотреть файл

@@ -9,22 +9,15 @@
//
///////////////////////////////////////////////////////////////////////////////////////////////////
#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 <exception>
#include <stdexcept>
#include <sstream>
#include <fstream>
#include <vector>
#include "PostfixIntegrate.hpp"
@@ -43,30 +36,37 @@ const std::string SnfMilterMainCfIntegrationString("smtpd_milters = unix:/var/sn
void
PostfixIntegrate::SetOperatingSystem(std::string OperatingSystemType) {
MtaIsRunningCommand = "ps -axl root | grep -v grep | grep -q 'postfix/master'";
if ("OpenBSD" == OperatingSystemType) {
PostfixMainCfPath = "/usr/local/etc/postfix/main.cf";
PostfixMasterCfPath = "/usr/local/etc/postfix/master.cf";
ReloadMtaCommand = "/usr/local/sbin/postfix reload";
} else if ("FreeBSD" == OperatingSystemType) {
PostfixMainCfPath = "/etc/postfix/main.cf";
PostfixMasterCfPath = "/etc/postfix/master.cf";
ReloadMtaCommand = "/usr/local/sbin/postfix reload";
} else if ("Ubuntu" == OperatingSystemType) {
PostfixMainCfPath = "/etc/postfix/main.cf";
PostfixMasterCfPath = "/etc/postfix/master.cf";
ReloadMtaCommand = "/usr/sbin/postfix reload";
} else if ("RedHat" == OperatingSystemType) {
PostfixMainCfPath = "/etc/postfix/main.cf";
PostfixMasterCfPath = "/etc/postfix/master.cf";
ReloadMtaCommand = "/usr/sbin/postfix reload";
} else if ("Suse" == OperatingSystemType) {
PostfixMainCfPath = "/etc/postfix/main.cf";
PostfixMasterCfPath = "/etc/postfix/master.cf";
ReloadMtaCommand = "/usr/sbin/postfix reload";
} else {
@@ -99,6 +99,8 @@ PostfixIntegrate::Integrate(FileBackup *SaveFile) {
if (!Explain()) {
SaveFile->CreateBackupFile(PostfixMainCfPath); // Save any existing file.
std::ofstream Output; // Append the configuration.
Output.open(PostfixMainCfPath.c_str(), std::ios::app);
@@ -155,95 +157,155 @@ PostfixIntegrate::Unintegrate(FileBackup *SaveFile) {
}
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;
Temp = "Error writing the postfix configuration file " + PostfixMainCfPath;
Temp = "Error reading the postfix configuration file " + PostfixMainCfPath;
Temp += ": ";
Temp += strerror(errno);
throw std::runtime_error(Temp);
}
Output.close();
if (!Output) {
Input.close();
if (Input.bad()) {
std::string Temp;
Temp = "Error closing the postfix configuration file " + PostfixMainCfPath;
Temp += " after writing: ";
Temp += " after reading: ";
Temp += strerror(errno);
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();
}
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
PostfixIntegrate::IsIntegrated() {

+ 10
- 0
SNFMilterConfig/PostfixIntegrate.hpp Просмотреть файл

@@ -29,6 +29,10 @@ public:
virtual void Unintegrate(FileBackup *SaveFile);
virtual bool MtaIsRunningDetected();
virtual bool ReloadMta();
private:
virtual bool IsIntegrated();
@@ -39,6 +43,12 @@ private:
/// Postfix master.cf file path.
std::string PostfixMasterCfPath;
/// Command to determine whether postfix is running.
std::string MtaIsRunningCommand;
/// Command to reload postfix.
std::string ReloadMtaCommand;
};
#endif

+ 59
- 210
SNFMilterConfig/SNFMilterConfig.cpp Просмотреть файл

@@ -38,25 +38,27 @@ using namespace std;
// Windows OS.
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
#ifdef DEFAULT_CONFIG_DIR
// *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::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
// 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
// configuration file.
const std::string SNFMilterConfig::DefaultConfigFile("");
const std::string SNFMilterConfig::DefaultSampleConfigFile("");
const std::string SNFMilterConfig::SampleConfigFile("");
const std::string SNFMilterConfig::SampleIdentityFile("");
#endif
#endif
const string ConfigFileKey("-config=");
const string IntegrateWithNoneKey("-mta=none");
const string IntegrateWithPostfixKey("-mta=postfix");
const string IntegrateWithSendmailKey("-mta=sendmail");
@@ -76,20 +78,23 @@ SNFMilterConfig::DisplayHelp(std::string Version) {
<< Version << endl
<< "Copyright (C) 2012, ARM Research Labs, LLC (www.armresearch.com)\n\n"
<< "Usage:\n\n"
<< "SNFMilterConfig [" << ConfigFileKey << "snf-config-file] "
<< "SNFMilterConfig "
<< IntegrateWithPostfixKey << " | "
<< IntegrateWithSendmailKey << " | "
<< IntegrateWithNoneKey << " "
<< 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=sendmail Integrate with sendmail\n"
<< " -mta=none Remove any integration with all supported MTAs\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";
};
@@ -99,29 +104,26 @@ SNFMilterConfig::GetCommandLineInput(int argc, char* argv[]) {
int i;
int NumCommandsFound = 0;
string OneInput;
string ConfigFile;
MtaCommand = NoCommand; // Default is to do nothing.
for (i = 1; i < argc; i++) { // Check each input.
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++;
} else if (OneInput == IntegrateWithPostfixKey) {
Command = IntegrateWithPostfixCmd;
MtaCommand = IntegrateWithPostfixCmd;
NumCommandsFound++;
} else if (0 == OneInput.find(IntegrateWithSendmailKey)) {
Command = IntegrateWithSendmailCmd;
MtaCommand = IntegrateWithSendmailCmd;
NumCommandsFound++;
} else {
@@ -137,17 +139,6 @@ SNFMilterConfig::GetCommandLineInput(int argc, char* argv[]) {
}
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);
}
@@ -204,20 +195,46 @@ SNFMilterConfig::CreateSocketDir() {
}
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();
UpdateIgnoreListFile();
@@ -227,7 +244,10 @@ SNFMilterConfig::UpdateConfigFiles() {
void
SNFMilterConfig::DoIntegrationCommand() {
switch (Command) {
switch (MtaCommand) {
case NoCommand:
break;
case IntegrateWithNoneCmd:
UnintegrateWithAllExcept();
@@ -249,7 +269,7 @@ SNFMilterConfig::DoIntegrationCommand() {
ostringstream Temp;
Temp << "Internal error in SNFMilterConfig::DoIntegrationCommand: Invalid value of command: "
<< Command;
<< MtaCommand;
throw runtime_error(Temp.str());
@@ -276,174 +296,3 @@ SNFMilterConfig::UnintegrateWithAllExcept(std::string Except) {
#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";
}

+ 26
- 12
SNFMilterConfig/SNFMilterConfig.hpp Просмотреть файл

@@ -28,7 +28,8 @@ class SNFMilterConfig : public UtilityConfig {
public:
/// Command.
enum CommandEnum {
enum MtaCommandEnum {
NoCommand, ///< Take no MTA integration/unintegration action.
IntegrateWithNoneCmd, ///< Remove integration with all MTAs.
IntegrateWithPostfixCmd, ///< Integrate with postfix.
IntegrateWithSendmailCmd ///< Integrate with sendmail.
@@ -52,6 +53,25 @@ public:
//
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.
//
// The SNFMilter.xml and GBUdbIgnoreList.txt files are created if
@@ -74,15 +94,7 @@ private:
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.
//
@@ -99,11 +111,13 @@ private:
//
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 DefaultSampleConfigFile; ///< Sample config file.
static const std::string SampleConfigFile; ///< Sample config file.
static const std::string SampleIdentityFile; ///< Sample identity file.
std::string SocketFileName;

+ 33
- 2
SNFMilterConfig/main.cpp Просмотреть файл

@@ -41,6 +41,22 @@ const char* SNF_MILTERCONFIG_VERSION = "SNFMilterConfig 0.0.1 Build: " __DATE__
// 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[]) {
SNFMilterConfig SnfMilterConfig;
@@ -66,8 +82,19 @@ int main(int argc, char* argv[]) {
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.
@@ -75,14 +102,18 @@ int main(int argc, char* argv[]) {
catch(exception& e) { // Report any normal exceptions.
cerr << "SNFMilterConfig Exception: " << e.what() << endl;
RestoreFiles(&SnfMilterConfig);
}
catch (snfCFGmgr::LoadFailure) { // Error loading configuration file.
cerr << "snfCFGmgr Exception: Unable to load the configuration file "
<< SnfMilterConfig.GetConfigFileName() << endl;
RestoreFiles(&SnfMilterConfig);
}
catch(...) { // Report any unexpected exceptions.
cerr << "SNFMilterConfig Panic! Unknown Exception!" << endl;
RestoreFiles(&SnfMilterConfig);
}
return 0; // Normally we return zero.
}

Загрузка…
Отмена
Сохранить