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

Move from PKG-SNF-CS-NIX.


git-svn-id: https://svn.microneil.com/svn/SNFUtility/trunk@63 aa37657e-1934-4a5f-aa6d-2d8eab27ff7c
master
adeniz 11 лет назад
Родитель
Сommit
694d780d2c

+ 629
- 0
SNFServerConfig/PostfixIntegrate.cpp Просмотреть файл

@@ -0,0 +1,629 @@
// /file PostfixIntegrate.cpp
//
// Copyright (C) 2013, ARM Research Labs, LLC.
// See www.armresearch.com for the copyright terms.
//
// This file contains the functions for PostfixIntegrate.
//
// $Id$
//
///////////////////////////////////////////////////////////////////////////////////////////////////
#include <cstdlib>
#include <cerrno>
#include <cstring>
#include <iostream>
#include <exception>
#include <stdexcept>
#include <sstream>
#include <fstream>
#include "PostfixIntegrate.hpp"
//////////////////////////////////////////////////////////////////////////////////////////////////////////
// Configuration. ////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////////////////////
// End of configuration. /////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////////////////////
void
PostfixIntegrate::SetOperatingSystem(std::string OperatingSystemType) {
MtaIsRunningCommand = "ps axl | grep -v grep | grep -q 'postfix/master'";
PostfixDefaultIsChrooted = false; // Overwritten if postfix is
SnfSnifferDirName = "/usr/sbin"; // by default chrooted.
SnfSnifferFileName = SnfSnifferDirName + "/snfSniffer";
SnfSnifferSampleFileName = SnfSnifferFileName + ".sample";
ContentFilterLine = " -o content_filter=snfilter:dummy\n";
ContentFilterSpec = "snfilter unix - n n - 10 pipe\n";
if ("OpenBSD" == OperatingSystemType) {
PostfixDefaultIsChrooted = true;
SnfSnifferDirName = "/usr/local/sbin";
SnfSnifferFileName = SnfSnifferDirName + "/snfSniffer";
SnfSnifferSampleFileName = "/usr/local/sbin/snfSniffer.sample";
ContentFilterSpec += " flags=Rq user=snfuser argv=/usr/local/sbin/snfSniffer\n";
PostfixMainCfPath = "/etc/postfix/main.cf";
PostfixMasterCfPath = "/etc/postfix/master.cf";
ReloadMtaCommand = "/usr/local/sbin/postfix reload";
} else if ("FreeBSD" == OperatingSystemType) {
ContentFilterSpec += " flags=Rq user=snfuser argv=/usr/local/sbin/snfSniffer\n";
SnfSnifferDirName = "/usr/local/sbin";
SnfSnifferFileName = SnfSnifferDirName + "/snfSniffer";
SnfSnifferSampleFileName = "/usr/local/sbin/snfSniffer.sample";
PostfixMainCfPath = "/usr/local/etc/postfix/main.cf";
PostfixMasterCfPath = "/usr/local/etc/postfix/master.cf";
ReloadMtaCommand = "/usr/local/sbin/postfix reload";
} else if ("Ubuntu" == OperatingSystemType) {
PostfixDefaultIsChrooted = true;
SnfSnifferFileName = SnfSnifferDirName + "/snfSniffer";
SnfSnifferSampleFileName = "/usr/sbin/snfSniffer.sample";
ContentFilterSpec += " flags=Rq user=snfuser argv=/usr/sbin/snfSniffer\n";
PostfixMainCfPath = "/etc/postfix/main.cf";
PostfixMasterCfPath = "/etc/postfix/master.cf";
ReloadMtaCommand = "/usr/sbin/postfix reload";
} else if ("RedHat" == OperatingSystemType) {
ContentFilterSpec += " flags=Rq user=snfuser argv=/usr/sbin/snfSniffer\n";
PostfixMainCfPath = "/etc/postfix/main.cf";
PostfixMasterCfPath = "/etc/postfix/master.cf";
ReloadMtaCommand = "/usr/sbin/postfix reload";
} else if ("Suse" == OperatingSystemType) {
ContentFilterSpec += " flags=Rq user=snfuser argv=/usr/sbin/snfSniffer\n";
PostfixMainCfPath = "/etc/postfix/main.cf";
PostfixMasterCfPath = "/etc/postfix/master.cf";
ReloadMtaCommand = "/usr/sbin/postfix reload";
} else if ("ArchLinux" == OperatingSystemType) {
ContentFilterSpec += " flags=Rq user=snfuser argv=/usr/sbin/snfSniffer\n";
PostfixMainCfPath = "/etc/postfix/main.cf";
PostfixMasterCfPath = "/etc/postfix/master.cf";
ReloadMtaCommand = "/usr/sbin/postfix reload";
} else {
std::ostringstream Temp;
Temp << "***Error from PostfixIntegrate::SetOperatingSystem: Invalid value of OperatingSystemType: "
<< OperatingSystemType;
throw std::runtime_error(Temp.str());
}
ContentFilterSpec += " -f ${sender} -- ${recipient}\n";
}
void
PostfixIntegrate::Integrate(FileBackup *SaveFile) {
if (IsIntegrated()) {
return;
}
// Check whether the chroot configuration is as expected.
bool IsChrooted;
IsChrooted = MtaConfigurationIsChrooted();
if (IsChrooted != PostfixDefaultIsChrooted) {
std::string Temp;
Temp = "Error--postfix must be configured to run ";
Temp += (PostfixDefaultIsChrooted ? "" : "not ");
Temp += "chrooted, which is the default for this operating system. ";
Temp += "postfix was detected to be configured to run ";
Temp += (IsChrooted ? "" : "not ");
Temp += "chrooted.";
throw std::runtime_error(Temp);
}
if (Verbose()) {
std::cout << "Integrate with postfix...\n";
}
std::string Content;
if (!Explain()) {
if (!FileExists(SnfSnifferFileName)) { // Create SnfSniffer script
// if it doesn't exist.
SaveFile->CreateBackupFile(SnfSnifferFileName);
if (!FileExists(SnfSnifferDirName)) {
MkDir(SnfSnifferDirName);
}
SetMode(SnfSnifferDirName, S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH);
SetOwnerGroup(SnfSnifferDirName);
Copy(SnfSnifferSampleFileName, SnfSnifferFileName);
SetMode(SnfSnifferFileName, S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH);
SetOwnerGroup(SnfSnifferFileName);
}
SaveFile->CreateBackupFile(PostfixMasterCfPath);
std::ifstream Input;
Input.open(PostfixMasterCfPath.c_str()); // Read the contents.
if (!Input) {
std::string Temp;
Temp = "Error opening the postfix configuration file " + PostfixMasterCfPath;
Temp += " for reading: ";
Temp += strerror(errno);
throw std::runtime_error(Temp);
}
std::string Line;
while (getline(Input, Line)) {
Content += Line + "\n"; // Copy this line.
if ( (Line.find("smtp") == 0) && (Line.find("inet") != std::string::npos) ) {
if (Verbose()) {
std::cout << " Add\n\n "
<< ContentFilterLine
<< "\n\n after\n\n"
<< Line
<< "\n\n in "
<< PostfixMasterCfPath << "...\n";
}
Content += ContentFilterLine;
}
}
if (!Input.eof()) { // Should be at end-of-file.
std::string Temp;
Temp = "Error reading the postfix configuration file " + PostfixMasterCfPath;
Temp += ": ";
Temp += strerror(errno);
throw std::runtime_error(Temp);
}
Input.close();
if (Input.bad()) {
std::string Temp;
Temp = "Error closing the postfix configuration file " + PostfixMasterCfPath;
Temp += " after reading: ";
Temp += strerror(errno);
throw std::runtime_error(Temp);
}
if (Verbose()) {
std::cout << " Add\n\n" << ContentFilterSpec << "\n\n to the end of "
<< PostfixMasterCfPath << "...\n";
}
Content += ContentFilterSpec;
if (!Explain()) {
std::ofstream Output; // Write the updated contents.
Output.open(PostfixMasterCfPath.c_str(), std::ios::trunc);
if (!Output) {
std::string Temp;
Temp = "Error opening the postfix configuration file " + PostfixMasterCfPath;
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 " + PostfixMasterCfPath;
Temp += ": ";
Temp += strerror(errno);
throw std::runtime_error(Temp);
}
Output.close();
if (!Output) {
std::string Temp;
Temp = "Error closing the postfix configuration file " + PostfixMasterCfPath;
Temp += " after writing: ";
Temp += strerror(errno);
throw std::runtime_error(Temp);
}
}
}
OutputVerboseEnd();
if (!ReloadMta()) {
std::cerr << "Unable to reload the postfix configuration. Please run "
<< "'postfix reload' for the integration with SNFServer to take effect.";
}
}
void
PostfixIntegrate::Unintegrate(FileBackup *SaveFile) {
if (!IsIntegrated()) {
return;
}
std::ifstream Input;
if (Verbose()) {
std::cout << "Remove integration in postfix file " << PostfixMasterCfPath << "--\n";
}
if (!Explain()) {
SaveFile->CreateBackupFile(PostfixMasterCfPath); // Save any existing file.
Input.open(PostfixMasterCfPath.c_str()); // Read the contents.
if (!Input) {
std::string Temp;
Temp = "Error opening the postfix configuration file " + PostfixMasterCfPath;
Temp += " for reading: ";
Temp += strerror(errno);
throw std::runtime_error(Temp);
}
std::ostringstream ContentStream;
ContentStream << Input.rdbuf();
Input.close();
if (!Input) {
std::string Temp;
Temp = "Error closing the postfix configuration file " + PostfixMasterCfPath;
Temp += ": ";
Temp += strerror(errno);
throw std::runtime_error(Temp);
}
std::string Content;
Content = ContentStream.str();
if (Verbose()) {
std::cout << " Remove all occurances of\n\n" << ContentFilterLine << "\n\n"
<< " from" << PostfixMasterCfPath << "...\n";
}
std::string::size_type IntegrationBegin = std::string::npos;
while ((IntegrationBegin = Content.find(ContentFilterLine)) != std::string::npos) {
Content.erase(IntegrationBegin, ContentFilterLine.length());
}
if (Verbose()) {
std::cout << " Remove all occurances of\n\n" << ContentFilterSpec << "\n\n"
<< " from" << PostfixMasterCfPath << "...\n";
}
IntegrationBegin = std::string::npos;
while ((IntegrationBegin = Content.find(ContentFilterSpec)) != std::string::npos) {
Content.erase(IntegrationBegin, ContentFilterSpec.length());
}
std::ofstream Output; // Write the updated contents.
Output.open(PostfixMasterCfPath.c_str(), std::ios::trunc);
if (!Output) {
std::string Temp;
Temp = "Error opening the postfix configuration file " + PostfixMasterCfPath;
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 " + PostfixMasterCfPath;
Temp += ": ";
Temp += strerror(errno);
throw std::runtime_error(Temp);
}
Output.close();
if (!Output) {
std::string Temp;
Temp = "Error closing the postfix configuration file " + PostfixMasterCfPath;
Temp += " after writing: ";
Temp += strerror(errno);
throw std::runtime_error(Temp);
}
}
OutputVerboseEnd();
if (!ReloadMta()) {
std::cerr << "Unable to reload the postfix configuration. Please run "
<< "'postfix reload' for the integration with SNFServer to take effect.";
}
}
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 (!MtaIsRunningDetected()) {
return true;
}
if (Verbose()) {
std::cout << "Reloading postfix...\n";
std::cout.flush();
}
bool Succeeded;
if (!Explain()) {
Succeeded = (std::system(ReloadMtaCommand.c_str()) == 0);
if (Verbose()) {
std::cout << (Succeeded ? "succeeded..." : "failed...");
}
}
OutputVerboseEnd();
return Succeeded;
}
bool
PostfixIntegrate::IsIntegrated() {
if (Verbose()) {
std::cout << "Checking for any SNFServer integration in the postfix file " << PostfixMasterCfPath << "...";
}
if (!FileExists(PostfixMasterCfPath)) {
if (Verbose()) {
std::cout << "file doesn't exist; postfix is not integrated...";
}
OutputVerboseEnd();
return false;
}
std::ifstream Input;
Input.open(PostfixMasterCfPath.c_str()); // Read the contents.
if (!Input) {
std::string Temp;
Temp = "Error opening the postfix configuration file " + PostfixMasterCfPath;
Temp += " for reading: ";
Temp += strerror(errno);
throw std::runtime_error(Temp);
}
std::ostringstream ContentStream;
ContentStream << Input.rdbuf();
Input.close();
if (!Input) {
std::string Temp;
Temp = "Error closing the postfix configuration file " + PostfixMasterCfPath;
Temp += ": ";
Temp += strerror(errno);
throw std::runtime_error(Temp);
}
std::string Content;
Content = ContentStream.str();
bool FoundContentFilterLine = (Content.find(ContentFilterLine) != std::string::npos);
bool FoundContentFilterSpec = (Content.find(ContentFilterSpec) != std::string::npos);
bool Integrated = (FoundContentFilterLine || FoundContentFilterSpec);
if (Verbose()) {
if (FoundContentFilterLine) {
std::cout << "found\n\n" << ContentFilterLine << "\n\n";
}
if (FoundContentFilterSpec) {
std::cout << "found\n\n" << ContentFilterSpec << "\n\n";
}
if (!Integrated) {
std::cout << "none found...";
}
}
OutputVerboseEnd();
return Integrated;
}
bool
PostfixIntegrate::DefaultIsChrooted() {
return PostfixDefaultIsChrooted;
}
bool
PostfixIntegrate::MtaConfigurationIsChrooted() {
std::string File;
std::ifstream Input;
File = PostfixMasterCfPath;
Input.open(File.c_str());
if (!Input) {
std::string Temp;
Temp = "Error opening postfix configuration file " + File;
Temp += " for reading: ";
Temp += strerror(errno);
throw std::runtime_error(Temp);
}
std::string Line;
bool ConfigurationIsChrooted = false;
while (getline(Input, Line)) {
if (CheckForString(Line, "smtp")) { // Check for smtp line.
std::istringstream Buffer(Line); // Parse buffer line.
std::string Token[8];
for (unsigned int iToken = 0; iToken < 8; iToken++) {
Buffer >> Token[iToken];
}
if ( ("y" == Token[4]) || ("-" == Token[4]) ) {
ConfigurationIsChrooted = true;
break;
}
}
}
Input.close();
if (Input.bad()) {
std::string Temp;
Temp = "Error closing the postfix configuration file " + File;
Temp += " after reading: ";
Temp += strerror(errno);
throw std::runtime_error(Temp);
}
return ConfigurationIsChrooted;
}

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

