您最多选择25个主题 主题必须以字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符

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