about summary refs log tree commit diff
diff options
context:
space:
mode:
-rwxr-xr-x.custom-format.py15
-rw-r--r--libtokencap/Makefile1
-rw-r--r--libtokencap/libtokencap.so.c372
3 files changed, 319 insertions, 69 deletions
diff --git a/.custom-format.py b/.custom-format.py
index 8d762006..70107997 100755
--- a/.custom-format.py
+++ b/.custom-format.py
@@ -27,12 +27,15 @@ with open(".clang-format") as f:
 
 CLANG_FORMAT_BIN = os.getenv("CLANG_FORMAT_BIN")
 if CLANG_FORMAT_BIN is None:
-    p = subprocess.Popen(["clang-format", "--version"], stdout=subprocess.PIPE)
-    o, _ = p.communicate()
-    o = str(o, "utf-8")
-    o = o[len("clang-format version "):].strip()
-    o = o[:o.find(".")]
-    o = int(o)
+    o = 0
+    try:
+        p = subprocess.Popen(["clang-format", "--version"], stdout=subprocess.PIPE)
+        o, _ = p.communicate()
+        o = str(o, "utf-8")
+        o = o[len("clang-format version "):].strip()
+        o = o[:o.find(".")]
+        o = int(o)
+    except: pass
     if o < 7:
         if subprocess.call(['which', 'clang-format-7'], stdout=subprocess.PIPE) == 0:
             CLANG_FORMAT_BIN = 'clang-format-7'
diff --git a/libtokencap/Makefile b/libtokencap/Makefile
index 6e1319d8..b1313430 100644
--- a/libtokencap/Makefile
+++ b/libtokencap/Makefile
@@ -20,6 +20,7 @@ VERSION     = $(shell grep '^\#define VERSION ' ../config.h | cut -d '"' -f2)
 
 CFLAGS      ?= -O3 -funroll-loops -I ../include/
 CFLAGS      += -Wall -D_FORTIFY_SOURCE=2 -g -Wno-pointer-sign
+LDFLAGS     += -ldl
 
 ifeq "$(shell uname)" "Linux"
   TARGETS = libtokencap.so
diff --git a/libtokencap/libtokencap.so.c b/libtokencap/libtokencap.so.c
index eea6d29f..e16fb772 100644
--- a/libtokencap/libtokencap.so.c
+++ b/libtokencap/libtokencap.so.c
@@ -19,27 +19,50 @@
 
  */
 
+#ifndef _GNU_SOURCE
+#define _GNU_SOURCE
+#endif
 #include <stdio.h>
 #include <string.h>
 #include <ctype.h>
 #include <unistd.h>
 #include <fcntl.h>
+#include <stdbool.h>
 
 #include "../types.h"
 #include "../config.h"
 
-#if !defined __linux__  && !defined __APPLE__  && !defined __FreeBSD__ && !defined __OpenBSD__ && !defined __NetBSD__
-# error "Sorry, this library is unsupported in this platform for now!"
-#endif /* !__linux__ && !__APPLE__ && ! __FreeBSD__ && ! __OpenBSD__ && !__NetBSD__*/
+#if !defined __linux__ && !defined __APPLE__ && !defined __FreeBSD__ && \
+    !defined __OpenBSD__ && !defined __NetBSD__
+#error "Sorry, this library is unsupported in this platform for now!"
+#endif /* !__linux__ && !__APPLE__ && ! __FreeBSD__ && ! __OpenBSD__ && \
+          !__NetBSD__*/
 
 #if defined __APPLE__
-# include <mach/vm_map.h>
-# include <mach/mach_init.h>
+#include <mach/vm_map.h>
+#include <mach/mach_init.h>
 #elif defined __FreeBSD__ || defined __OpenBSD__ || defined __NetBSD__
