summaryrefslogtreecommitdiff
path: root/sys
diff options
context:
space:
mode:
authorMike Frantzen <frantzen@cvs.openbsd.org>2004-04-27 18:28:08 +0000
committerMike Frantzen <frantzen@cvs.openbsd.org>2004-04-27 18:28:08 +0000
commitc78ab32436ce042d6bfcc5f54d2cbd8909c2930c (patch)
tree7c9173034fcb650c71633f34cc739ab2823cedc0 /sys
parent71520fa0b9894dfab56ef5279f7446d4a21d9c94 (diff)
validate the sequence numbers on TCP resets are an exact match. check is only
enabled when we're doing full frag reassembly and thus have full seq info ok markus@
Diffstat (limited to 'sys')
-rw-r--r--sys/net/pf.c15
-rw-r--r--sys/net/pf_norm.c13
-rw-r--r--sys/net/pfvar.h9
3 files changed, 24 insertions, 13 deletions
diff --git a/sys/net/pf.c b/sys/net/pf.c
index 80d95be10d0..3a249514656 100644
--- a/sys/net/pf.c
+++ b/sys/net/pf.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: pf.c,v 1.442 2004/04/26 02:03:38 mcbride Exp $ */
+/* $OpenBSD: pf.c,v 1.443 2004/04/27 18:28:07 frantzen Exp $ */
/*
* Copyright (c) 2001 Daniel Hartmeier
@@ -3649,7 +3649,7 @@ pf_test_state_tcp(struct pf_state **state, int direction, struct pfi_kif *kif,
struct pf_state key;
struct tcphdr *th = pd->hdr.tcp;
u_int16_t win = ntohs(th->th_win);
- u_int32_t ack, end, seq;
+ u_int32_t ack, end, seq, orig_seq;
u_int8_t sws, dws;
int ackskew;
int copyback = 0;
@@ -3762,7 +3762,7 @@ pf_test_state_tcp(struct pf_state **state, int direction, struct pfi_kif *kif,
* tcp_filtering.ps
*/
- seq = ntohl(th->th_seq);
+ orig_seq = seq = ntohl(th->th_seq);
if (src->seqlo == 0) {
/* First packet from this end. Set its state */
@@ -3872,8 +3872,11 @@ pf_test_state_tcp(struct pf_state **state, int direction, struct pfi_kif *kif,
/* Retrans: not more than one window back */
(ackskew >= -MAXACKWINDOW) &&
/* Acking not more than one reassembled fragment backwards */
- (ackskew <= (MAXACKWINDOW << sws))) {
+ (ackskew <= (MAXACKWINDOW << sws)) &&
/* Acking not more than one window forward */
+ ((th->th_flags & TH_RST) == 0 || orig_seq == src->seqlo ||
+ (pd->flags & PFDESC_IP_REAS) == 0)) {
+ /* Require an exact sequence match on resets when possible */
/* update max window */
if (src->max_win < win)
@@ -5280,7 +5283,7 @@ pf_test(int dir, struct ifnet *ifp, struct mbuf **m0)
}
/* We do IP header normalization and packet reassembly here */
- if (pf_normalize_ip(m0, dir, kif, &reason) != PF_PASS) {
+ if (pf_normalize_ip(m0, dir, kif, &reason, &pd) != PF_PASS) {
action = PF_DROP;
goto done;
}
@@ -5585,7 +5588,7 @@ pf_test6(int dir, struct ifnet *ifp, struct mbuf **m0)
}
/* We do IP header normalization and packet reassembly here */
- if (pf_normalize_ip6(m0, dir, kif, &reason) != PF_PASS) {
+ if (pf_normalize_ip6(m0, dir, kif, &reason, &pd) != PF_PASS) {
action = PF_DROP;
goto done;
}
diff --git a/sys/net/pf_norm.c b/sys/net/pf_norm.c
index a05d2b6d0df..2fc6049b166 100644
--- a/sys/net/pf_norm.c
+++ b/sys/net/pf_norm.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: pf_norm.c,v 1.82 2004/04/26 02:03:38 mcbride Exp $ */
+/* $OpenBSD: pf_norm.c,v 1.83 2004/04/27 18:28:07 frantzen Exp $ */
/*
* Copyright 2001 Niels Provos <provos@citi.umich.edu>
@@ -810,7 +810,8 @@ pf_fragcache(struct mbuf **m0, struct ip *h, struct pf_fragment **frag, int mff,
}
int
-pf_normalize_ip(struct mbuf **m0, int dir, struct pfi_kif *kif, u_short *reason)
+pf_normalize_ip(struct mbuf **m0, int dir, struct pfi_kif *kif, u_short *reason,
+ struct pf_pdesc *pd)
{
struct mbuf *m = *m0;
struct pf_rule *r;
@@ -978,6 +979,8 @@ pf_normalize_ip(struct mbuf **m0, int dir, struct pfi_kif *kif, u_short *reason)
if (r->rule_flag & PFRULE_RANDOMID)
h->ip_id = ip_randomid();
+ if ((r->rule_flag & (PFRULE_FRAGCROP|PFRULE_FRAGDROP)) == 0)
+ pd->flags |= PFDESC_IP_REAS;
return (PF_PASS);
@@ -985,7 +988,8 @@ pf_normalize_ip(struct mbuf **m0, int dir, struct pfi_kif *kif, u_short *reason)
/* Enforce a minimum ttl, may cause endless packet loops */
if (r->min_ttl && h->ip_ttl < r->min_ttl)
h->ip_ttl = r->min_ttl;
-
+ if ((r->rule_flag & (PFRULE_FRAGCROP|PFRULE_FRAGDROP)) == 0)
+ pd->flags |= PFDESC_IP_REAS;
return (PF_PASS);
no_mem:
@@ -1017,7 +1021,7 @@ pf_normalize_ip(struct mbuf **m0, int dir, struct pfi_kif *kif, u_short *reason)
#ifdef INET6
int
pf_normalize_ip6(struct mbuf **m0, int dir, struct pfi_kif *kif,
- u_short *reason)
+ u_short *reason, struct pf_pdesc *pd)
{
struct mbuf *m = *m0;
struct pf_rule *r;
@@ -1167,6 +1171,7 @@ pf_normalize_ip6(struct mbuf **m0, int dir, struct pfi_kif *kif,
goto badfrag;
/* do something about it */
+ /* remember to set pd->flags |= PFDESC_IP_REAS */
return (PF_PASS);
shortpkt:
diff --git a/sys/net/pfvar.h b/sys/net/pfvar.h
index fec984ceacf..bcafb1e220b 100644
--- a/sys/net/pfvar.h
+++ b/sys/net/pfvar.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: pfvar.h,v 1.190 2004/04/26 00:12:28 cedric Exp $ */
+/* $OpenBSD: pfvar.h,v 1.191 2004/04/27 18:28:07 frantzen Exp $ */
/*
* Copyright (c) 2001 Daniel Hartmeier
@@ -851,6 +851,7 @@ struct pf_pdesc {
u_int16_t flags; /* Let SCRUB trigger behavior in
* state code. Easier than tags */
#define PFDESC_TCP_NORM 0x0001 /* TCP shall be statefully scrubbed */
+#define PFDESC_IP_REAS 0x0002 /* IP frags would've been reassembled */
sa_family_t af;
u_int8_t proto;
u_int8_t tos;
@@ -1362,8 +1363,10 @@ int pf_match_uid(u_int8_t, uid_t, uid_t, uid_t);
int pf_match_gid(u_int8_t, gid_t, gid_t, gid_t);
void pf_normalize_init(void);
-int pf_normalize_ip(struct mbuf **, int, struct pfi_kif *, u_short *);
-int pf_normalize_ip6(struct mbuf **, int, struct pfi_kif *, u_short *);
+int pf_normalize_ip(struct mbuf **, int, struct pfi_kif *, u_short *,
+ struct pf_pdesc *);
+int pf_normalize_ip6(struct mbuf **, int, struct pfi_kif *, u_short *,
+ struct pf_pdesc *);
int pf_normalize_tcp(int, struct pfi_kif *, struct mbuf *, int, int, void *,
struct pf_pdesc *);
void pf_normalize_tcp_cleanup(struct pf_state *);