Вы не можете выбрать более 25 тем Темы должны начинаться с буквы или цифры, могут содержать дефисы(-) и должны содержать не более 35 символов.

SendmailIntegrate.cpp 11KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454
  1. // /file SendmailIntegrate.cpp
  2. //
  3. // Copyright (C) 2011, ARM Research Labs, LLC.
  4. // See www.armresearch.com for the copyright terms.
  5. //
  6. // This file contains the functions for SendmailIntegrate.
  7. //
  8. // $Id$
  9. //
  10. ///////////////////////////////////////////////////////////////////////////////////////////////////
  11. #include <cstdlib>
  12. #include <cerrno>
  13. #include <cstring>
  14. #include <iostream>
  15. #include <exception>
  16. #include <stdexcept>
  17. #include <sstream>
  18. #include <fstream>
  19. #include "SendmailIntegrate.hpp"
  20. //////////////////////////////////////////////////////////////////////////////////////////////////////////
  21. // Configuration. ////////////////////////////////////////////////////////////////////////////////////////
  22. //////////////////////////////////////////////////////////////////////////////////////////////////////////
  23. const std::string SnfMilterSendmailMcSearchString("Added by SNFMilterConfig");
  24. const std::string SnfMilterSendmailMcIntegrationString("INPUT_MAIL_FILTER(`SNFMilter', `S=unix:/var/snf-milter/socket')dnl # Added by SNFMilterConfig");
  25. const std::string MtaIsRunningCommand("ps axl | grep -v grep | grep -q ' sendmail: '");
  26. //////////////////////////////////////////////////////////////////////////////////////////////////////////
  27. // End of configuration. /////////////////////////////////////////////////////////////////////////////////
  28. //////////////////////////////////////////////////////////////////////////////////////////////////////////
  29. void
  30. SendmailIntegrate::SetOperatingSystem(std::string OperatingSystemType) {
  31. if ("OpenBSD" == OperatingSystemType) {
  32. SendmailSendmailMcPath = "/etc/mail/sendmail.mc";
  33. SendmailSendmailCfPath = "/etc/mail/sendmail.cf";
  34. ReloadMtaCommand = "/usr/local/sbin/postfix reload";
  35. FileToBackup.push_back(SendmailSendmailMcPath);
  36. FileToBackup.push_back(SendmailSendmailCfPath);
  37. } else if ("FreeBSD" == OperatingSystemType) {
  38. SendmailSendmailMcPath = "/etc/mail/sendmail.mc";
  39. SendmailSendmailCfPath = "/etc/mail/sendmail.cf";
  40. ReloadMtaCommand = "/usr/local/sbin/postfix reload";
  41. FileToBackup.push_back(SendmailSendmailMcPath);
  42. FileToBackup.push_back(SendmailSendmailCfPath);
  43. } else if ("Ubuntu" == OperatingSystemType) {
  44. SendmailSendmailMcPath = "/etc/mail/sendmail.mc";
  45. SendmailSendmailCfPath = "/etc/mail/sendmail.cf";
  46. BuildInstallSendmailCfFile = "(cd /etc/mail && make)";
  47. ReloadMtaCommand = "/usr/sbin/service sendmail reload";
  48. FileToBackup.push_back(SendmailSendmailMcPath);
  49. FileToBackup.push_back(SendmailSendmailCfPath);
  50. } else if ("RedHat" == OperatingSystemType) {
  51. SendmailSendmailMcPath = "/etc/mail/sendmail.mc";
  52. SendmailSendmailCfPath = "/etc/mail/sendmail.cf";
  53. BuildInstallSendmailCfFile = "(cd /etc/mail && make)";
  54. ReloadMtaCommand = "/sbin/service sendmail reload";
  55. FileToBackup.push_back(SendmailSendmailMcPath);
  56. FileToBackup.push_back(SendmailSendmailCfPath);
  57. } else if ("Suse" == OperatingSystemType) {
  58. SendmailSendmailMcPath = "/etc/mail/linux.mc";
  59. SendmailSendmailCfPath = "/etc/mail/sendmail.cf";
  60. BuildInstallSendmailCfFile = "(cd /etc/mail && rm -f sendmail.cf && m4 /etc/mail/linux.mc > sendmail.cf)";
  61. ReloadMtaCommand = "/sbin/service sendmail reload";
  62. FileToBackup.push_back(SendmailSendmailMcPath);
  63. FileToBackup.push_back(SendmailSendmailCfPath);
  64. } else {
  65. std::ostringstream Temp;
  66. Temp << "***Error from SendmailIntegrate::SetOperatingSystem: Invalid value of OperatingSystemType: "
  67. << OperatingSystemType;
  68. throw std::runtime_error(Temp.str());
  69. }
  70. }
  71. void
  72. SendmailIntegrate::Integrate(FileBackup *SaveFile) {
  73. if (IsIntegrated()) {
  74. return;
  75. }
  76. if (Verbose()) {
  77. std::cout << "Add to sendmail file " << SendmailSendmailMcPath << ": '"
  78. << SnfMilterSendmailMcIntegrationString << "' and generate new "
  79. << SendmailSendmailCfPath << " file with the command '"
  80. << BuildInstallSendmailCfFile << "'...";
  81. }
  82. if (!Explain()) {
  83. for (FileToBackupType::iterator iFile = FileToBackup.begin(); iFile != FileToBackup.end(); iFile++) {
  84. SaveFile->CreateBackupFile(*iFile); // Save any existing file.
  85. }
  86. std::ofstream Output; // Append the configuration.
  87. Output.open(SendmailSendmailMcPath.c_str(), std::ios::app);
  88. if (!Output) {
  89. std::string Temp;
  90. Temp = "Error opening the sendmail configuration file " + SendmailSendmailMcPath;
  91. Temp += " for writing: ";
  92. Temp += strerror(errno);
  93. throw std::runtime_error(Temp);
  94. }
  95. Output << SnfMilterSendmailMcIntegrationString << "\n";
  96. if (!Output) {
  97. std::string Temp;
  98. Temp = "Error appending to the sendmail configuration file " + SendmailSendmailMcPath;
  99. Temp += ": ";
  100. Temp += strerror(errno);
  101. throw std::runtime_error(Temp);
  102. }
  103. Output.close();
  104. if (!Output) {
  105. std::string Temp;
  106. Temp = "Error closing the sendmail configuration file " + SendmailSendmailMcPath;
  107. Temp += " after appending: ";
  108. Temp += strerror(errno);
  109. throw std::runtime_error(Temp);
  110. }
  111. if (std::system(BuildInstallSendmailCfFile.c_str()) != 0) {
  112. std::string Temp;
  113. Temp = "Error generating sendmail configuration file " + SendmailSendmailCfPath;
  114. throw std::runtime_error(Temp);
  115. }
  116. }
  117. OutputVerboseEnd();
  118. if (!ReloadMta()) {
  119. std::cerr << "Unable to reload the sendmail configuration. Please reload "
  120. << " the sendmail configuration for the integration with SNFMilter to take effect.";
  121. }
  122. }
  123. void
  124. SendmailIntegrate::Unintegrate(FileBackup *SaveFile) {
  125. if (!IsIntegrated()) {
  126. return;
  127. }
  128. std::ifstream Input;
  129. if (Verbose()) {
  130. std::cout << "Remove integration in sendmail file " << SendmailSendmailMcPath
  131. << " and generate new " << SendmailSendmailCfPath << " file with the command '"
  132. << BuildInstallSendmailCfFile << "'--\n";
  133. }
  134. if (!Explain()) {
  135. for (FileToBackupType::iterator iFile = FileToBackup.begin(); iFile != FileToBackup.end(); iFile++) {
  136. SaveFile->CreateBackupFile(*iFile); // Save any existing file.
  137. }
  138. Input.open(SendmailSendmailMcPath.c_str()); // Read the contents.
  139. if (!Input) {
  140. std::string Temp;
  141. Temp = "Error opening the sendmail configuration file " + SendmailSendmailMcPath;
  142. Temp += " for reading: ";
  143. Temp += strerror(errno);
  144. throw std::runtime_error(Temp);
  145. }
  146. std::string Content;
  147. std::string Line;
  148. while (getline(Input, Line)) {
  149. if (std::string::npos != Line.find(SnfMilterSendmailMcSearchString)) { // Check for integration line.
  150. if (Verbose()) {
  151. std::cout << " Remove '" << Line << "'...\n";
  152. }
  153. continue; // Do not copy this line.
  154. }
  155. Content += Line + "\n"; // Copy this line.
  156. }
  157. if (!Input.eof()) { // Should be at end-of-file.
  158. std::string Temp;
  159. Temp = "Error reading the sendmail configuration file " + SendmailSendmailMcPath;
  160. Temp += ": ";
  161. Temp += strerror(errno);
  162. throw std::runtime_error(Temp);
  163. }
  164. Input.close();
  165. if (Input.bad()) {
  166. std::string Temp;
  167. Temp = "Error closing the sendmail configuration file " + SendmailSendmailMcPath;
  168. Temp += " after reading: ";
  169. Temp += strerror(errno);
  170. throw std::runtime_error(Temp);
  171. }
  172. std::ofstream Output; // Write the updated contents.
  173. Output.open(SendmailSendmailMcPath.c_str(), std::ios::trunc);
  174. if (!Output) {
  175. std::string Temp;
  176. Temp = "Error opening the sendmail configuration file " + SendmailSendmailMcPath;
  177. Temp += " for writing: ";
  178. Temp += strerror(errno);
  179. throw std::runtime_error(Temp);
  180. }
  181. Output << Content;
  182. if (!Output) {
  183. std::string Temp;
  184. Temp = "Error writing the sendmail configuration file " + SendmailSendmailMcPath;
  185. Temp += ": ";
  186. Temp += strerror(errno);
  187. throw std::runtime_error(Temp);
  188. }
  189. Output.close();
  190. if (!Output) {
  191. std::string Temp;
  192. Temp = "Error closing the sendmail configuration file " + SendmailSendmailMcPath;
  193. Temp += " after writing: ";
  194. Temp += strerror(errno);
  195. throw std::runtime_error(Temp);
  196. }
  197. if (std::system(BuildInstallSendmailCfFile.c_str()) != 0) { // Rebuild and install the sendmail configuration file.
  198. std::string Temp;
  199. Temp = "Error generating sendmail configuration file " + SendmailSendmailCfPath;
  200. throw std::runtime_error(Temp);
  201. }
  202. }
  203. OutputVerboseEnd();
  204. if (!ReloadMta()) {
  205. std::cerr << "Unable to reload the sendmail configuration. Please run "
  206. << "'sendmail reload' for the integration with SNFMilter to take effect.";
  207. }
  208. }
  209. bool
  210. SendmailIntegrate::MtaIsRunningDetected() {
  211. if (Verbose()) {
  212. std::cout << "Checking whether sendmail is detected to be running...";
  213. }
  214. bool IsRunningDetected;
  215. IsRunningDetected = (std::system(MtaIsRunningCommand.c_str()) == 0);
  216. if (Verbose()) {
  217. std::cout << (IsRunningDetected ? "yes..." : "no...");
  218. }
  219. OutputVerboseEnd();
  220. return IsRunningDetected;
  221. }
  222. bool
  223. SendmailIntegrate::ReloadMta() {
  224. if (!MtaIsRunningDetected()) {
  225. return true;
  226. }
  227. if (Verbose()) {
  228. std::cout << "Reloading sendmail with the command '"
  229. << ReloadMtaCommand << "'...\n";
  230. std::cout.flush();
  231. }
  232. bool Succeeded;
  233. if (!Explain()) {
  234. Succeeded = (std::system(ReloadMtaCommand.c_str()) == 0);
  235. if (Verbose()) {
  236. std::cout << (Succeeded ? "succeeded..." : "failed...");
  237. }
  238. }
  239. OutputVerboseEnd();
  240. return Succeeded;
  241. }
  242. bool
  243. SendmailIntegrate::IsIntegrated() {
  244. if (Verbose()) {
  245. std::cout << "Checking for any SNFMilter integration in the sendmail file " << SendmailSendmailMcPath << "...";
  246. }
  247. if (!FileExists(SendmailSendmailMcPath)) {
  248. if (Verbose()) {
  249. std::cout << "file doesn't exist; sendmail is not integrated...";
  250. }
  251. OutputVerboseEnd();
  252. return false;
  253. }
  254. bool Integrated = false;
  255. std::ifstream Input;
  256. Input.open(SendmailSendmailMcPath.c_str()); // Read the contents.
  257. if (!Input) {
  258. std::string Temp;
  259. Temp = "Error opening the sendmail configuration file " + SendmailSendmailMcPath;
  260. Temp += " for reading: ";
  261. Temp += strerror(errno);
  262. throw std::runtime_error(Temp);
  263. }
  264. std::string Line;
  265. while (getline(Input, Line)) {
  266. if (std::string::npos != Line.find(SnfMilterSendmailMcSearchString)) { // Check for integration line.
  267. Integrated = true; // Found it.
  268. break;
  269. }
  270. }
  271. Input.close();
  272. if (Input.bad()) {
  273. std::string Temp;
  274. Temp = "Error closing the sendmail configuration file " + SendmailSendmailMcPath;
  275. Temp += " after reading: ";
  276. Temp += strerror(errno);
  277. throw std::runtime_error(Temp);
  278. }
  279. if (Verbose()) {
  280. if (Integrated) {
  281. std::cout << "found '" << Line << "'...";
  282. } else {
  283. std::cout << "none found...";
  284. }
  285. }
  286. OutputVerboseEnd();
  287. return Integrated;
  288. }