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

SendmailIntegrate.cpp 11KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452
  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 sendmail.cf; m4 /etc/mail/linux.mc > sendmail.cf)";
  61. ReloadMtaCommand = "/usr/sbin/postfix 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 << "--\n";
  131. }
  132. if (!Explain()) {
  133. for (FileToBackupType::iterator iFile = FileToBackup.begin(); iFile != FileToBackup.end(); iFile++) {
  134. SaveFile->CreateBackupFile(*iFile); // Save any existing file.
  135. }
  136. Input.open(SendmailSendmailMcPath.c_str()); // Read the contents.
  137. if (!Input) {
  138. std::string Temp;
  139. Temp = "Error opening the sendmail configuration file " + SendmailSendmailMcPath;
  140. Temp += " for reading: ";
  141. Temp += strerror(errno);
  142. throw std::runtime_error(Temp);
  143. }
  144. std::string Content;
  145. std::string Line;
  146. while (getline(Input, Line)) {
  147. if (std::string::npos != Line.find(SnfMilterSendmailMcSearchString)) { // Check for integration line.
  148. if (Verbose()) {
  149. std::cout << " Remove '" << Line << "'...\n";
  150. }
  151. continue; // Do not copy this line.
  152. }
  153. Content += Line + "\n"; // Copy this line.
  154. }
  155. if (!Input.eof()) { // Should be at end-of-file.
  156. std::string Temp;
  157. Temp = "Error reading the sendmail configuration file " + SendmailSendmailMcPath;
  158. Temp += ": ";
  159. Temp += strerror(errno);
  160. throw std::runtime_error(Temp);
  161. }
  162. Input.close();
  163. if (Input.bad()) {
  164. std::string Temp;
  165. Temp = "Error closing the sendmail configuration file " + SendmailSendmailMcPath;
  166. Temp += " after reading: ";
  167. Temp += strerror(errno);
  168. throw std::runtime_error(Temp);
  169. }
  170. std::ofstream Output; // Write the updated contents.
  171. Output.open(SendmailSendmailMcPath.c_str(), std::ios::trunc);
  172. if (!Output) {
  173. std::string Temp;
  174. Temp = "Error opening the sendmail configuration file " + SendmailSendmailMcPath;
  175. Temp += " for writing: ";
  176. Temp += strerror(errno);
  177. throw std::runtime_error(Temp);
  178. }
  179. Output << Content;
  180. if (!Output) {
  181. std::string Temp;
  182. Temp = "Error writing the sendmail configuration file " + SendmailSendmailMcPath;
  183. Temp += ": ";
  184. Temp += strerror(errno);
  185. throw std::runtime_error(Temp);
  186. }
  187. Output.close();
  188. if (!Output) {
  189. std::string Temp;
  190. Temp = "Error closing the sendmail configuration file " + SendmailSendmailMcPath;
  191. Temp += " after writing: ";
  192. Temp += strerror(errno);
  193. throw std::runtime_error(Temp);
  194. }
  195. if (std::system(BuildInstallSendmailCfFile.c_str()) != 0) { // Rebuild and install the sendmail configuration file.
  196. std::string Temp;
  197. Temp = "Error generating sendmail configuration file " + SendmailSendmailCfPath;
  198. throw std::runtime_error(Temp);
  199. }
  200. }
  201. OutputVerboseEnd();
  202. if (!ReloadMta()) {
  203. std::cerr << "Unable to reload the sendmail configuration. Please run "
  204. << "'sendmail reload' for the integration with SNFMilter to take effect.";
  205. }
  206. }
  207. bool
  208. SendmailIntegrate::MtaIsRunningDetected() {
  209. if (Verbose()) {
  210. std::cout << "Checking whether sendmail is detected to be running...";
  211. }
  212. bool IsRunningDetected;
  213. IsRunningDetected = (std::system(MtaIsRunningCommand.c_str()) == 0);
  214. if (Verbose()) {
  215. std::cout << (IsRunningDetected ? "yes..." : "no...");
  216. }
  217. OutputVerboseEnd();
  218. return IsRunningDetected;
  219. }
  220. bool
  221. SendmailIntegrate::ReloadMta() {
  222. if (!MtaIsRunningDetected()) {
  223. return true;
  224. }
  225. if (Verbose()) {
  226. std::cout << "Reloading sendmail with the command '"
  227. << ReloadMtaCommand << "'...\n";
  228. std::cout.flush();
  229. }
  230. bool Succeeded;
  231. if (!Explain()) {
  232. Succeeded = (std::system(ReloadMtaCommand.c_str()) == 0);
  233. if (Verbose()) {
  234. std::cout << (Succeeded ? "succeeded..." : "failed...");
  235. }
  236. }
  237. OutputVerboseEnd();
  238. return Succeeded;
  239. }
  240. bool
  241. SendmailIntegrate::IsIntegrated() {
  242. if (Verbose()) {
  243. std::cout << "Checking for any SNFMilter integration in the sendmail file " << SendmailSendmailMcPath << "...";
  244. }
  245. if (!FileExists(SendmailSendmailMcPath)) {
  246. if (Verbose()) {
  247. std::cout << "file doesn't exist; sendmail is not integrated...";
  248. }
  249. OutputVerboseEnd();
  250. return false;
  251. }
  252. bool Integrated = false;
  253. std::ifstream Input;
  254. Input.open(SendmailSendmailMcPath.c_str()); // Read the contents.
  255. if (!Input) {
  256. std::string Temp;
  257. Temp = "Error opening the sendmail configuration file " + SendmailSendmailMcPath;
  258. Temp += " for reading: ";
  259. Temp += strerror(errno);
  260. throw std::runtime_error(Temp);
  261. }
  262. std::string Line;
  263. while (getline(Input, Line)) {
  264. if (std::string::npos != Line.find(SnfMilterSendmailMcSearchString)) { // Check for integration line.
  265. Integrated = true; // Found it.
  266. break;
  267. }
  268. }
  269. Input.close();
  270. if (Input.bad()) {
  271. std::string Temp;
  272. Temp = "Error closing the sendmail configuration file " + SendmailSendmailMcPath;
  273. Temp += " after reading: ";
  274. Temp += strerror(errno);
  275. throw std::runtime_error(Temp);
  276. }
  277. if (Verbose()) {
  278. if (Integrated) {
  279. std::cout << "found '" << Line << "'...";
  280. } else {
  281. std::cout << "none found...";
  282. }
  283. }
  284. OutputVerboseEnd();
  285. return Integrated;
  286. }