]> git.ipfire.org Git - thirdparty/bird.git/commitdiff
working version of ao tcp
authorKaterina Kubecova <katerina.kubecova@nic.cz>
Mon, 5 Feb 2024 13:43:46 +0000 (14:43 +0100)
committerKaterina Kubecova <katerina.kubecova@nic.cz>
Mon, 5 Feb 2024 13:43:46 +0000 (14:43 +0100)
sysdep/linux/sysio.h
sysdep/linux/tcp-ao.h [new file with mode: 0644]

index f13eda7c08ad2b1f5b6847bd744d6656e478f4fb..1aa78ab91b2c5502235a48f64bbe17e0a3e01a1b 100644 (file)
@@ -6,6 +6,8 @@
  *     Can be freely distributed and used under the terms of the GNU GPL.
  */
 
+#include "sysdep/linux/tcp-ao.h"
+
 #ifndef IPV6_MINHOPCOUNT
 #define IPV6_MINHOPCOUNT 73
 #endif
 #define TCP_MD5SIG_FLAG_PREFIX 1
 #endif
 
+#ifndef TCP_AO_ADD_KEY
+#define TCP_AO_ADD_KEY         38      /* Add/Set MKT */
+#define TCP_AO_DEL_KEY         39      /* Delete MKT */
+#define TCP_AO_INFO            40      /* Set/list TCP-AO per-socket options */
+#define TCP_AO_GET_KEYS                41      /* List MKT(s) */
+#define TCP_AO_REPAIR          42      /* Get/Set SNEs and ISNs */
+
+#endif
+
 /* We redefine the tcp_md5sig structure with different name to avoid collision with older headers */
 struct tcp_md5sig_ext {
   struct  sockaddr_storage tcpm_addr;          /* Address associated */
@@ -166,7 +177,7 @@ sk_prepare_cmsgs4(sock *s, struct msghdr *msg, void *cbuf, size_t cbuflen)
  */
 
 int
-sk_set_md5_auth(sock *s, ip_addr local UNUSED, ip_addr remote, int pxlen, struct iface *ifa, const char *passwd, int setkey UNUSED)
+sk_set_md5_auth(sock *s, ip_addr local, ip_addr remote, int pxlen, struct iface *ifa, const char *passwd, int setkey UNUSED) // local UNUSED
 {
   struct tcp_md5sig_ext md5;
 
@@ -184,6 +195,69 @@ sk_set_md5_auth(sock *s, ip_addr local UNUSED, ip_addr remote, int pxlen, struct
     memcpy(&md5.tcpm_key, passwd, len);
   }
 
+  if (pxlen < 0)
+  {
+    struct tcp_ao_add_ext ao;
+    memset(&ao, 0, sizeof(struct tcp_ao_add_ext));
+    sockaddr_fill((sockaddr *) &ao.addr, s->af, remote, ifa, 0);
+    ao.set_current     = 0;
+    ao.set_rnext       = 0;
+    ao.prefix  = -1;
+    ao.sndid   = 100;
+    ao.rcvid   = 100;
+    ao.maclen  = 0;
+    ao.keyflags        = 0;
+    ao.keylen  = strlen(passwd);
+    ao.ifindex = 0;
+
+    memcpy(ao.key, passwd, (strlen(passwd) > TCP_AO_MAXKEYLEN_) ? TCP_AO_MAXKEYLEN_ : strlen(passwd));
+
+    int IPPROTO_TCP_ = 6;
+    if (setsockopt(s->fd, SOL_TCP, TCP_AO_ADD_KEY, &md5, sizeof(md5)) < 0)
+      bug("tcp ao err %i", errno);
+    log("ok");
+    /*if (setsockopt(s->fd, SOL_TCP, TCP_MD5SIG_EXT, &md5, sizeof(md5)) < 0)
+      if (errno == ENOPROTOOPT)
+       ERR_MSG("Kernel does not support TCP MD5 signatures");
+      else
+       ERR("TCP_MD5SIG");*/
+  }
+  else
+  {
+    md5.tcpm_flags = TCP_MD5SIG_FLAG_PREFIX;
+    md5.tcpm_prefixlen = pxlen;
+
+    if (setsockopt(s->fd, SOL_TCP, TCP_MD5SIG_EXT, &md5, sizeof(md5)) < 0)
+    {
+      if (errno == ENOPROTOOPT)
+       ERR_MSG("Kernel does not support extended TCP MD5 signatures");
+      else
+       ERR("TCP_MD5SIG_EXT");
+    }
+  }
+
+  return 0;
+}
+
+/**int
+sk_set_tcpao_auth(sock *s, ip_addr local UNUSED, ip_addr remote, int pxlen, struct iface *ifa, const char *passwd, int setkey UNUSED)
+{
+  struct tcp_ao_add *ao;
+
+  memset(&ao, 0, sizeof(struct tcp_ao_add));
+  sockaddr_fill((sockaddr *) &md5.tcpm_addr, s->af, remote, ifa, 0);
+
+  if (passwd)
+  {
+    int len = strlen(passwd);
+
+    if (len > TCP_MD5SIG_MAXKEYLEN)
+      ERR_MSG("The password for TCP MD5 Signature is too long");
+
+    md5.tcpm_keylen = len;
+    memcpy(&md5.tcpm_key, passwd, len);
+  }
+
   if (pxlen < 0)
   {
     if (setsockopt(s->fd, SOL_TCP, TCP_MD5SIG, &md5, sizeof(md5)) < 0)
@@ -207,7 +281,7 @@ sk_set_md5_auth(sock *s, ip_addr local UNUSED, ip_addr remote, int pxlen, struct
   }
 
   return 0;
-}
+}**/
 
 static inline int
 sk_set_min_ttl4(sock *s, int ttl)
diff --git a/sysdep/linux/tcp-ao.h b/sysdep/linux/tcp-ao.h
new file mode 100644 (file)
index 0000000..523952c
--- /dev/null
@@ -0,0 +1,95 @@
+
+#define TCP_AO_MAXKEYLEN_      80
+
+#define DEFAULT_TEST_ALGO      "cmac(aes128)"
+
+struct tcp_ao_add_ext { /* setsockopt(TCP_AO_ADD_KEY) */
+       struct sockaddr_storage addr;   /* peer's address for the key */
+       char    alg_name[64];           /* crypto hash algorithm to use */
+       s32     ifindex;                /* L3 dev index for VRF */
+       u32   set_current       :1,     /* set key as Current_key at once */
+               set_rnext       :1,     /* request it from peer with RNext_key */
+               reserved        :30;    /* must be 0 */
+       u16     reserved2;              /* padding, must be 0 */
+       u8      prefix;                 /* peer's address prefix */
+       u8      sndid;                  /* SendID for outgoing segments */
+       u8      rcvid;                  /* RecvID to match for incoming seg */
+       u8      maclen;                 /* length of authentication code (hash) */
+       u8      keyflags;               /* see TCP_AO_KEYF_ */
+       u8      keylen;                 /* length of ::key */
+       u8      key[TCP_AO_MAXKEYLEN_];
+} __attribute__((aligned(8)));
+
+struct tcp_ao_del_ext { /* setsockopt(TCP_AO_DEL_KEY) */
+       struct sockaddr_storage addr;   /* peer's address for the key */
+       s32     ifindex;                /* L3 dev index for VRF */
+       u32   set_current       :1,     /* corresponding ::current_key */
+               set_rnext       :1,     /* corresponding ::rnext */
+               del_async       :1,     /* only valid for listen sockets */
+               reserved        :29;    /* must be 0 */
+       u16     reserved2;              /* padding, must be 0 */
+       u8      prefix;                 /* peer's address prefix */
+       u8      sndid;                  /* SendID for outgoing segments */
+       u8      rcvid;                  /* RecvID to match for incoming seg */
+       u8      current_key;            /* KeyID to set as Current_key */
+       u8      rnext;                  /* KeyID to set as Rnext_key */
+       u8      keyflags;               /* see TCP_AO_KEYF_ */
+} __attribute__((aligned(8)));
+
+struct tcp_ao_info_opt_ext { /* setsockopt(TCP_AO_INFO), getsockopt(TCP_AO_INFO) */
+       /* Here 'in' is for setsockopt(), 'out' is for getsockopt() */
+       u32   set_current       :1,     /* in/out: corresponding ::current_key */
+               set_rnext       :1,     /* in/out: corresponding ::rnext */
+               ao_required     :1,     /* in/out: don't accept non-AO connects */
+               set_counters    :1,     /* in: set/clear ::pkt_* counters */
+               accept_icmps    :1,     /* in/out: accept incoming ICMPs */
+               reserved        :27;    /* must be 0 */
+       u16     reserved2;              /* padding, must be 0 */
+       u8      current_key;            /* in/out: KeyID of Current_key */
+       u8      rnext;                  /* in/out: keyid of RNext_key */
+       u64     pkt_good;               /* in/out: verified segments */
+       u64     pkt_bad;                /* in/out: failed verification */
+       u64     pkt_key_not_found;      /* in/out: could not find a key to verify */
+       u64     pkt_ao_required;        /* in/out: segments missing TCP-AO sign */
+       u64     pkt_dropped_icmp;       /* in/out: ICMPs that were ignored */
+} __attribute__((aligned(8)));
+
+struct tcp_ao_getsockopt_ext { /* getsockopt(TCP_AO_GET_KEYS) */
+       struct sockaddr_storage addr;   /* in/out: dump keys for peer
+                                                * with this address/prefix
+                                                */
+       char    alg_name[64];           /* out: crypto hash algorithm */
+       u8      key[TCP_AO_MAXKEYLEN_];
+       u32     nkeys;                  /* in: size of the userspace buffer
+                                        * @optval, measured in @optlen - the
+                                        * sizeof(struct tcp_ao_getsockopt)
+                                        * out: number of keys that matched
+                                        */
+       u16   is_current        :1,     /* in: match and dump Current_key,
+                                        * out: the dumped key is Current_key
+                                        */
+
+               is_rnext        :1,     /* in: match and dump RNext_key,
+                                        * out: the dumped key is RNext_key
+                                        */
+               get_all         :1,     /* in: dump all keys */
+               reserved        :13;    /* padding, must be 0 */
+       u8      sndid;                  /* in/out: dump keys with SendID */
+       u8      rcvid;                  /* in/out: dump keys with RecvID */
+       u8      prefix;                 /* in/out: dump keys with address/prefix */
+       u8      maclen;                 /* out: key's length of authentication
+                                        * code (hash)
+                                        */
+       u8      keyflags;               /* in/out: see TCP_AO_KEYF_ */
+       u8      keylen;                 /* out: length of ::key */
+       s32     ifindex;                /* in/out: L3 dev index for VRF */
+       u64     pkt_good;               /* out: verified segments */
+       u64     pkt_bad;                /* out: segments that failed verification */
+} __attribute__((aligned(8)));
+
+struct tcp_ao_repair_ext { /* {s,g}etsockopt(TCP_AO_REPAIR) */
+       u32                     snt_isn;  //should be __be32 alias fdt32_t - 32-bit, big-endian, unsigned integer
+       u32                     rcv_isn;  //should be __be32 alias fdt32_t - 32-bit, big-endian, unsigned integer
+       u32                     snd_sne;
+       u32                     rcv_sne;
+} __attribute__((aligned(8)));