On Wed, Jul 12, 2017 at 01:45:36PM +1000, David Gwynne wrote:
> On Tue, Jul 11, 2017 at 11:48:47AM +0000, Florian Obser wrote:
> > On Tue, Jul 11, 2017 at 11:08:23AM +0100, Stuart Henderson wrote:
> > > On 2017/07/11 07:45, Florian Obser wrote:
> > > > The way I want to move forward with this is:
> > > > 
> > > > 1) generate a random key at boot if it's not present yet (like we do
> > > > for ssh host keys and ipsec)
> > > > 2) if /etc/netstart brings up an interface set the key there by
> > > > enabling the feature per default like we do with privacy addresses.
> > > > NOTE that this does NOT enable v6.
> > > > If you do not want this you have to put -soiikey into the hostname.if
> > > > file (like -autoconfprivacy)
> > > 
> > > It's slightly different to autoconfprivacy as that is enabled by
> > > default in the kernel for new interfaces, whereas with this it depends
> > > on the key being configured. So there are implications for dynamically
> > > created interfaces (USB, vlan etc) which may not always be handled by
> > > netstart.
> > > 
> > > I'm wondering if we should have a "system soiikey" (e.g. in a sysctl)
> > > that is automatically applied to newly created interfaces? (Does the
> > > key even need to be configurable per-interface or would a per-system
> > > one be enough by itself?)
> > 
> > I was also considering this. A per system key is probably enough.  I
> > went with the per-interface key because that made it easier to disable
> > the feature on an interface. If we go with per-system we need a
> > interface flag to disable the feature (like -autoconfprivacy).
> > 
> > The rfc seems to assume a per system secret.
> > 
> > hmm... are there sysctls that are only readable as root?
> 
> yeah. see below for example code for a net.inet6.ip6.soiikey sysctl.
> it looks big cos it teaches sysctl how to handle binary strings
> represented by hex.

Awesome, thank you very much, I will adapt my diff to this.

I don't think that we need to check securelevel (re: your comment in
the diff).
I don't really believe in securelevel, also it seems that even at 2
you are still allowed to change ip addresses on interfaces. And this
is all this key influences. Additionally I think it is valid to change
the key during runtime.

> 
> are we tied to sha512 for this? siphash makes a nice 8 byte output...

Nope, the rfc intentionally does not specify the hash function.