@@ -0,0 +1,88 @@
// \file PostfixIntegrate.hpp
//
// Copyright (C) 2012 ARM Research Labs, LLC.
// See www.armresearch.com for the copyright terms.
//
// This file defines the PostfixIntegrate interface.
//
// $Id$
//
///////////////////////////////////////////////////////////////////////////////////////////////////
#ifndef PostfixIntegratehpp_included
#define PostfixIntegratehpp_included
#include "MtaIntegrate.hpp"
/// Class to manage the SNFServer integration with postfix.
//
// This class implements the MtaIntegrate interface for postfix.
//
//////////////////////////////////////////////////////////////////////////////////////////////////////////
class PostfixIntegrate : public MtaIntegrate {
public:
virtual void SetOperatingSystem(std::string OperatingSystemType);
virtual void Integrate(FileBackup *SaveFile);
virtual void Unintegrate(FileBackup *SaveFile);
// Return the default chroot configuration of Postfix.
//
// \returns true if the default configuration is for postfix to
// run chrooted, false otherwise.
//
bool DefaultIsChrooted();
private:
virtual bool MtaIsRunningDetected();
virtual bool ReloadMta();
virtual bool IsIntegrated();
bool MtaConfigurationIsChrooted();
/// Directory containing the snfSniffer script.
std::string SnfSnifferDirName;
/// snfSniffer script file name, including the directory.
std::string SnfSnifferFileName;
/// Sample snfSniffer script file name, including the directory.
std::string SnfSnifferSampleFileName;
/// Content filter line.
//
// To integrate, this line is added to master.cf just after the
// "smtp" line.
//
std::string ContentFilterLine;
/// Content filter specification.
//
// To integrate this is added to the end of the master.cf line.
//
std::string ContentFilterSpec;
/// Postfix main.cf file path.
std::string PostfixMainCfPath;
/// 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;
/// True if postfix runs chrooted by default.
bool PostfixDefaultIsChrooted;
};
#endif

