mirror of
https://github.com/freebsd/freebsd-src
synced 2024-09-06 17:18:32 +00:00
pf: improve SCTP state validation
Only create new states for INIT chunks, or when we're creating a secondary state for a multihomed association. Store and verify verification tag. MFC after: 3 weeks Sponsored by: Orange Business Services
This commit is contained in:
parent
1a28d5fea7
commit
51a78dd276
|
@ -900,7 +900,10 @@ struct pf_state_scrub {
|
|||
#define PFSS_DATA_NOTS 0x0080 /* no timestamp on data packets */
|
||||
u_int8_t pfss_ttl; /* stashed TTL */
|
||||
u_int8_t pad;
|
||||
u_int32_t pfss_ts_mod; /* timestamp modulation */
|
||||
union {
|
||||
u_int32_t pfss_ts_mod; /* timestamp modulation */
|
||||
u_int32_t pfss_v_tag; /* SCTP verification tag */
|
||||
};
|
||||
};
|
||||
|
||||
struct pf_state_host {
|
||||
|
@ -1583,6 +1586,7 @@ struct pf_pdesc {
|
|||
#define PFDESC_SCTP_DATA 0x0040
|
||||
#define PFDESC_SCTP_ASCONF 0x0080
|
||||
#define PFDESC_SCTP_OTHER 0x0100
|
||||
#define PFDESC_SCTP_ADD_IP 0x0200
|
||||
u_int16_t sctp_flags;
|
||||
u_int32_t sctp_initiate_tag;
|
||||
|
||||
|
@ -2297,6 +2301,8 @@ int pf_normalize_tcp_init(struct mbuf *, int, struct pf_pdesc *,
|
|||
int pf_normalize_tcp_stateful(struct mbuf *, int, struct pf_pdesc *,
|
||||
u_short *, struct tcphdr *, struct pf_kstate *,
|
||||
struct pf_state_peer *, struct pf_state_peer *, int *);
|
||||
int pf_normalize_sctp_init(struct mbuf *, int, struct pf_pdesc *,
|
||||
struct pf_state_peer *, struct pf_state_peer *);
|
||||
int pf_normalize_sctp(int, struct pfi_kkif *, struct mbuf *, int,
|
||||
int, void *, struct pf_pdesc *);
|
||||
u_int32_t
|
||||
|
|
|
@ -4909,11 +4909,7 @@ pf_create_state(struct pf_krule *r, struct pf_krule *nr, struct pf_krule *a,
|
|||
if (s->state_flags & PFSTATE_SCRUB_TCP &&
|
||||
pf_normalize_tcp_init(m, off, pd, th, &s->src, &s->dst)) {
|
||||
REASON_SET(&reason, PFRES_MEMORY);
|
||||
pf_src_tree_remove_state(s);
|
||||
s->timeout = PFTM_UNLINKED;
|
||||
STATE_DEC_COUNTERS(s);
|
||||
pf_free_state(s);
|
||||
return (PF_DROP);
|
||||
goto drop;
|
||||
}
|
||||
if (s->state_flags & PFSTATE_SCRUB_TCP && s->src.scrub &&
|
||||
pf_normalize_tcp_stateful(m, off, pd, &reason, th, s,
|
||||
|
@ -4922,12 +4918,13 @@ pf_create_state(struct pf_krule *r, struct pf_krule *nr, struct pf_krule *a,
|
|||
DPFPRINTF(PF_DEBUG_URGENT,
|
||||
("pf_normalize_tcp_stateful failed on first "
|
||||
"pkt\n"));
|
||||
pf_src_tree_remove_state(s);
|
||||
s->timeout = PFTM_UNLINKED;
|
||||
STATE_DEC_COUNTERS(s);
|
||||
pf_free_state(s);
|
||||
return (PF_DROP);
|
||||
goto drop;
|
||||
}
|
||||
} else if (pd->proto == IPPROTO_SCTP) {
|
||||
if (pf_normalize_sctp_init(m, off, pd, &s->src, &s->dst))
|
||||
goto drop;
|
||||
if (! (pd->sctp_flags & (PFDESC_SCTP_INIT | PFDESC_SCTP_ADD_IP)))
|
||||
goto drop;
|
||||
}
|
||||
s->direction = pd->dir;
|
||||
|
||||
|
@ -5024,6 +5021,13 @@ pf_create_state(struct pf_krule *r, struct pf_krule *nr, struct pf_krule *a,
|
|||
}
|
||||
|
||||
return (PF_DROP);
|
||||
|
||||
drop:
|
||||
pf_src_tree_remove_state(s);
|
||||
s->timeout = PFTM_UNLINKED;
|
||||
STATE_DEC_COUNTERS(s);
|
||||
pf_free_state(s);
|
||||
return (PF_DROP);
|
||||
}
|
||||
|
||||
static int
|
||||
|
@ -5891,6 +5895,13 @@ pf_test_state_sctp(struct pf_kstate **state, struct pfi_kkif *kif,
|
|||
}
|
||||
}
|
||||
|
||||
if (src->scrub != NULL) {
|
||||
if (src->scrub->pfss_v_tag == 0) {
|
||||
src->scrub->pfss_v_tag = pd->hdr.sctp.v_tag;
|
||||
} else if (src->scrub->pfss_v_tag != pd->hdr.sctp.v_tag)
|
||||
return (PF_DROP);
|
||||
}
|
||||
|
||||
(*state)->expire = time_uptime;
|
||||
|
||||
/* translate source/destination address, if necessary */
|
||||
|
@ -5931,6 +5942,7 @@ pf_sctp_multihome_delayed(struct pf_pdesc *pd, int off, struct pfi_kkif *kif,
|
|||
|
||||
TAILQ_FOREACH_SAFE(j, &pd->sctp_multihome_jobs, next, tmp) {
|
||||
PF_RULES_RLOCK();
|
||||
j->pd.sctp_flags |= PFDESC_SCTP_ADD_IP;
|
||||
action = pf_test_rule(&r, &sm, kif,
|
||||
j->m, off, &j->pd, &ra, &rs, NULL);
|
||||
PF_RULES_RUNLOCK();
|
||||
|
|
|
@ -1565,11 +1565,28 @@ pf_normalize_tcp_init(struct mbuf *m, int off, struct pf_pdesc *pd,
|
|||
void
|
||||
pf_normalize_tcp_cleanup(struct pf_kstate *state)
|
||||
{
|
||||
/* XXX Note: this also cleans up SCTP. */
|
||||
uma_zfree(V_pf_state_scrub_z, state->src.scrub);
|
||||
uma_zfree(V_pf_state_scrub_z, state->dst.scrub);
|
||||
|
||||
/* Someday... flush the TCP segment reassembly descriptors. */
|
||||
}
|
||||
int
|
||||
pf_normalize_sctp_init(struct mbuf *m, int off, struct pf_pdesc *pd,
|
||||
struct pf_state_peer *src, struct pf_state_peer *dst)
|
||||
{
|
||||
src->scrub = uma_zalloc(V_pf_state_scrub_z, M_ZERO | M_NOWAIT);
|
||||
if (src->scrub == NULL)
|
||||
return (1);
|
||||
|
||||
dst->scrub = uma_zalloc(V_pf_state_scrub_z, M_ZERO | M_NOWAIT);
|
||||
if (dst->scrub == NULL) {
|
||||
uma_zfree(V_pf_state_scrub_z, src);
|
||||
return (1);
|
||||
}
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
int
|
||||
pf_normalize_tcp_stateful(struct mbuf *m, int off, struct pf_pdesc *pd,
|
||||
|
|
Loading…
Reference in a new issue