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

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