+ 313
- 0
SNFServerConfig/SNFServerConfig.cpp Просмотреть файл

@@ -0,0 +1,313 @@
// /file SNFServerConfig.cpp
//
// Copyright (C) 2011, ARM Research Labs, LLC.
// See www.armresearch.com for the copyright terms.
//
// This file contains the functions for SNFServerConfig.
//
// $Id$
//
///////////////////////////////////////////////////////////////////////////////////////////////////
#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 <exception>
#include <stdexcept>
#include <sstream>
#include <iostream>
#include <fstream>
#include <vector>
#include "SNFServerConfig.hpp"
using namespace std;
//////////////////////////////////////////////////////////////////////////////////////////////////////////
// Configuration. ////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////////////////////
// Initialize default configuration file path.
#ifdef WIN
// Windows OS.
const std::string SNFServerConfig::DefaultConfigFile("C:\\SNF\\SNFServer.xml");
const std::string SNFServerConfig::SampleConfigFile("C:\\SNF\\SNFServer.xml.sample");
const std::string SNFServerConfig::SampleIdentityFile("C:\\SNF\\identity.xml.sample");
const std::string InstallFile("");
#else
#ifdef DEFAULT_CONFIG_DIR
// *nix, DEFAULT_CONFIG_DIR is specified on the compile command line.
const std::string SNFServerConfig::DefaultConfigFile(DEFAULT_CONFIG_DIR "/snf-server/SNFServer.xml");
const std::string SNFServerConfig::SampleConfigFile(DEFAULT_CONFIG_DIR "/snf-server/SNFServer.xml.sample");
const std::string SNFServerConfig::SampleIdentityFile(DEFAULT_CONFIG_DIR "/snf-server/identity.xml.sample");
const std::string InstallFile(DOC_DIR "/INSTALL");
#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 SNFServerConfig::DefaultConfigFile("");
const std::string SNFServerConfig::SampleConfigFile("");
const std::string SNFServerConfig::SampleIdentityFile("");
const std::string InstallFile("INSTALL");
#endif
#endif
const string SNFServerConfig::ApplicationName("SNFServer");
const string IntegrateWithNoneKey("-with=none");
const string IntegrateWithPostfixKey("-with=postfix");
const string IntegrateWithSendmailKey("-with=sendmail");
//////////////////////////////////////////////////////////////////////////////////////////////////////////
// End of configuration. /////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////////////////////
void
SNFServerConfig::DisplayHelp(std::string Version) {
std::string ExclusiveCommands;
std::string ExclusiveCommandsHelp;
ExclusiveCommands = IntegrateWithPostfixKey + " | ";
ExclusiveCommands += IntegrateWithSendmailKey + " | ";
ExclusiveCommands += IntegrateWithNoneKey;
ExclusiveCommandsHelp = " -with=postfix Integrate with postfix and start/reload postfix\n";
ExclusiveCommandsHelp += " -with=sendmail Integrate with sendmail and start/reload sendmail\n";
ExclusiveCommandsHelp += " (Not available on OpenBSD or FreeBSD)\n";
ExclusiveCommandsHelp += " -with=none Remove any integration with all supported MTAs\n";
cout
<< Version << endl
<< "Copyright (C) 2012, ARM Research Labs, LLC (www.armresearch.com)\n\n"
<< "Usage:\n\n"
<< "SNFServerConfig "
<< UtilityConfig::HelpCommandLine(ExclusiveCommands) << "\n\n"
<< "SNFServerConfig "
<< UtilityConfig::HelpDescription(ExclusiveCommandsHelp) << "\n"
<< "The configuration file name is:\n\n"
<< " " << DefaultConfigFile << "\n\n"
<< "If the above file doesn't exist, then it is copied from the following file:\n\n"
<< " " << SampleConfigFile << "\n\n"
<< "If integration with an MTA is specified, the MTA's configuration is reloaded "
<< "if the MTA is running.\n\n";
};
bool
SNFServerConfig::GetCommandLineInput(int argc, char* argv[]) {
int i;
int NumCommandsFound = 0;
string OneInput;
Command = NoCommand; // Default is to do nothing.
for (i = 1; i < argc; i++) { // Check each input.
OneInput = argv[i];
if (OneInput == IntegrateWithPostfixKey) {
Command = IntegrateWithPostfixCommand;
NumCommandsFound++;
} else if (0 == OneInput.find(IntegrateWithSendmailKey)) {
std::string OsType;
OsType = GetOperatingSystemType(); // Check whether the platform is supported.
if ( ("OpenBSD" == OsType) || ("FreeBSD" == OsType) ) {
std::string Temp;
Temp = "Integration with sendmail is not supported on " + OsType;
Temp += ".\n";
Temp += "Please see " + InstallFile;
Temp += " for information on integration with sendmail.\n";
throw std::runtime_error(Temp);
}
Command = IntegrateWithSendmailCommand;
NumCommandsFound++;
} else if (OneInput == IntegrateWithNoneKey) {
Command = IntegrateWithNoneCommand;
NumCommandsFound++;
} else {
// Process command-line input by the base class.
if (!ProcessCommandLineItem(OneInput)) {
Command = UnknownCommand;
return false; // Illegal input.
}
}
}
if (UpdateCredentialsSpecified()) {
Command = UpdateCredentialsCommand;
NumCommandsFound++;
}
if (SetupRepairSpecified()) {
Command = SetupRepairCommand;
NumCommandsFound++;
}
if (StartSnifferSpecified()) {
Command = StartSnifferCommand;
NumCommandsFound++;
}
if (StopSnifferSpecified()) {
Command = StopSnifferCommand;
NumCommandsFound++;
}
return ( (NumCommandsFound == 1) && CommandLineIsOkay() );
}
void
SNFServerConfig::ExecuteCommand() {
Postfix.SetOperatingSystem(GetOperatingSystemType());
Postfix.SetVerbose(Verbose());
Postfix.SetExplain(Explain());
Sendmail.SetOperatingSystem(GetOperatingSystemType());
Sendmail.SetVerbose(Verbose());
Sendmail.SetExplain(Explain());
SetConfigFileName(DefaultConfigFile);
if (SetupRepairCommand == Command) {
CreateDefaultConfigFile(SampleConfigFile); // Create the file if it doesn't exist,
// Set owner and mode in any case.
}
LoadConfig();
LoadInfo(); // Load the file paths.
switch (Command) {
case SetupRepairCommand:
SetupRepair(SampleIdentityFile);
break;
case UpdateCredentialsCommand:
UpdateRulebaseScriptCredentials();
DownloadRulebase();
UpdateIdentityFile();
break;
case IntegrateWithPostfixCommand:
Postfix.Integrate(&SaveFile);
UnintegrateWithAllExcept("postfix");
break;
case IntegrateWithSendmailCommand:
Sendmail.Integrate(&SaveFile);
UnintegrateWithAllExcept("sendmail");
break;
case IntegrateWithNoneCommand:
UnintegrateWithAllExcept();
break;
case StartSnifferCommand:
LoadCredentials();
StartSniffer("snf-server start", ApplicationName);
break;
case StopSnifferCommand:
LoadCredentials();
StopSniffer("snf-server stop", ApplicationName);
break;
default:
break;
}
}
void
SNFServerConfig::SaveFileState() {
if (!Explain()) {
SaveFile.CreateBackupFile(GetRulebaseScriptName());
if (UpdateCredentialsSpecified()) {
SaveFile.CreateBackupFile(GetRulebaseFileName());
}
SaveFile.CreateBackupFile(GetIdentityFileName());
SaveFile.CreateBackupFile(GetIgnoreListFileName());
}
}
void
SNFServerConfig::UnintegrateWithAllExcept(std::string Except) {
if (Except != "postfix") {
Postfix.Unintegrate(&SaveFile);
}
if (Except != "sendmail") {
Sendmail.Unintegrate(&SaveFile);
}
}

