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.

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

> 
> > 
> > > 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,

Reply via email to