# # $Id: PatchICMP,v 1.11 2000/07/04 15:12:26 jean Exp $ # # Install script for ICMP stateful # if [ -f base.def -a -f formats.def -a -f fwui_head.def ] ; then echo "Modifying files in current directory" else # # Try to see if FWDIR is setup # if [ -f ${FWDIR}/lib/base.def -a -f ${FWDIR}/lib/formats.def -a -f ${FWDIR}/lib/fwui_head.def ] ; then cd ${FWDIR}/lib echo "Find the FW lib directory under ${FWDIR}/lib" echo "Using it!" else echo "Cannot find files to modify" echo "Please, cd to your \$FWDIR/lib directory" echo "or set your \$FWDIR variable" exit fi fi # echo "Ready? [y/n] : \c" read RE if [ ! "X${RE}" = "Xy" ] ; then echo "See you next time." exit fi echo "Creating icmpstate.def" cat > 'icmpstate.def' << %EOF% #ifndef __icmpstate_def__ #define __icmpstate_def__ // // # Id: icmpstate.def,v 1.3 2000/07/04 04:52:15 jean Exp # // Stateful ICMP ping // ICMP errors, Jean Chouanard // //ICMP INSPECT SCRIPT // This code is under BSD license: // Copyright (c) 2000, Jean Chouanard , Xerox - PARC // All rights reserved. // // Redistribution and use in source and binary forms, with or without modification, are // permitted provided that the following conditions are met: // // Redistributions of source code must retain the above copyright notice, this list // of conditions and the following disclaimer. // // Redistributions in binary form must reproduce the above copyright notice, this list // of conditions and the following disclaimer in the documentation and/or other // materials provided with the distribution. // // Neither name of the Xerox-PARC nor the names of its contributors may be used to // endorse or promote products derived from this software without specific // prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS'' AND ANY // EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES // OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL // THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, // EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) // HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF // THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // // // This code is originally based of Checkpoint stateful_icmp function defined in base.def // and from the code of William D. Burns (shadow@netscape.com), // http://people.netscape.com/shadow/work/inspect/index.html // // It was modify to: // - restrict ICMP request to echo-request // - restrict ICMP replies to echo-reply // - check the icmp sequence (From the code of William D. Burns) // - Delete entries from the icmp table when a match is found // to limit ICMP reply to *one* packet (From the code of William D. Burns) // - the recording of the outgoing accepted ICMP request in the ICMP connection table is // done in the CONN_RECORD macro so that only accepted request will be recorded. // - Offer to accept ICMP error code related to existing UDP TCP or ICMP connections // as an option // #ifdef ICMPSTATE // // The max size for an ICMP error messages. // See TCP Illustrated Vol I, page 79: // 20 (IP Header) + 8 (ICMP Header) + 20 (IP Header included) + 64 (On Solaris, first 64 data bytes) // =112 bytes // Most of the BSP implementation will return a max of 56, as they return only the first 8 data bytes. // #define MAX_ERROR_SIZE 112 // icmp_requests_connections = dynamic {} expires 60; icmp_allow_requests = { ICMP_ECHO }; icmp_allow_replies = { ICMP_ECHOREPLY }; icmp_allow_errors = { ICMP_UNREACH, ICMP_SOURCEQUENCH, ICMP_TIMXCEED }; // // ICMP packet format for ICMP error : // 20 bytes : IP Header // ICMP message // 8 bytes : ICMP header // data portion of ICMP message // 20 bytes : IP Header // // // icmp_ip_p is defined in tcpip.def as icmp_ip_p [ 37 : 1] // which is [9 : 1] in the data portion of ICMP message // For an ERROR ICMP messages, it will point to the protocol // record of the IP header of the packets that generated the // error // // icmp_ip_src is defined in tcpip.def as icmp_ip_src [ 40 , b] // which is [12 : b] in the data portion of ICMP message // For an ERROR ICMP messages, it will point to the 32 bit src-IP addr // record of the IP header of the packets that generated the // error // define ping_stateful_prolog (dir){ icmp, ( icmp_type in icmp_allow_replies, ( in icmp_requests_connections, ( (direction = dir , delete from icmp_requests_connections #ifdef ICMPSTATEDEBUG ,log icmp_deleted_form #endif ) or (1) ), set sr1 0, #ifdef ICMPSTATEDEBUG log icmp_allowed_form, #endif #ifdef LOG_IMPLIED_RULES IMPLIED_LOG, #endif accept ) or (set sr1 0, #ifdef ICMPSTATEDEBUG log icmp_denied_form, #endif drop) ) }; define icmperror_stateful_prolog { icmp, ( icmp_type in icmp_allow_errors, dst = icmp_ip_src, ( ip_len <= MAX_ERROR_SIZE or ( set sr1 0, log icmp_badip_form, drop ) ), ( icmp_ip_p = PROTO_tcp or icmp_ip_p = PROTO_udp, ( in connections or in connections), #ifdef ICMPSTATEDEBUG log icmp_allowed_form, #endif #ifdef LOG_IMPLIED_RULES IMPLIED_LOG, #endif accept ) or (icmp_ip_p = PROTO_icmp, in icmp_requests_connections, #ifdef ICMPSTATEDEBUG log icmp_allowed_form, #endif #ifdef LOG_IMPLIED_RULES IMPLIED_LOG, #endif accept ) ) }; #define ping_stateful_inbound ping_stateful_prolog(0); #define ping_stateful_outbound ping_stateful_prolog(1); #define ping_stateful_eitherbound ping_stateful_prolog(1); #define icmperror_stateful icmperror_stateful_prolog; #endif /* ICMPSTATE */ #endif /* __icmpstate_def__ */ %EOF% chmod 0644 'icmpstate.def' # timestamp="`date +%Y.%m.%d-%H.%M.%S`" echo "Backing-up base.def formats.def fwui_head.def with the '.Before-ICMP_Statefull-Patch_${timestamp}' prefix" cp base.def base.def.Before-ICMP_Statefull-Patch_${timestamp} cp formats.def formats.def.Before-ICMP_Statefull-Patch_${timestamp} cp fwui_head.def fwui_head.def.Before-ICMP_Statefull-Patch_${timestamp} # cat > /tmp/base.sed<<%EOF% /^deffunc RECORD_CONN/i\\ \#ifdef ICMPSTATE\\ \#include "icmpstate.def"\\ \#endif /* ICMPSTATE */\\ /UDP_RECORD(udpconn,r_ckey,r_ctype,r_cflags)/{n;n;n;n;a\\ \#ifdef ICMPSTATE\\ or\\ (icmp,\\ (\\ WAS_ENCRYPTED, drop\\ ) or (\\ ip_len >= 32,\\ icmp_type in icmp_allow_requests,\\ record in icmp_requests_connections\\ \#ifdef ICMPSTATEDEBUG\\ , log icmp_recorded_form \\ \#endif\\ )\\ )\\ \#endif /* ICMPSTATE*/ } %EOF% sed -f /tmp/base.sed base.def > /tmp/base.def mv /tmp/base.def base.def cat >> formats.def << %EOF% #ifdef ICMPSTATEDEBUG icmp_recorded_form = format { <"DEBUG Recording ICMP proto", proto, ip_p>, <"src", ipaddr, src>, <"dst", ipaddr, dst>, <"icmp_id", hex, icmp_id>, <"icmp_seq", hex, icmp_seq>, <"icmp-type", hex, [(IPHLEN):1]>, <"icmp-code", hex, [(IPHLEN+1):1]>, <"h_len", int, IPHLEN>, <"ip_len", int, ip_len>, <"ip_vers", int, ip_hl / 16>, <"rule", rule, sr1> }; icmp_denied_form = format { <"DEBUG ICMP not on the table proto", proto, ip_p>, <"src", ipaddr, src>, <"dst", ipaddr, dst>, <"icmp_id", hex, icmp_id>, <"icmp_seq", hex, icmp_seq>, <"icmp-type", hex, [(IPHLEN):1]>, <"icmp-code", hex, [(IPHLEN+1):1]>, <"h_len", int, IPHLEN>, <"ip_len", int, ip_len>, <"ip_vers", int, ip_hl / 16>, <"rule", rule, sr1> }; icmp_allowed_form = format { <"DEBUG allowed ICMP proto", proto, ip_p>, <"src", ipaddr, src>, <"dst", ipaddr, dst>, <"icmp_id", hex, icmp_id>, <"icmp_seq", hex, icmp_seq>, <"icmp-type", hex, [(IPHLEN):1]>, <"icmp-code", hex, [(IPHLEN+1):1]>, <"h_len", int, IPHLEN>, <"ip_len", int, ip_len>, <"ip_vers", int, ip_hl / 16>, <"rule", rule, sr1> }; icmp_deleted_form = format { <"DEBUG Allow ICMP reply and deleted it proto", proto, ip_p>, <"src", ipaddr, src>, <"dst", ipaddr, dst>, <"icmp_id", hex, icmp_id>, <"icmp_seq", hex, icmp_seq>, <"icmp-type", hex, [(IPHLEN):1]>, <"icmp-code", hex, [(IPHLEN+1):1]>, <"h_len", int, IPHLEN>, <"ip_len", int, ip_len>, <"ip_vers", int, ip_hl / 16>, <"rule", rule, sr1> }; #endif /* ICMPSTATEDEBUG */ %EOF% cat > /tmp/fwui_head.sed << %EOF% /define __fwui_head__/a\\ \\ //\\ // The Following are use to control the ICMP Stateful code:\\ // See http://yasp.parc.xerox.com/fw1/icmp.html\\ // ICMPSTATE: if not defined, no change are done to the existing code\\ // ICMPSTATEDEBUG: will print extra logs useful for debugging\\ //\\ // #define ICMPSTATE\\ // #define ICMPSTATEDEBUG\\ %EOF% sed -f /tmp/fwui_head.sed fwui_head.def > /tmp/fwui_head.def mv /tmp/fwui_head.def fwui_head.def echo "Done."