+ 107
- 0
SNFServerConfig/SNFServerConfig.hpp Просмотреть файл

@@ -0,0 +1,107 @@
// \file SNFServerConfig.hpp
//
// Copyright (C) 2012 ARM Research Labs, LLC.
// See www.armresearch.com for the copyright terms.
//
// This file defines the SNFServerConfig interface.
//
// $Id$
//
///////////////////////////////////////////////////////////////////////////////////////////////////
#ifndef SNFServerConfighpp_included
#define SNFServerConfighpp_included
#include <string>
#include "UtilityConfig.hpp"
#include "PostfixIntegrate.hpp"
#include "SendmailIntegrate.hpp"
/// Class to manage the SNFServer configuration.
//
// This class creates/maintains the sniffer configuration file, and
// integrates/unintegrates with MTAs.
//
//////////////////////////////////////////////////////////////////////////////////////////////////////////
class SNFServerConfig : public UtilityConfig {
public:
/// Command specified.
enum CommandEnum {
SetupRepairCommand, ///< Setup or repair the configuration.
UpdateCredentialsCommand, ///< Update the credentials.
IntegrateWithPostfixCommand, ///< Integrate with postfix.
IntegrateWithSendmailCommand, ///< Integrate with sendmail.
IntegrateWithNoneCommand, ///< Unintegrate with all supported MTAs.
StartSnifferCommand, ///< Start the Sniffer.
StopSnifferCommand, ///< Stop the Sniffer.
NoCommand, ///< No command specified.
UnknownCommand ///< Unknown.
};
/// Display usage.
//
// \param[in] Version is the SNFServer version.
//
void DisplayHelp(std::string Version);
/// Get the command-line input parameters for SNFServer.
//
// \param[in] argc is the number of parameters.
//
// \param[in] argv is the parameters.
//
// \returns true if all the required command line parameters are
// present and there are no unknown command-line parameters, false
// otherwise.
//
bool GetCommandLineInput(int argc, char* argv[]);
/// Execute the command specified by the command-line parameters.
//
void ExecuteCommand(void);
/// Save the state of all files that might be changed, except the
/// config file.
//
void SaveFileState(void); // OBSOLETE.
private:
PostfixIntegrate Postfix; ///< Postfix integration object.
SendmailIntegrate Sendmail; ///< Sendmail integration object.
/// Unintegrate with MTAs.
//
// Unintegrate with all MTAs except the specified MTA.
//
// \param[in] Except is the MTA to not integrate with. The
// acceptable values are:
//
// <ol>
// <li> "postfix" </li>
// <li> "sendmail" </li>
// <li> "" </li>
// </ol>
//
// The default value is "", which specifies unintegration with all
// MTAs.
//
void UnintegrateWithAllExcept(std::string Except = "");
CommandEnum Command; ///< Specified command.
static const std::string DefaultConfigFile; ///< Default config file.
static const std::string SampleConfigFile; ///< Sample config file.
static const std::string SampleIdentityFile; ///< Sample identity file.
static const std::string ApplicationName; ///< Application name.
};
#endif

