Ви не можете вибрати більше 25 тем Теми мають розпочинатися з літери або цифри, можуть містити дефіси (-) і не повинні перевищувати 35 символів.

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