Updated all README files.master
20090707 Upgraded Engine to SNFMulti V3.0.8 (contains minor bug fixes). | |||||
20090704 Getting closer - new DLL, new features, a little polish. | |||||
NOTE: Beginning with this update this ChangeLog will only list hilights. | |||||
For more details check the logs at https://svn.microneil.com/websvn/ | |||||
* snfmulti.dll is now at version 3.0, engine 3.0.7 | |||||
* Used newer MinGW with improved optimizations | |||||
* Using newest SNF engine with several minor bug fixes | |||||
* Added startupSNFAuthenticated() so OEMs can protect SNF license info | |||||
* Added getIPReputation() to aid in converting GBUdb stats to weights | |||||
* Added C++ sample code | |||||
* Reorganized SNFMulti code base. | |||||
20090317 Work in progess toward SDK release. | |||||
* Included latest getRulebase.cmd and curl.exe | |||||
* Included SNFClient_readme.txt and SNFServer_readme.txt | |||||
* Included / updated SNFClient, and snf_engine.xml | |||||
* Added ReadMe.html - includes API documentation | |||||
* Added missing snf_ERROR_EXCEPTION to snfmultidll.h file | |||||
* Removed redundant #define EXP __declspec(dllexport) from snfmultidll.cpp | |||||
20080723 Version 2.9r3 - Engine 3.0 | |||||
* Compiled DLL using new SNF engine V3.0. | |||||
* Added snf_ERROR_EXCEPTION result (-3) to show when an exception occurred | |||||
during a call that could not be expressed with one of the normal SNF result | |||||
codes. | |||||
* Wraped DLLMain() functions in a try/catch to eat any exceptions. If an | |||||
exception occurs the function will return false; | |||||
* Added pre-allocation to result cache buffers to minimize heap allocation | |||||
during operations. The pre-allocated amount should be sufficient for all | |||||
cases. If it is not then the string objects will allocate more as needed. | |||||
* Changed snf_ERROR_UNKNOWN to snf_ERROR_EXCEPTION for startupSNF() and | |||||
shutdownSNF(). | |||||
* Wrapped testIP() in try/catch - now returns snf_ERROR_EXCEPTION if an | |||||
exception occurs. | |||||
* Wrapped getScanXHeaders() in try/catch - now returns snf_ERROR_EXCEPTION | |||||
if an exception occurs. | |||||
* Wrapped getScanXMLLog() in try/catch - now returns snf_ERROR_EXCEPTION | |||||
if an exception occurs. | |||||
* Wrapped getScanClassicLog() in try/catch - now returns snf_ERROR_EXCEPTION | |||||
if an exception occurs. | |||||
* Wrapped closeScan() in try/catch - now returns snf_ERROR_EXCEPTION | |||||
if an exception occurs. | |||||
# List of IPs to Ignore on startup | |||||
# Each IP in this list is set to Ignore in GBUdb when | |||||
# The configuration is loaded. | |||||
# Hash mark on the beginning of a line indicates a comment. | |||||
# Comments after an IP are also ignored. | |||||
# One line per IP. Sorry, no CIDR yet. | |||||
# Be sure to list ALL of your gateways :-) | |||||
127.0.0.1 # ignore localhost, of course. |
<!-- Copyright 2009, ARM Research Labs, LLC --> | |||||
<html> | |||||
<body> | |||||
<font face="sans-serif"> | |||||
<h1>Message Sniffer SDK for Win* V3.1</h1> | |||||
<h2>Contents</h2> | |||||
</font><h3><ol> | |||||
<p><font face="sans-serif">Introduction</font></p> | |||||
<li><font face="sans-serif"><a href="#Begin">Before you begin!</a></font></li> | |||||
<li><font face="sans-serif"><a href="#Contents">Contents of the SDK</a></font></li> | |||||
<li><font face="sans-serif"><a href="#Description">SNFMulti DLL Description</a></font></li> | |||||
<li><font face="sans-serif"><a href="ChangeLog.txt">Change Log</a></font></li> | |||||
<p><font face="sans-serif">Setup notes and important instructions</font></p> | |||||
<li><font face="sans-serif"><a href="SNFServer_readme.txt">SNFServer Setup Readme</a></font></li> | |||||
<li><font face="sans-serif"><a href="SNFClient_readme.txt">SNFClient Setup Readme</a></font></li> | |||||
<p><font face="sans-serif">Code Samples</font></p> | |||||
<li><font face="sans-serif"><a href="32bitDll/snfmultidll.h">C Header File (snfmultidll.h></a></font></li> | |||||
<li><font face="sans-serif"><a href="32bitDll/libsnfmulti.def">Module Definition File (libsnfmulti.def)</a></font></li> | |||||
<li><font face="sans-serif"><a href="C++/main.cpp">C++ Sample Code</a></font></li> | |||||
<li><font face="sans-serif"><a href="VB/SNFMulti_in_VB.Net.txt">VB.Net Sample Code</a></font></li> | |||||
<p><font face="sans-serif">API Reference - Functions listed in the order they should be used</font></p> | |||||
<li><font face="sans-serif"><a href="#startupSNF">startupSNF()</a> - Initializes the SNF engine and loads the rule base</font></li> | |||||
<li><font face="sans-serif"><a href="#startupSNFAuthenticated">startupSNFAuthenticated()</a> - Initializes SNF with license info</font></li> | |||||
<li><font face="sans-serif"><a href="#setThrottle">setThrottle()</a> - Sets a concurrent thread limit (if desired)</font></li> | |||||
<li><font face="sans-serif"><a href="#testIP">testIP()</a> - Returns the GBUdb reputation range for an IP</font></li> | |||||
<li><font face="sans-serif"><a href="#getIPReputation">getIPReputation()</a> - Returns IP Reputation Figure for an IP</font></li> | |||||
<li><font face="sans-serif"><a href="#scanBuffer">scanBuffer()</a> - Scans a message buffer</font></li> | |||||
<li><font face="sans-serif"><a href="#scanFile">scanFile()</a> - Scans a message file</font></li> | |||||
<li><font face="sans-serif"><a href="#getScanXHeaders">getScanXHeaders()</a> - Returns the scan result and XHeaders</font></li> | |||||
<li><font face="sans-serif"><a href="#getScanXMLLog">getScanXMLLog()</a> - Returns the scan result and XML Log data</font></li> | |||||
<li><font face="sans-serif"><a href="#getScanClassicLog">getScanClassicLog()</a> - Returns the scan result and Classic Log Data</font></li> | |||||
<li><font face="sans-serif"><a href="#getScanResult">getScanResult()</a> - Returns the scan result (nothing else)</font></li> | |||||
<li><font face="sans-serif"><a href="#closeScan">closeScan()</a> - Closes the scan and releases resources</font></li> | |||||
<li><font face="sans-serif"><a href="#shutdownSNF">shutdownSNF()</a> - Shuts down the SNF engine</font></li> | |||||
<p><font face="sans-serif">Miscellaneous</font></p> | |||||
<li><font face="sans-serif"><a href="#ResultCodes">Result Codes</a> - Error and Scan Result Mnemonics</font></li> | |||||
</ol></h3><font face="sans-serif"> | |||||
<hr/> | |||||
<a name="Begin"><h3>Before you begin!</h3></a> | |||||
<p>This SDK contains a complete Message Sniffer engine. You MUST be familiar with that engine | |||||
before you can effectively use this SDK. If you do not already have an OEM license or trial | |||||
SNF rule base license then please <a href="http://www.armresearch.com/">visit our web site first | |||||
and get one!</a> The engine won't run without it.</p> | |||||
<p>We highly recommend that you have some experience with our SNFServer and SNFClient applications | |||||
before you begin writing your own or begin integrating the SNF engine into your own software.</p> | |||||
<p>We're not saying it's hard to do -- quite the opposite actually, BUT SNF is a sophisticated | |||||
piece of software with a lot of capabilities and options. You will have much better results | |||||
if you are familiar with these before you begin ;-)</p> | |||||
<hr/> | |||||
<a name="Contents"><h3>Contents of the SDK</h3></a> | |||||
<p>This SDK contains the following: | |||||
<ol> | |||||
<li><font face="sans-serif">Documentation files, including | |||||
this file.</font></li> | |||||
<li><font face="sans-serif">DLLs (both 32 bit and 64 bit | |||||
versions) and the required header files (in | |||||
directory <b>include</b>).</font></li> | |||||
<li><font face="sans-serif">Sample programs in C++ (in | |||||
directory <b>CPPSample</b>), C# (<b>CSSample</b>), and Visual | |||||
Basic (<b>VBSample</b>).</font></li> | |||||
<li><font face="sans-serif">VS 2008 Solution files to build | |||||
the sample program in C++ (in | |||||
directory <b>VS2008CPPSample</b>), in C# | |||||
(<b>VS2008CSSample</b>), and Visual Basic | |||||
(<b>VS2008VBSample</b>).<br> | |||||
The <b>VS2008CPPSample\README</b> contains instructions for | |||||
creating the SNFMulti import libraries for use with VS 2008. | |||||
</font></li> | |||||
<li><font face="sans-serif">Other applications | |||||
(<b>curl</b>, <b>SNFClient</b>, and <b>getRulebase</b>) and | |||||
configuration files needed to support SNF | |||||
operation.</font></li> | |||||
</ol> | |||||
There are also directions for building VS 2008 import libraries in <b>VS2008CPPSample\README</b>. | |||||
</p> | |||||
<hr/> | |||||
<a name="Description"><h3>SNFMulti DLL Description</h3></a> | |||||
<p>The SNF SDK for Win* is based on a DLL. The DLLs for both the 32 bit | |||||
and 64 bit versions are included here. | |||||
</p> | |||||
<p>The DLL contains the entire SNFServer engine and provides a simple API for starting the | |||||
engine, scanning messages, and retrieving the results. Since the entire SNFServer engine is | |||||
included you also have the option of using the SNFClient utility once your application has | |||||
started the SNF engine. You can also make calls to the engine using the XCI protocol (which | |||||
is how SNFClient does it's work)</p> | |||||
<p>Of course the best way to use the DLL is to perform scans directly through the API. The | |||||
best performance can be achieved by scanning a message in memory via the scanBuffer() function | |||||
since this can be done at the full speed of the processor without waiting for IO operations.</p> | |||||
<p>The DLL is fully thread-safe so you can perform as many concurrent scans as you wish. Also, | |||||
just in case it will make things easier for you, the DLL provides a throttling function which | |||||
can limit the number of concurrent scans. (It won't unless you ask it to.)</p> | |||||
<p>The general form of an application using the DLL will first start the engine, then | |||||
optionally set the throttle, then perform scans (perform a scan, get results, close the scan, repeat), | |||||
and finally it will shutdown the engine.</p> | |||||
<p>Since the DLL contains the entire SNFServer engine, it can (and must) be configured in | |||||
exactly the same way as SNFServer. <a href="http://www.armresearch.com/support/articles/software/snfServer/config/index.jsp"> | |||||
Documentation for configuring SNFServer can be found on our web site.</a></p> | |||||
<p>New in snfmulti.dll V3.0!</p> | |||||
<p>OEM developers can now protect their licenseID and Authentication string by providing it directly to the SNF engine at run-time. When combined with an internal mechanism for downloading rule base files this makes it practical to control SNF license information entirely within the OEM's application. <a href="#startupSNFAuthenticated">See startupSNFAuthenticated() for details.</a></p> | |||||
<hr/> | |||||
<a name="startupSNF"><h3>int startupSNF(char* path);</h3></a> | |||||
<p>This function initializes the SNF scanning engine using the configuration file provided. | |||||
The configuration file identifies all of the operational parameters for the SNF engine including | |||||
the location of the working directories and rule base file, SNF license information, and | |||||
much more. <a href="http://www.armresearch.com/support/articles/software/snfServer/config/index.jsp"> | |||||
See our web site for details on configuring the SNF engine.</a></p> | |||||
<dl> | |||||
<dd><b>path</b> = The full path to the snf_engine.xml file as a null terminated string.</dd> | |||||
<dd><b>returns</b> snf_SUCCESS when successful, otherwise see <a href="#ResultCodes">Error Codes</a>.</dd> | |||||
</dl> | |||||
<hr/> | |||||
<a name="startupSNFAuthenticated"><h3>int startupSNFAuthenticated(char* path, char* lic, char* auth);</h3></a> | |||||
<p>This function initializes the SNF scanning engine using the configuration file and authentication | |||||
information provided. When SNF is started with this function the identity.xml file can be omitted and | |||||
the identity= attribute of the <node/> element in snf_engine.xml can be omitted. This allows OEM | |||||
developers to protect their authentication string by retrieving it from an encrypted source at run-time | |||||
and providing it directly to the SNF engine.</p> | |||||
<p>In all other ways the SNF engine is configured in the same as when using <a href="#startupSNF">startupSNF() (see above)</a></p> | |||||
<p>Note that if you intend to use this mechanism to protect your SNF license information you will also need to | |||||
address the mechanism you use to download and verify rule base files. Either build a mechanism to download and | |||||
authenticate your rule base file without exposing your authentication string or you might modify the existing | |||||
getRulebase script to remove the snf2check operation and the associated authentication string. The SNF engine will | |||||
check all rule base files before they are loaded for scanning and will refuse to load a rule base file that does | |||||
not authenticate properly.</p> | |||||
<dl> | |||||
<dd><b>path</b> = The full path to the snf_engine.xml file as a null terminated string.</dd> | |||||
<dd><b>lic</b> = The 8 character license id as a null terminated string.</dd> | |||||
<dd><b>auth</b> = The 16 character authentication string as a null terminated string.</dd> | |||||
<dd><b>returns</b> snf_SUCCESS when successful, otherwise see <a href="#ResultCodes">Error Codes</a>.</dd> | |||||
</dl> | |||||
<hr/> | |||||
<a name="setThrottle"><h3>int setThrottle(int Threads);</h3></a> | |||||
<p>This function establishes a limit on the number of concurrent scans that can run. Any additional | |||||
threads will block until at least one of the active scans is completed.</p> | |||||
<p>The default value for the throttle setting is zero. When the throttle is set to zero then no limits | |||||
are placed on the number of concurrent scans. In this mode the application must limit the number of | |||||
concurrent scans.</p> | |||||
<dl> | |||||
<dd><b>Threads</b> = The number of concurrent scans allowed.</dd> | |||||
<dd><b>returns</b> the number of Threads if successful otherwise snf_ERROR_EXCEPTION.</dd> | |||||
</dl> | |||||
<hr/> | |||||
<a name="testIP"><h3>int testIP(unsigned long int IPToCheck);</h3></a> | |||||
<p>This function tests an IP against the GBUdb. This function returns very quickly and can be called | |||||
as often as required without any follow-up actions as long as the SNF Engine is active (between startupSNF() | |||||
and shutdownSNF()). This function is thread-safe and does not interfere with other scanning functions.</p> | |||||
<p>GBUdb gathers it's statistics based on the message scans that are performed. Information about those | |||||
scans is also shared with other SNF nodes approximately once every minute. No external queries are | |||||
performed to gather GBUdb data. As a result GBUdb can only provide an IP reputation for IPs that sourced | |||||
messages scanned by this SNF node.</p> | |||||
<p>Put another way - GBUdb does not work like a conventional real-time black list. Message scans must | |||||
be performed in order for GBUdb to provide IP reputation information.</p> | |||||
<p>For more information on how GBUdb works visit the | |||||
<a href="http://www.armresearch.com/support/articles/technology/GBUdb/index.jsp"> | |||||
GBUdb Technology section of our web site.</a></p> | |||||
<dl> | |||||
<dd><b>IPToCheck</b> = The IP to test.</dd> | |||||
<dd><b>returns</b> an integer representing the GBUdb Range associated with the IP if successful | |||||
otherwise snf_ERROR_EXCEPTION.</dd> | |||||
</dl> | |||||
<h4>GBUdb Range MNemonics from enum snfIPRange</h4> | |||||
<dl> | |||||
<dd>Unknown, snf_IP_Unknown = 0</dd> | |||||
<dd>White, snf_IP_White = 1</dd> | |||||
<dd>Normal, snf_IP_Normal = 2</dd> | |||||
<dd>New, snf_IP_New = 3</dd> | |||||
<dd>Caution, snf_IP_Caution = 4</dd> | |||||
<dd>Black, snf_IP_Black = 5</dd> | |||||
<dd>Truncate, snf_IP_Truncate = 6</dd> | |||||
</dl> | |||||
<hr/> | |||||
<a name="getIPReputation"><h3>double getIPReputation(unsigned long int IPToCheck);</h3></a> | |||||
<p>This function returns a number representing the overall reputation of the IP based on local GBUdb statistics. | |||||
This number (Reputation Figure) can be easily manipulated to provide additional weight values in systems that combine | |||||
multiple tests using a weight based scoring system. The Reputation Figure is calculated by combining the Probability figure and the Confidence figure using the formula:</p> | |||||
<pre>R = sign(P) * sqrt(abs(P * C))</pre> | |||||
<p>This function returns very quickly and can be called as often as required without any follow-up actions as long | |||||
as the SNF Engine is active (between startupSNF...() and shutdownSNF()). This function is thread-safe and does not interfere with other scanning functions.</p> | |||||
<dl> | |||||
<dd><b>IPToCheck</b> = The IP to test.</dd> | |||||
<dd><b>returns</b> a number between -1.0 and +1.0 representing the combined probability that the IP will produce spam.</dd> | |||||
</dl> | |||||
<h4>Converting IP Reputation Figures To Weights</h4> | |||||
<p>There are a number of ways to convert a Reputation figure to a weight value. The simplest is to simply multiply | |||||
the Reputation figure by the maximum weight you wish to give to this test.</p> | |||||
<pre>SimpleWeight = R * MaxReputationWeight</pre> | |||||
<p>Since many legitimate ISPs also produce a lot of spam it might be useful to apply a bias to this weight so that | |||||
these systems appear closer to zero. For example if you applied a maximum weight of 10 and found that many ISPs | |||||
regularly scored 5 or more then you might add a Bias of -5 to bring those systems toward zero.</p> | |||||
<pre>BiasedWeight = (R * MaxReputationWeight) + Bias</pre> | |||||
<p>A more sophisticated system might allow for different weights on the positive and negative going Reputation | |||||
figures so that the amount of negative or positive weight that can be applied can be adjusted independently. Such | |||||
a system might also wish to apply a bias directly to the reputation figure before doing that calculation so that | |||||
the zero point can be adjusted to compensate for averages.</p> | |||||
<p>In a system like this if legitimate ISPs tended to get a Reputation Figure of 0.5 then the bias might be -0.5 | |||||
so that this would become the zero point. Then the positive and negative weight factors could be adjusted so that | |||||
the desired maximum and minimum weights can be achieved... Note that in this scenario the positive and negative | |||||
weight settings are not maximum values. | |||||
<pre>SplitWeight = (0 > (R + Bias)) ? ((R + Bias) * NegativeWeightFactor) : ((R + Bias) * PositiveWeightFactor) | |||||
MaximumNegativeWeight is given by (-1.0 + Bias) * NegativeWeightFactor | |||||
MaximumPositiveWeight is given by (+1.0 + Bias) * PositiveWeightFactor | |||||
When R + Bias == 0.0, the weight will be 0.</pre> | |||||
<p>The most sophisticated system might provide a graphic interface that maps the reputation figure directly | |||||
to a desired weight. This would allow the user to shape the effect of the Reputation figure any way they wish in | |||||
order to gain very tight control over their systems accuracy.</p> | |||||
<hr/> | |||||
<a name="scanBuffer"><h3>int scanBuffer(unsigned char* Bfr, int Length, char* Name, int Setup);</h3></a> | |||||
<p>This function scans an SMTP message from a buffer. A scan result block is allocated for the scan | |||||
and a handle representing the scan result block is returned. The application can then use this handle to retrieve | |||||
the scan results using the get...() functions. When the application is finished it MUST release the | |||||
scan result block with a call to closeScan().</p> | |||||
<p>The message buffer is expected to contain the raw SMTP data for the message with the local Received: | |||||
header at the top. The message should not be broken into MIME segments before it is scanned by SNFMulti. | |||||
This is important because Message Sniffer examines the entire message as well as how the message was | |||||
assembled by the originating system. Any additional processing is both unnecessary and may remove subtle | |||||
defects and artifacts that will help Message Sniffer classify the message.</p> | |||||
<p>If the message is particularly large it is acceptable to scan only the first 32K bytes of the message. | |||||
This means that if the calling application wants to scan a large incoming message before it has received | |||||
all of the DATA during the SMTP connection then it can scan the first 32K of the message and potentially | |||||
reject the remainder based on the scan result.</p> | |||||
<p>When the application is finished with the results from this scan it must release the scan result block | |||||
with a call to closeScan(). Scan result blocks are allocated as needed and then recycled in order to improve | |||||
performance. If the application fails to close the scan result blocks then the DLL will continue to | |||||
allocate additional blocks until there is no more RAM.</p> | |||||
<p>The entire scan is performed before this function returns. After that the scanning thread is no longer | |||||
considered to be active. The resulting scan result buffer may be accessed as often as needed to gather | |||||
results data from this scan without impacting any other scan operations.</p> | |||||
<p>Any number of scan...() operations may be active concurrently up to the limits of the platform.</p> | |||||
<p>The scanBuffer() function accepts two additional parameters that are passed on to the logging system | |||||
to aid in debugging.</p> | |||||
<p>The Name parameter is a null terminated string containing an identifier for the | |||||
message being scanned. This can be any name that can be used later to identify this particular message | |||||
in the log files such as a serial number, unique hash, or the message-id. For example, when the | |||||
scanFile() function is called this parameter is filled in with the path to the file that was scanned.</p> | |||||
<p>The Setup parameter is an integer representing the number of milliseconds spent so far setting up | |||||
the message to be scanned. This can be any useful metric - but generally it should represent how much | |||||
time the system has spent working on preparing and evaluating the message so far. For example, when the | |||||
scanFile() function is called this value is automatically established with the amount of time spent | |||||
opening and reading the message file.</p> | |||||
<p><b>IMPORTANT:</b> SNF expects to identify the source IP for the message by searching Received: headers | |||||
in the message. The application must ensure that the local Received: header is present as the first | |||||
Received: header in the message in order for this search to be accurate. If necessary the calling application can | |||||
simulate the local received header using the following minimal form:</p> | |||||
<p><pre>Received: from connecting.mta.example.com [12.34.56.78] by this.scanning.system</pre></p> | |||||
<p>where <b><i>connecting.mta.example.com</i></b> is the optional reverse DNS resolved for the connecting MTA; | |||||
<b><i>12.34.56.78</i></b> is the IP of the connecting MTA; and <b><i>by this.scanning.system</i></b> is an optional | |||||
reference to the calling application.</p> | |||||
</font><dl> | |||||
<dd><font face="sans-serif"><b>Bfr</b> = a pointer to the buffer that is to be scanned.</font></dd> | |||||
<dd><font face="sans-serif"><b>Length</b> = the length of the message buffer in bytes.</font></dd> | |||||
<dd><font face="sans-serif"><b>Name</b> = a message identifier as a null terminated string.</font></dd> | |||||
<dd><font face="sans-serif"><b>Setup</b> = the time in milliseconds already spent setting up this message for scanning.</font></dd> | |||||
<dd><font face="sans-serif"><b>returns</b> a handle to the scan result block upon success otherwise an error code: | |||||
</font><dl> | |||||
<dd><font face="sans-serif">snf_ERROR_NO_HANDLE - There was a problem allocating a scan result block.</font></dd> | |||||
<dd><font face="sans-serif">snf_ERROR_SCAN_FAILED - There was a problem performing the scan.</font></dd> | |||||
</dl> | |||||
<p><font face="sans-serif">In general a result > 0 indicates a valid scan handle and a result <= 0 indicates an error. | |||||
NOTE that the scan may have failed even if you get a valid handle. The scan result code you retrieve | |||||
from get...() may indicate an error. <a href="#ResultCodes">See Result Codes</a> for details.</font></p> | |||||
</dd> | |||||
</dl><font face="sans-serif"> | |||||
<hr/> | |||||
<a name="scanFile"><h3>int scanFile(char* FilePath, int Setup);</h3></a> | |||||
<p>This function scans an SMTP message from a file. A scan result block is allocated for the scan | |||||
and a handle representing the results is returned. The application can then use this handle to retrieve | |||||
the scan results using the get...() functions. When the application is finished it MUST release the | |||||
scan result block with a call to closeScan().</p> | |||||
<p>The scanFile() function is nearly identical to the <a href="#scanBuffer">scanBuffer() function (see above)</a> | |||||
except that this function accepts the path to a file (null terminated string) instead of a pointer to a message | |||||
buffer.</p> | |||||
<p>One other key difference with between scanBuffer() and scanFile() is that the SNF engine can be configured | |||||
to inject it's X- headers when scanFile() is used. These same X- headers are available to the calling application | |||||
when using scanBuffer(), however if the application wishes to pass the message file on to other additional | |||||
scanners and external processes then scanFile() might be more convenient.</p> | |||||
<p>NOTE: There are significant performance implications to scanning files and injecting headers. Each time | |||||
headers are injected into a message the message file must be rewritten. For optimal performance it is best | |||||
to collect headers from scanning tools before writing the message to disk so that the message only needs to | |||||
be written once. Extra file IO is the cost of the convenience of passing a message file to external processes.</p> | |||||
<p>The Setup time passed to scanFile() will be added to the time required to open and read the message file | |||||
prior to scanning. This value will be passed on to the logging system. For example, the calling application | |||||
might include the number of milliseconds required to perform any previous message testing and the time it | |||||
has taken to create a temporary message file for scanning. The log will then reflect the complete setup time | |||||
separately from the time required to perform the SNF message scan.</p> | |||||
<p>The FilePath will be passed on to the logging system to identify this message scan in the logs.</p> | |||||
</font><dl> | |||||
<dd><font face="sans-serif"><b>FilePath</b> = The full path (a null terminated string) to the message file to be scanned.</font></dd> | |||||
<dd><font face="sans-serif"><b>Setup</b> = The time in milliseconds spent so far preparing this message to be scanned.</font></dd> | |||||
<dd><font face="sans-serif"><b>returns</b> a handle to the scan result block upon success otherwise an error code: | |||||
</font><dl> | |||||
<dd><font face="sans-serif">snf_ERROR_NO_HANDLE - There was a problem allocating a scan result block.</font></dd> | |||||
<dd><font face="sans-serif">snf_ERROR_SCAN_FAILED - There was a problem performing the scan.</font></dd> | |||||
</dl> | |||||
<p><font face="sans-serif">In general a result > 0 indicates a valid scan handle and a result <= 0 indicates an error. | |||||
NOTE that the scan may have failed even if you get a valid handle. The scan result code you retrieve | |||||
from get...() may indicate an error. <a href="#ResultCodes">See Result Codes</a> for details.</font></p> | |||||
</dd> | |||||
</dl><font face="sans-serif"> | |||||
<hr/> | |||||
<a name="getScanXHeaders"><h3>int getScanXHeaders(int ScanHandle, char** Bfr, int* Length);</h3></a> | |||||
<p>This function returns the scan result code <a href="#ResultCodes">(see Result Codes)</a> and a pointer | |||||
to a buffer containing any X- headers that were produced for the scan associated with the ScanHandle.</p> | |||||
<p>The function is passed a valid ScanHandle which identifies the scan result block to query; the address of | |||||
a char* which will be changed to point to a buffer containing any X- headers that | |||||
were produced; and the address of an integer which will be changed to the length of the | |||||
X- headers buffer.</p> | |||||
<p>If no X- headers were produced for the scan then the pointer Bfr will point to a safe empty string | |||||
and Length will be set to zero. Put another way, Bfr and Length will be consistent with an empty null terminated | |||||
string.</p> | |||||
<p>The char* Bfr and the int Length will remain valid until closeScan() is called for this ScanHandle.</p> | |||||
<p>In order for X- headers to be produced the engine must be configured properly. For details visit the | |||||
<a href="http://www.armresearch.com/support/articles/software/snfServer/config/node/logs/scan/xheaders/index.jsp"> | |||||
XHeader configuration documentation</a> on our web site.</p> | |||||
<dl> | |||||
<dd><b>ScanHandle</b> = a valid scan handle from scanBuffer() or scanFile().</dd> | |||||
<dd><b>Bfr</b> = a pointer to a char* where the char* will be changed to point to the XHeaders.</dd> | |||||
<dd><b>Length</b> = a pointer to an int where the int will be changed to the length of the XHeaders.</dd> | |||||
<dd><b>returns</b> the scan result code upon success otherwise an error code: | |||||
<dl> | |||||
<dd>snf_ERROR_NO_HANDLE - The ScanHandle is not valid.</dd> | |||||
<dd>snf_ERROR_EXCEPTION - There was a problem retrieving the data.</dd> | |||||
<dd><a href="#ResultCodes">See Result Codes</a> for other possible return values.</dd> | |||||
</dl> | |||||
</dd> | |||||
</dl> | |||||
<hr/> | |||||
<a name="getScanXMLLog"><h3>int getScanXMLLog(int ScanHandle, char** Bfr, int* Length);</h3></a> | |||||
<p>This function returns the scan result code <a href="#ResultCodes">(see Result Codes)</a> and a pointer | |||||
to a buffer containing any XML Log Data that was produced for the scan associated with the ScanHandle.</p> | |||||
<p>The function is passed a valid ScanHandle which identifies the scan result block to query; the address of | |||||
a char* which will be changed to point to a buffer containing any XML Log Data that | |||||
was produced; and the address of an integer which will be changed to the length of the | |||||
XML Log Data buffer.</p> | |||||
<p>If no XML Log Data was produced for the scan then the pointer Bfr will point to a safe empty string | |||||
and Length will be set to zero. Put another way, Bfr and Length will be consistent with an empty null terminated | |||||
string.</p> | |||||
<p>The char* Bfr and the int Length will remain valid until closeScan() is called for this ScanHandle.</p> | |||||
<p>In order for XML Log Data to be produced the engine must be configured properly. For details visit the | |||||
<a href="http://www.armresearch.com/support/articles/software/snfServer/config/node/logs/scan/xml.jsp"> | |||||
XML Log configuration documentation</a> on our web site.</p> | |||||
<dl> | |||||
<dd><b>ScanHandle</b> = a valid scan handle from scanBuffer() or scanFile().</dd> | |||||
<dd><b>Bfr</b> = a pointer to a char* where the char* will be changed to point to the XML Log Data.</dd> | |||||
<dd><b>Length</b> = a pointer to an int where the int will be changed to the length of the XML Log Data.</dd> | |||||
<dd><b>returns</b> the scan result code upon success otherwise an error code: | |||||
<dl> | |||||
<dd>snf_ERROR_NO_HANDLE - The ScanHandle is not valid.</dd> | |||||
<dd>snf_ERROR_EXCEPTION - There was a problem retrieving the data.</dd> | |||||
<dd><a href="#ResultCodes">See Result Codes</a> for other possible return values.</dd> | |||||
</dl> | |||||
</dd> | |||||
</dl> | |||||
<hr/> | |||||
<a name="getScanClassicLog"><h3>int getScanClassicLog(int ScanHandle, char** Bfr, int* Length);</h3></a> | |||||
<p>This function returns the scan result code <a href="#ResultCodes">(see Result Codes)</a> and a pointer | |||||
to a buffer containing any Classic Log Data that was produced for the scan associated with the ScanHandle.</p> | |||||
<p>The function is passed a valid ScanHandle which identifies the scan result block to query; the address of | |||||
a char* which will be changed to point to a buffer containing any Classic Log Data that | |||||
was produced; and the address of an integer which will be changed to the length of the | |||||
Classic Log Data buffer.</p> | |||||
<p>If no Classic Log Data was produced for the scan then the pointer Bfr will point to a safe empty string | |||||
and Length will be set to zero. Put another way, Bfr and Length will be consistent with an empty null terminated | |||||
string.</p> | |||||
<p>The char* Bfr and the int Length will remain valid until closeScan() is called for this ScanHandle.</p> | |||||
<p>In order for XML Log Data to be produced the engine must be configured properly. For details visit the | |||||
<a href="http://www.armresearch.com/support/articles/software/snfServer/config/node/logs/scan/classic.jsp"> | |||||
Classic Log configuration documentation</a> on our web site.</p> | |||||
<dl> | |||||
<dd><b>ScanHandle</b> = a valid scan handle from scanBuffer() or scanFile().</dd> | |||||
<dd><b>Bfr</b> = a pointer to a char* where the char* will be changed to point to the Classic Log Data.</dd> | |||||
<dd><b>Length</b> = a pointer to an int where the int will be changed to the length of the Classic Log Data.</dd> | |||||
<dd><b>returns</b> the scan result code upon success otherwise an error code: | |||||
<dl> | |||||
<dd>snf_ERROR_NO_HANDLE - The ScanHandle is not valid.</dd> | |||||
<dd>snf_ERROR_EXCEPTION - There was a problem retrieving the data.</dd> | |||||
<dd><a href="#ResultCodes">See Result Codes</a> for other possible return values.</dd> | |||||
</dl> | |||||
</dd> | |||||
</dl> | |||||
<hr/> | |||||
<a name="getScanResult"><h3>int getScanResult(int ScanHandle);</h3></a> | |||||
<p>This function returns the scan result code <a href="#ResultCodes">(see Result Codes)</a> | |||||
for the scan associated with the ScanHandle.</p> | |||||
<dl> | |||||
<dd><b>ScanHandle</b> = a valid scan handle from scanBuffer() or scanFile().</dd> | |||||
<dd><b>returns</b> the scan result code upon success otherwise an error code: | |||||
<dl> | |||||
<dd>snf_ERROR_NO_HANDLE - The ScanHandle is not valid.</dd> | |||||
<dd><a href="#ResultCodes">See Result Codes</a> for other possible return values.</dd> | |||||
</dl> | |||||
</dd> | |||||
</dl> | |||||
<hr/> | |||||
<a name="closeScan"><h3>int closeScan(int ScanHandle);</h3></a> | |||||
<p>This function closes a ScanHandle and releases the associated Scan Result Block to the pool. This | |||||
function MUST be called once for each ScanHandle produced in a scan...() function. Once this function | |||||
is called the ScanHandle is no longer valid and any pointers returned by previous | |||||
calls to get...() functions should be discarded (forgotten, not freed!)</p> | |||||
<dl> | |||||
<dd><b>ScanHandle</b> = a valid scan handle from scanBuffer() or scanFile().</dd> | |||||
<dd><b>returns:</b> | |||||
<dl> | |||||
<dd>snf_SUCCESS - The ScanHandle was closed successfully.</dd> | |||||
<dd>snf_ERROR_NO_HANDLE - The ScanHandle is not valid.</dd> | |||||
<dd>snf_ERROR_EXCEPTION - There was a problem closing the ScanHandle.</dd> | |||||
</dl> | |||||
</dd> | |||||
</dl> | |||||
<hr/> | |||||
<a name="shutdownSNF"><h3>int shutdownSNF();</h3></a> | |||||
<p>This function shuts down the SNFMulti engine. All previously allocated ScanHandles MUST be closed | |||||
before this function is called. This should be the last function in the DLL that is called by your | |||||
application (call no other SNFMultiDLL functions after this).</p> | |||||
<dl> | |||||
<dd><b>returns:</b> | |||||
<dl> | |||||
<dd>snf_SUCCESS - The shutdown was successful.</dd> | |||||
<dd>snf_ERROR_EXCEPTION - An error occurred during shutdown.</dd> | |||||
</dl> | |||||
</dd> | |||||
</dl> | |||||
<hr/> | |||||
<a name="ResultCodes"><h3>Result Codes</h3></a> | |||||
<h4>Error Codes</h4> | |||||
</font><dl> | |||||
<dd><font face="sans-serif">snf_SUCCESS = 0</font></dd> | |||||
<dd><font face="sans-serif">snf_ERROR_CMD_LINE = 65</font></dd> | |||||
<dd><font face="sans-serif">snf_ERROR_LOG_FILE = 66</font></dd> | |||||
<dd><font face="sans-serif">snf_ERROR_RULE_FILE = 67</font></dd> | |||||
<dd><font face="sans-serif">snf_ERROR_RULE_DATA = 68</font></dd> | |||||
<dd><font face="sans-serif">snf_ERROR_RULE_AUTH = 73</font></dd> | |||||
<dd><font face="sans-serif">snf_ERROR_MSG_FILE = 69</font></dd> | |||||
<dd><font face="sans-serif">snf_ERROR_ALLOCATION = 70</font></dd> | |||||
<dd><font face="sans-serif">snf_ERROR_BAD_MATRIX = 71</font></dd> | |||||
<dd><font face="sans-serif">snf_ERROR_MAX_EVALS = 72</font></dd> | |||||
<dd><font face="sans-serif">snf_ERROR_UNKNOWN = 99</font></dd> | |||||
<font face="sans-serif"><br/> | |||||
<dd>snf_ERROR_NO_HANDLE = -1, Invalid scan handle used or created.</dd></font> | |||||
<dd><font face="sans-serif">snf_ERROR_SCAN_FAILED = -2, An unexpected exception during a scan. </font></dd> | |||||
<dd><font face="sans-serif">snf_ERROR_EXCEPTION = -3, An unexpected exception occurred.</font></dd> | |||||
</dl><font face="sans-serif"> | |||||
<p> | |||||
<a href="http://www.armresearch.com/support/articles/software/snfServer/errors.jsp"> | |||||
See our web site for more detailed descriptions of these error codes.</a></p> | |||||
<h4>Scan Result Codes</h4> | |||||
<p>Scan results codes 0 through 63 represent normal scan results. By convention a result of | |||||
0 indicates ham (not spam); a result of 1 indicates a white-ruled message; and other non-zero | |||||
result values that are less than 64 indicate some kind of spam or malware was detected. | |||||
<a href="http://www.armresearch.com/support/articles/software/snfServer/core.jsp"> | |||||
For more details on message scan result codes please see our web site.</a></p> | |||||
<hr/> | |||||
<div align="right"><font size="-3">Copyright (C) 2009 ARM Research Labs, LLC</font></div> | |||||
</font> | |||||
</body> | |||||
</html> |
SNFClient Readme | |||||
Copyright (c) 2010 ARM Research Laboratories | |||||
Command line client for SNF. This utility formats and processes SNF_XCI | |||||
requests through the SNF Engine working on the local machine. In general | |||||
this utility can be used as a replacement for the earlier SNF command | |||||
line scanner. It is also useful for other uses such as debugging and | |||||
communicating with GBUdb. | |||||
Note: Unlike prior versions of SNF, this command line utility does not | |||||
need to be "branded" (renamed for the SNF license id). | |||||
_________ | |||||
Help Mode | |||||
SNFClient.exe | |||||
When called with no command line parameters the utility produces | |||||
help and version information. | |||||
__________ | |||||
Debug Mode | |||||
SNFDebugClient.exe | |||||
When "debug" or "Debug" appears in the path to the program name | |||||
or if the program's name is altered to include the word "debug" or | |||||
"Debug" then the program will produce additional information about | |||||
it's operation to aid in debugging problems. This includes the | |||||
entire raw SNF_XCI request and response. | |||||
__________________ | |||||
Message Scan Modes | |||||
These modes are used to scan email message files (the data part of | |||||
smtp). This utility can be used as a drop-in replacement for previous | |||||
verions of SNF (Message Sniffer) for scanning messages. However, this | |||||
new version does not need to be "branded" (renamed for the license id) | |||||
and will ignore the authentication string if it is provided. Also, | |||||
since the newer version of SNF uses a client-server model and not a | |||||
peer-server model, there is no need for a "persistent" mode. | |||||
If "persistent" is passed to this utility on the command line as it | |||||
would be used in prior versions of SNF then it will be treated like | |||||
a file name and the scan will normally fail since a file named | |||||
"persistent" is not likely to exist. | |||||
SNFClient.exe <FileNameToScan> | |||||
Scan Mode: Scans <FileNameToScan> and returns a result code. | |||||
SNFClient.exe <authenticationxx> <FileNameToScan> | |||||
Compatibility Mode: Ignores <authenticationxx> then scans the | |||||
<FileNameToScan> and returns a result code. This mode provides | |||||
drop-in compatibility with previous versions of SNF. | |||||
SNFClient.exe -xhdr <FileNameToScan> | |||||
XHeader Mode: Scans <FileNameToScan> and returns the result. Also | |||||
outputs the contents of the X-Headers created by the SNF engine. If | |||||
the SNF engine is configured to inject these headers then they will | |||||
also have been injected into the <FileNameToScan>. | |||||
The SNF Engine can be configured to provide the X-Headers only to | |||||
the API without injecting them. In this case the XHeader Mode will | |||||
display the X-Headers that would be injected, but they will not | |||||
have been injected into the <FileNameToScan>. | |||||
If the SNF Engine is configured not to produce X-Headers (none) then | |||||
the XHeader Mode will not produce X-Headers because they will not | |||||
have been generated by the engine. | |||||
(note: -xhdr and -source options can be combined) | |||||
SNFClient.exe -source=<IP4Address> <FileNameToScan> | |||||
Source-IP Mode: Scans <FileNameToScan> and returns the result. The | |||||
provided source IP is injected into the scan as the first Received | |||||
header so that the scanning engine will presume the IP is the source | |||||
of the message. This allows you to pre-define the source IP for the | |||||
message when there is no other received header or when the received | |||||
headers may be incorrect or may not present the actual source of | |||||
the message. | |||||
(note: -xhdr and -source options can be combined) | |||||
_____________________________ | |||||
SNFServer Status Report Modes | |||||
SNFClient.exe -status.second | |||||
SNFClient.exe -status.minute | |||||
SNFClient.exe -status.hour | |||||
This mode returns the latest posted status report as indicated. | |||||
Normally these status reports are also posted to files in the | |||||
SNFServer workspace. | |||||
In this mode the SNFClient will return a result code (error level) | |||||
of 0 when the request is successful and 99 (or some nonzero value) | |||||
when the request is not successful. This allows the SNFClient to | |||||
be used to verify that the SNFServer is running. | |||||
Note: In most other modes the SNFClient returns a fail-safe 0 | |||||
result code to avoid tagging messages as spam when there are errors. | |||||
________________________ | |||||
XCI Server Command Modes | |||||
These features will expand as needed in later versions. | |||||
SNFClient.exe -shutdown | |||||
If the SNF Engine is running in an application that accepts SNF_XCI | |||||
server commands then this mode will send that command. The shutdown | |||||
command may have no effect if the application does not use the SNF_XCI | |||||
server commnand interface or does not recognize the command. | |||||
___________ | |||||
GBUdb Modes | |||||
These modes are used to communicate with the GBUdb system on the | |||||
local node. It is possible to test (read out) an IP record or make | |||||
any of a number of changes to IP data in the GBUdb. | |||||
SNFClient.exe -test <IP4Address> | |||||
Returns the current GBUdb statistics for the <IP4Address> | |||||
SNFClient also returns a result code that matches the GBUdb range | |||||
for the tested IP. These ranges are defined in the SNFServer | |||||
configuration file. By default they are: | |||||
20 - Truncate | |||||
63 - Black | |||||
40 - Caution | |||||
0 - Normal | |||||
SNFClient.exe -set <IP4Address> <flag> <bad> <good> | |||||
Creates or updates the data for <IP4Address> as provided. The | |||||
<IP4Address> must be provided as well as at least one of | |||||
<flag>, <bad>, and <good>. If <flag>, <bad>, or <good> are | |||||
to be left unchanged then they should be entered as a dash "-". | |||||
Examples: | |||||
Set all data for an IP. The flag will be "ugly", the bad count | |||||
will be 0 and the good count will be 1000. | |||||
SNFClient.exe -set 12.34.56.78 Ugly 0 1000 | |||||
Set the flag to "ignore" and do not change the counts. | |||||
SNFClient.exe -set 12.34.56.78 ignore - - | |||||
Set the good count to 400 and do not change anything else. | |||||
SNFClient.exe -set 12.34.56.78 - - 400 | |||||
SNFClient.exe -good <IP4Address> | |||||
Creates or updates statistics for the <IP4Address>. Increases the | |||||
good count by one. (Record a good event) | |||||
SNFClient.exe -bad <IP4Address> | |||||
Creates or updates statistics for the <IP4Address>. Increases the | |||||
bad count by one. (Record a bad event) | |||||
SNFClient.exe -drop <IP4Address> | |||||
Removes all local data for the <IP4Address>. Anything the local | |||||
system "knows" about the IP is forgotten. Next time the IP is | |||||
encountered it will be treated as new. | |||||
____________________ | |||||
For More Information | |||||
See www.armresearch.com | |||||
Copyright (C) 2007-2008 Arm Research Labs, LLC. | |||||
SNF_Server V3.0 installation brief | |||||
Copyright (c) 2010 ARM Research Laboratories | |||||
This is a generalized guide. For specific platform guides see: | |||||
http://www.armresearch.com/support/articles/installation/index.jsp | |||||
Create a directory for SNF_Server. ( c:\SNF or /var/spool/snfilter ) | |||||
Copy all of the files to that directory. | |||||
Make a copy of the SNFServer<version>.exe file and give it the name | |||||
SNFServer.exe. Later on if newer versions are provided you will | |||||
be able to keep track of them by name and swap newer versions into | |||||
place by copying them over your SNFServer.exe file. If you decide | |||||
you have to go back to a previous version then you will be able to | |||||
do that easily by deleting your SNFServer.exe file and copying the | |||||
version you wish to use into place. | |||||
Modify the identity.xml file to match your SNF license ID and your | |||||
authentication string. | |||||
Download your .snf file and place that in the SNF_Server working | |||||
directory. | |||||
RULEBASE UPDATES (NEW!): The latest version of the SNFServer engine | |||||
includes a mechanism that will run an a script when the rulebase file | |||||
on our server is newer than the active file in SNF. By default this | |||||
feature is configured to run the included getRulebase script. If | |||||
the script is not successful it will be launched again every 3 minutes | |||||
until the rulebase file is successfully updated. | |||||
Be sure to modify the top of the getRulebase script to include | |||||
your correct license ID, authentication string, and working directory. | |||||
Be sure to verify that the <update-script/> section of your snf_engine | |||||
file is correct (points to the correct location of getRulebase). | |||||
getRulebase uses wget and gzip (included for your convenience in | |||||
the Win* distribution. See About-Wget-and-Gzip.txt.). These are open | |||||
source utilities for downloading files from web servers and unzipping | |||||
those files -- in this case, SNF rulebase files. | |||||
If you have any gateways or other internal systems that will relay | |||||
mail to SNF then include their IPs in GBUdbIgnoreList.txt. The GBUdb | |||||
component of SNF uses the IPs in this list to determine the actual | |||||
source IP for a message by reviewing the Received headers. Each | |||||
Received header is evaluated in turn. If the source (connect) IP is | |||||
found in the Ignore list then that Received IP is considered to be | |||||
part of your infrastructure and is ignored. The first Received IP | |||||
found that is NOT in the Ignore list is selected as the source IP. | |||||
The GBUdbIgnoreList is a "safety net" that ensures the listed IPs are | |||||
present in your GBUdb with their Ignore flag set. It is loaded every | |||||
time the configuration is changed, SNFServer is started, or a new | |||||
rulebase is loaded. This way if your GBUdb database is lost then your | |||||
critical infrastructure will be re-listed in the new .gbx file that | |||||
is created. | |||||
The ignore list allows only SINGLE IP ENTRIES. This can be a problem | |||||
in some cases - such as when you want to ignore large blocks of network | |||||
addresses. | |||||
SNF can learn to Ignore large blocks of IPs using the <drilldown/> | |||||
feature. For example if you want to ignore all of 12.34.56.0/24 then | |||||
you can make an entry in the <drilldown/> training section like this: | |||||
<training on-off='on'> | |||||
... | |||||
<drilldown> | |||||
<received ordinal='0' find='[12.34.56.'/> | |||||
</drilldown> | |||||
... | |||||
</training> | |||||
GBUdb learns the behavior of source IPs so it is important that GBUdb | |||||
knows any friendly sources that might send spammy messages to your | |||||
server or else it will learn that those sources are not to be trusted. | |||||
Since not all friendly spam sources can be identified by IP ahead of | |||||
time, there are features in the <training/> section of snf_engine.xml | |||||
that allow you to adjust the training scenarios to compensate. The | |||||
most likely of these is that you may wish to bypass training for | |||||
messages that are to your support addresses or spam submission | |||||
addresses. For example: | |||||
<training on-off='on'> | |||||
... | |||||
<bypass> | |||||
<header name='To:' find='support@example.com'/> | |||||
<header name='To:' find='spam@example.com'/> | |||||
</bypass> | |||||
... | |||||
</training> | |||||
Evaluate the snf_engine.xml file carefully. In most cases the | |||||
default settings are appropriate, however you may want to alter | |||||
some of the settings to match your system policies or particular | |||||
installation. | |||||
IMPORTANT: Be sure that any file paths / directories referenced in | |||||
the configuration file exist on your system and that SNF has full | |||||
access rights to these - especially the SNF working directory. | |||||
** If you selected a working directory for SNF other than c:\SNF\ | |||||
then be sure you have changed these paths in the top of your | |||||
snf_engine.xml file. Pay close attentiont to these 5 elements: | |||||
<node identity='c:/SNF/identity.xml'> | |||||
<log path='c:/SNF/'/> | |||||
<rulebase path='c:/SNF/'/> | |||||
<workspace path='c:/SNF/'/> | |||||
<update-script ... call='c:/SNF/getRulebase.cmd' ... /> | |||||
Once you are happy with your configuration and you have all of your | |||||
files and directories in place (including your .snf file) then you | |||||
can start SNF_Server. | |||||
The command line (from inside the SNF workspace) is: | |||||
SNFServer.exe snf_engine.xml | |||||
That is: SNFServer <configuration> | |||||
If you want to lauch SNFServer from some other location it would be | |||||
best to use the entire path for both the SNFServer engine and the | |||||
configuration file: | |||||
c:\SNF\SNFServer.exe c:\SNF\snf_engine.xml | |||||
You should begin by testing SNFServer by running it in a command line | |||||
window where you can watch it's output. | |||||
Once you are happy with it then you will probably want to run it as | |||||
a service using a utility such as the srvany utility from the win2k | |||||
toolkit, or detached as a daemon on *nix systems (snfctrl file example | |||||
included). | |||||
This section of our site might be helpful: | |||||
http://www.armresearch.com/support/articles/installation/serviceSetup/index.jsp | |||||
SNFServer is the server side of a client/server system. In order to | |||||
scan messages you will need to use the client utility (SNFClient.exe | |||||
or SNFIMailShim.exe) to scan messages. | |||||
SNFClient.exe is a drop-in replacement for the production (2-3.x) | |||||
SNF program when it is called from Declude or mxGuard or other similar | |||||
software. There is no need to "brand" the SNFClient.exe | |||||
program and it is not necessary to include the authentication string | |||||
on the command line -- however, if you do it will be accepted and | |||||
ignored without an error. | |||||
SNFServer MUST be running for SNFClient to work. If SNFClient cannot | |||||
reach SNFServer then it will wait for quite a while as it attempts to | |||||
make contact. | |||||
Here are a few ways to call SNFClient.exe: | |||||
SNFClient.exe -shutdown | |||||
Sends the Shutdown command to the SNF_Server. | |||||
SNFClient.exe authenticationxx filetoscan | |||||
Compatibility mode - ignores authenticationxx and scans filetoscan. | |||||
SNFClient.exe filetoscan | |||||
Normal scan mode - scans filetoscan. | |||||
SNFClient.exe -xhdr filetoscan | |||||
XHDR scan mode - scans filetoscan and returns X Headers. | |||||
See the SNFClient_Readme.txt file for details. | |||||
The SNF Client/Server pair communicate using short XML messages via a local | |||||
TCP connection (typically to port 9001). Examples of SNF_XCI messages are | |||||
included in snf_xci.xml (not a well formed xml file! - just some examples). | |||||
It is possible to communicate directly with the SNF_Server engine via TCP | |||||
from your software using the SNF_XCI (SNF XML Command Interface) protocol. The | |||||
server expects to see one connection per request. The client sends an SNF_XCI | |||||
request to the server. The server responds with an appropriate SNF_XCI | |||||
formatted response and terminates the connection. | |||||
Requests and responses are expected to terminate with a newline character. | |||||
You can see the XCI protocol at work by running the SNFClient in debug mode | |||||
(SNFdebugClient). | |||||
If you run into trouble check out our web site: www.armresearch.com and/or | |||||
contact us by email: support@armresearch.com | |||||
____________________ | |||||
For More Information | |||||
See www.armresearch.com | |||||
Copyright (C) 2007-2008 Arm Research Labs, LLC. |
@ECHO OFF | |||||
SETLOCAL | |||||
REM ----- Edit This Section -------- | |||||
SET SNIFFER_PATH=c:\SNF | |||||
SET AUTHENTICATION=authenticationxx | |||||
SET LICENSE_ID=licensid | |||||
REM -------------------------------- | |||||
CD /d %SNIFFER_PATH% | |||||
echo Running SNF getRulebase.cmd > getRulebase.txt | |||||
if not exist UpdateReady.txt echo No UpdateReady.txt >> getRulebase.txt | |||||
if not exist UpdateReady.txt goto DONE | |||||
REM The next line may cause trouble if your system stops while this | |||||
REM script is running. It is not needed when this script is run | |||||
REM from SNF's <update-script/> feature since only one copy will run | |||||
REM at a time. However, if you are going to run a version of this | |||||
REM script as a scheduled task you will want to uncomment the next | |||||
REM line to make sure only one copy runs at a time-- just be sure to | |||||
REM clean out any stale .lck files after a restart. | |||||
REM if exist UpdateReady.lck echo getRulebase.cmd locked/running >> getRulebase.txt | |||||
REM if exist UpdateReady.lck goto DONE | |||||
:DOWNLOAD | |||||
copy UpdateReady.txt UpdateReady.lck > nul | |||||
if exist %LICENSE_ID%.new del %LICENSE_ID%.new | |||||
echo. | |||||
curl -v "http://www.sortmonster.net/Sniffer/Updates/%LICENSE_ID%.snf" -o %LICENSE_ID%.new -s -S -R -z %LICENSE_ID%.snf -H "Accept-Encoding:gzip" --compressed -u sniffer:ki11sp8m 2>> getRulebase.txt | |||||
if %ERRORLEVEL% NEQ 0 del %LICENSE_ID%.new 2> nul | |||||
if not exist %LICENSE_ID%.new echo New rulebase file NOT downloaded >> getRulebase.txt | |||||
if not exist %LICENSE_ID%.new goto CLEANUP | |||||
snf2check.exe %LICENSE_ID%.new %AUTHENTICATION% 2>> getRulebase.txt | |||||
if errorlevel 1 goto CLEANUP | |||||
echo New rulebase file tested OK >> getRulebase.txt | |||||
if exist %LICENSE_ID%.old del %LICENSE_ID%.old | |||||
if exist %LICENSE_ID%.snf rename %LICENSE_ID%.snf %LICENSE_ID%.old | |||||
rename %LICENSE_ID%.new %LICENSE_ID%.snf | |||||
if exist UpdateReady.txt del UpdateReady.txt | |||||
if exist UpdateReady.lck del UpdateReady.lck | |||||
:CLEANUP | |||||
if exist %LICENSE_ID%.new del %LICENSE_ID%.new | |||||
if exist UpdateReady.lck del UpdateReady.lck | |||||
:DONE | |||||
echo Done >> getRulebase.txt | |||||
REM This is a good place to add a line that will email getrulebase.txt to | |||||
REM yourself so that you know what just happened. | |||||
ENDLOCAL |
<!-- Change 'licenseid' and 'xxxxxxxxxxxxxxxx' to match your license info --> | |||||
<snf><identity licenseid='licensid' authentication='authenticationxx'/></snf> | |||||
<!-- SNFMulti V3.0 Configuration File, Setup: Typical of Win* Client / Server --> | |||||
<!-- http://www.armresearch.com/support/articles/software/snfServer/config/snfEngine.jsp --> | |||||
<snf> | |||||
<node identity='c:/SNF/identity.xml'> | |||||
<paths> | |||||
<log path='c:/SNF/'/> | |||||
<rulebase path='c:/SNF/'/> | |||||
<workspace path='c:/SNF/'/> | |||||
</paths> | |||||
<logs> | |||||
<rotation localtime='no'/> | |||||
<status> | |||||
<second log='yes' append='no'/> | |||||
<minute log='yes' append='no'/> | |||||
<hour log='no' append='no'/> | |||||
</status> | |||||
<scan> | |||||
<identifier force-message-id='no'/> | |||||
<classic mode='none' rotate='yes' matches='unique'/> | |||||
<xml mode='file' rotate='yes' matches='all' performance='yes' gbudb='yes'/> | |||||
<xheaders> | |||||
<output mode='none'/> | |||||
<version on-off='off'>X-MessageSniffer-Version</version> | |||||
<license on-off='off'>X-MessageSniffer-License</license> | |||||
<rulebase on-off='off'>X-MessageSniffer-RulebaseUTC</rulebase> | |||||
<identifier on-off='off'>X-MessageSniffer-Identifier</identifier> | |||||
<gbudb on-off='on'>X-GBUdb-Analysis</gbudb> | |||||
<result on-off='off'>X-MessageSniffer-Scan-Result</result> | |||||
<matches on-off='on'>X-MessageSniffer-Rules</matches> | |||||
<black on-off='off'>X-MessageSniffer-Spam: Yes</black> | |||||
<white on-off='off'>X-MessageSniffer-White: Yes</white> | |||||
<clean on-off='off'>X-MessageSniffer-Clean: Yes</clean> | |||||
<symbol on-off='off' n='0'>X-MessageSniffer-SNF-Group: OK</symbol> | |||||
<symbol on-off='off' n='20'>X-MessageSniffer-SNF-Group: Truncated</symbol> | |||||
<symbol on-off='off' n='40'>X-MessageSniffer-SNF-Group: Caution</symbol> | |||||
<symbol on-off='off' n='63'>X-MessageSniffer-SNF-Group: Black</symbol> | |||||
<symbol on-off='off' n='62'>X-MessageSniffer-SNF-Group: Obfuscation</symbol> | |||||
<symbol on-off='off' n='61'>X-MessageSniffer-SNF-Group: Abstract</symbol> | |||||
<symbol on-off='off' n='60'>X-MessageSniffer-SNF-Group: General</symbol> | |||||
<symbol on-off='off' n='59'>X-MessageSniffer-SNF-Group: Casinos-Gambling</symbol> | |||||
<symbol on-off='off' n='58'>X-MessageSniffer-SNF-Group: Debt-Credit</symbol> | |||||
<symbol on-off='off' n='57'>X-MessageSniffer-SNF-Group: Get-Rich</symbol> | |||||
<symbol on-off='off' n='56'>X-MessageSniffer-SNF-Group: Ink-Toner</symbol> | |||||
<symbol on-off='off' n='55'>X-MessageSniffer-SNF-Group: Malware</symbol> | |||||
<symbol on-off='off' n='54'>X-MessageSniffer-SNF-Group: Porn-Dating-Adult</symbol> | |||||
<symbol on-off='off' n='53'>X-MessageSniffer-SNF-Group: Scam-Phishing</symbol> | |||||
<symbol on-off='off' n='52'>X-MessageSniffer-SNF-Group: Snake-Oil</symbol> | |||||
<symbol on-off='off' n='51'>X-MessageSniffer-SNF-Group: Spamware</symbol> | |||||
<symbol on-off='off' n='50'>X-MessageSniffer-SNF-Group: Media-Theft</symbol> | |||||
<symbol on-off='off' n='49'>X-MessageSniffer-SNF-Group: AV-Push</symbol> | |||||
<symbol on-off='off' n='48'>X-MessageSniffer-SNF-Group: Insurance</symbol> | |||||
<symbol on-off='off' n='47'>X-MessageSniffer-SNF-Group: Travel</symbol> | |||||
</xheaders> | |||||
</scan> | |||||
</logs> | |||||
<network> | |||||
<sync secs='30' host='sync.messagesniffer.net' port='25'/> | |||||
<update-script on-off='on' call='c:/SNF/getRulebase.cmd' guard-time='180'/> | |||||
</network> | |||||
<xci on-off='on' port='9001'/> | |||||
<gbudb> | |||||
<database> | |||||
<condense minimum-seconds-between='600'> | |||||
<time-trigger on-off='on' seconds='86400'/> | |||||
<posts-trigger on-off='off' posts='1200000'/> | |||||
<records-trigger on-off='off' records='600000'/> | |||||
<size-trigger on-off='on' megabytes='150'/> | |||||
</condense> | |||||
<checkpoint on-off='on' secs='3600'/> | |||||
</database> | |||||
<regions> | |||||
<white on-off='on' symbol='0'> | |||||
<edge probability='-1.0' confidence='0.4'/> | |||||
<edge probability='-0.8' confidence='1.0'/> | |||||
<panic on-off='on' rule-range='1000'/> | |||||
</white> | |||||
<caution on-off='on' symbol='40'> | |||||
<edge probability='0.4' confidence='0.0'/> | |||||
<edge probability='0.8' confidence='0.5'/> | |||||
</caution> | |||||
<black on-off='on' symbol='63'> | |||||
<edge probability='0.8' confidence='0.2'/> | |||||
<edge probability='0.8' confidence='1.0'/> | |||||
<truncate on-off='on' probability='0.9' peek-one-in='5' symbol='20'/> | |||||
<sample on-off='on' probability='0.8' grab-one-in='5' passthrough='no' passthrough-symbol='0'/> | |||||
</black> | |||||
</regions> | |||||
<training on-off='on'> | |||||
<bypass> | |||||
<!-- <header name='To:' find='spam@example.com'/> --> | |||||
<!-- <header name='Received:' ordinal='1' find='friendlyhost.com'/> --> | |||||
</bypass> | |||||
<drilldown> | |||||
<!-- <received ordinal='0' find='[12.34.56.'/> where we want to ignore 12.34.56.0/24 --> | |||||
<!-- <received ordinal='0' find='mixed-source.com'/> --> | |||||
<!-- <received ordinal='1' find='mixed-source-internal.com'/> --> | |||||
</drilldown> | |||||
<source> | |||||
<!-- <header name='X-Use-This-Source:' received='mixedsource.com [' ordinal='0' /> --> | |||||
<!-- <header name='X-Originating-IP:' received='hotmail.com [' ordinal='0' /> --> | |||||
</source> | |||||
<white> | |||||
<result code='1'/> | |||||
<!-- <header name='Received:' ordinal='0' find='.friendlyhost.com'/> --> | |||||
</white> | |||||
</training> | |||||
</gbudb> | |||||
<rule-panics> | |||||
<!-- | |||||
<rule id='123456'/> | |||||
<rule id='123457'/> | |||||
--> | |||||
</rule-panics> | |||||
<platform/> | |||||
<msg-file type='rfc822'/> | |||||
</node> | |||||
</snf> | |||||
<!-- SNF Xml Command Interface Examples --> | |||||
<!-- Scanner --> | |||||
<snf><xci><scanner><scan file='filepath'/></scanner></xci></snf> | |||||
<snf><xci><scanner><result code='63'/></scanner></xci></snf> | |||||
<snf><xci><scanner><scan file='filepath' xhdr='yes' log='no' ip='12.34.56.78'/></scanner></xci></snf> | |||||
<snf><xci><scanner><result code='63'><xhdr> | |||||
X-Signature-Violations: | |||||
57-1404199-965-976-m | |||||
57-1404199-1352-1363-m | |||||
57-1404199-965-976-f | |||||
</xhdr></result></scanner></xci></snf> | |||||
<!-- GBUdb --> | |||||
<snf><xci><gbudb><set ip='12.34.56.78' type='good'/></gbudb></xci></snf> <!-- Set flag to good on ip --> | |||||
<snf><xci><gbudb><set ip='12.34.56.78' type='bad'/></gbudb></xci></snf> <!-- Set flag to bad on ip --> | |||||
<snf><xci><gbudb><set ip='12.34.56.78' type='ugly'/></gbudb></xci></snf> <!-- Set flag to ugly on ip --> | |||||
<snf><xci><gbudb><set ip='12.34.56.78' type='ignore'/></gbudb></xci></snf> <!-- Set flag to ignore on ip --> | |||||
<snf><xci><gbudb><set ip='12.34.56.78' type='ugly' b='1' g='0'/></gbudb></xci></snf> <!-- Set flag and counts on ip --> | |||||
<snf><xci><gbudb><good ip='12.34.56.78'/></gbudb></xci></snf> <!-- Record a "good" event on ip --> | |||||
<snf><xci><gbudb><bad ip='12.34.56.78'/></gbudb></xci></snf> <!-- Record a "bad" event on ip --> | |||||
<snf><xci><gbudb><test ip='12.34.56.78'/></gbudb></xci></snf> <!-- Return the state of ip --> | |||||
<snf><xci><gbudb><drop ip='12.34.56.78'/></gbudb></xci></snf> <!-- Forget the IP --> | |||||
<!-- GBUdb Result, always --> | |||||
<snf><xci><gbudb><result ip='12.34.56.78' type='ugly' p='1.0' c='0.001' b='1' g='0' range='caution' code='40'/></gbudb></xci></snf> | |||||
<!-- status report request --> | |||||
<snf><xci><report><request><status class='second'/></request></report></xci></snf> | |||||
<!-- status report result --> | |||||
<snf><xci><report><response><!-- actual status report --></response></report></xcl></snf> | |||||
<!-- Server --> | |||||
<snf><xci><server><command command='shutdown'/></server></xci></snf> | |||||
<snf><xci><server><response message='shutdown in progress' code='0'/></server></xci></snf> | |||||
<!-- Specialized Server Requests --> | |||||
<snf><xci><server><command command='systemdefinedcommand'> | |||||
<system-defined/><command/><elements/> | |||||
</command></server></xci></snf> | |||||
<snf><xci><server><response message='shutdown in progress' code='0'> | |||||
<system-defined/><response/><elements/> | |||||
</response></server></xci></snf> | |||||
<!-- XCI Error Response --> | |||||
<snf><xci><error message="What was that?"/></xci></snf> | |||||
#!/usr/bin/bash | |||||
# | |||||
# This scripts copies the files for a distribution to a zipfile. | |||||
# | |||||
# Usage: createDistribution VERSION | |||||
# | |||||
# where VERSION is the version of the distribution. | |||||
# | |||||
# The files are copied to a new directory named SNFMultiSDK_Windows, | |||||
# which is zipped to create the zipfile. | |||||
# | |||||
############################################################################ | |||||
# Name of the directory. | |||||
DirName=SNFMultiSDK_Windows | |||||
# Get the version. | |||||
if [ "$#" -ne 1 ] | |||||
then | |||||
echo Usage: $0 VERSION | |||||
echo where VERSION is the version of the distribution to create | |||||
exit -1 | |||||
fi | |||||
VERSION=$1 | |||||
ZipFile="$DirName"_$VERSION.zip | |||||
# Create the directory. | |||||
rm -rf $DirName | |||||
cp --archive SNFMultiSDK_Windows_Base $DirName | |||||
for dir in 32bitDll 64bitDLL CPPSample include VS2019CPPSample VS2019CSSample VS2019VBSample | |||||
do | |||||
mkdir $DirName/$dir | |||||
done | |||||
# Copy 32-bit DLL files | |||||
for file in IMPORTANT.txt libgcc_s_sjlj-1.dll libstdc++-6.dll libwinpthread-1.dll snfmulti.def snfmulti.dll vs2019_snfmulti.exp vs2019_snfmulti.lib | |||||
do | |||||
cp 32bitDLL/$file $DirName/32bitDLL | |||||
done | |||||
# Copy 64-bit DLL files | |||||
for file in IMPORTANT.txt libgcc_s_seh-1.dll libstdc++-6.dll libwinpthread-1.dll snfmulti.def snfmulti.dll vs2019_snfmulti.exp vs2019_snfmulti.lib | |||||
do | |||||
cp 64bitDLL/$file $DirName/64bitDLL | |||||
done | |||||
# Copy CPP sample files. | |||||
for file in main.cpp main.cpp.html README.txt | |||||
do | |||||
cp CPPSample/$file $DirName/CPPSample | |||||
done | |||||
for file in README VS2019CPPSample.sln VS2019CPPSample.vcxproj VS2019CPPSample.vcxproj.filters VS2019CPPSample.vcxproj.user | |||||
do | |||||
cp VS2019CPPSample/$file $DirName/VS2019CPPSample | |||||
done | |||||
# Copy C# sample files. | |||||
for file in main.cs README VS2019CSSample.csproj VS2019CSSample.csproj.user VS2019CSSample.sln | |||||
do | |||||
cp VS2019CSSample/$file $DirName/VS2019CSSample | |||||
done | |||||
# Copy VB sample files. | |||||
for file in main.vb README VS2019VBSample.sln VS2019VBSample.vbproj VS2019VBSample.vbproj.user | |||||
do | |||||
cp VS2019VBSample/$file $DirName/VS2019VBSample | |||||
done | |||||
# Copy include file. | |||||
cp include/snfmultidll.h include/snfmultidll.h.html $DirName/include | |||||
# Create the zipfile. | |||||
jzip -p -r $ZipFile $DirName | |||||
echo Created zipfile $ZipFile |
Studio files for building the C# and VB example applications, and | Studio files for building the C# and VB example applications, and | ||||
the C++ test. | the C++ test. | ||||
To build the applications in the MinGW-64, MinGW-32, CodeBlocks, and | |||||
VS2008 directories: | |||||
To build the applications in the MinGW-64, MinGW-32, and VS2019 | |||||
directories: | |||||
1) Ensure that the SNFMultiTest, SNFMulti, and CodeDweller | 1) Ensure that the SNFMultiTest, SNFMulti, and CodeDweller | ||||
directories are present. | directories are present. | ||||
2) Install the 64-bit MinGW toolchain. Unpack the 64-bit toolchain | |||||
(e.g. mingw-w64-bin_i686-mingw_20090220.zip) into c:\MinGW-64. If | |||||
done correctly, c:\MinGW-64 should have the directories bin, | |||||
include, x86_64-pc-mingw32, and other directories. The MinGW .CMD | |||||
files and the Code::Blocks project files are configured to use the | |||||
64-bit toolchain in c:\MinGW-64. | |||||
2) Install the 64-bit MinGW toolchain. The scripts in MinGW-64 are | |||||
for MinGW-W64 version 8.1.0, posix threads, and seh exception. | |||||
If a different version is installed, the scripts would need to be | |||||
modified. | |||||
3) Install the 32-bit MinGW toolchain to C:\MinGW. | |||||
3) Install the 32-bit MinGW toolchain (i686 architecture), version | |||||
8.1.0, posix threads, and sjlj exception. If a different version | |||||
is installed, the scripts would need to be modified. | |||||
4) Install VS 2008. | |||||
4) Install VS 2019. and the .NET runtime. | |||||
5) Follow the directions in each directorie's README file. | |||||
5) Follow the directions in README file in MinGW-32, MinGW-64, and | |||||
VS2019 directories. | |||||
To build and test the SDK: | To build and test the SDK: | ||||
c) buildSNFMultiTestDLL.cmd. | c) buildSNFMultiTestDLL.cmd. | ||||
d) buildvs2008SNFMultiImportLib.cmd (in vs2008 command prompt). | |||||
d) buildvs2019SNFMultiImportLib.cmd (in vs2019 command prompt). | |||||
e) SNFMultiTest.exe. | e) SNFMultiTest.exe. | ||||
2) Repeat in MinGW-64. | 2) Repeat in MinGW-64. | ||||
3) Build and run VS2008CPPSample, x32 and x64. First copy | |||||
snf_engine.xml to VS2008CPPSample. For x32, copy *.dll from | |||||
32bitDll to VS2008CPPSample. For x64, copy *.dll from 64bitDll | |||||
to VS2008CPPSample. | |||||
3) Build and run VS2019CPPSample, x32 and x64, following the | |||||
instructions in the README file. | |||||
4) Build and run VS2008CSSample, any, x32, and x64. Copy | |||||
snf_engine.xml to VS2008CSSample. Modify main.cs to specify | |||||
the location of snf_engine.xml and snfmulti.dll, which is | |||||
different for any, x32, and x64. | |||||
4) Build and run VS2019CSSample, any, x32, and x64, following the | |||||
instructions in the README file. | |||||
5) Build and run VS2008VBSample, any, x32, and x64. Copy | |||||
snf_engine.xml to VS2008VBSample. Modify main.vb to specify | |||||
the location of snf_engine.xml and snfmulti.dll, which is | |||||
different for any, x32, and x64. | |||||
5) Build and run VS2019VBSample, any, x32, and x64, following the | |||||
instructions in the README file. | |||||
To create a zipfile distribution: | To create a zipfile distribution: | ||||
1) Install jZip. | 1) Install jZip. | ||||
2) Edit BuildDistribution.cmd to specify the DISTDIR variable, and | |||||
optionally the TEMPDIR variable. | |||||
2) Add jZip to the path for the MinGW-W64 bash command line. | |||||
3) Run BuildDistribution. This creates a zip file in the current | |||||
directory with the name %DISTDIR%.zip. | |||||
3) At a MinGW bash prompt, run | |||||
Note: When you run BuildDistribution, you will get a message saying | |||||
that %DISTDIR%.zip could not be found. This message can be ignored. | |||||
./createDistribution VERSION | |||||
Note: For more information on the procedure for creating a zipfile | |||||
distribution, see the BuildDistribution.cmd file and the | |||||
BuildDistribution\README file. | |||||
where VERSION is the version to create. This creates a | |||||
distribution in SNFMultiSDK_Windows, and zips the distribution | |||||
into SNFMultiSDK_Windows_VERSION.zip. |