+ 631
- 0
SNFServerConfig/SendmailIntegrate.cpp Просмотреть файл

@@ -0,0 +1,631 @@
// /file SendmailIntegrate.cpp
//
// Copyright (C) 2013, ARM Research Labs, LLC.
// See www.armresearch.com for the copyright terms.
//
// This file contains the functions for SendmailIntegrate.
//
// $Id$
//
///////////////////////////////////////////////////////////////////////////////////////////////////
#include <cstdlib>
#include <cerrno>
#include <cstring>
#include <iostream>
#include <exception>
#include <stdexcept>
#include <sstream>
#include <fstream>
#include "SendmailIntegrate.hpp"
//////////////////////////////////////////////////////////////////////////////////////////////////////////
// Configuration. ////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////////////////////
const std::string SendmailLdaKey("FEATURE(`local_procmail'"); ///< Line in sendmail.cf that specifies the LDA.
const std::string MtaIsRunningCommand("ps axl | grep -v grep | grep -q ' sendmail: '");
//////////////////////////////////////////////////////////////////////////////////////////////////////////
// End of configuration. /////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////////////////////
void
SendmailIntegrate::SetOperatingSystem(std::string OperatingSystemType) {
ProcmailRcFileName = "/etc/procmailrc";
if ("OpenBSD" == OperatingSystemType) {
IntegrationIsSupported = false;
} else if ("FreeBSD" == OperatingSystemType) {
IntegrationIsSupported = false;
} else if ("Ubuntu" == OperatingSystemType) {
IntegrationIsSupported = true;
SendmailSendmailMcPath = "/etc/mail/sendmail.mc";
SendmailSendmailCfPath = "/etc/mail/sendmail.cf";
SnfSnifferDirName = "/var/spool/postfix/snf-server";
SnfSnifferFileName = SnfSnifferDirName + "/snfSnifferFilter";
SnfSnifferSampleFileName = "/usr/sbin/snfSnifferFilter.sample";
BuildInstallSendmailCfFile = "(cd /etc/mail && make)";
ReloadMtaCommand = "/etc/init.d/sendmail reload";
FileToBackup.push_back(SendmailSendmailMcPath);
FileToBackup.push_back(SendmailSendmailCfPath);
} else if ("RedHat" == OperatingSystemType) {
IntegrationIsSupported = true;
SendmailSendmailMcPath = "/etc/mail/sendmail.mc";
SendmailSendmailCfPath = "/etc/mail/sendmail.cf";
SnfSnifferDirName = "/usr/sbin";
SnfSnifferFileName = SnfSnifferDirName + "/snfSnifferFilter";
SnfSnifferSampleFileName = SnfSnifferDirName + "/snfSnifferFilter.sample";
BuildInstallSendmailCfFile = "(cd /etc/mail && make)";
ReloadMtaCommand = "/etc/init.d/sendmail reload";
FileToBackup.push_back(SendmailSendmailMcPath);
FileToBackup.push_back(SendmailSendmailCfPath);
} else if ("Suse" == OperatingSystemType) {
IntegrationIsSupported = true;
SendmailSendmailMcPath = "/etc/mail/linux.mc";
SendmailSendmailCfPath = "/etc/mail/sendmail.cf";
SnfSnifferDirName = "/usr/sbin";
SnfSnifferFileName = SnfSnifferDirName + "/snfSnifferFilter";
SnfSnifferSampleFileName = SnfSnifferDirName + "/snfSnifferFilter.sample";
BuildInstallSendmailCfFile = "(cd /etc/mail && rm -f sendmail.cf && m4 /etc/mail/linux.mc > sendmail.cf)";
ReloadMtaCommand = "/etc/init.d/sendmail reload";
FileToBackup.push_back(SendmailSendmailMcPath);
FileToBackup.push_back(SendmailSendmailCfPath);
} else {
std::ostringstream Temp;
Temp << "***Error from SendmailIntegrate::SetOperatingSystem: Invalid value of OperatingSystemType: "
<< OperatingSystemType;
throw std::runtime_error(Temp.str());
}
ProcmailRcSnifferIntegration = ":0 fw\n| " + SnfSnifferFileName;
ProcmailRcSnifferIntegration += "\n";
}
void
SendmailIntegrate::Integrate(FileBackup *SaveFile) {
if (!IntegrationIsSupported) {
std::ostringstream Temp;
Temp << "Integration with sendmail is not supported on this platform. "
<< "Please see " << DOC_DIR << "/INSTALL for instructions for manual "
<< "integration with sendmail.";
throw std::runtime_error(Temp.str());
}
if (IsIntegrated()) {
return;
}
// Check whether the configuration has procmail as the LDA.
if (!MtaConfigurationHasProcmailForLda()) {
std::string Temp;
Temp = "Error--sendmail must be configured to use procmail as the LDA.";
throw std::runtime_error(Temp);
}
if (Verbose()) {
std::cout << "Create " << SnfSnifferFileName << " if it doesn't exist...";
}
if (!Explain()) {
if (!FileExists(SnfSnifferFileName)) { // Create SnfSnifferFilter script
// if it doesn't exist.
SaveFile->CreateBackupFile(SnfSnifferFileName);
if (!FileExists(SnfSnifferDirName)) {
MkDir(SnfSnifferDirName);
}
SetMode(SnfSnifferDirName, S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH);
SetOwnerGroup(SnfSnifferDirName);
Copy(SnfSnifferSampleFileName, SnfSnifferFileName);
SetMode(SnfSnifferFileName, S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH);
SetOwnerGroup(SnfSnifferFileName);
}
}
OutputVerboseEnd();
if (Verbose()) {
std::cout << "Add\n\n" << ProcmailRcSnifferIntegration << "\n\nto " << ProcmailRcFileName << "...";
}
std::string ProcmailRcFileContent;
if (!Explain()) {
if (FileExists(ProcmailRcFileName)) { // Read any existing procmail configuration.
std::ifstream Input;
Input.open(ProcmailRcFileName.c_str());
if (!Input) {
std::string Temp;
Temp = "Error opening the procmail configuration file " + ProcmailRcFileName;
Temp += " for reading: ";
Temp += strerror(errno);
throw std::runtime_error(Temp);
}
if (!Input.eof()) {
std::ostringstream Buffer;
Buffer << Input.rdbuf();
ProcmailRcFileContent = Buffer.str();
}
Input.close();
if (!Input) {
std::string Temp;
Temp = "Error closing the procmail configuration file " + ProcmailRcFileName;
Temp += " after reading: ";
Temp += strerror(errno);
throw std::runtime_error(Temp);
}
}
ProcmailRcFileContent = ProcmailRcSnifferIntegration + ProcmailRcFileContent;
SaveFile->CreateBackupFile(ProcmailRcFileName);
std::ofstream Output; // Write the updated contents.
Output.open(ProcmailRcFileName.c_str(), std::ios::trunc);
if (!Output) {
std::string Temp;
Temp = "Error opening the procmail configuration file " + ProcmailRcFileName;
Temp += " for writing: ";
Temp += strerror(errno);
throw std::runtime_error(Temp);
}
Output << ProcmailRcFileContent;
if (!Output) {
std::string Temp;
Temp = "Error writing the procmail configuration file " + ProcmailRcFileName;
Temp += ": ";
Temp += strerror(errno);
throw std::runtime_error(Temp);
}
Output.close();
if (!Output) {
std::string Temp;
Temp = "Error closing the procmail configuration file " + ProcmailRcFileName;
Temp += " after writing: ";
Temp += strerror(errno);
throw std::runtime_error(Temp);
}
}
OutputVerboseEnd();
if (!ReloadMta()) {
std::cerr << "Unable to reload the sendmail configuration. Please reload "
<< " the sendmail configuration for the integration with SNFServer to take effect.";
}
}
void
SendmailIntegrate::Unintegrate(FileBackup *SaveFile) {
if (!IntegrationIsSupported) {
return;
}
if (!IsIntegrated()) {
return;
}
std::ifstream Input;
if (Verbose()) {
std::cout << "Remove integration in procmail file " << ProcmailRcFileName << "--\n";
}
if (!Explain()) {
Input.open(ProcmailRcFileName.c_str());
if (!Input) {
std::string Temp;
Temp = "Error opening the procmail configuration file " + ProcmailRcFileName;
Temp += " for reading: ";
Temp += strerror(errno);
throw std::runtime_error(Temp);
}
std::ostringstream ContentStream;
ContentStream << Input.rdbuf();
Input.close();
if (!Input) {
std::string Temp;
Temp = "Error closing the procmail configuration file " + ProcmailRcFileName;
Temp += ": ";
Temp += strerror(errno);
throw std::runtime_error(Temp);
}
std::string Content;
Content = ContentStream.str();
if (Verbose()) {
std::cout << " Remove all occurances of\n\n" << ProcmailRcSnifferIntegration << "\n\n"
<< " from" << ProcmailRcFileName << "...\n";
}
std::string::size_type IntegrationBegin = std::string::npos;
while ((IntegrationBegin = Content.find(ProcmailRcSnifferIntegration)) != std::string::npos) {
Content.erase(IntegrationBegin, ProcmailRcSnifferIntegration.length());
}
SaveFile->CreateBackupFile(ProcmailRcFileName);
std::ofstream Output; // Write the updated contents.
Output.open(ProcmailRcFileName.c_str(), std::ios::trunc);
if (!Output) {
std::string Temp;
Temp = "Error opening the procmail configuration file " + ProcmailRcFileName;
Temp += " for writing: ";
Temp += strerror(errno);
throw std::runtime_error(Temp);
}
Output << Content;
if (!Output) {
std::string Temp;
Temp = "Error writing the procmail configuration file " + ProcmailRcFileName;
Temp += ": ";
Temp += strerror(errno);
throw std::runtime_error(Temp);
}
Output.close();
if (!Output) {
std::string Temp;
Temp = "Error closing the procmail configuration file " + ProcmailRcFileName;
Temp += " after writing: ";
Temp += strerror(errno);
throw std::runtime_error(Temp);
}
}
OutputVerboseEnd();
if (!ReloadMta()) {
std::cerr << "Unable to reload the sendmail configuration. Please run "
<< "'sendmail reload' for the integration with SNFServer to take effect.";
}
}
bool
SendmailIntegrate::MtaIsRunningDetected() {
if (Verbose()) {
std::cout << "Checking whether sendmail 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
SendmailIntegrate::ReloadMta() {
if (!MtaIsRunningDetected()) {
return true;
}
if (Verbose()) {
std::cout << "Reloading sendmail with the command '"
<< ReloadMtaCommand << "'...\n";
std::cout.flush();
}
bool Succeeded;
if (!Explain()) {
Succeeded = (std::system(ReloadMtaCommand.c_str()) == 0);
if (Verbose()) {
std::cout << (Succeeded ? "succeeded..." : "failed...");
}
}
OutputVerboseEnd();
return Succeeded;
}
bool
SendmailIntegrate::IsIntegrated() {
if (Verbose()) {
std::cout << "Checking for any SNFServer integration in the procmail file " << ProcmailRcFileName << "...";
}
if (!FileExists(ProcmailRcFileName)) {
if (Verbose()) {
std::cout << "file doesn't exist; sendmail is not integrated...";
}
OutputVerboseEnd();
return false;
}
bool Integrated = false;
std::ifstream Input;
Input.open(ProcmailRcFileName.c_str()); // Read the contents.
if (!Input) {
std::string Temp;
Temp = "Error opening the procmail configuration file " + ProcmailRcFileName;
Temp += " for reading: ";
Temp += strerror(errno);
throw std::runtime_error(Temp);
}
std::string ProcmailRcFileContent;
if (!Input.eof()) {
std::ostringstream Buffer;
Buffer << Input.rdbuf();
ProcmailRcFileContent = Buffer.str();
}
Input.close();
if (!Input) {
std::string Temp;
Temp = "Error closing the procmail configuration file " + ProcmailRcFileName;
Temp += " after reading: ";
Temp += strerror(errno);
throw std::runtime_error(Temp);
}
Integrated = (ProcmailRcFileContent.find(ProcmailRcSnifferIntegration) != std::string::npos);
if (Verbose()) {
if (Integrated) {
std::cout << "found\n\n" << ProcmailRcSnifferIntegration << "\n\n...";
} else {
std::cout << "none found...";
}
}
OutputVerboseEnd();
return Integrated;
}
bool
SendmailIntegrate::MtaConfigurationHasProcmailForLda() {
std::string File;
std::ifstream Input;
File = SendmailSendmailMcPath;
if (Verbose()) {
std::cout << "Checking sendmail configuraton file " + File
<< " to verify that procmail is the Local Delivery Agent.\n";
}
Input.open(File.c_str());
if (!Input) {
std::string Temp;
Temp = "Error opening sendmail configuration file " + File;
Temp += " for reading: ";
Temp += strerror(errno);
throw std::runtime_error(Temp);
}
std::string Line;
bool LdaIsProcmail = true;
bool FoundLdaLine = false;
while (getline(Input, Line)) {
if (Line.substr(0, SendmailLdaKey.length()) == SendmailLdaKey) { // Check for LDA line.
FoundLdaLine = true;
if (Line.find(",", SendmailLdaKey.length()) != std::string::npos) { // Additional arguments?
if (Line.find("procmail", SendmailLdaKey.length()) == std::string::npos) { // Yes.
LdaIsProcmail = false; // procmail not specified in the config line.
if (Verbose()) {
std::cout << "The following line indicates that the sendmail LDA is not procmail:\n\n"
<< Line << "\n";
}
break;
} else { // procmail is specified in the config line.
if (Verbose()) {
std::cout << "The following line indicates that the sendmail LDA is procmail, "
<< "as required to integrate with SNFServer:\n\n"
<< Line << "\n\n";
}
break;
}
} else { // LDA line uses default, which is procmail.
if (Verbose()) {
std::cout << "The following line indicates that the sendmail LDA is procmail, "
<< "as required to integrate with SNFServer:\n\n"
<< Line << "\n\n";
}
break;
}
}
}
Input.close();
if (Input.bad()) {
std::string Temp;
Temp = "Error closing the sendmail configuration file " + File;
Temp += " after reading: ";
Temp += strerror(errno);
throw std::runtime_error(Temp);
}
if (Verbose() && !FoundLdaLine) {
std::cout << "The absence of \"" << SendmailLdaKey << "\" indicates that the LDA is procmail, "
<< "as required to integrate with SNFServer.\n";
}
return LdaIsProcmail;
}

+ 82
- 0
SNFServerConfig/SendmailIntegrate.hpp Просмотреть файл

@@ -0,0 +1,82 @@
// \file SendmailIntegrate.hpp
//
// Copyright (C) 2012 ARM Research Labs, LLC.
// See www.armresearch.com for the copyright terms.
//
// This file defines the SendmailIntegrate interface.
//
// $Id$
//
///////////////////////////////////////////////////////////////////////////////////////////////////
#ifndef SendmailIntegratehpp_included
#define SendmailIntegratehpp_included
#include <vector>
#include "MtaIntegrate.hpp"
/// Class to manage the SNFServer integration with sendmail.
//
// This class implements the MtaIntegrate interface for sendmail.
//
//////////////////////////////////////////////////////////////////////////////////////////////////////////
class SendmailIntegrate : public MtaIntegrate {
public:
virtual void SetOperatingSystem(std::string OperatingSystemType);
virtual void Integrate(FileBackup *SaveFile);
virtual void Unintegrate(FileBackup *SaveFile);
private:
virtual bool MtaIsRunningDetected();
virtual bool ReloadMta();
virtual bool IsIntegrated();
bool MtaConfigurationHasProcmailForLda();
/// Directory containing the snfSniffer script.
std::string SnfSnifferDirName;
/// snfSniffer script file name, including the directory.
std::string SnfSnifferFileName;
/// Sample snfSniffer script file name, including the directory.
std::string SnfSnifferSampleFileName;
/// procmail system configuration file name.
std::string ProcmailRcFileName;
/// Integration lines for procmail configuration file.
std::string ProcmailRcSnifferIntegration;
/// Sendmail sendmail.mc file path.
std::string SendmailSendmailMcPath;
/// Sendmail sendmail.cf file path.
std::string SendmailSendmailCfPath;
/// Command to build and install the sendmail.cf file.
std::string BuildInstallSendmailCfFile;
/// Command to reload the MTA.
std::string ReloadMtaCommand;
/// True if integration is supported on this platform.
bool IntegrationIsSupported;
/// typedef for container of filenames to backup up before integrating or unintegrating.
typedef std::vector<std::string> FileToBackupType;
/// Files to back up before integrating or unintegrating.
FileToBackupType FileToBackup;
};
#endif

+ 115
- 0
SNFServerConfig/main.cpp Просмотреть файл

@@ -0,0 +1,115 @@
// main.cpp
//
// Copyright (C) 2012, ARM Research Labs, LLC.
// See www.armresearch.com for the copyright terms.
//
// Create and maintain the sniffer configuration file for SNFServer.
//
// The configuration file and instructions are specified on the
// command line, and are used to create/modify the configuration file,
// and integrate or unintegrate with the specified MTA.
//
//
// $Id$
//
///////////////////////////////////////////////////////////////////////////////////////////////////
#include <errno.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <pwd.h>
#include <sys/stat.h>
#include <exception>
#include <iostream>
#include <fstream>
#include "SNFMulti.hpp"
#include "SNFServerConfig.hpp"
using namespace std;
//////////////////////////////////////////////////////////////////////////////////////////////////////////
// Configuration. ////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////////////////////
/// Version string.
const char* SNF_SERVERCONFIG_VERSION = "SNFServerConfig 0.0.1 Build: " __DATE__ " " __TIME__;
//////////////////////////////////////////////////////////////////////////////////////////////////////////
// End of configuration. /////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////////////////////
void RestoreFiles(SNFServerConfig *Config) {
try {
cerr << "Restoring all configuration files...";
Config->SaveFile.RestoreAllFilesFromBackup();
Config->SetOwnerPermissionsOfConfigFiles();
cerr << "done.\n\n"
<< "Configuration files that resulted in this error are saved with a suffix \""
<< Config->SaveFile.GetFailedFileName("") << "\".\n";
}
catch(exception& e) {
cerr << "SNFServerConfig::SaveFile Exception: " << e.what() << endl;
}
}
int main(int argc, char* argv[]) {
SNFServerConfig SnfServerConfig;
try { // Catch anything that breaks loose.
if (!SnfServerConfig.GetCommandLineInput(argc, argv) || // If our command line arguments
SnfServerConfig.Help()) { // don't look right, or if help is
// requested then display our help
SnfServerConfig.DisplayHelp(SNF_SERVERCONFIG_VERSION); // screen.
return 0;
}
bool DebugMode = false; // This will be our debug mode.
string argv0(argv[0]); // Capture how we were called.
if(
string::npos != argv0.find("Debug") || // If we find "Debug" or
string::npos != argv0.find("debug") // "debug" in our command path
) { // then we are in DebugMode.
DebugMode = true; // Set the flag and tell the
cout << SNF_SERVERCONFIG_VERSION << endl; // watchers.
cout << "Debug Mode" << endl;
SnfServerConfig.SetDebug(true);
}
SnfServerConfig.ExecuteCommand();
} // That's all folks.
catch(exception& e) { // Report any normal exceptions.
cerr << "\n\nSNFServerConfig Exception: " << e.what() << endl << endl;
RestoreFiles(&SnfServerConfig);
return(-1);
}
catch (snfCFGmgr::LoadFailure) { // Error loading configuration file.
cerr << "\n\nsnfCFGmgr Exception: Unable to load the configuration file "
<< SnfServerConfig.GetConfigFileName() << endl << endl;
RestoreFiles(&SnfServerConfig);
return(-1);
}
catch(...) { // Report any unexpected exceptions.
cerr << "\n\nSNFServerConfig Panic! Unknown Exception!" << endl << endl;
RestoreFiles(&SnfServerConfig);
return(-1);
}
return 0; // Normally we return zero.
}

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