diff options
Diffstat (limited to 'sys/netipsec/ipsec.c')
-rw-r--r-- | sys/netipsec/ipsec.c | 135 |
1 files changed, 51 insertions, 84 deletions
diff --git a/sys/netipsec/ipsec.c b/sys/netipsec/ipsec.c index 93e37e8..bf02f93 100644 --- a/sys/netipsec/ipsec.c +++ b/sys/netipsec/ipsec.c @@ -117,11 +117,12 @@ VNET_DEFINE(int, ip4_esp_trans_deflev) = IPSEC_LEVEL_USE; VNET_DEFINE(int, ip4_esp_net_deflev) = IPSEC_LEVEL_USE; VNET_DEFINE(int, ip4_ah_trans_deflev) = IPSEC_LEVEL_USE; VNET_DEFINE(int, ip4_ah_net_deflev) = IPSEC_LEVEL_USE; -VNET_DEFINE(struct secpolicy, ip4_def_policy); /* ECN ignore(-1)/forbidden(0)/allowed(1) */ VNET_DEFINE(int, ip4_ipsec_ecn) = 0; VNET_DEFINE(int, ip4_esp_randpad) = -1; +static VNET_DEFINE(struct secpolicy, def_policy); +#define V_def_policy VNET(def_policy) /* * Crypto support requirements: * @@ -140,7 +141,7 @@ SYSCTL_DECL(_net_inet_ipsec); /* net.inet.ipsec */ SYSCTL_VNET_INT(_net_inet_ipsec, IPSECCTL_DEF_POLICY, def_policy, - CTLFLAG_RW, &VNET_NAME(ip4_def_policy).policy, 0, + CTLFLAG_RW, &VNET_NAME(def_policy).policy, 0, "IPsec default policy."); SYSCTL_VNET_INT(_net_inet_ipsec, IPSECCTL_DEF_ESP_TRANSLEV, esp_trans_deflev, CTLFLAG_RW, &VNET_NAME(ip4_esp_trans_deflev), 0, @@ -212,7 +213,7 @@ SYSCTL_DECL(_net_inet6_ipsec6); /* net.inet6.ipsec6 */ SYSCTL_VNET_INT(_net_inet6_ipsec6, IPSECCTL_DEF_POLICY, def_policy, CTLFLAG_RW, - &VNET_NAME(ip4_def_policy).policy, 0, + &VNET_NAME(def_policy).policy, 0, "IPsec default policy."); SYSCTL_VNET_INT(_net_inet6_ipsec6, IPSECCTL_DEF_ESP_TRANSLEV, esp_trans_deflev, CTLFLAG_RW, &VNET_NAME(ip6_esp_trans_deflev), 0, @@ -236,6 +237,7 @@ SYSCTL_VNET_PCPUSTAT(_net_inet6_ipsec6, IPSECCTL_STATS, ipsecstats, struct ipsecstat, ipsec6stat, "IPsec IPv6 statistics."); #endif /* INET6 */ +static int ipsec_in_reject(struct secpolicy *, struct mbuf *); static int ipsec_setspidx_inpcb(struct mbuf *, struct inpcb *); static int ipsec_setspidx(struct mbuf *, struct secpolicyindex *, int); static void ipsec4_get_ulp(struct mbuf *m, struct secpolicyindex *, int); @@ -261,7 +263,7 @@ key_allocsp_default(const char* where, int tag) KEYDEBUG(KEYDEBUG_IPSEC_STAMP, printf("DP key_allocsp_default from %s:%u\n", where, tag)); - sp = &V_ip4_def_policy; + sp = &V_def_policy; if (sp->policy != IPSEC_POLICY_DISCARD && sp->policy != IPSEC_POLICY_NONE) { ipseclog((LOG_INFO, "fixed system default policy: %d->%d\n", @@ -331,6 +333,12 @@ ipsec_getpolicybysock(struct mbuf *m, u_int dir, struct inpcb *inp, int *error) IPSEC_ASSERT(dir == IPSEC_DIR_INBOUND || dir == IPSEC_DIR_OUTBOUND, ("invalid direction %u", dir)); + if (!key_havesp(dir)) { + /* No SP found, use system default. */ + sp = KEY_ALLOCSP_DEFAULT(); + return (sp); + } + /* Set spidx in pcb. */ *error = ipsec_setspidx_inpcb(m, inp); if (*error) @@ -416,7 +424,7 @@ ipsec_getpolicybysock(struct mbuf *m, u_int dir, struct inpcb *inp, int *error) * others : error occured. */ struct secpolicy * -ipsec_getpolicybyaddr(struct mbuf *m, u_int dir, int flag, int *error) +ipsec_getpolicybyaddr(struct mbuf *m, u_int dir, int *error) { struct secpolicyindex spidx; struct secpolicy *sp; @@ -427,17 +435,16 @@ ipsec_getpolicybyaddr(struct mbuf *m, u_int dir, int flag, int *error) ("invalid direction %u", dir)); sp = NULL; + *error = 0; if (key_havesp(dir)) { /* Make an index to look for a policy. */ - *error = ipsec_setspidx(m, &spidx, - (flag & IP_FORWARDING) ? 0 : 1); + *error = ipsec_setspidx(m, &spidx, 0); if (*error != 0) { - DPRINTF(("%s: setpidx failed, dir %u flag %u\n", - __func__, dir, flag)); + DPRINTF(("%s: setpidx failed, dir %u\n", + __func__, dir)); return (NULL); } spidx.dir = dir; - sp = KEY_ALLOCSP(&spidx, dir); } if (sp == NULL) /* No SP found, use system default. */ @@ -447,14 +454,13 @@ ipsec_getpolicybyaddr(struct mbuf *m, u_int dir, int flag, int *error) } struct secpolicy * -ipsec4_checkpolicy(struct mbuf *m, u_int dir, u_int flag, int *error, - struct inpcb *inp) +ipsec4_checkpolicy(struct mbuf *m, u_int dir, int *error, struct inpcb *inp) { struct secpolicy *sp; *error = 0; if (inp == NULL) - sp = ipsec_getpolicybyaddr(m, dir, flag, error); + sp = ipsec_getpolicybyaddr(m, dir, error); else sp = ipsec_getpolicybysock(m, dir, inp, error); if (sp == NULL) { @@ -829,17 +835,13 @@ ipsec_init_policy(struct socket *so, struct inpcbpolicy **pcb_sp) ipsec_delpcbpolicy(new); return (ENOBUFS); } - new->sp_in->state = IPSEC_SPSTATE_ALIVE; new->sp_in->policy = IPSEC_POLICY_ENTRUST; - if ((new->sp_out = KEY_NEWSP()) == NULL) { KEY_FREESP(&new->sp_in); ipsec_delpcbpolicy(new); return (ENOBUFS); } - new->sp_out->state = IPSEC_SPSTATE_ALIVE; new->sp_out->policy = IPSEC_POLICY_ENTRUST; - *pcb_sp = new; return (0); @@ -928,7 +930,6 @@ ipsec_deepcopy_policy(struct secpolicy *src) } dst->req = newchain; - dst->state = src->state; dst->policy = src->policy; /* Do not touch the refcnt fields. */ @@ -980,8 +981,6 @@ ipsec_set_policy_internal(struct secpolicy **pcb_sp, int optname, if ((newsp = key_msg2sp(xpl, len, &error)) == NULL) return (error); - newsp->state = IPSEC_SPSTATE_ALIVE; - /* Clear old SP and set new SP. */ KEY_FREESP(pcb_sp); *pcb_sp = newsp; @@ -1198,7 +1197,7 @@ ipsec_get_reqlevel(struct ipsecrequest *isr) * 0: valid * 1: invalid */ -int +static int ipsec_in_reject(struct secpolicy *sp, struct mbuf *m) { struct ipsecrequest *isr; @@ -1266,6 +1265,9 @@ ipsec_in_reject(struct secpolicy *sp, struct mbuf *m) return (0); /* Valid. */ } +/* + * Non zero return value means security policy DISCARD or policy violation. + */ static int ipsec46_in_reject(struct mbuf *m, struct inpcb *inp) { @@ -1278,13 +1280,9 @@ ipsec46_in_reject(struct mbuf *m, struct inpcb *inp) IPSEC_ASSERT(m != NULL, ("null mbuf")); - /* - * Get SP for this packet. - * When we are called from ip_forward(), we call - * ipsec_getpolicybyaddr() with IP_FORWARDING flag. - */ + /* Get SP for this packet. */ if (inp == NULL) - sp = ipsec_getpolicybyaddr(m, IPSEC_DIR_INBOUND, IP_FORWARDING, &error); + sp = ipsec_getpolicybyaddr(m, IPSEC_DIR_INBOUND, &error); else sp = ipsec_getpolicybysock(m, IPSEC_DIR_INBOUND, inp, &error); @@ -1292,8 +1290,7 @@ ipsec46_in_reject(struct mbuf *m, struct inpcb *inp) result = ipsec_in_reject(sp, m); KEY_FREESP(&sp); } else { - result = 0; /* XXX Should be panic? - * -> No, there may be error. */ + result = 1; /* treat errors as policy violation */ } return (result); } @@ -1413,12 +1410,9 @@ ipsec_hdrsiz(struct mbuf *m, u_int dir, struct inpcb *inp) IPSEC_ASSERT(m != NULL, ("null mbuf")); - /* Get SP for this packet. - * When we are called from ip_forward(), we call - * ipsec_getpolicybyaddr() with IP_FORWARDING flag. - */ + /* Get SP for this packet. */ if (inp == NULL) - sp = ipsec_getpolicybyaddr(m, dir, IP_FORWARDING, &error); + sp = ipsec_getpolicybyaddr(m, dir, &error); else sp = ipsec_getpolicybysock(m, dir, inp, &error); @@ -1506,6 +1500,7 @@ ipsec_chkreplay(u_int32_t seq, struct secasvar *sav) int ipsec_updatereplay(u_int32_t seq, struct secasvar *sav) { + char buf[128]; struct secreplay *replay; u_int32_t diff; int fr; @@ -1585,7 +1580,8 @@ ok: return (1); ipseclog((LOG_WARNING, "%s: replay counter made %d cycle. %s\n", - __func__, replay->overflow, ipsec_logsastr(sav))); + __func__, replay->overflow, + ipsec_logsastr(sav, buf, sizeof(buf)))); } replay->count++; @@ -1616,67 +1612,37 @@ vshiftl(unsigned char *bitmap, int nbit, int wsize) } } -#ifdef INET -/* Return a printable string for the IPv4 address. */ -static char * -inet_ntoa4(struct in_addr ina) -{ - static char buf[4][4 * sizeof "123" + 4]; - unsigned char *ucp = (unsigned char *) &ina; - static int i = 3; - - /* XXX-BZ Returns static buffer. */ - i = (i + 1) % 4; - sprintf(buf[i], "%d.%d.%d.%d", ucp[0] & 0xff, ucp[1] & 0xff, - ucp[2] & 0xff, ucp[3] & 0xff); - return (buf[i]); -} -#endif - /* Return a printable string for the address. */ -char * -ipsec_address(union sockaddr_union* sa) +char* +ipsec_address(union sockaddr_union* sa, char *buf, socklen_t size) { -#ifdef INET6 - char ip6buf[INET6_ADDRSTRLEN]; -#endif switch (sa->sa.sa_family) { #ifdef INET case AF_INET: - return (inet_ntoa4(sa->sin.sin_addr)); + return (inet_ntop(AF_INET, &sa->sin.sin_addr, buf, size)); #endif /* INET */ #ifdef INET6 case AF_INET6: - return (ip6_sprintf(ip6buf, &sa->sin6.sin6_addr)); + return (inet_ntop(AF_INET6, &sa->sin6.sin6_addr, buf, size)); #endif /* INET6 */ default: return ("(unknown address family)"); } } -const char * -ipsec_logsastr(struct secasvar *sav) +char * +ipsec_logsastr(struct secasvar *sav, char *buf, size_t size) { - static char buf[256]; - char *p; - struct secasindex *saidx = &sav->sah->saidx; - - IPSEC_ASSERT(saidx->src.sa.sa_family == saidx->dst.sa.sa_family, - ("address family mismatch")); - - p = buf; - snprintf(buf, sizeof(buf), "SA(SPI=%u ", (u_int32_t)ntohl(sav->spi)); - while (p && *p) - p++; - /* NB: only use ipsec_address on one address at a time. */ - snprintf(p, sizeof (buf) - (p - buf), "src=%s ", - ipsec_address(&saidx->src)); - while (p && *p) - p++; - snprintf(p, sizeof (buf) - (p - buf), "dst=%s)", - ipsec_address(&saidx->dst)); + char sbuf[INET6_ADDRSTRLEN], dbuf[INET6_ADDRSTRLEN]; + + IPSEC_ASSERT(sav->sah->saidx.src.sa.sa_family == + sav->sah->saidx.dst.sa.sa_family, ("address family mismatch")); + snprintf(buf, size, "SA(SPI=%08lx src=%s dst=%s)", + (u_long)ntohl(sav->spi), + ipsec_address(&sav->sah->saidx.src, sbuf, sizeof(sbuf)), + ipsec_address(&sav->sah->saidx.dst, dbuf, sizeof(dbuf))); return (buf); } @@ -1705,14 +1671,15 @@ ipsec_dumpmbuf(struct mbuf *m) } static void -ipsec_init(const void *unused __unused) +def_policy_init(const void *unused __unused) { - SECPOLICY_LOCK_INIT(&V_ip4_def_policy); - V_ip4_def_policy.refcnt = 1; /* NB: disallow free. */ + bzero(&V_def_policy, sizeof(struct secpolicy)); + V_def_policy.policy = IPSEC_POLICY_NONE; + V_def_policy.refcnt = 1; } -VNET_SYSINIT(ipsec_init, SI_SUB_PROTO_DOMAININIT, SI_ORDER_ANY, ipsec_init, - NULL); +VNET_SYSINIT(def_policy_init, SI_SUB_PROTO_DOMAININIT, SI_ORDER_ANY, + def_policy_init, NULL); /* XXX This stuff doesn't belong here... */ |