Firewall Development Kit v1.0 for SafeFire (c) Link Guard Solutions Ltd. 1. Introduction Since nobody can implement every feature particular user need, Link Guard Solutions have decided to make SafeFire configuration even more flexible by providing Firewall Development Kit. This package allows user to create it's own unique passive firewall or statistical kit that will integrate into almost any SafeFire product (the only exception is SafeFire Firewall). This package provides abilities to intercept any network packet at one or multiple points (i.e. before or after NAT module). User program can analyze packet and then choose either to pass packet futher or drop it with or without writing warning information to SafeFire log. 2. Detailed description 2.1 Limitations This Kit has next functional limitations. They MAY be removed if there will be enough requests from users. 1) It can't send any packets. 2) It can't alter any packets. 3) It does not have access to any special SafeFire functions like Information Bus or Plugin Manager (yet normal REXX functionality is available for REXX script, providing some additional features). 4) It can't get additional packet information, like source or destination MAC addresses, packet priority or creation time. 2.2 User module API 2.2.1 DLL API Primary interface for user module is Dynamic Link Library (DLL). It can be written in any programming language that has compiler that is able to build DLLs. All samples in this package are written in C++ programming language and must be compiled with Visual Age C++ 3.08/3.65. DLL may have some of next defined entry points (System calling convension). Yet any entry point can be ommited, it is recommended to have at least Write entry point or module won't be able to process packets. All entries are loaded by numbers and not names. There are two versions of DLL API for now - version 1.0 and version 1.1 Only first (1.0) one is available in the SafeFire PPP 1.0. Main difference between them is that 1.0 DLL can't be used multiple times by single SafeFire PPP process (by loading multiple similar plugins) because it can not differenciate between instances. 1.1 version of API was introduced to resolve this problem. Single DLL can implement both APIs to work in all SafeFire PPP versions and use advanced functionality if it is available. List of entry point follows. Two entry point numbers is specified - one for 1.0 and other for 1.1 API. If parameter is market "v1.1 only" - it does not exists in 1.0 entry points. 1) Init entry point. Must have 200(v.1.0) or 205(v.1.1) number. This entry point is called during plugin init. It is passed next parameters: - configuration file section name - ASCIIZ pointer. - v1.1 only - instance identifier - 4 bytes pointer. Entry point should fill memory address supplied with this parameter with unique value. This value will be latter passed as parameter and can be used to differenciate between instances. Caller does not use this values, it simply pass it back when calling libarry. It must not return anything 2) Configuration entry point. Must have 201(v.1.0) or 206(v.1.1) number. This entry point is used to pass configuration parameters to plugin. Every parameter that starts with "ext." will be passed to module ("ext." prefix will be removed). Some preprocessing is done against parameter name and value: leading and trailing blanks are removed, value can be enclosed in double quotes (they are removed). If quoted value has leading or trailing blanks, they are not removed. Entry point is passed next parametes: - v1.1 only - instance identifier - four bytes integer - parameter name - ASCIIZ pointer - parameter value - ASCIIZ pointer It must not return anything 3) Write entry point. Must have 202(v.1.0) or 207(v.1.1) number. This entry is called for each packet. This entry may be called from multiple threads (even with same Source) and must perform serialization by itself. Next parameters are passed to this entry: - v1.1 only - instance identifier - four bytes integer - Source - four bytes integer - contains 0 if packet is going from IN1 to IN2 and 1 if from IN2 to IN1. - Protocol - four bytes integer - contains packet protocol number. Please see h\sfproto.h to get full protocol list. Note: You MUST pass any option packets (starting from 0x10000000 protocol) - Packet - flat pointer - pointer to packet itself. Note: you must NOT change it's contents - Packet Size - four bytes integer - contains packet length as received from network (may contain padding). - Stream Index - four bytes integer, may contain values from 0 to 0xffff Since multiple paralel streams may be passed through the plugin (depending on configuration), this option provides stream number. Returns: This entry must return 0 if it wishes to pass packet, 1 to silently discard packet or other value (4 bytes integer) to discard packet and log number returned to SafeFire log. 4) Done entry point. Exists only in API v.1.1 and has 208 number. This entry is called when plugin is to be unloaded to indicate that resources assotiated with single parameter (instance identifier - four bytes integer) must be freed. It must not return anything 2.2.2 REXX API Sample provided in this package was designed to perform two goals: to provide sample for anyone who wishes to write it's own module and to perform REXX transition layer. By using this sample anyone can write REXX scripts that intercept packets. Note: REXX creates GREAT overhead if used for every packet processing, so some prefiltering is highly recommended, especially in LAN environment. REXX module must be create as single rexx script that performs multiple functions. First argument (arg(1)) value must be used to determine what function is requested. If script does not implement funciton, it MUST simply "return" without any return value. Next functions are defined: 1) arg(1) = 'QUERY'. This function is called first. It must be implemented and must return decimal value that specify what other functions are implemented with this script. Each funciton (but 'QUERY') has integer value assotiated with. This function must return bit 'OR' of values of all available functions. 2) arg(1) = 'LOAD', query value = 1. This function will be called right after QUERY. It has single additional parameter: arg(2) contains configuration section name. This function must return anything 3) arg(1) = 'CONFIG', query value = 2. This function is called for each configuration parameter that must be passed. It has three additional parameters: - arg(2) - configuration section name - arg(3) - parameter name - arg(4) - parameter value. Please see DLL Configuration Entry Point above to get more information on passing parameters to module. This function must return anything 4) arg(1) = 'W', query value = 4. This function is called for each packet. We'd recommend to put it to the top of REXX file to achive maximum performance. It is passed next parameters: - arg(2) - configuration section name - arg(3) - packet source - either 'IN1' or 'IN2' - arg(4) - protocol number (binary, 4 bytes, least significant byte first). To check if the protocol if 0xabcd perform arg(4) = 'cdab0000'x check. Please see h\sfproto.h to get full protocol list. Note: You MUST pass any option packets (starting from 10000000 protocol) - arg(5) - packet - arg(6) - stream index. (binary, 4 bytes. See note about arg(4) above) See DLL Write entry description above to get more information about this parameter. This function must return decimal number. O will mean to pass packet, 1 - to drop packet, other decimal number - to drop packet and write warning to SafeFire log. Note: Binary values for arg(4) and arg(6) are used to make code faster (no integer -> string conversion, comparision of binary is faster) 5) arg(1) = 'DONE', query value = 8. This function is called when plugin assotiated with section is to be unloaded and rexx script can return any resources it allocated. It is passed next parameter: - arg(2) - configuration section name This function must return anything Note: This will never be called if v1.0 of API was loaded 2.2.3 Installation and loading 2.2.3.1 DLL API Since DLL created using FDK (will be refered as FDK DLL below) does not implement fully functional SafeFireplugin, special SafeFire plugin (will be reffered as converter below) is use dto perform next functions: - Provide enhanced SafeFire plugin functionality for SafeFire Plugin Manager. - Pass control to DLL when needed - Hide internal API specifics (that can be changed) from DLL and perform as "converter" from internal plugin API to FDK API. pl_ext.dll Plugin Library is used to hold converter plugins: - EXTERNAL - plugin that performs as v1.0 API converter. Only this plugin is available in SafeFire PPP 1.0 - EXTFILT - plugin that performs as v1.1 API converter. Providing information above load variable must look like the next: load=pl_ext:external or for v.1.1: load=pl_ext:extfilt All difference between two plugins is FDK API used. All documentation below is applicable to both (you will need to supply corect "load" value in the examples. Converter itself uses "library" variable to know what FDK DLL to load. This variable must be specified BEFORE any "ext." variables. Example: library=userdll will load "userdll.dll" as FDK DLL. Also converter will pass any variable with name starting with "ext." to FDK DLL. Converter uses two Stream Packs - IN1 and IN2. Packets from IN1 (if accepted by FDK DLL) will be sent to IN2 and vica versa. 0 will be indicated as packet source if packet was received from IN1 and 1 if from IN2. 2.2.3.2 Examples and HOW-TO for using DLL API 2.2.3.2.1 Except from real configuration file used by one of the FDK DLL [filter] bind=stack:extern.in1 [extern] load=pl_ext:external bind=in2:cl_pppstack.io library=sfstat ext.PipeName = sf0 2.2.3.2.2 HOW-TO on inserting FDK DLL into existing plugin chain If we have next configuration file ("<" and ">" characters are used to indicate variable strings that must be inserted in the corresponding places into the resulting configuration file): .... [] .... bind=:. .... And we want to use .dll FDK dll between and , the configuration file will look like the next: .... [extern] load=pl_ext:external bind=in2:. library= ....put any "ext." params needed here... [] .... bind=:extern.in1 .... Note 1: If there is other "extern" section already in the file, you can use any other unused section name, but be sure to replace extern to new name in the last "bind" variable Note 2: To change packet flow to reverse direction, simply replace in1 with in2 and vica versa. Note 3: Be sure to replace pl_ext:external to pl_ext:extfilt if you want to load v1.1 FDK DLL (or dual version DLL in 1.1 mode). You must have at least SafeFire PPP 1.1 (is not available as of January, 2001) to use v1.1 API. 2.2.3.3 REXX API Special DLL (sample\rexxcall\ple_rexx.dll) provides C to REXX conversion layer. So it must be copied to any LIBPATH directory and installed as any other FDK DLL (See 2.2.3.1, 2.2.3.2). This DLL supports both 1.0 and 1.1 C API version. This means that you must use load=pl_ext:external for SafeFire PPP 1.0 and load=pl_ext:extfilt for SafeFire PPP 1.1 or SafeFire Links. In the SafeFire PPP 1.0 case you can load only one instance of the DLL (but remember that you can link multiple streams to single instance). As soon as you installed DLL and configured your SafeFire configuration file, add ext.script variable to your plugin section ([extern] in the examples above). This variable must contain script name and must be added AFTER library variable. All the ext.* variables starting from ext.scipt will be passed to REXX script (if it supports parameter passing). Here is example of the [extern] section you could create: .... [extern] load=pl_ext:external library=ple_ext ext.script=c:\safefire\scripts\analyser.cmd ext.param=script parameter ..... 3 Contacts Last version of this kit can be found at http://www.lgs.kiev.ua If you have any problems or questions, feel free to contact LGS support Current support e-mail is support@lgs.kiev.ua