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

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258
  1. // SNFMilter.hpp
  2. // Copyright (C) 2007 ARM Research Labs, LLC.
  3. // See www.armresearch.com for the copyright terms.
  4. //
  5. // This file defines the SNFMilter configuration data structures and interface.
  6. #ifndef SNFMilterhpp_included
  7. #define SNFMilterhpp_included
  8. #include <signal.h>
  9. #include <libmilter/mfapi.h>
  10. #include <vector>
  11. #include <string>
  12. #include "ProductionQueue.hpp"
  13. #include "MailHeaders.hpp"
  14. #include "timing.hpp"
  15. #include "threading.hpp"
  16. using namespace std;
  17. class snf_EngineHandler; // We must know that these exist.
  18. class snf_RulebaseHandler;
  19. // Connection types.
  20. enum SNFMilterSocketType {
  21. TCPMilterSocket = 1,
  22. UNIXMilterSocket = 2,
  23. NOMilterSocket = 3
  24. };
  25. // SNFMilterAction - What we can do.
  26. enum SNFMilterAction { // SNFMilter Actions
  27. Error = -1, // Error result.
  28. Allow = 0, // Process the message.
  29. Accept = 1, // White-List the message.
  30. Retry = 2, // Return Try Again (tmp fail)
  31. Reject = 3, // Reject the message.
  32. Discard = 4, // Silently discard.
  33. Quarantine = 5, // Store in quarantine.
  34. NoAction = 6, // Take no action.
  35. NMilterActions
  36. };
  37. //
  38. // Configuration.
  39. //
  40. const string AllowActionMnemonic = "0";
  41. const string AcceptActionMnemonic = "1";
  42. const string RetryActionMnemonic = "2";
  43. const string RejectActionMnemonic = "3";
  44. const string DiscardActionMnemonic = "4";
  45. const string QuarantineActionMnemonic = "5";
  46. const string NoActionMnemonic = "6";
  47. const string TCPMilterSocketMnemonic = "1";
  48. const string UNIXMilterSocketMnemonic = "2";
  49. const int ResultCodesCount = 64; // Number of valid result codes.
  50. const int ConfigurationLifetime = 1000; // Config life time in ms.
  51. const bool PrependLocalReceivedHeader = true; // True to prepend local received headers
  52. // to the buffer to scan.
  53. const sfsistat FailSafeMilterResponse = SMFIS_CONTINUE; // Return value to libmilter
  54. // in case of error.
  55. const string::size_type MailBufferReserveSize = 65536; // Maximum amount of email message to scan.
  56. const string SMTPENDL = "\r\n"; // SMTP endline.
  57. const int ShutdownPeriods = 5; // Number of time periods to wait while
  58. // shutting down.
  59. const int ShutdownWaitPeriod_ms = 1000; // Time period duration for shutting down.
  60. const string UnknownExceptionMessage = "Unknown exception occurred."; // Logged when an unknown exception occurs.
  61. const int ShutdownSignal = SIGTERM; // Signal for shutdown.
  62. //
  63. // End of configuration.
  64. //
  65. // The SNFMilterEngine class provides up to date configuration data and
  66. // a scanning engine for the milter. It is presumed that at one of these objects
  67. // will be used in each message scan. They can be created, used, and destroyed,
  68. // or for a more optimized approach they can be created, used, stored in a pool,
  69. // and refreshed, and used again for a new scan. They should all be properly
  70. // destroyed before runLibMilter() returns.
  71. class SNFMilterEngine { // Milter config objec. One per scan.
  72. private:
  73. Mutex ConfigMutex; // Configuration lock mutex.
  74. snf_RulebaseHandler* myRulebase; // Where is my rulebase?
  75. snf_EngineHandler* myEngine; // Where is my engine?
  76. // Configuration data.
  77. // IP scan actions
  78. SNFMilterAction WhiteAction; // Action for White IP.
  79. SNFMilterAction CautionAction; // Action for Caution IP.
  80. SNFMilterAction BlackAction; // Action for Black IP.
  81. SNFMilterAction TruncateAction; // Action for Truncate IP.
  82. SNFMilterAction NonZeroAction; // Action for nonzero scans.
  83. // Message scan actions
  84. SNFMilterAction ResultActions[ResultCodesCount]; // Array of possible scan actions.
  85. Timeout ConfigurationCheckTime; // Timer for checking the configuration.
  86. string RunningConfiguration; // The current running config string.
  87. void readConfiguration(); // Parses the configuration.
  88. void checkConfiguration(); // Reload the config if it is old.
  89. public:
  90. SNFMilterEngine(snf_RulebaseHandler* R); // Construct the configuration.
  91. ~SNFMilterEngine(); // Destroy the configuration.
  92. void setResultAction(int Result, SNFMilterAction Action); // Set a result / action pair.
  93. SNFMilterAction scanIP(unsigned long int IP); // Scans an IP.
  94. SNFMilterAction scanMessage(const unsigned char* bfr, int length); // Scans a message.
  95. string XHeaders(); // Return X headers from last scan.
  96. };
  97. // The SNFMilterContext class maintains the context for a connection
  98. // from the MTA. There is one SNFMilterContext object for each
  99. // connection from the MTA. They can be created, used, and destroyed,
  100. // or for a more optimized approach they can be created, used, stored
  101. // in a pool, and refreshed, and used again for a new scan. They
  102. // should all be properly destroyed before runLibMilter() returns.
  103. class SNFMilterContext { // Milter connection context object.
  104. public:
  105. // Object states. The object transitions to the corresponding state
  106. // when a libmilter callback is invoked. The object is in the
  107. // Pooled state when the object is not being used.
  108. enum SNFMilterState {
  109. Pooled,
  110. Connect,
  111. Helo,
  112. EnvFrom,
  113. EnvRcpt,
  114. Data,
  115. Header,
  116. EOH,
  117. Body,
  118. EOM,
  119. Close,
  120. NMilterStates
  121. } State;
  122. SNFMilterContext(snf_RulebaseHandler *);
  123. ~SNFMilterContext();
  124. sfsistat SkipReturn; // libmilter return value when further
  125. // callbacks of the same type are to be skipped.
  126. // Map the scan result to the libmilter return value.
  127. sfsistat
  128. smfisReturn(SNFMilterAction);
  129. // Scanning engine.
  130. SNFMilterEngine milterEngine;
  131. string getLocalReceivedHeader();
  132. // Connection data.
  133. struct SNFMilterConnectionData {
  134. string HostName;
  135. IP4Address HostIP;
  136. string HostHelo;
  137. // Clear the object.
  138. void clear() {
  139. HostName.clear();
  140. HostIP = (long unsigned )0;
  141. HostHelo.clear();
  142. }
  143. } ConnectionData;
  144. // Message buffer.
  145. struct SNFMilterMessageData {
  146. // Buffer to hold the message.
  147. string MessageBuffer;
  148. // Sender address.
  149. string SenderAddress;
  150. // Constructor reserves memory to hold the message.
  151. SNFMilterMessageData(string::size_type reserveSize) {
  152. MessageBuffer.reserve(reserveSize);
  153. }
  154. // Clear the object.
  155. void clear() {
  156. MessageBuffer.clear();
  157. SenderAddress.clear();
  158. }
  159. } MessageData;
  160. };
  161. class SNFMilterContextPool { // SNFMilter Pool Manager
  162. private:
  163. Mutex ContextAllocationControl; // Protects context allocation.
  164. vector<SNFMilterContext*> ContextPool; // Contains all created contexts.
  165. ProductionQueue<SNFMilterContext*> AvailableContexts; // Contains all available contexts.
  166. snf_RulebaseHandler* myRulebase; // Rulebase handler.
  167. // Connection info.
  168. SNFMilterSocketType MilterSocketType;
  169. string MilterSocketPath;
  170. string MilterSocketGroup;
  171. string MilterSocketIP;
  172. int MilterSocketPort;
  173. public:
  174. SNFMilterContextPool(snf_RulebaseHandler* Rulebase); // Ctor needs a live rulebase handler.
  175. ~SNFMilterContextPool(); // Dtor gracefully discards contexts.
  176. SNFMilterSocketType getSocketType(); // Named pipe or TCP socket specified
  177. // in the configuration.
  178. string getSocketPath(); // Path of named pipe specified in
  179. // the configuration
  180. string getSocketGroup(); // Group specified for named pipe
  181. // in the conofiguration.
  182. string getSocketIP(); // IP (host) specified in the
  183. // configuration.
  184. int getSocketPort(); // TCP port specified in the
  185. // configuration
  186. SNFMilterContext* grab(); // Get an context to use.
  187. void drop(SNFMilterContext* E); // Drop an context after use.
  188. bool allUnused(); // Return true if no contexts are in use.
  189. void logThisError(string ContextName, int Code, string Text); // Log an error message.
  190. void logThisInfo(string ContextName, int Code, string Text); // Log an informational message.
  191. };
  192. // The runLibMilter function establishes the appropriate libmilter call backs and
  193. // accepts calls from the MTA via libmilter until it is told to quit. When it
  194. // is told to quit it gracefully closes down, reclaims any memory it allocated,
  195. // and returns.
  196. // The actual code for the runLibMilter() function call is found in SNFMilter.cpp.
  197. void runLibMilter(SNFMilterContextPool* Contexts, bool DebugMode); // Run the milter 'til it's done.
  198. #endif