From 67ac2acfdbac0376d2632f27f5b66394f7a1fb24 Mon Sep 17 00:00:00 2001
From: Aki Tuomi <cmouse@cmouse.fi>
Date: Thu, 23 Aug 2012 23:45:34 +0300
Subject: [PATCH 1/3] Adds support for checking ipv6 tempaddr usage.
 Signed-off-by: Aki Tuomi <cmouse@cmouse.fi>

---
 configure.in        |    3 +-
 src/common/compat.c |  107 +++++++++++++++++++++++++++++++++++++++++++++++++++
 src/common/compat.h |    1 +
 src/or/main.c       |    7 ++++
 4 files changed, 117 insertions(+), 1 deletion(-)

diff --git a/configure.in b/configure.in
index 1c342c5..23187b2 100644
--- a/configure.in
+++ b/configure.in
@@ -687,7 +687,8 @@ AC_CHECK_HEADERS(
         sys/utime.h \
         sys/wait.h \
         syslog.h \
-        utime.h
+        utime.h \
+        dirent.h
 )
 
 AC_CHECK_HEADERS(sys/param.h)
diff --git a/src/common/compat.c b/src/common/compat.c
index ca850a3..7d33de7 100644
--- a/src/common/compat.c
+++ b/src/common/compat.c
@@ -59,6 +59,14 @@
 #include <crt_externs.h>
 #endif
 
+#ifdef HAVE_DIRENT_H
+#include <dirent.h>
+#endif
+
+#ifdef HAVE_SYS_STAT_H
+#include <sys/stat.h>
+#endif
+
 #ifndef HAVE_GETTIMEOFDAY
 #ifdef HAVE_FTIME
 #include <sys/timeb.h>
@@ -3090,3 +3098,102 @@ format_win32_error(DWORD err)
 }
 #endif
 
+/**
+ * Checks for any interface(s) that do not have use_tempaddr set
+ * enabling possible leak of MAC address. Logging can be enabled
+ * setting verbose to 1.
+ *
+ * Returns -1 on error, 0 on success/non-applicable, or
+ * number of interfaces that have failed.
+ */
+#ifdef _WIN32
+int
+check_ipv6_tempaddr(int verbose)
+{
+  return 0;
+}
+#elif HAVE_DIRENT_H && HAVE_SYS_STAT_H
+int
+check_ipv6_tempaddr(int verbose)
+{
+  struct stat buf;
+  DIR *dir;
+  struct dirent *ent;
+  int n_of_interfaces;
+
+  /* check for proc access */
+  if (stat("/proc/sys/net/ipv6", &buf) == -1) {
+    return 0; /* no ipv6 enabled, or no proc fs */
+  }
+
+  /* then we check the interfaces */
+  dir = opendir("/proc/sys/net/ipv6/conf");
+  if (dir == NULL) {
+    if (verbose != 0)
+      log_warn(LD_GENERAL, "Could not open /proc/sys/net/ipv6/conf");
+    return -1;
+  }
+
+  n_of_interfaces = 0;
+  while ((ent = readdir(dir) ) != NULL) {
+     char fname[1024] = {0};
+
+     /* skip dot-files */
+     if (ent->d_name[0] == '.') continue;
+     /* not an interface */
+     if (!strncmp(ent->d_name, "all", 3) ||
+         /* not an interface */
+         !strncmp(ent->d_name, "default", 7) ||
+         /* localhost is not outbound */
+         !strncmp(ent->d_name, "lo", 2)) continue;
+
+     snprintf(fname, sizeof fname, "%s/%s", "/proc/sys/net/ipv6/conf",
+              ent->d_name);
+     if (stat(fname, &buf) == 0) {
+       if (!S_ISDIR(buf.st_mode)) continue; /* not a directory */
+     } else {
+       continue; /* not accessible */
+     }
+
+     snprintf(fname, sizeof fname, "%s/%s/use_tempaddr",
+              "/proc/sys/net/ipv6/conf", ent->d_name);
+     if (stat(fname, &buf) == 0) {
+        int state;
+        FILE *f;
+        /* read the value */
+        f = fopen(fname, "r");
+        if (f == NULL) {
+           if (verbose)
+             log_warn(LD_GENERAL, "Cannot check use_tempaddr for interface %s",
+                      ent->d_name);
+           continue;
+        }
+        state = 0;
+        if (fscanf(f, "%d", &state) == 1) {
+           if (state == 0) {
+             n_of_interfaces++;
+             if (verbose)
+                log_warn(LD_GENERAL, "Interface %s might expose your MAC \
+address to world, you can fix this with \
+sysctl -p net.ipv6.conf.%s.use_tempaddr=2", ent->d_name, ent->d_name);
+           }
+        } else {
+            if (verbose)
+              log_warn(LD_GENERAL,
+                       "Cannot check use_tempaddr for interface %s",
+                       ent->d_name);
+        }
+        fclose(f);
+     }
+  }
+  closedir(dir);
+  return n_of_interfaces;
+}
+#else
+int
+check_ipv6_tempaddr(int verbose)
+{
+  return 0;
+}
+#endif
+
diff --git a/src/common/compat.h b/src/common/compat.h
index 42648bb..01e3a12 100644
--- a/src/common/compat.h
+++ b/src/common/compat.h
@@ -692,3 +692,4 @@ char *format_win32_error(DWORD err);
 
 #endif
 
+int check_ipv6_tempaddr(int);
diff --git a/src/or/main.c b/src/or/main.c
index 20a1e08..f9affdb 100644
--- a/src/or/main.c
+++ b/src/or/main.c
@@ -63,6 +63,10 @@
 #include <event2/bufferevent.h>
 #endif
 
+#ifdef HAVE_DIRENT_H
+#include <dirent.h>
+#endif
+
 void evdns_shutdown(int);
 
 /********* PROTOTYPES **********/
@@ -1850,6 +1854,9 @@ do_main_loop(void)
   int loop_result;
   time_t now;
 
+  /* check for IPv6 tempaddr use, in verbose mode */
+  check_ipv6_tempaddr(1);
+
   /* initialize dns resolve map, spawn workers if needed */
   if (dns_init() < 0) {
     if (get_options()->ServerDNSAllowBrokenConfig)
-- 
1.7.9.5

