From owner-svn-src-projects@freebsd.org Tue Dec 6 12:52:21 2016 Return-Path: Delivered-To: svn-src-projects@mailman.ysv.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:1900:2254:206a::19:1]) by mailman.ysv.freebsd.org (Postfix) with ESMTP id 5D720C6911C for ; Tue, 6 Dec 2016 12:52:21 +0000 (UTC) (envelope-from ae@FreeBSD.org) Received: from repo.freebsd.org (repo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:0]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by mx1.freebsd.org (Postfix) with ESMTPS id 1E807F31; Tue, 6 Dec 2016 12:52:21 +0000 (UTC) (envelope-from ae@FreeBSD.org) Received: from repo.freebsd.org ([127.0.1.37]) by repo.freebsd.org (8.15.2/8.15.2) with ESMTP id uB6CqKpP071527; Tue, 6 Dec 2016 12:52:20 GMT (envelope-from ae@FreeBSD.org) Received: (from ae@localhost) by repo.freebsd.org (8.15.2/8.15.2/Submit) id uB6CqKnH071526; Tue, 6 Dec 2016 12:52:20 GMT (envelope-from ae@FreeBSD.org) Message-Id: <201612061252.uB6CqKnH071526@repo.freebsd.org> X-Authentication-Warning: repo.freebsd.org: ae set sender to ae@FreeBSD.org using -f From: "Andrey V. Elsukov" Date: Tue, 6 Dec 2016 12:52:20 +0000 (UTC) To: src-committers@freebsd.org, svn-src-projects@freebsd.org Subject: svn commit: r309614 - projects/ipsec/sys/netipsec X-SVN-Group: projects MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-projects@freebsd.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: "SVN commit messages for the src " projects" tree" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Tue, 06 Dec 2016 12:52:21 -0000 Author: ae Date: Tue Dec 6 12:52:20 2016 New Revision: 309614 URL: https://svnweb.freebsd.org/changeset/base/309614 Log: Due to the changes in SADB now each SA has unique SPI. Previously TCP-MD5 SAs have one magic SPI = 0x1000. This was used by some applications. E.g. bird uses SADB_ADD and SADB_DELETE PF_KEY messages to configure security key used by TCP_MD5SIG socket option. To support old applications and configs add the workaround. When SADB_ADD, SADB_GET and SADB_DELETE messages are used for IPPROTO_TCP, do lookup for needed SA using its secasindex, instead of SPI. When several TCP-MD5 SAs added with one SPI value, use key_do_getnewspi to allocate new SPI value in SADB_ADD. Modified: projects/ipsec/sys/netipsec/key.c Modified: projects/ipsec/sys/netipsec/key.c ============================================================================== --- projects/ipsec/sys/netipsec/key.c Tue Dec 6 12:43:07 2016 (r309613) +++ projects/ipsec/sys/netipsec/key.c Tue Dec 6 12:52:20 2016 (r309614) @@ -4732,6 +4732,58 @@ key_do_getnewspi(struct sadb_spirange *s } /* + * Find TCP-MD5 SA with corresponding secasindex. + * If not found, return NULL and fill SPI with usable value if needed. + */ +static struct secasvar * +key_getsav_tcpmd5(struct secasindex *saidx, uint32_t *spi) +{ + SAHTREE_RLOCK_TRACKER; + struct secashead *sah; + struct secasvar *sav; + + IPSEC_ASSERT(saidx->proto == IPPROTO_TCP, ("wrong proto")); + SAHTREE_RLOCK(); + LIST_FOREACH(sah, SAHADDRHASH_HASH(saidx), addrhash) { + if (sah->saidx.proto != IPPROTO_TCP) + continue; + if (!key_sockaddrcmp(&saidx->dst.sa, &sah->saidx.dst.sa, + key_portfromsaddr(&sah->saidx.dst.sa))) + break; + } + if (sah != NULL) { + if (V_key_preferred_oldsa) + sav = TAILQ_LAST(&sah->savtree_alive, secasvar_queue); + else + sav = TAILQ_FIRST(&sah->savtree_alive); + if (sav != NULL) { + SAV_ADDREF(sav); + SAHTREE_RUNLOCK(); + return (sav); + } + } + if (spi == NULL) { + /* No SPI required */ + SAHTREE_RUNLOCK(); + return (NULL); + } + /* Check that SPI is unique */ + LIST_FOREACH(sav, SAVHASH_HASH(*spi), spihash) { + if (sav->spi == *spi) + break; + } + if (sav == NULL) { + SAHTREE_RUNLOCK(); + /* SPI is already unique */ + return (NULL); + } + SAHTREE_RUNLOCK(); + /* XXX: not optimal */ + *spi = key_do_getnewspi(NULL, saidx); + return (NULL); +} + +/* * SADB_UPDATE processing * receive * sadb_sa_spi); + spi = sa0->sadb_sa_spi; + /* + * XXX: For TCP-MD5 SAs we don't use SPI. + * Check the uniqueness using secasindex. + */ + if (proto == IPPROTO_TCP) { + sav = key_getsav_tcpmd5(&saidx, &spi); + if (sav == NULL && spi == 0) { + /* Failed to allocate SPI */ + ipseclog((LOG_DEBUG, "%s: SA already exists.\n", + __func__)); + return key_senderror(so, m, EEXIST); + } + /* XXX: SPI that we report back can have another value */ + } else { + /* We can create new SA only if SPI is different. */ + sav = key_getsavbyspi(spi); + } if (sav != NULL) { key_freesav(&sav); ipseclog((LOG_DEBUG, "%s: SA already exists.\n", __func__)); return key_senderror(so, m, EEXIST); } - sav = key_newsav(mhp, &saidx, sa0->sadb_sa_spi, &error); + sav = key_newsav(mhp, &saidx, spi, &error); if (sav == NULL) return key_senderror(so, m, error); KEYDBG(KEY_STAMP, @@ -5333,7 +5402,10 @@ key_delete(struct socket *so, struct mbu return (key_senderror(so, m, EINVAL)); } sa0 = (struct sadb_sa *)mhp->ext[SADB_EXT_SA]; - sav = key_getsavbyspi(sa0->sadb_sa_spi); + if (proto == IPPROTO_TCP) + sav = key_getsav_tcpmd5(&saidx, NULL); + else + sav = key_getsavbyspi(sa0->sadb_sa_spi); if (sav == NULL) { ipseclog((LOG_DEBUG, "%s: no SA found for SPI %u.\n", __func__, ntohl(sa0->sadb_sa_spi))); @@ -5504,14 +5576,17 @@ key_get(struct socket *so, struct mbuf * key_porttosaddr(&saidx.src.sa, 0); key_porttosaddr(&saidx.dst.sa, 0); - sav = key_getsavbyspi(sa0->sadb_sa_spi); + if (proto == IPPROTO_TCP) + sav = key_getsav_tcpmd5(&saidx, NULL); + else + sav = key_getsavbyspi(sa0->sadb_sa_spi); if (sav == NULL) { ipseclog((LOG_DEBUG, "%s: no SA found.\n", __func__)); return key_senderror(so, m, ESRCH); } if (key_cmpsaidx(&sav->sah->saidx, &saidx, CMP_HEAD) == 0) { ipseclog((LOG_DEBUG, "%s: saidx mismatched for SPI %u.\n", - __func__, ntohl(sav->spi))); + __func__, ntohl(sa0->sadb_sa_spi))); key_freesav(&sav); return (key_senderror(so, m, ESRCH)); }