-# include <sys/types.h>
-# include <sys/sysctl.h>
-# include <sys/user.h>
-# include <sys/mman.h>
+#include <sys/types.h>
+#include <sys/sysctl.h>
+#include <sys/user.h>
+#include <sys/mman.h>
+#endif
+
+#include <dlfcn.h>
+
+#ifdef RTLD_NEXT
+/* The libc functions are a magnitude faster than our replacements.
+   Use them when RTLD_NEXT is available. */
+int (*__libc_strcmp)(const char* str1, const char* str2);
+int (*__libc_strncmp)(const char* str1, const char* str2, size_t len);
+int (*__libc_strcasecmp)(const char* str1, const char* str2);
+int (*__libc_strncasecmp)(const char* str1, const char* str2, size_t len);
+int (*__libc_memcmp)(const void* mem1, const void* mem2, size_t len);
+int (*__libc_bcmp)(const void* mem1, const void* mem2, size_t len);
+char* (*__libc_strstr)(const char* haystack, const char* needle);
+char* (*__libc_strcasestr)(const char* haystack, const char* needle);
+void* (*__libc_memmem)(const void* haystack, size_t haystack_len,
+                       const void* needle, size_t needle_len);
 #endif
 
 /* Mapping data and such */
@@ -50,7 +73,7 @@ static struct mapping { void *st, *en; } __tokencap_ro[MAX_MAPPINGS];
 
 static u32   __tokencap_ro_cnt;
 static u8    __tokencap_ro_loaded;
-static int __tokencap_out_file = -1;
+static int   __tokencap_out_file = -1;
 static pid_t __tokencap_pid = -1;
 
 /* Identify read-only regions in memory. Only parameters that fall into these
@@ -88,49 +111,60 @@ static void __tokencap_load_mappings(void) {
 #elif defined __APPLE__
 
   struct vm_region_submap_info_64 region;
-  mach_msg_type_number_t cnt = VM_REGION_SUBMAP_INFO_COUNT_64;
-  vm_address_t base = 0;
-  vm_size_t size = 0;
-  natural_t depth = 0;
+  mach_msg_type_number_t          cnt = VM_REGION_SUBMAP_INFO_COUNT_64;
+  vm_address_t                    base = 0;
+  vm_size_t                       size = 0;
+  natural_t                       depth = 0;
 
   __tokencap_ro_loaded = 1;
 
   while (1) {
 
     if (vm_region_recurse_64(mach_task_self(), &base, &size, &depth,
-       (vm_region_info_64_t)&region, &cnt) != KERN_SUCCESS) break;
+                             (vm_region_info_64_t)&region,
+                             &cnt) != KERN_SUCCESS)
+      break;
 
     if (region.is_submap) {
-       depth++;
+
+      depth++;
+
     } else {
-       /* We only care of main map addresses and the read only kinds */
-       if ((region.protection & VM_PROT_READ) && !(region.protection & VM_PROT_WRITE)) {
-          __tokencap_ro[__tokencap_ro_cnt].st = (void *)base;
-          __tokencap_ro[__tokencap_ro_cnt].en = (void *)(base + size);
 
-	  if (++__tokencap_ro_cnt == MAX_MAPPINGS) break;
-       }
+      /* We only care of main map addresses and the read only kinds */
+      if ((region.protection & VM_PROT_READ) &&
+          !(region.protection & VM_PROT_WRITE)) {
+
+        __tokencap_ro[__tokencap_ro_cnt].st = (void*)base;
+        __tokencap_ro[__tokencap_ro_cnt].en = (void*)(base + size);
+
+        if (++__tokencap_ro_cnt == MAX_MAPPINGS) break;
+
+      }
+
     }
+
   }
 
 #elif defined __FreeBSD__ || defined __OpenBSD__ || defined __NetBSD__
 
-#if defined __FreeBSD__
-  int mib[] = {CTL_KERN, KERN_PROC, KERN_PROC_VMMAP, __tokencap_pid};
+#if defined   __FreeBSD__
+  int    mib[] = {CTL_KERN, KERN_PROC, KERN_PROC_VMMAP, __tokencap_pid};
 #elif defined __OpenBSD__
   int mib[] = {CTL_KERN, KERN_PROC_VMMAP, __tokencap_pid};
 #elif defined __NetBSD__
