|
|
@@ -0,0 +1,450 @@ |
|
|
|
// /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: MTA:'");
|
|
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
// End of configuration. /////////////////////////////////////////////////////////////////////////////////
|
|
|
|
//////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
void
|
|
|
|
SendmailIntegrate::SetOperatingSystem(std::string OperatingSystemType) {
|
|
|
|
|
|
|
|
if ("OpenBSD" == OperatingSystemType) {
|
|
|
|
|
|
|
|
SendmailSendmailMcPath = "/etc/mail/sendmail.mc";
|
|
|
|
SendmailSendmailCfPath = "/etc/mail/sendmail.cf";
|
|
|
|
ReloadMtaCommand = "/usr/local/sbin/postfix reload";
|
|
|
|
|
|
|
|
FileToBackup.push_back(SendmailSendmailMcPath);
|
|
|
|
FileToBackup.push_back(SendmailSendmailCfPath);
|
|
|
|
|
|
|
|
} else if ("FreeBSD" == OperatingSystemType) {
|
|
|
|
|
|
|
|
SendmailSendmailMcPath = "/etc/mail/sendmail.mc";
|
|
|
|
SendmailSendmailCfPath = "/etc/mail/sendmail.cf";
|
|
|
|
ReloadMtaCommand = "/usr/local/sbin/postfix reload";
|
|
|
|
|
|
|
|
FileToBackup.push_back(SendmailSendmailMcPath);
|
|
|
|
FileToBackup.push_back(SendmailSendmailCfPath);
|
|
|
|
|
|
|
|
} else if ("Ubuntu" == OperatingSystemType) {
|
|
|
|
|
|
|
|
SendmailSendmailMcPath = "/etc/mail/sendmail.mc";
|
|
|
|
SendmailSendmailCfPath = "/etc/mail/sendmail.cf";
|
|
|
|
BuildInstallSendmailCfFile = "(cd /etc/mail; make)";
|
|
|
|
ReloadMtaCommand = "/usr/sbin/service sendmail reload";
|
|
|
|
|
|
|
|
FileToBackup.push_back(SendmailSendmailMcPath);
|
|
|
|
FileToBackup.push_back(SendmailSendmailCfPath);
|
|
|
|
|
|
|
|
} else if ("RedHat" == OperatingSystemType) {
|
|
|
|
|
|
|
|
SendmailSendmailMcPath = "/etc/mail/sendmail.mc";
|
|
|
|
SendmailSendmailCfPath = "/etc/mail/sendmail.cf";
|
|
|
|
BuildInstallSendmailCfFile = "(cd /etc/mail; make)";
|
|
|
|
ReloadMtaCommand = "/usr/sbin/postfix reload";
|
|
|
|
|
|
|
|
FileToBackup.push_back(SendmailSendmailMcPath);
|
|
|
|
FileToBackup.push_back(SendmailSendmailCfPath);
|
|
|
|
|
|
|
|
} else if ("Suse" == OperatingSystemType) {
|
|
|
|
|
|
|
|
SendmailSendmailMcPath = "/etc/mail/linux.mc";
|
|
|
|
SendmailSendmailCfPath = "/etc/mail/sendmail.cf";
|
|
|
|
BuildInstallSendmailCfFile = "(cd /etc/mail; rm sendmail.cf; m4 /etc/mail/linux.mc > sendmail.cf)";
|
|
|
|
ReloadMtaCommand = "/usr/sbin/postfix 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 (IsIntegrated()) {
|
|
|
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
if (Verbose()) {
|
|
|
|
|
|
|
|
std::cout << "Add to sendmail file " << SendmailSendmailMcPath << ": '"
|
|
|
|
<< SnfMilterSendmailMcIntegrationString << "' and generate new "
|
|
|
|
<< SendmailSendmailCfPath << " file...";
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
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 (!IsIntegrated()) {
|
|
|
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
std::ifstream Input;
|
|
|
|
|
|
|
|
if (Verbose()) {
|
|
|
|
|
|
|
|
std::cout << "Remove integration in sendmail file " << SendmailSendmailMcPath << "--\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...\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;
|
|
|
|
|
|
|
|
}
|