From owner-freebsd-bugs@FreeBSD.ORG Mon Aug 25 22:00:38 2003 Return-Path: Delivered-To: freebsd-bugs@hub.freebsd.org Received: from mx1.FreeBSD.org (mx1.freebsd.org [216.136.204.125]) by hub.freebsd.org (Postfix) with ESMTP id BDA6816A4BF for ; Mon, 25 Aug 2003 22:00:38 -0700 (PDT) Received: from freefall.freebsd.org (freefall.freebsd.org [216.136.204.21]) by mx1.FreeBSD.org (Postfix) with ESMTP id 33A5343F93 for ; Mon, 25 Aug 2003 22:00:37 -0700 (PDT) (envelope-from gnats@FreeBSD.org) Received: from freefall.freebsd.org (gnats@localhost [127.0.0.1]) by freefall.freebsd.org (8.12.9/8.12.9) with ESMTP id h7Q50bUp000741 for ; Mon, 25 Aug 2003 22:00:37 -0700 (PDT) (envelope-from gnats@freefall.freebsd.org) Received: (from gnats@localhost) by freefall.freebsd.org (8.12.9/8.12.9/Submit) id h7Q50bg8000740; Mon, 25 Aug 2003 22:00:37 -0700 (PDT) Resent-Date: Mon, 25 Aug 2003 22:00:37 -0700 (PDT) Resent-Message-Id: <200308260500.h7Q50bg8000740@freefall.freebsd.org> Resent-From: FreeBSD-gnats-submit@FreeBSD.org (GNATS Filer) Resent-To: freebsd-bugs@FreeBSD.org Resent-Reply-To: FreeBSD-gnats-submit@FreeBSD.org, "Christian S.J.Peron" Received: from mx1.FreeBSD.org (mx1.freebsd.org [216.136.204.125]) by hub.freebsd.org (Postfix) with ESMTP id B171416A4BF for ; Mon, 25 Aug 2003 21:58:19 -0700 (PDT) Received: from staff.seccuris.com (staff.seccuris.com [204.112.0.40]) by mx1.FreeBSD.org (Postfix) with SMTP id D83F443FDD for ; Mon, 25 Aug 2003 21:58:18 -0700 (PDT) (envelope-from cperon@staff.seccuris.com) Received: (qmail 72588 invoked by uid 1006); 26 Aug 2003 04:58:17 -0000 Message-Id: <20030826045817.72587.qmail@staff.seccuris.com> Date: 26 Aug 2003 04:58:17 -0000 From: "Christian S.J.Peron" To: FreeBSD-gnats-submit@FreeBSD.org X-Send-Pr-Version: 3.113 Subject: kern/55984: [patch] time based firewalling support for ipfw2 X-BeenThere: freebsd-bugs@freebsd.org X-Mailman-Version: 2.1.1 Precedence: list Reply-To: "Christian S.J.Peron" List-Id: Bug reports List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Tue, 26 Aug 2003 05:00:38 -0000 >Number: 55984 >Category: kern >Synopsis: [patch] time based firewalling support for ipfw2 >Confidential: no >Severity: non-critical >Priority: low >Responsible: freebsd-bugs >State: open >Quarter: >Keywords: >Date-Required: >Class: change-request >Submitter-Id: current-users >Arrival-Date: Mon Aug 25 22:00:36 PDT 2003 >Closed-Date: >Last-Modified: >Originator: Christian S.J. Peron >Release: FreeBSD 5.1-CURRENT i386 >Organization: Seccuris Inc >Environment: System: FreeBSD movl 5.1-CURRENT FreeBSD 5.1-CURRENT #14: Mon Aug 25 17:22:40 CDT 2003 modulus@movl:/usr/src/sys/i386/compile/RAID0 i386 >Description: I have enclosed a patch which allows ipfw2 to filter based on the time of day. Mostly looking for approval/testers. I have tested this patch but it may be missing something. CAVEATS As noted in the BUGS section of the ipfw.8 diff, if your system shifts its time for daylight savings, firewall rules will have to be refreshed, because the kernel is not aware of such things. QUICK EXAMPLE ipfw add allow ip from any to any times 09:00:00 17:00:00 Allow all IP traffic from 9:00 AM to 5:00 PM. Thanks, enjoy! Christian S.J. Peron >How-To-Repeat: N/A >Fix: --- sys/netinet/ip_fw.h.timeless Mon Aug 25 00:22:54 2003 +++ sys/netinet/ip_fw.h Mon Aug 25 17:18:34 2003 @@ -93,6 +93,7 @@ O_TCPACK, /* u32 = desired seq. */ O_ICMPTYPE, /* u32 = icmp bitmap */ O_TCPOPTS, /* arg1 = 2*u8 bitmap */ + O_TIME, /* arg1 = from time arg2 = to time */ O_VERREVPATH, /* none */ @@ -215,6 +216,16 @@ u_char addr[12]; /* dst[6] + src[6] */ u_char mask[12]; /* dst[6] + src[6] */ } ipfw_insn_mac; + +/* + * This is used for the time constraint specifications. + */ +typedef struct _ipfw_insn_time { + ipfw_insn o; + long tzoff; + u_long from; + u_long to; +} ipfw_insn_time; /* * This is used for interface match rules (recv xx, xmit xx). --- sys/netinet/ip_fw2.c.timeless Mon Aug 25 00:20:24 2003 +++ sys/netinet/ip_fw2.c Mon Aug 25 17:15:24 2003 @@ -22,7 +22,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $FreeBSD: /repoman/r/ncvs/src/sys/netinet/ip_fw2.c,v 1.37 2003/07/15 23:07:34 luigi Exp $ + * $FreeBSD: src/sys/netinet/ip_fw2.c,v 1.37 2003/07/15 23:07:34 luigi Exp $ */ #define DEB(x) @@ -283,6 +283,40 @@ return 1; } +/* + * For this example we will assume the current time is ``HH:MM:SS'' + * 10:12:22 + * + * f(x) = (HOURS * 3600) + (MINUTES * 60) + SECONDS + * = (10 * 3600) + (12 * 60) + 22 + * = 36000 + 720 + 22 + * = 36742 + * + * IF [ f(10:12:22) >= f(9:00:00) && f(10:12:22) <= (17:00:00) ] + * current time (10:12:22) falls within time constraint + * ELSE + * current time (10:12:22) does not fall in time constraint + * ENDIF + */ + +static u_long +ipfw_calc_time_sum(time_t T) +{ + u_long S, M, H, R; + u_long SUM, MH, MM; + + R = (T / 3600); + H = (R % 24); + MH = (H * 3600); + R = (T / 60); + M = (R % 60); + MM = (M * 60); + S = (T % 60); + SUM = (MH + MM + S); + + return(SUM); +} + static int ipopts_match(struct ip *ip, ipfw_insn *cmd) { @@ -1590,6 +1624,21 @@ m->m_pkthdr.rcvif, (ipfw_insn_if *)cmd); break; + case O_TIME: + { + struct timeval tm; + u_long from, to, sum; + long tzoff; + + microtime(&tm); + tzoff = ((ipfw_insn_time *)cmd)->tzoff; + from = ((ipfw_insn_time *)cmd)->from; + to = ((ipfw_insn_time *)cmd)->to; + sum = ipfw_calc_time_sum(tm.tv_sec + tzoff); + match = (sum >= from && sum <= to); + } + break; + case O_MACADDR2: if (args->eh != NULL) { /* have MAC header */ u_int32_t *want = (u_int32_t *) @@ -2457,6 +2506,11 @@ } if (cmdlen != F_INSN_SIZE(ipfw_insn_u32) + (cmd->arg1+31)/32 ) + goto bad_size; + break; + + case O_TIME: + if (cmdlen != F_INSN_SIZE(ipfw_insn_time)) goto bad_size; break; --- sbin/ipfw/ipfw.8.timeless Tue Jul 22 02:41:24 2003 +++ sbin/ipfw/ipfw.8 Mon Aug 25 15:38:58 2003 @@ -1,5 +1,5 @@ .\" -.\" $FreeBSD: /repoman/r/ncvs/src/sbin/ipfw/ipfw.8,v 1.131 2003/07/22 07:41:24 luigi Exp $ +.\" $FreeBSD: src/sbin/ipfw/ipfw.8,v 1.131 2003/07/22 07:41:24 luigi Exp $ .\" .Dd August 13, 2002 .Dt IPFW 8 @@ -1178,6 +1178,13 @@ The absence of a particular option may be denoted with a .Ql \&! . +.It Cm times Ar from to +Match all packets which are processed by the firewall between +times +.Ar from +and +.Ar to . +Time specifications must be given in ``HH:MM:SS'' format. .It Cm uid Ar user Match all TCP or UDP packets sent by or received for a .Ar user . @@ -2152,6 +2159,10 @@ applied, making the order of .Cm divert rules in the rule sequence very important. +.Pp +If the system clock automatically shifts for daylight savings time, any firewall +rules which implement time constraints or time based filtering +must be refreshed with ipfw(8). .Sh AUTHORS .An Ugen J. S. Antsilevich , .An Poul-Henning Kamp , --- sbin/ipfw/ipfw2.c.timeless Sun Aug 24 20:15:08 2003 +++ sbin/ipfw/ipfw2.c Mon Aug 25 23:25:40 2003 @@ -221,6 +221,7 @@ TOK_TCPSEQ, TOK_TCPACK, TOK_TCPWIN, + TOK_TIME, TOK_ICMPTYPES, TOK_MAC, TOK_MACTYPE, @@ -326,6 +327,7 @@ { "tcpseq", TOK_TCPSEQ }, { "tcpack", TOK_TCPACK }, { "tcpwin", TOK_TCPWIN }, + { "times", TOK_TIME }, { "icmptype", TOK_ICMPTYPES }, { "icmptypes", TOK_ICMPTYPES }, { "dst-ip", TOK_DSTIP }, @@ -351,6 +353,51 @@ { NULL, 0 } /* terminator */ }; +static u_long +timeconv(char *timespec) +{ + u_long M, H, SUM; + struct tm *tmp; + time_t t; + char *p; + + t = time(0); + tmp = localtime(&t); + + if ((p = strptime(timespec, "%H:%M:%S", tmp)) == 0) + errx(1, "time conversion failed"); + + if ((t = mktime(tmp)) < 0) + errx(1, "mktime failed"); + + tmp = localtime(&t); + H = M = SUM = 0; + H = tmp->tm_hour * 3600; + M = tmp->tm_min * 60; + SUM = (H + M + tmp->tm_sec); + + return(SUM); +} + +/* + * Basically do the reverse of timeconv(). Given the + * sum translate it into a clock. + */ +static void +revtimesum(u_long T) +{ + u_long S, M, H, R; + + R = (T / 3600); + H = (R % 24); + R = (T / 60); + M = (R % 60); + S = (T % 60); + printf(" %02u:%02u:%02u", H, M, S); + + return; +} + static __inline uint64_t align_uint64(uint64_t *pll) { uint64_t ret; @@ -1067,6 +1114,22 @@ flags |= HAVE_MAC | HAVE_MACTYPE | HAVE_OPTIONS; break; + case O_TIME: + { + ipfw_insn_time *m = (ipfw_insn_time *)cmd; + + if ((cmd->len & F_OR) && !or_block) + printf(" {"); + if (cmd->len & F_NOT) + printf(" not"); + + printf(" times"); + revtimesum(m->from); + printf(" to"); + revtimesum(m->to); + } + break; + case O_IP_SRC: case O_IP_SRC_MASK: case O_IP_SRC_ME: @@ -2617,6 +2680,36 @@ } static ipfw_insn * +add_time_constraint(ipfw_insn *cmd, int ac, char *av[]) +{ + ipfw_insn_time *fw_time; + time_t t; + struct tm *tmp; + + if (ac < 2) + errx(EX_DATAERR, "time from to"); + + cmd->opcode = O_TIME; + cmd->len = (cmd->len & (F_NOT | F_OR)) | F_INSN_SIZE(ipfw_insn_time); + + t = time(0); + tmp = localtime(&t); + fw_time = (ipfw_insn_time *)cmd; + fw_time->from = timeconv(av[0]); + fw_time->to = timeconv(av[1]); + + if (fw_time->from > fw_time->to) + errx(EX_USAGE, "`from' timespec is later than `to'"); + + if (fw_time->from == fw_time->to) + errx(EX_USAGE, "time specifications are equal."); + + fw_time->tzoff = tmp->tm_gmtoff; + + return(cmd); +} + +static ipfw_insn * add_mactype(ipfw_insn *cmd, int ac, char *av) { if (ac < 1) @@ -3391,6 +3484,13 @@ if (!add_mactype(cmd, ac, *av)) errx(EX_DATAERR, "invalid mac type %s", *av); ac--; av++; + break; + + case TOK_TIME: + if (add_time_constraint(cmd, ac, av)) { + ac -= 2; + av += 2; + } break; case TOK_VERREVPATH: >Release-Note: >Audit-Trail: >Unformatted: