ip_fw2.c (193894) | ip_fw2.c (194498) |
---|---|
1/*- 2 * Copyright (c) 2002 Luigi Rizzo, Universita` di Pisa 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions 6 * are met: 7 * 1. Redistributions of source code must retain the above copyright 8 * notice, this list of conditions and the following disclaimer. --- 10 unchanged lines hidden (view full) --- 19 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 20 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 21 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 22 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 23 * SUCH DAMAGE. 24 */ 25 26#include <sys/cdefs.h> | 1/*- 2 * Copyright (c) 2002 Luigi Rizzo, Universita` di Pisa 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions 6 * are met: 7 * 1. Redistributions of source code must retain the above copyright 8 * notice, this list of conditions and the following disclaimer. --- 10 unchanged lines hidden (view full) --- 19 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 20 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 21 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 22 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 23 * SUCH DAMAGE. 24 */ 25 26#include <sys/cdefs.h> |
27__FBSDID("$FreeBSD: head/sys/netinet/ipfw/ip_fw2.c 193894 2009-06-10 10:34:59Z luigi $"); | 27__FBSDID("$FreeBSD: head/sys/netinet/ipfw/ip_fw2.c 194498 2009-06-19 17:10:35Z brooks $"); |
28 29#define DEB(x) 30#define DDB(x) x 31 32/* 33 * Implement IP packet firewall (new version) 34 */ 35 --- 94 unchanged lines hidden (view full) --- 130#else 131static int default_to_accept; 132#endif 133static uma_zone_t ipfw_dyn_rule_zone; 134 135struct ip_fw *ip_fw_default_rule; 136 137/* | 28 29#define DEB(x) 30#define DDB(x) x 31 32/* 33 * Implement IP packet firewall (new version) 34 */ 35 --- 94 unchanged lines hidden (view full) --- 130#else 131static int default_to_accept; 132#endif 133static uma_zone_t ipfw_dyn_rule_zone; 134 135struct ip_fw *ip_fw_default_rule; 136 137/* |
138 * Data structure to cache our ucred related 139 * information. This structure only gets used if 140 * the user specified UID/GID based constraints in 141 * a firewall rule. 142 */ 143struct ip_fw_ugid { 144 gid_t fw_groups[NGROUPS]; 145 int fw_ngroups; 146 uid_t fw_uid; 147 int fw_prid; 148}; 149 150/* | |
151 * list of rules for layer 3 152 */ 153#ifdef VIMAGE_GLOBALS 154struct ip_fw_chain layer3_chain; 155#endif 156 157MALLOC_DEFINE(M_IPFW, "IpFw/IpAcct", "IpFw/IpAcct chain's"); 158MALLOC_DEFINE(M_IPFW_TBL, "ipfw_tbl", "IpFw tables"); --- 1845 unchanged lines hidden (view full) --- 2004 if (tbl->tbl >= IPFW_TABLES_MAX) 2005 return (EINVAL); 2006 rnh = ch->tables[tbl->tbl]; 2007 tbl->cnt = 0; 2008 rnh->rnh_walktree(rnh, dump_table_entry, tbl); 2009 return (0); 2010} 2011 | 138 * list of rules for layer 3 139 */ 140#ifdef VIMAGE_GLOBALS 141struct ip_fw_chain layer3_chain; 142#endif 143 144MALLOC_DEFINE(M_IPFW, "IpFw/IpAcct", "IpFw/IpAcct chain's"); 145MALLOC_DEFINE(M_IPFW_TBL, "ipfw_tbl", "IpFw tables"); --- 1845 unchanged lines hidden (view full) --- 1991 if (tbl->tbl >= IPFW_TABLES_MAX) 1992 return (EINVAL); 1993 rnh = ch->tables[tbl->tbl]; 1994 tbl->cnt = 0; 1995 rnh->rnh_walktree(rnh, dump_table_entry, tbl); 1996 return (0); 1997} 1998 |
2012static void 2013fill_ugid_cache(struct inpcb *inp, struct ip_fw_ugid *ugp) 2014{ 2015 struct ucred *cr; 2016 2017 cr = inp->inp_cred; 2018 ugp->fw_prid = jailed(cr) ? cr->cr_prison->pr_id : -1; 2019 ugp->fw_uid = cr->cr_uid; 2020 ugp->fw_ngroups = cr->cr_ngroups; 2021 bcopy(cr->cr_groups, ugp->fw_groups, sizeof(ugp->fw_groups)); 2022} 2023 | |
2024static int 2025check_uidgid(ipfw_insn_u32 *insn, int proto, struct ifnet *oif, 2026 struct in_addr dst_ip, u_int16_t dst_port, struct in_addr src_ip, | 1999static int 2000check_uidgid(ipfw_insn_u32 *insn, int proto, struct ifnet *oif, 2001 struct in_addr dst_ip, u_int16_t dst_port, struct in_addr src_ip, |
2027 u_int16_t src_port, struct ip_fw_ugid *ugp, int *ugid_lookupp, | 2002 u_int16_t src_port, struct ucred **uc, int *ugid_lookupp, |
2028 struct inpcb *inp) 2029{ 2030 INIT_VNET_INET(curvnet); 2031 struct inpcbinfo *pi; 2032 int wildcard; 2033 struct inpcb *pcb; 2034 int match; | 2003 struct inpcb *inp) 2004{ 2005 INIT_VNET_INET(curvnet); 2006 struct inpcbinfo *pi; 2007 int wildcard; 2008 struct inpcb *pcb; 2009 int match; |
2035 gid_t *gp; | |
2036 2037 /* 2038 * Check to see if the UDP or TCP stack supplied us with 2039 * the PCB. If so, rather then holding a lock and looking 2040 * up the PCB, we can use the one that was supplied. 2041 */ 2042 if (inp && *ugid_lookupp == 0) { 2043 INP_LOCK_ASSERT(inp); 2044 if (inp->inp_socket != NULL) { | 2010 2011 /* 2012 * Check to see if the UDP or TCP stack supplied us with 2013 * the PCB. If so, rather then holding a lock and looking 2014 * up the PCB, we can use the one that was supplied. 2015 */ 2016 if (inp && *ugid_lookupp == 0) { 2017 INP_LOCK_ASSERT(inp); 2018 if (inp->inp_socket != NULL) { |
2045 fill_ugid_cache(inp, ugp); | 2019 *uc = crhold(inp->inp_cred); |
2046 *ugid_lookupp = 1; 2047 } else 2048 *ugid_lookupp = -1; 2049 } 2050 /* 2051 * If we have already been here and the packet has no 2052 * PCB entry associated with it, then we can safely 2053 * assume that this is a no match. --- 16 unchanged lines hidden (view full) --- 2070 dst_ip, htons(dst_port), 2071 src_ip, htons(src_port), 2072 wildcard, oif) : 2073 in_pcblookup_hash(pi, 2074 src_ip, htons(src_port), 2075 dst_ip, htons(dst_port), 2076 wildcard, NULL); 2077 if (pcb != NULL) { | 2020 *ugid_lookupp = 1; 2021 } else 2022 *ugid_lookupp = -1; 2023 } 2024 /* 2025 * If we have already been here and the packet has no 2026 * PCB entry associated with it, then we can safely 2027 * assume that this is a no match. --- 16 unchanged lines hidden (view full) --- 2044 dst_ip, htons(dst_port), 2045 src_ip, htons(src_port), 2046 wildcard, oif) : 2047 in_pcblookup_hash(pi, 2048 src_ip, htons(src_port), 2049 dst_ip, htons(dst_port), 2050 wildcard, NULL); 2051 if (pcb != NULL) { |
2078 fill_ugid_cache(pcb, ugp); | 2052 *uc = crhold(inp->inp_cred); |
2079 *ugid_lookupp = 1; 2080 } 2081 INP_INFO_RUNLOCK(pi); 2082 if (*ugid_lookupp == 0) { 2083 /* 2084 * If the lookup did not yield any results, there 2085 * is no sense in coming back and trying again. So 2086 * we can set lookup to -1 and ensure that we wont 2087 * bother the pcb system again. 2088 */ 2089 *ugid_lookupp = -1; 2090 return (0); 2091 } 2092 } 2093 if (insn->o.opcode == O_UID) | 2053 *ugid_lookupp = 1; 2054 } 2055 INP_INFO_RUNLOCK(pi); 2056 if (*ugid_lookupp == 0) { 2057 /* 2058 * If the lookup did not yield any results, there 2059 * is no sense in coming back and trying again. So 2060 * we can set lookup to -1 and ensure that we wont 2061 * bother the pcb system again. 2062 */ 2063 *ugid_lookupp = -1; 2064 return (0); 2065 } 2066 } 2067 if (insn->o.opcode == O_UID) |
2094 match = (ugp->fw_uid == (uid_t)insn->d[0]); 2095 else if (insn->o.opcode == O_GID) { 2096 for (gp = ugp->fw_groups; 2097 gp < &ugp->fw_groups[ugp->fw_ngroups]; gp++) 2098 if (*gp == (gid_t)insn->d[0]) { 2099 match = 1; 2100 break; 2101 } 2102 } else if (insn->o.opcode == O_JAIL) 2103 match = (ugp->fw_prid == (int)insn->d[0]); | 2068 match = ((*uc)->cr_uid == (uid_t)insn->d[0]); 2069 else if (insn->o.opcode == O_GID) 2070 match = groupmember((gid_t)insn->d[0], *uc); 2071 else if (insn->o.opcode == O_JAIL) 2072 match = ((*uc)->cr_prison->pr_id == (int)insn->d[0]); |
2104 return match; 2105} 2106 2107/* 2108 * The main check routine for the firewall. 2109 * 2110 * All arguments are in args so we can modify them and return them 2111 * back to the caller. --- 61 unchanged lines hidden (view full) --- 2173 2174 /* 2175 * For rules which contain uid/gid or jail constraints, cache 2176 * a copy of the users credentials after the pcb lookup has been 2177 * executed. This will speed up the processing of rules with 2178 * these types of constraints, as well as decrease contention 2179 * on pcb related locks. 2180 */ | 2073 return match; 2074} 2075 2076/* 2077 * The main check routine for the firewall. 2078 * 2079 * All arguments are in args so we can modify them and return them 2080 * back to the caller. --- 61 unchanged lines hidden (view full) --- 2142 2143 /* 2144 * For rules which contain uid/gid or jail constraints, cache 2145 * a copy of the users credentials after the pcb lookup has been 2146 * executed. This will speed up the processing of rules with 2147 * these types of constraints, as well as decrease contention 2148 * on pcb related locks. 2149 */ |
2181 struct ip_fw_ugid fw_ugid_cache; 2182 int ugid_lookup = 0; | 2150 struct ucred *ucred_cache = NULL; 2151 int ucred_lookup = 0; |
2183 2184 /* 2185 * divinput_flags If non-zero, set to the IP_FW_DIVERT_*_FLAG 2186 * associated with a packet input on a divert socket. This 2187 * will allow to distinguish traffic and its direction when 2188 * it originates from a divert socket. 2189 */ 2190 u_int divinput_flags = 0; --- 445 unchanged lines hidden (view full) --- 2636 if (is_ipv6) /* XXX to be fixed later */ 2637 break; 2638 if (proto == IPPROTO_TCP || 2639 proto == IPPROTO_UDP) 2640 match = check_uidgid( 2641 (ipfw_insn_u32 *)cmd, 2642 proto, oif, 2643 dst_ip, dst_port, | 2152 2153 /* 2154 * divinput_flags If non-zero, set to the IP_FW_DIVERT_*_FLAG 2155 * associated with a packet input on a divert socket. This 2156 * will allow to distinguish traffic and its direction when 2157 * it originates from a divert socket. 2158 */ 2159 u_int divinput_flags = 0; --- 445 unchanged lines hidden (view full) --- 2605 if (is_ipv6) /* XXX to be fixed later */ 2606 break; 2607 if (proto == IPPROTO_TCP || 2608 proto == IPPROTO_UDP) 2609 match = check_uidgid( 2610 (ipfw_insn_u32 *)cmd, 2611 proto, oif, 2612 dst_ip, dst_port, |
2644 src_ip, src_port, &fw_ugid_cache, 2645 &ugid_lookup, args->inp); | 2613 src_ip, src_port, &ucred_cache, 2614 &ucred_lookup, args->inp); |
2646 break; 2647 2648 case O_RECV: 2649 match = iface_match(m->m_pkthdr.rcvif, 2650 (ipfw_insn_if *)cmd); 2651 break; 2652 2653 case O_XMIT: --- 611 unchanged lines hidden (view full) --- 3265 break; 3266 mtag = m_tag_get(PACKET_TAG_DIVERT, 3267 sizeof(struct divert_tag), 3268 M_NOWAIT); 3269 if (mtag == NULL) { 3270 /* XXX statistic */ 3271 /* drop packet */ 3272 IPFW_RUNLOCK(chain); | 2615 break; 2616 2617 case O_RECV: 2618 match = iface_match(m->m_pkthdr.rcvif, 2619 (ipfw_insn_if *)cmd); 2620 break; 2621 2622 case O_XMIT: --- 611 unchanged lines hidden (view full) --- 3234 break; 3235 mtag = m_tag_get(PACKET_TAG_DIVERT, 3236 sizeof(struct divert_tag), 3237 M_NOWAIT); 3238 if (mtag == NULL) { 3239 /* XXX statistic */ 3240 /* drop packet */ 3241 IPFW_RUNLOCK(chain); |
3242 if (ucred_cache != NULL) 3243 crfree(ucred_cache); |
|
3273 return (IP_FW_DENY); 3274 } 3275 dt = (struct divert_tag *)(mtag+1); 3276 dt->cookie = f->rulenum; 3277 if (cmd->arg1 == IP_FW_TABLEARG) 3278 dt->info = tablearg; 3279 else 3280 dt->info = cmd->arg1; --- 189 unchanged lines hidden (view full) --- 3470 3471 } /* end of inner for, scan opcodes */ 3472 3473next_rule:; /* try next rule */ 3474 3475 } /* end of outer for, scan rules */ 3476 printf("ipfw: ouch!, skip past end of rules, denying packet\n"); 3477 IPFW_RUNLOCK(chain); | 3244 return (IP_FW_DENY); 3245 } 3246 dt = (struct divert_tag *)(mtag+1); 3247 dt->cookie = f->rulenum; 3248 if (cmd->arg1 == IP_FW_TABLEARG) 3249 dt->info = tablearg; 3250 else 3251 dt->info = cmd->arg1; --- 189 unchanged lines hidden (view full) --- 3441 3442 } /* end of inner for, scan opcodes */ 3443 3444next_rule:; /* try next rule */ 3445 3446 } /* end of outer for, scan rules */ 3447 printf("ipfw: ouch!, skip past end of rules, denying packet\n"); 3448 IPFW_RUNLOCK(chain); |
3449 if (ucred_cache != NULL) 3450 crfree(ucred_cache); |
|
3478 return (IP_FW_DENY); 3479 3480done: 3481 /* Update statistics */ 3482 f->pcnt++; 3483 f->bcnt += pktlen; 3484 f->timestamp = time_uptime; 3485 IPFW_RUNLOCK(chain); | 3451 return (IP_FW_DENY); 3452 3453done: 3454 /* Update statistics */ 3455 f->pcnt++; 3456 f->bcnt += pktlen; 3457 f->timestamp = time_uptime; 3458 IPFW_RUNLOCK(chain); |
3459 if (ucred_cache != NULL) 3460 crfree(ucred_cache); |
|
3486 return (retval); 3487 3488pullup_failed: 3489 if (V_fw_verbose) 3490 printf("ipfw: pullup failed\n"); 3491 return (IP_FW_DENY); 3492} 3493 --- 1260 unchanged lines hidden --- | 3461 return (retval); 3462 3463pullup_failed: 3464 if (V_fw_verbose) 3465 printf("ipfw: pullup failed\n"); 3466 return (IP_FW_DENY); 3467} 3468 --- 1260 unchanged lines hidden --- |