> 
> > 
> > > 
> > > > 3) if v6 is enabled in hostname.if you get a random but stable link
> > > > local address according to RFC 7217.
> > > > 4) if autoconf6 is enabled on the interface slaacd will generate a
> > > > random but stable global address according to RFC 7217
> > > > 
> > > > Also note that RFC 8064 is a thing and we are kinda supposed to do this.
> > > > Also I think it's a good idea[tm].
> > > > 
> > > > Comments, OKs?
> > > 
> > > A couple of other comments:
> > > 
> > > - system administrators should know in advance of updating that their
> > > IP address may change in case they need to prepare for it (adjust
> > > firewalls/nat-pt/proxies).
> > 
> > sure, /me glances at current.html
> > 
> > > 
> > > - ramdisk upgrades may need to load the key from the installed system
> > > (e.g. in presence of restrictive firewall policies).
> > > 
> > 
> > good point
> > 
> > > - a half-related idea came up while pondering this,
> > > "block in inet6 to autoconfprivacy" (similar UI to urpf-failed)
> > > (I'm meant to be doing something else and likely to forget so I'd
> > > like to at least plant the idea :)
> > 
> > heh, interesting
> > 
> > -- 
> > I'm not entirely sure you are real.
> 
> 
> Index: sbin/sysctl/sysctl.c
> ===================================================================
> RCS file: /cvs/src/sbin/sysctl/sysctl.c,v
> retrieving revision 1.226
> diff -u -p -r1.226 sysctl.c
> --- sbin/sysctl/sysctl.c      25 Apr 2017 17:33:16 -0000      1.226
> +++ sbin/sysctl/sysctl.c      12 Jul 2017 03:39:33 -0000
> @@ -212,7 +212,7 @@ int sysctl_chipset(char *, char **, int 
>  #endif
>  void vfsinit(void);
>  
> -char *equ = "=";
> +const char *equ = "=";
>  
>  int
>  main(int argc, char *argv[])
> @@ -286,6 +286,52 @@ listall(char *prefix, struct list *lp)
>       }
>  }
>  
> +int
> +parse_hex_char(char ch)
> +{
> +     if (ch >= '0' && ch <= '9')
> +             return (ch - '0');
> +     if (ch >= 'a' && ch <= 'f')
> +             return (ch - 'a');
> +     if (ch >= 'A' && ch <= 'F')
> +             return (ch - 'A');
> +
> +     return (-1);
> +}
> +
> +ssize_t
> +parse_hex_string(unsigned char *dst, size_t dstlen, const char *src)
> +{
> +     ssize_t len = 0;
> +     int digit;
> +
> +     while (len < dstlen) {
> +             if (*src == '\0')
> +                     return (len);
> +
> +             digit = parse_hex_char(*src++);
> +             if (digit == -1)
> +                     return (-1);
> +             dst[len] = digit << 4;
> +
> +             digit = parse_hex_char(*src++);
> +             if (digit == -1)
> +                     return (-1);
> +             
> +             dst[len] |= digit;
> +             len++;
> +     }
> +
> +     while (*src != '\0') {
> +             if (parse_hex_char(*src++) == -1 ||
> +                 parse_hex_char(*src++) == -1)
> +                     return (-1);
> +             len++;
> +     }
> +
> +     return (len);
> +}
> +
>  /*
>   * Parse a name into a MIB entry.
>   * Lookup and print out the MIB entry if it exists.
> @@ -566,6 +612,9 @@ parse(char *string, int flags)
>                       len = sysctl_inet6(string, &bufp, mib, flags, &type);
>                       if (len < 0)
>                               return;
> +                     if (mib[2] == IPPROTO_IPV6 &&
> +                         mib[3] == IPV6CTL_SOIIKEY)
> +                             special |= HEX;
>  
>                       if ((mib[2] == IPPROTO_IPV6 && mib[3] == 
> IPV6CTL_MRTMFC) ||
>                           (mib[2] == IPPROTO_IPV6 && mib[3] == 
> IPV6CTL_MRTMIF) ||
> @@ -717,6 +766,29 @@ parse(char *string, int flags)
>                       newval = &quadval;
>                       newsize = sizeof(quadval);
>                       break;
> +             case CTLTYPE_STRING:
> +                     if (special & HEX) {
> +                             ssize_t len;
> +
> +                             len = parse_hex_string(buf, sizeof(buf),
> +                                 newval);
> +                             if (len == -1) {
> +                                     warnx("%s: hex string %s: invalid",
> +                                         string, newval);
> +                                     return;
> +                             }
> +                             if (len > sizeof(buf)) {
> +                                     warnx("%s: hex string %s: too long",
> +                                         string, newval);
> +                                     return;
> +                             }
> +
> +                             newval = buf;
> +                             newsize = len;
> +
> +                             printf("newsize = %zu\n", newsize);
> +                     }
> +                     break;
>               }
>       }
>       size = (special & SMALLBUF) ? 512 : SYSCTL_BUFSIZ;
> @@ -936,13 +1008,26 @@ parse(char *string, int flags)
>               if (newval == NULL) {
>                       if (!nflag)
>                               (void)printf("%s%s", string, equ);
> -                     (void)puts(buf);
> -             } else {
> -                     if (!qflag) {
> -                             if (!nflag)
> -                                     (void)printf("%s: %s -> ", string, buf);
> -                             (void)puts((char *)newval);
> +                     if (special & HEX) {
> +                             size_t i;
> +                             for (i = 0; i < size; i++)
> +                                     (void)printf("%02x", buf[i]);
> +                             (void)printf("\n");
> +                     } else
> +                             (void)puts(buf);
> +             } else if (!qflag) {
> +                     if (!nflag) {
> +                             (void)printf("%s: ", string);
> +                             if (special & HEX) {
> +                                     size_t i;
> +                                     for (i = 0; i < size; i++)
> +                                             (void)printf("%02x", buf[i]);
> +                             } else
> +                                     (void)printf("%s", cp);
> +
> +                             (void)printf(" -> ");
>                       }
> +                     (void)puts(cp);
>               }
>               return;
>  
> Index: sys/netinet6/in6.h
> ===================================================================
> RCS file: /cvs/src/sys/netinet6/in6.h,v
> retrieving revision 1.96
> diff -u -p -r1.96 in6.h
> --- sys/netinet6/in6.h        30 May 2017 09:10:49 -0000      1.96
> +++ sys/netinet6/in6.h        12 Jul 2017 03:39:33 -0000
> @@ -592,7 +592,8 @@ ifatoia6(struct ifaddr *ifa)
>  #define IPV6CTL_IFQUEUE              51
>  #define IPV6CTL_MRTMIF               52
>  #define IPV6CTL_MRTMFC               53
> -#define IPV6CTL_MAXID                54
> +#define IPV6CTL_SOIIKEY              54
> +#define IPV6CTL_MAXID                55
>  
>  /* New entries should be added here from current IPV6CTL_MAXID value. */
>  /* to define items, should talk with KAME guys first, for *BSD compatibility 
> */
> @@ -652,6 +653,7 @@ ifatoia6(struct ifaddr *ifa)
>       { "ifq", CTLTYPE_NODE }, \
>       { "mrtmif", CTLTYPE_STRUCT }, \
>       { "mrtmfc", CTLTYPE_STRUCT }, \
> +     { "soiikey", CTLTYPE_STRING }, /* binary string */ \
>  }
>  
>  #define IPV6CTL_VARS { \
> Index: sys/netinet6/ip6_input.c
> ===================================================================
> RCS file: /cvs/src/sys/netinet6/ip6_input.c,v
> retrieving revision 1.198
> diff -u -p -r1.198 ip6_input.c
> --- sys/netinet6/ip6_input.c  5 Jul 2017 11:34:10 -0000       1.198
> +++ sys/netinet6/ip6_input.c  12 Jul 2017 03:39:34 -0000
> @@ -1375,6 +1375,56 @@ ip6_sysctl_ip6stat(void *oldp, size_t *o
>       return (ret);
>  }
>  
> +struct ip6_soiikey {
> +     unsigned int len;
> +     unsigned char key[32];
> +};
> +
> +struct ip6_soiikey ip6_soiikey = { .len = 0 };
> +
> +int
> +ip6_sysctl_soiikey(void *oldp, size_t *oldlenp, void *newp, size_t newlen)
> +{
> +     unsigned char key[32];
> +     int error;
> +
> +     error = suser(curproc, 0);
> +     if (error != 0)
> +             return (error);
> +
> +     if (oldp != NULL) {
> +             if (newp == NULL && ip6_soiikey.len == 0)
> +                     return (EOPNOTSUPP);
> +             if (*oldlenp < ip6_soiikey.len)
> +                     return (ENOMEM);
> +     }
> +     if (newp != NULL) {
> +             /* check securelevel? */
> +             if (newlen > sizeof(ip6_soiikey.key))
> +                     return (EINVAL);
> +             if (newlen > 0) {
> +                     error = copyin(newp, key, newlen);
> +                     if (error != 0)
> +                             return (error);
> +             }
> +     }
> +     if (oldp != NULL) {
> +             error = copyout(ip6_soiikey.key, oldp, *oldlenp);
> +             if (error != 0)
> +                     return (error);
> +             *oldlenp = ip6_soiikey.len;
> +     }
> +
> +     if (newp != NULL) {
> +             /* commit */
> +             if (newlen > 0)
> +                     memcpy(ip6_soiikey.key, key, newlen);
> +             ip6_soiikey.len = newlen;
> +     }
> +
> +     return (0);
> +}
> +
>  int
>  ip6_sysctl(int *name, u_int namelen, void *oldp, size_t *oldlenp,
>      void *newp, size_t newlen)
> @@ -1429,6 +1479,8 @@ ip6_sysctl(int *name, u_int namelen, voi
>       case IPV6CTL_IFQUEUE:
>               return (sysctl_niq(name + 1, namelen - 1,
>                   oldp, oldlenp, newp, newlen, &ip6intrq));
> +     case IPV6CTL_SOIIKEY:
> +             return (ip6_sysctl_soiikey(oldp, oldlenp, newp, newlen));
>       default:
>               if (name[0] < IPV6CTL_MAXID)
>                       return (sysctl_int_arr(ipv6ctl_vars, name, namelen,
> 


-- 
I'm not entirely sure you are real.

Reply via email to