net/tcp: Prevent TCP-MD5 with TCP-AO being set
[linux-2.6-microblaze.git] / net / ipv4 / tcp_ipv4.c
index a4746c2..698e58a 100644 (file)
@@ -1082,7 +1082,7 @@ static bool better_md5_match(struct tcp_md5sig_key *old, struct tcp_md5sig_key *
 /* Find the Key structure for an address.  */
 struct tcp_md5sig_key *__tcp_md5_do_lookup(const struct sock *sk, int l3index,
                                           const union tcp_md5_addr *addr,
-                                          int family)
+                                          int family, bool any_l3index)
 {
        const struct tcp_sock *tp = tcp_sk(sk);
        struct tcp_md5sig_key *key;
@@ -1101,7 +1101,8 @@ struct tcp_md5sig_key *__tcp_md5_do_lookup(const struct sock *sk, int l3index,
                                 lockdep_sock_is_held(sk)) {
                if (key->family != family)
                        continue;
-               if (key->flags & TCP_MD5SIG_FLAG_IFINDEX && key->l3index != l3index)
+               if (!any_l3index && key->flags & TCP_MD5SIG_FLAG_IFINDEX &&
+                   key->l3index != l3index)
                        continue;
                if (family == AF_INET) {
                        mask = inet_make_mask(key->prefixlen);
@@ -1313,7 +1314,7 @@ int tcp_md5_do_del(struct sock *sk, const union tcp_md5_addr *addr, int family,
 }
 EXPORT_SYMBOL(tcp_md5_do_del);
 
-static void tcp_clear_md5_list(struct sock *sk)
+void tcp_clear_md5_list(struct sock *sk)
 {
        struct tcp_sock *tp = tcp_sk(sk);
        struct tcp_md5sig_key *key;
@@ -1383,6 +1384,12 @@ static int tcp_v4_parse_md5_keys(struct sock *sk, int optname,
        if (cmd.tcpm_keylen > TCP_MD5SIG_MAXKEYLEN)
                return -EINVAL;
 
+       /* Don't allow keys for peers that have a matching TCP-AO key.
+        * See the comment in tcp_ao_add_cmd()
+        */
+       if (tcp_ao_required(sk, addr, AF_INET))
+               return -EKEYREJECTED;
+
        return tcp_md5_do_add(sk, addr, AF_INET, prefixlen, l3index, flags,
                              cmd.tcpm_key, cmd.tcpm_keylen);
 }
@@ -2279,6 +2286,7 @@ static const struct tcp_sock_af_ops tcp_sock_ipv4_specific = {
        .md5_parse              = tcp_v4_parse_md5_keys,
 #endif
 #ifdef CONFIG_TCP_AO
+       .ao_lookup              = tcp_v4_ao_lookup,
        .ao_parse               = tcp_v4_parse_ao,
 #endif
 };