From d468f5520cb27434701c19a9a1c745b39679516b Mon Sep 17 00:00:00 2001 From: "Angelos D. Keromytis" Date: Tue, 12 Jun 2001 10:59:54 +0000 Subject: IPsec-related socket options; these can be set/removed/retrieved, but are not taken into consideration in anything just yet. --- sys/netinet/in_pcb.c | 8 ++- sys/netinet/in_pcb.h | 5 +- sys/netinet/ip_output.c | 159 +++++++++++++++++++++++++++++++++++++++++------- sys/netinet/tcp_input.c | 14 +++-- 4 files changed, 155 insertions(+), 31 deletions(-) (limited to 'sys/netinet') diff --git a/sys/netinet/in_pcb.c b/sys/netinet/in_pcb.c index eec4c6ef0bb..413fd282fdb 100644 --- a/sys/netinet/in_pcb.c +++ b/sys/netinet/in_pcb.c @@ -1,4 +1,4 @@ -/* $OpenBSD: in_pcb.c,v 1.54 2001/06/08 03:53:45 angelos Exp $ */ +/* $OpenBSD: in_pcb.c,v 1.55 2001/06/12 10:59:53 angelos Exp $ */ /* $NetBSD: in_pcb.c,v 1.25 1996/02/13 23:41:53 christos Exp $ */ /* @@ -578,8 +578,10 @@ in_pcbdetach(v) ipsp_reffree(inp->inp_ipsec_localcred); if (inp->inp_ipsec_remotecred) ipsp_reffree(inp->inp_ipsec_remotecred); - if (inp->inp_ipsec_auth) - ipsp_reffree(inp->inp_ipsec_auth); + if (inp->inp_ipsec_localauth) + ipsp_reffree(inp->inp_ipsec_localauth); + if (inp->inp_ipsec_remoteauth) + ipsp_reffree(inp->inp_ipsec_remoteauth); splx(s); #endif s = splnet(); diff --git a/sys/netinet/in_pcb.h b/sys/netinet/in_pcb.h index 7dfc1441c3e..324c1a0ec5c 100644 --- a/sys/netinet/in_pcb.h +++ b/sys/netinet/in_pcb.h @@ -1,4 +1,4 @@ -/* $OpenBSD: in_pcb.h,v 1.36 2001/06/09 07:03:40 angelos Exp $ */ +/* $OpenBSD: in_pcb.h,v 1.37 2001/06/12 10:59:53 angelos Exp $ */ /* $NetBSD: in_pcb.h,v 1.14 1996/02/13 23:42:00 christos Exp $ */ /* @@ -140,7 +140,8 @@ struct inpcb { struct ipsec_ref *inp_ipsec_remoteid; struct ipsec_ref *inp_ipsec_localcred; struct ipsec_ref *inp_ipsec_remotecred; - struct ipsec_ref *inp_ipsec_auth; + struct ipsec_ref *inp_ipsec_localauth; + struct ipsec_ref *inp_ipsec_remoteauth; #define inp_flowinfo inp_hu.hu_ipv6.ip6_flow int in6p_cksum; diff --git a/sys/netinet/ip_output.c b/sys/netinet/ip_output.c index 01480a04faa..180412f42ec 100644 --- a/sys/netinet/ip_output.c +++ b/sys/netinet/ip_output.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ip_output.c,v 1.101 2001/06/08 03:53:46 angelos Exp $ */ +/* $OpenBSD: ip_output.c,v 1.102 2001/06/12 10:59:53 angelos Exp $ */ /* $NetBSD: ip_output.c,v 1.28 1996/02/13 23:43:07 christos Exp $ */ /* @@ -801,7 +801,8 @@ ip_ctloutput(op, so, level, optname, mp) register struct mbuf *m = *mp; register int optval = 0; #ifdef IPSEC - struct proc *p = curproc; /* XXX */ + struct ipsec_ref *ipr; + u_int16_t opt16val; #endif int error = 0; @@ -919,7 +920,7 @@ ip_ctloutput(op, so, level, optname, mp) switch (optname) { case IP_AUTH_LEVEL: if (optval < ipsec_auth_default_level && - suser(p->p_ucred, &p->p_acflag)) { + (so->so_state & SS_PRIV)) { error = EACCES; break; } @@ -928,7 +929,7 @@ ip_ctloutput(op, so, level, optname, mp) case IP_ESP_TRANS_LEVEL: if (optval < ipsec_esp_trans_default_level && - suser(p->p_ucred, &p->p_acflag)) { + (so->so_state & SS_PRIV)) { error = EACCES; break; } @@ -937,7 +938,7 @@ ip_ctloutput(op, so, level, optname, mp) case IP_ESP_NETWORK_LEVEL: if (optval < ipsec_esp_network_default_level && - suser(p->p_ucred, &p->p_acflag)) { + (so->so_state & SS_PRIV)) { error = EACCES; break; } @@ -949,29 +950,125 @@ ip_ctloutput(op, so, level, optname, mp) #endif break; + case IP_IPSEC_REMOTE_CRED: + case IP_IPSEC_REMOTE_AUTH: + /* Can't set the remote credential or key */ + error = EOPNOTSUPP; + break; + case IP_IPSEC_LOCAL_ID: case IP_IPSEC_REMOTE_ID: case IP_IPSEC_LOCAL_CRED: - case IP_IPSEC_REMOTE_CRED: - case IP_IPSEC_AUTH: + case IP_IPSEC_LOCAL_AUTH: #ifndef IPSEC error = EOPNOTSUPP; #else + if (m->m_len < 2) { + error = EINVAL; + break; + } + + m_copydata(m, 0, 2, (caddr_t) &opt16val); + + /* If the type is 0, then we cleanup and return */ + if (opt16val == 0) { + switch (optname) { + case IP_IPSEC_LOCAL_ID: + if (inp->inp_ipsec_localid != NULL) + ipsp_reffree(inp->inp_ipsec_localid); + inp->inp_ipsec_localid = NULL; + break; + + case IP_IPSEC_REMOTE_ID: + if (inp->inp_ipsec_remoteid != NULL) + ipsp_reffree(inp->inp_ipsec_remoteid); + inp->inp_ipsec_remoteid = NULL; + break; + + case IP_IPSEC_LOCAL_CRED: + if (inp->inp_ipsec_localcred != NULL) + ipsp_reffree(inp->inp_ipsec_localcred); + inp->inp_ipsec_localcred = NULL; + break; + + case IP_IPSEC_LOCAL_AUTH: + if (inp->inp_ipsec_localauth != NULL) + ipsp_reffree(inp->inp_ipsec_localauth); + inp->inp_ipsec_localauth = NULL; + break; + } + + error = 0; + break; + } + + /* Can't have an empty payload */ + if (m->m_len == 2) { + error = EINVAL; + break; + } + + MALLOC(ipr, struct ipsec_ref *, + sizeof(struct ipsec_ref) + m->m_len - 2, + M_CREDENTIALS, M_NOWAIT); + if (ipr == NULL) { + error = ENOBUFS; + break; + } + ipr->ref_count = 1; + ipr->ref_malloctype = M_CREDENTIALS; + ipr->ref_len = m->m_len - 2; + ipr->ref_type = opt16val; + m_copydata(m, 2, m->m_len - 2, (caddr_t)(ipr + 1)); + switch (optname) { case IP_IPSEC_LOCAL_ID: - /* XXX */ + /* Check valid types and NUL-termination */ + if (ipr->ref_type < IPSP_IDENTITY_PREFIX + || ipr->ref_type > IPSP_IDENTITY_CONNECTION + || ((char *)(ipr + 1))[ipr->ref_len - 1]) { + FREE(ipr, M_CREDENTIALS); + error = EINVAL; + } else { + if (inp->inp_ipsec_localid != NULL) + ipsp_reffree(inp->inp_ipsec_localid); + inp->inp_ipsec_localid = ipr; + } break; case IP_IPSEC_REMOTE_ID: - /* XXX */ + /* Check valid types and NUL-termination */ + if (ipr->ref_type < IPSP_IDENTITY_PREFIX + || ipr->ref_type > IPSP_IDENTITY_CONNECTION + || ((char *)(ipr + 1))[ipr->ref_len - 1]) { + FREE(ipr, M_CREDENTIALS); + error = EINVAL; + } else { + if (inp->inp_ipsec_remoteid != NULL) + ipsp_reffree(inp->inp_ipsec_remoteid); + inp->inp_ipsec_remoteid = ipr; + } break; case IP_IPSEC_LOCAL_CRED: - /* XXX */ - break; - case IP_IPSEC_REMOTE_CRED: - /* XXX */ + if (ipr->ref_type < IPSP_CRED_KEYNOTE || + ipr->ref_type > IPSP_CRED_X509) { + FREE(ipr, M_CREDENTIALS); + error = EINVAL; + } else { + if (inp->inp_ipsec_localcred != NULL) + ipsp_reffree(inp->inp_ipsec_localcred); + inp->inp_ipsec_localcred = ipr; + } break; - case IP_IPSEC_AUTH: - /* XXX */ + case IP_IPSEC_LOCAL_AUTH: + if (ipr->ref_type < IPSP_AUTH_PASSPHRASE || + ipr->ref_type > IPSP_AUTH_RSA) { + FREE(ipr, M_CREDENTIALS); + error = EINVAL; + } else { + if (inp->inp_ipsec_localauth != NULL) + ipsp_reffree(inp->inp_ipsec_localauth); + inp->inp_ipsec_localauth = ipr; + } break; } #endif @@ -1081,27 +1178,45 @@ ip_ctloutput(op, so, level, optname, mp) case IP_IPSEC_REMOTE_ID: case IP_IPSEC_LOCAL_CRED: case IP_IPSEC_REMOTE_CRED: - case IP_IPSEC_AUTH: + case IP_IPSEC_LOCAL_AUTH: + case IP_IPSEC_REMOTE_AUTH: #ifndef IPSEC error = EOPNOTSUPP; #else + *mp = m = m_get(M_WAIT, MT_SOOPTS); + m->m_len = sizeof(u_int16_t); switch (optname) { case IP_IPSEC_LOCAL_ID: - /* XXX */ + ipr = inp->inp_ipsec_localid; + opt16val = IPSP_IDENTITY_NONE; break; case IP_IPSEC_REMOTE_ID: - /* XXX */ + ipr = inp->inp_ipsec_remoteid; + opt16val = IPSP_IDENTITY_NONE; break; case IP_IPSEC_LOCAL_CRED: - /* XXX */ + ipr = inp->inp_ipsec_localcred; + opt16val = IPSP_CRED_NONE; break; case IP_IPSEC_REMOTE_CRED: - /* XXX */ + ipr = inp->inp_ipsec_remotecred; + opt16val = IPSP_CRED_NONE; + break; + case IP_IPSEC_LOCAL_AUTH: + ipr = inp->inp_ipsec_localauth; break; - case IP_IPSEC_AUTH: - /* XXX */ + case IP_IPSEC_REMOTE_AUTH: + ipr = inp->inp_ipsec_remoteauth; break; } + if (ipr == NULL) + *mtod(m, u_int16_t *) = opt16val; + else { + m->m_len += ipr->ref_len; + *mtod(m, u_int16_t *) = ipr->ref_type; + m_copyback(m, sizeof(u_int16_t), ipr->ref_len, + (caddr_t)(ipr + 1)); + } #endif break; default: diff --git a/sys/netinet/tcp_input.c b/sys/netinet/tcp_input.c index 103e4a03694..750b3e58b8f 100644 --- a/sys/netinet/tcp_input.c +++ b/sys/netinet/tcp_input.c @@ -1,4 +1,4 @@ -/* $OpenBSD: tcp_input.c,v 1.93 2001/06/08 03:53:46 angelos Exp $ */ +/* $OpenBSD: tcp_input.c,v 1.94 2001/06/12 10:59:53 angelos Exp $ */ /* $NetBSD: tcp_input.c,v 1.23 1996/02/13 23:43:44 christos Exp $ */ /* @@ -734,9 +734,15 @@ findpcb: newinp->inp_ipsec_remotecred = inp->inp_ipsec_remotecred; inp->inp_ipsec_remotecred->ref_count++; } - if (inp->inp_ipsec_auth != NULL) { - newinp->inp_ipsec_auth = inp->inp_ipsec_auth; - inp->inp_ipsec_auth->ref_count++; + if (inp->inp_ipsec_localauth != NULL) { + newinp->inp_ipsec_localauth + = inp->inp_ipsec_localauth; + inp->inp_ipsec_localauth->ref_count++; + } + if (inp->inp_ipsec_remoteauth != NULL) { + newinp->inp_ipsec_remoteauth + = inp->inp_ipsec_remoteauth; + inp->inp_ipsec_remoteauth->ref_count++; } } #endif /* IPSEC */ -- cgit v1.2.3