git-svn-id: https://svn.microneil.com/svn/PKG-SNF-CS-NIX/trunk@69 233e721a-07f6-49eb-a7da-05e0e16828fcmaster
## See www.armresearch.com for the copyright terms. | ## See www.armresearch.com for the copyright terms. | ||||
## | ## | ||||
SUBDIRS = \ | |||||
CodeDweller \ | |||||
SNFMulti \ | |||||
SNFServer \ | |||||
SNFClient \ | |||||
SNF2Check \ | |||||
SUBDIRS = \ | |||||
CodeDweller \ | |||||
SNFMulti \ | |||||
SNFServer \ | |||||
SNFClient \ | |||||
SNF2Check \ | |||||
SNFUtility/Common \ | SNFUtility/Common \ | ||||
SNFUtility/CommonTests \ | SNFUtility/CommonTests \ | ||||
SNFUtility/SNFMilterConfig \ | |||||
SNFUtility/SNFMilterConfigTests \ | |||||
Scripts \ | |||||
config_files \ | |||||
SNFUtility/SNFServerConfig \ | |||||
Scripts \ | |||||
config_files \ | |||||
Docs | Docs | ||||
doc_DATA = \ | |||||
BUGS \ | |||||
ChangeLog \ | |||||
README \ | |||||
TODO \ | |||||
INSTALL \ | |||||
doc_DATA = \ | |||||
BUGS \ | |||||
ChangeLog \ | |||||
README \ | |||||
TODO \ | |||||
INSTALL \ | |||||
COPYING | COPYING | ||||
EXTRA_DIST = \ | |||||
$(doc_DATA) \ | |||||
Makefile.am \ | |||||
configure.ac \ | |||||
configure.ac.in \ | |||||
SNF4SA/INSTALL \ | |||||
SNF4SA/README \ | |||||
SNF4SA/snf4sa.cf \ | |||||
EXTRA_DIST = \ | |||||
$(doc_DATA) \ | |||||
Makefile.am \ | |||||
configure.ac \ | |||||
configure.ac.in \ | |||||
SNF4SA/INSTALL \ | |||||
SNF4SA/README \ | |||||
SNF4SA/snf4sa.cf \ | |||||
SNF4SA/snf4sa.pm | SNF4SA/snf4sa.pm | ||||
DISTCHECK_CONFIGURE_FLAGS=--enable-os-type=OpenBSD | DISTCHECK_CONFIGURE_FLAGS=--enable-os-type=OpenBSD |
## Process this file with automake to produce Makefile.in | |||||
## | |||||
## $Id$ | |||||
## | |||||
## automake input for the MicroNeil SNFServerConfig application. | |||||
## | |||||
## Author: Alban Deniz | |||||
## | |||||
## Copyright (C) 2012 ARM Research Labs, LLC. | |||||
## See www.armresearch.com for the copyright terms. | |||||
## | |||||
## | |||||
LIBS = @SNF_LIBS@ -L../../SNFMulti -L../../CodeDweller -L../Common -lUtilityCommon \ | |||||
-lSNFMulti -lCodeDweller @LIBS@ | |||||
CXXFLAGS = $(SNF_CXXFLAGS) -I@top_srcdir@/SNFMulti -I@top_srcdir@/CodeDweller \ | |||||
-I@top_srcdir@/SNFUtility/Common -DDEFAULT_CONFIG_DIR=\"@sysconfdir@\" \ | |||||
-DDOC_DIR=\"@docdir@\" | |||||
sbin_PROGRAMS = \ | |||||
SNFServerConfig | |||||
SNFServerConfig_SOURCES = \ | |||||
@top_srcdir@/SNFUtility/SNFServerConfig/main.cpp \ | |||||
@top_srcdir@/SNFUtility/SNFServerConfig/SNFServerConfig.cpp \ | |||||
@top_srcdir@/SNFUtility/SNFServerConfig/PostfixIntegrate.cpp \ | |||||
@top_srcdir@/SNFUtility/SNFServerConfig/SendmailIntegrate.cpp | |||||
noinst_HEADERS = \ | |||||
@top_srcdir@/SNFUtility/SNFServerConfig/SNFServerConfig.hpp \ | |||||
@top_srcdir@/SNFUtility/SNFServerConfig/PostfixIntegrate.hpp \ | |||||
@top_srcdir@/SNFUtility/SNFServerConfig/SendmailIntegrate.hpp | |||||
EXTRA_DIST = \ | |||||
Makefile.am \ | |||||
ChangeLog | |||||
install-exec-hook: | |||||
ln -f $(DESTDIR)$(sbindir)/SNFServerConfig$(EXEEXT) $(DESTDIR)$(sbindir)/SNFDebugServerConfig$(EXEEXT) | |||||
uninstall-hook: | |||||
rm -f $(DESTDIR)$(sbindir)/SNFDebugServerConfig$(EXEEXT) | |||||
clean-local: | |||||
rm -f *.gcno *.gcov *.gcda *~ $(CONFDATA) |
// /file PostfixIntegrate.cpp | |||||
// | |||||
// Copyright (C) 2012, 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 = "/var/spool/postfix/snf-server"; | |||||
SnfSnifferFileName = SnfSnifferDirName + "/snfSniffer"; | |||||
SnfSnifferSampleFileName = "/usr/local/sbin/snfSniffer.sample"; | |||||
ContentFilterSpec += " flags=Rq user=snfuser argv=/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/sbin/snfSniffer\n"; | |||||
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; | |||||
SnfSnifferDirName = "/var/spool/postfix"; | |||||
SnfSnifferFileName = SnfSnifferDirName + "/snfSniffer"; | |||||
SnfSnifferSampleFileName = "/usr/local/sbin/snfSniffer.sample"; | |||||
ContentFilterSpec += " flags=Rq user=snfuser argv=/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 { | |||||
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."; | |||||
Temp += strerror(errno); | |||||
throw std::runtime_error(Temp); | |||||
} | |||||
std::ifstream Input; | |||||
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); | |||||
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); | |||||
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) { | |||||
if (Verbose()) { | |||||
std::cout << " Add\n\n " << ContentFilterLine << "\n\n after 'smtp' line in " | |||||
<< PostfixMasterCfPath << "...\n"; | |||||
} | |||||
Content += ContentFilterLine + "\n"; | |||||
} | |||||
} | |||||
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()); | |||||
} | |||||
} | |||||
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) { | |||||
} else { | |||||
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]) ) { | |||||
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 true; | |||||
} | |||||
} | |||||
} | |||||
Input.close(); | |||||
if (Input.bad()) { | |||||
std::string Temp; | |||||
Temp = "Error closing the rulebase download script file " + File; | |||||
Temp += " after reading: "; | |||||
Temp += strerror(errno); | |||||
throw std::runtime_error(Temp); | |||||
} | |||||
return false; | |||||
} |
// \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 |
// /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); | |||||
} | |||||
} |
// \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 |
// /file SendmailIntegrate.cpp | |||||
// | |||||
// Copyright (C) 2011, 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 SnfMilterSendmailMcSearchString("Added by SNFMilterConfig"); | |||||
const std::string SnfMilterSendmailMcIntegrationString("INPUT_MAIL_FILTER(`SNFMilter', `S=unix:/var/snf-milter/socket')dnl # Added by SNFMilterConfig"); | |||||
const std::string MtaIsRunningCommand("ps axl | grep -v grep | grep -q ' sendmail: '"); | |||||
////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||||
// End of configuration. ///////////////////////////////////////////////////////////////////////////////// | |||||
////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||||
void | |||||
SendmailIntegrate::SetOperatingSystem(std::string OperatingSystemType) { | |||||
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"; | |||||
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"; | |||||
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"; | |||||
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()); | |||||
} | |||||
} | |||||
void | |||||
SendmailIntegrate::Integrate(FileBackup *SaveFile) { | |||||
if (!IntegrationIsSupported) { | |||||
return; | |||||
} | |||||
if (IsIntegrated()) { | |||||
return; | |||||
} | |||||
if (Verbose()) { | |||||
std::cout << "Add to sendmail file " << SendmailSendmailMcPath << ": '" | |||||
<< SnfMilterSendmailMcIntegrationString << "' and generate new " | |||||
<< SendmailSendmailCfPath << " file with the command '" | |||||
<< BuildInstallSendmailCfFile << "'..."; | |||||
} | |||||
if (!Explain()) { | |||||
for (FileToBackupType::iterator iFile = FileToBackup.begin(); iFile != FileToBackup.end(); iFile++) { | |||||
SaveFile->CreateBackupFile(*iFile); // Save any existing file. | |||||
} | |||||
std::ofstream Output; // Append the configuration. | |||||
Output.open(SendmailSendmailMcPath.c_str(), std::ios::app); | |||||
if (!Output) { | |||||
std::string Temp; | |||||
Temp = "Error opening the sendmail configuration file " + SendmailSendmailMcPath; | |||||
Temp += " for writing: "; | |||||
Temp += strerror(errno); | |||||
throw std::runtime_error(Temp); | |||||
} | |||||
Output << SnfMilterSendmailMcIntegrationString << "\n"; | |||||
if (!Output) { | |||||
std::string Temp; | |||||
Temp = "Error appending to the sendmail configuration file " + SendmailSendmailMcPath; | |||||
Temp += ": "; | |||||
Temp += strerror(errno); | |||||
throw std::runtime_error(Temp); | |||||
} | |||||
Output.close(); | |||||
if (!Output) { | |||||
std::string Temp; | |||||
Temp = "Error closing the sendmail configuration file " + SendmailSendmailMcPath; | |||||
Temp += " after appending: "; | |||||
Temp += strerror(errno); | |||||
throw std::runtime_error(Temp); | |||||
} | |||||
if (std::system(BuildInstallSendmailCfFile.c_str()) != 0) { | |||||
std::string Temp; | |||||
Temp = "Error generating sendmail configuration file " + SendmailSendmailCfPath; | |||||
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 SNFMilter to take effect."; | |||||
} | |||||
} | |||||
void | |||||
SendmailIntegrate::Unintegrate(FileBackup *SaveFile) { | |||||
if (!IntegrationIsSupported) { | |||||
return; | |||||
} | |||||
if (!IsIntegrated()) { | |||||
return; | |||||
} | |||||
std::ifstream Input; | |||||
if (Verbose()) { | |||||
std::cout << "Remove integration in sendmail file " << SendmailSendmailMcPath | |||||
<< " and generate new " << SendmailSendmailCfPath << " file with the command '" | |||||
<< BuildInstallSendmailCfFile << "'--\n"; | |||||
} | |||||
if (!Explain()) { | |||||
for (FileToBackupType::iterator iFile = FileToBackup.begin(); iFile != FileToBackup.end(); iFile++) { | |||||
SaveFile->CreateBackupFile(*iFile); // Save any existing file. | |||||
} | |||||
Input.open(SendmailSendmailMcPath.c_str()); // Read the contents. | |||||
if (!Input) { | |||||
std::string Temp; | |||||
Temp = "Error opening the sendmail configuration file " + SendmailSendmailMcPath; | |||||
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(SnfMilterSendmailMcSearchString)) { // Check for integration line. | |||||
if (Verbose()) { | |||||
std::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. | |||||
std::string Temp; | |||||
Temp = "Error reading the sendmail configuration file " + SendmailSendmailMcPath; | |||||
Temp += ": "; | |||||
Temp += strerror(errno); | |||||
throw std::runtime_error(Temp); | |||||
} | |||||
Input.close(); | |||||
if (Input.bad()) { | |||||
std::string Temp; | |||||
Temp = "Error closing the sendmail configuration file " + SendmailSendmailMcPath; | |||||
Temp += " after reading: "; | |||||
Temp += strerror(errno); | |||||
throw std::runtime_error(Temp); | |||||
} | |||||
std::ofstream Output; // Write the updated contents. | |||||
Output.open(SendmailSendmailMcPath.c_str(), std::ios::trunc); | |||||
if (!Output) { | |||||
std::string Temp; | |||||
Temp = "Error opening the sendmail configuration file " + SendmailSendmailMcPath; | |||||
Temp += " for writing: "; | |||||
Temp += strerror(errno); | |||||
throw std::runtime_error(Temp); | |||||
} | |||||
Output << Content; | |||||
if (!Output) { | |||||
std::string Temp; | |||||
Temp = "Error writing the sendmail configuration file " + SendmailSendmailMcPath; | |||||
Temp += ": "; | |||||
Temp += strerror(errno); | |||||
throw std::runtime_error(Temp); | |||||
} | |||||
Output.close(); | |||||
if (!Output) { | |||||
std::string Temp; | |||||
Temp = "Error closing the sendmail configuration file " + SendmailSendmailMcPath; | |||||
Temp += " after writing: "; | |||||
Temp += strerror(errno); | |||||
throw std::runtime_error(Temp); | |||||
} | |||||
if (std::system(BuildInstallSendmailCfFile.c_str()) != 0) { // Rebuild and install the sendmail configuration file. | |||||
std::string Temp; | |||||
Temp = "Error generating sendmail configuration file " + SendmailSendmailCfPath; | |||||
throw std::runtime_error(Temp); | |||||
} | |||||
} | |||||
OutputVerboseEnd(); | |||||
if (!ReloadMta()) { | |||||
std::cerr << "Unable to reload the sendmail configuration. Please run " | |||||
<< "'sendmail reload' for the integration with SNFMilter 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 SNFMilter integration in the sendmail file " << SendmailSendmailMcPath << "..."; | |||||
} | |||||
if (!FileExists(SendmailSendmailMcPath)) { | |||||
if (Verbose()) { | |||||
std::cout << "file doesn't exist; sendmail is not integrated..."; | |||||
} | |||||
OutputVerboseEnd(); | |||||
return false; | |||||
} | |||||
bool Integrated = false; | |||||
std::ifstream Input; | |||||
Input.open(SendmailSendmailMcPath.c_str()); // Read the contents. | |||||
if (!Input) { | |||||
std::string Temp; | |||||
Temp = "Error opening the sendmail configuration file " + SendmailSendmailMcPath; | |||||
Temp += " for reading: "; | |||||
Temp += strerror(errno); | |||||
throw std::runtime_error(Temp); | |||||
} | |||||
std::string Line; | |||||
while (getline(Input, Line)) { | |||||
if (std::string::npos != Line.find(SnfMilterSendmailMcSearchString)) { // Check for integration line. | |||||
Integrated = true; // Found it. | |||||
break; | |||||
} | |||||
} | |||||
Input.close(); | |||||
if (Input.bad()) { | |||||
std::string Temp; | |||||
Temp = "Error closing the sendmail configuration file " + SendmailSendmailMcPath; | |||||
Temp += " after reading: "; | |||||
Temp += strerror(errno); | |||||
throw std::runtime_error(Temp); | |||||
} | |||||
if (Verbose()) { | |||||
if (Integrated) { | |||||
std::cout << "found '" << Line << "'..."; | |||||
} else { | |||||
std::cout << "none found..."; | |||||
} | |||||
} | |||||
OutputVerboseEnd(); | |||||
return Integrated; | |||||
} |
// \file SendmailIntegrate.hpp | |||||
// | |||||
// Copyright (C) 2011 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 SNFMilter 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(); | |||||
/// 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 |
// 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. | |||||
} |