-  int mib[] = {CTL_VM, VM_PROC, VM_PROC_MAP, __tokencap_pid, sizeof(struct kinfo_vmentry)};
+  int mib[] = {CTL_VM, VM_PROC, VM_PROC_MAP, __tokencap_pid,
+               sizeof(struct kinfo_vmentry)};
 #endif
-  char *buf, *low, *high;
-  size_t miblen = sizeof(mib)/sizeof(mib[0]);
+  char * buf, *low, *high;
+  size_t miblen = sizeof(mib) / sizeof(mib[0]);
   size_t len;
 
   if (sysctl(mib, miblen, NULL, &len, NULL, 0) == -1) return;
 
 #if defined __FreeBSD__ || defined __NetBSD__
   len = len * 4 / 3;
-#elif defined __OpenBSD__
+#elif defined                      __OpenBSD__
   len -= len % sizeof(struct kinfo_vmentry);
 #endif
 
@@ -139,8 +173,8 @@ static void __tokencap_load_mappings(void) {
 
   if (sysctl(mib, miblen, buf, &len, NULL, 0) == -1) {
 
-     munmap(buf, len);
-     return;
+    munmap(buf, len);
+    return;
 
   }
 
@@ -150,41 +184,48 @@ static void __tokencap_load_mappings(void) {
   __tokencap_ro_loaded = 1;
 
   while (low < high) {
-     struct kinfo_vmentry *region = (struct kinfo_vmentry *)low;
+
+    struct kinfo_vmentry* region = (struct kinfo_vmentry*)low;
 
 #if defined __FreeBSD__ || defined __NetBSD__
 
-#if defined __FreeBSD__
-     size_t size = region->kve_structsize;
+#if defined   __FreeBSD__
+    size_t                size = region->kve_structsize;
 
-     if (size == 0) break;
+    if (size == 0) break;
 #elif defined __NetBSD__
-     size_t size = sizeof (*region);
+    size_t size = sizeof(*region);
 #endif
 
-     /* We go through the whole mapping of the process and track read-only addresses */
-     if ((region->kve_protection & KVME_PROT_READ) &&
-	 !(region->kve_protection & KVME_PROT_WRITE)) {
+    /* We go through the whole mapping of the process and track read-only
+     * addresses */
+    if ((region->kve_protection & KVME_PROT_READ) &&
+        !(region->kve_protection & KVME_PROT_WRITE)) {
 
 #elif defined __OpenBSD__
 
-     size_t size = sizeof (*region);
+    size_t size = sizeof(*region);
+
+    /* We go through the whole mapping of the process and track read-only
+     * addresses */
+    if ((region->kve_protection & KVE_PROT_READ) &&
+        !(region->kve_protection & KVE_PROT_WRITE)) {
 
-     /* We go through the whole mapping of the process and track read-only addresses */
-     if ((region->kve_protection & KVE_PROT_READ) &&
-	 !(region->kve_protection & KVE_PROT_WRITE)) {
 #endif
-          __tokencap_ro[__tokencap_ro_cnt].st = (void *)region->kve_start;
-          __tokencap_ro[__tokencap_ro_cnt].en = (void *)region->kve_end;
+      __tokencap_ro[__tokencap_ro_cnt].st = (void*)region->kve_start;
+      __tokencap_ro[__tokencap_ro_cnt].en = (void*)region->kve_end;
+
+      if (++__tokencap_ro_cnt == MAX_MAPPINGS) break;
+
+    }
 
-	  if (++__tokencap_ro_cnt == MAX_MAPPINGS) break;
-     }
+    low += size;
 
-     low += size;
   }
 
   munmap(buf, len);
 #endif
+
 }
 
 /* Check an address against the list of read-only mappings. */
@@ -237,9 +278,9 @@ static void __tokencap_dump(const u8* ptr, size_t len, u8 is_text) {
 
   buf[pos] = 0;
 
-  int wrt_ok = (  1 == write(__tokencap_out_file, "\"", 1));
-  wrt_ok    &= (pos == write(__tokencap_out_file, buf, pos));
-  wrt_ok    &= (2   == write(__tokencap_out_file, "\"\n", 2));
+  int wrt_ok = (1 == write(__tokencap_out_file, "\"", 1));
+  wrt_ok &= (pos == write(__tokencap_out_file, buf, pos));
+  wrt_ok &= (2 == write(__tokencap_out_file, "\"\n", 2));
 
 }
 
@@ -253,6 +294,10 @@ int strcmp(const char* str1, const char* str2) {
   if (__tokencap_is_ro(str1)) __tokencap_dump(str1, strlen(str1), 1);
   if (__tokencap_is_ro(str2)) __tokencap_dump(str2, strlen(str2), 1);
 
+#ifdef RTLD_NEXT
+  if (__libc_strcmp) return __libc_strcmp(str1, str2);
+#endif
+
   while (1) {
 
     const unsigned char c1 = *str1, c2 = *str2;
@@ -273,6 +318,10 @@ int strncmp(const char* str1, const char* str2, size_t len) {
   if (__tokencap_is_ro(str1)) __tokencap_dump(str1, len, 1);
   if (__tokencap_is_ro(str2)) __tokencap_dump(str2, len, 1);
 
+#ifdef RTLD_NEXT
+  if (__libc_strncmp) return __libc_strncmp(str1, str2, len);
+#endif
+
   while (len--) {
 
     unsigned char c1 = *str1, c2 = *str2;
@@ -295,6 +344,10 @@ int strcasecmp(const char* str1, const char* str2) {
   if (__tokencap_is_ro(str1)) __tokencap_dump(str1, strlen(str1), 1);
   if (__tokencap_is_ro(str2)) __tokencap_dump(str2, strlen(str2), 1);
 
+#ifdef RTLD_NEXT
+  if (__libc_strcasecmp) return __libc_strcasecmp(str1, str2);
+#endif
+
   while (1) {
 
     const unsigned char c1 = tolower(*str1), c2 = tolower(*str2);
@@ -315,6 +368,10 @@ int strncasecmp(const char* str1, const char* str2, size_t len) {
   if (__tokencap_is_ro(str1)) __tokencap_dump(str1, len, 1);
   if (__tokencap_is_ro(str2)) __tokencap_dump(str2, len, 1);
 
+#ifdef RTLD_NEXT
+  if (__libc_strncasecmp) return __libc_strncasecmp(str1, str2, len);
+#endif
+
   while (len--) {
 
     const unsigned char c1 = tolower(*str1), c2 = tolower(*str2);
@@ -337,8 +394,12 @@ int memcmp(const void* mem1, const void* mem2, size_t len) {
   if (__tokencap_is_ro(mem1)) __tokencap_dump(mem1, len, 0);
   if (__tokencap_is_ro(mem2)) __tokencap_dump(mem2, len, 0);
 
-  const char *strmem1 = (const char *)mem1;
-  const char *strmem2 = (const char *)mem2;
+#ifdef RTLD_NEXT
+  if (__libc_memcmp) return __libc_memcmp(mem1, mem2, len);
+#endif
+
+  const char* strmem1 = (const char*)mem1;
+  const char* strmem2 = (const char*)mem2;
 
   while (len--) {
 
@@ -360,8 +421,12 @@ int bcmp(const void* mem1, const void* mem2, size_t len) {
   if (__tokencap_is_ro(mem1)) __tokencap_dump(mem1, len, 0);
   if (__tokencap_is_ro(mem2)) __tokencap_dump(mem2, len, 0);
 
-  const char *strmem1 = (const char *)mem1;
-  const char *strmem2 = (const char *)mem2;
+#ifdef RTLD_NEXT
+  if (__libc_bcmp) return __libc_bcmp(mem1, mem2, len);
+#endif
+
+  const char* strmem1 = (const char*)mem1;
+  const char* strmem2 = (const char*)mem2;
 
   while (len--) {
 
@@ -373,6 +438,7 @@ int bcmp(const void* mem1, const void* mem2, size_t len) {
   }
 
   return 0;
+
 }
 
 #undef strstr
@@ -384,6 +450,10 @@ char* strstr(const char* haystack, const char* needle) {
 
   if (__tokencap_is_ro(needle)) __tokencap_dump(needle, strlen(needle), 1);
 
+#ifdef RTLD_NEXT
+  if (__libc_strstr) return __libc_strstr(haystack, needle);
+#endif
+
   do {
 
     const char* n = needle;
@@ -409,6 +479,10 @@ char* strcasestr(const char* haystack, const char* needle) {
 
   if (__tokencap_is_ro(needle)) __tokencap_dump(needle, strlen(needle), 1);
 
+#ifdef RTLD_NEXT
+  if (__libc_strcasestr) return __libc_strcasestr(haystack, needle);
+#endif
+
   do {
 
     const char* n = needle;
@@ -427,26 +501,32 @@ char* strcasestr(const char* haystack, const char* needle) {
 
 #undef memmem
 
-void* memmem(const void *haystack, size_t haystack_len, const void *needle, size_t needle_len)
-{
-  if (__tokencap_is_ro(haystack))
-    __tokencap_dump(haystack, haystack_len, 1);
+void* memmem(const void* haystack, size_t haystack_len, const void* needle,
+             size_t needle_len) {
+
+  if (__tokencap_is_ro(haystack)) __tokencap_dump(haystack, haystack_len, 1);
 
   if (__tokencap_is_ro(needle)) __tokencap_dump(needle, needle_len, 1);
 
-  const char *n = (const char *)needle;
-  const char *h = (const char *)haystack;
+#ifdef RTLD_NEXT
+  if (__libc_memmem)
+    return __libc_memmem(haystack, haystack_len, needle, needle_len);
+#endif
+
+  const char* n = (const char*)needle;
+  const char* h = (const char*)haystack;
   if (haystack_len < needle_len) return 0;
-  if (needle_len == 0) return (void *)haystack;
+  if (needle_len == 0) return (void*)haystack;
   if (needle_len == 1) return memchr(haystack, *n, haystack_len);
 
-  const char *end = h + (haystack_len - needle_len);
+  const char* end = h + (haystack_len - needle_len);
 
   do {
 
     if (*h == *n) {
 
-	    if (memcmp(h, n, needle_len) == 0) return (void *)h;
+      if (memcmp(h, n, needle_len) == 0) return (void*)h;
+
     }
 
   } while (h++ <= end);
@@ -455,6 +535,158 @@ void* memmem(const void *haystack, size_t haystack_len, const void *needle, size
 
 }
 
+/* Common libraries wrappers (from honggfuzz) */
+
+/*
+ * Apache's httpd wrappers
+ */
+int ap_cstr_casecmp(const char* s1, const char* s2) {
+
+  return strcasecmp(s1, s2);
+
+}
+
+int ap_cstr_casecmpn(const char* s1, const char* s2, size_t n) {
+
+  return strncasecmp(s1, s2, n);
+
+}
+
+const char* ap_strcasestr(const char* s1, const char* s2) {
+
+  return strcasestr(s1, s2);
+
+}
+
+int apr_cstr_casecmp(const char* s1, const char* s2) {
+
+  return strcasecmp(s1, s2);
+
+}
+
+int apr_cstr_casecmpn(const char* s1, const char* s2, size_t n) {
+
+  return strncasecmp(s1, s2, n);
+
+}
+
+/*
+ * *SSL wrappers
+ */
+int CRYPTO_memcmp(const void* m1, const void* m2, size_t len) {
+
+  return memcmp(m1, m2, len);
+
+}
+
+int OPENSSL_memcmp(const void* m1, const void* m2, size_t len) {
+
+  return memcmp(m1, m2, len);
+
+}
+
+int OPENSSL_strcasecmp(const char* s1, const char* s2) {
+
+  return strcasecmp(s1, s2);
+
+}
+
+int OPENSSL_strncasecmp(const char* s1, const char* s2, size_t len) {
+
+  return strncasecmp(s1, s2, len);
+
+}
+
+int32_t memcmpct(const void* s1, const void* s2, size_t len) {
+
+  return memcmp(s1, s2, len);
+
+}
+
+/*
+ * libXML wrappers
+ */
+int xmlStrncmp(const char* s1, const char* s2, int len) {
+
+  if (len <= 0) { return 0; }
+  if (s1 == s2) { return 0; }
+  if (s1 == NULL) { return -1; }
+  if (s2 == NULL) { return 1; }
+  return strncmp(s1, s2, (size_t)len);
+
+}
+
+int xmlStrcmp(const char* s1, const char* s2) {
+
+  if (s1 == s2) { return 0; }
+  if (s1 == NULL) { return -1; }
+  if (s2 == NULL) { return 1; }
+  return strcmp(s1, s2);
+
+}
+
+int xmlStrEqual(const char* s1, const char* s2) {
+
+  if (s1 == s2) { return 1; }
+  if (s1 == NULL) { return 0; }
+  if (s2 == NULL) { return 0; }
+  if (strcmp(s1, s2) == 0) { return 1; }
+  return 0;
+
+}
+
+int xmlStrcasecmp(const char* s1, const char* s2) {
+
+  if (s1 == s2) { return 0; }
+  if (s1 == NULL) { return -1; }
+  if (s2 == NULL) { return 1; }
+  return strcasecmp(s1, s2);
+
+}
+
+int xmlStrncasecmp(const char* s1, const char* s2, int len) {
+
+  if (len <= 0) { return 0; }
+  if (s1 == s2) { return 0; }
+  if (s1 == NULL) { return -1; }
+  if (s2 == NULL) { return 1; }
+  return strncasecmp(s1, s2, (size_t)len);
+
+}
+
+const char* xmlStrstr(const char* haystack, const char* needle) {
+
+  if (haystack == NULL) { return NULL; }
+  if (needle == NULL) { return NULL; }
+  return strstr(haystack, needle);
+
+}
+
+const char* xmlStrcasestr(const char* haystack, const char* needle) {
+
+  if (haystack == NULL) { return NULL; }
+  if (needle == NULL) { return NULL; }
+  return strcasestr(haystack, needle);
+
+}
+
+/*
+ * Samba wrappers
+ */
+int memcmp_const_time(const void* s1, const void* s2, size_t n) {
+
+  return memcmp(s1, s2, n);
+
+}
+
+bool strcsequal(const void* s1, const void* s2) {
+
+  if (s1 == s2) { return true; }
+  if (!s1 || !s2) { return false; }
+  return (strcmp(s1, s2) == 0);
+
+}
+
 /* Init code to open the output file (or default to stderr). */
 
 __attribute__((constructor)) void __tokencap_init(void) {
@@ -464,10 +696,24 @@ __attribute__((constructor)) void __tokencap_init(void) {
   if (__tokencap_out_file == -1) __tokencap_out_file = STDERR_FILENO;
   __tokencap_pid = getpid();
 
+#ifdef RTLD_NEXT
+  __libc_strcmp = dlsym(RTLD_NEXT, "strcmp");
+  __libc_strncmp = dlsym(RTLD_NEXT, "strncmp");
+  __libc_strcasecmp = dlsym(RTLD_NEXT, "strcasecmp");
+  __libc_strncasecmp = dlsym(RTLD_NEXT, "strncasecmp");
+  __libc_memcmp = dlsym(RTLD_NEXT, "memcmp");
+  __libc_bcmp = dlsym(RTLD_NEXT, "bcmp");
+  __libc_strstr = dlsym(RTLD_NEXT, "strstr");
+  __libc_strcasestr = dlsym(RTLD_NEXT, "strcasestr");
+  __libc_memmem = dlsym(RTLD_NEXT, "memmem");
+#endif
+
 }
 
 /* closing as best as we can the tokens file */
 __attribute__((destructor)) void __tokencap_shutdown(void) {
+
   if (__tokencap_out_file != STDERR_FILENO) close(__tokencap_out_file);
+
 }