diff options
Diffstat (limited to 'src/common')
32 files changed, 1044 insertions, 3557 deletions
diff --git a/src/common/Makefile.am b/src/common/Makefile.am deleted file mode 100644 index 5e7684259a..0000000000 --- a/src/common/Makefile.am +++ /dev/null @@ -1,67 +0,0 @@ - -noinst_LIBRARIES = libor.a libor-crypto.a libor-event.a - -EXTRA_DIST = common_sha1.i sha256.c Makefile.nmake - -#CFLAGS = -Wall -Wpointer-arith -O2 - -if USE_OPENBSD_MALLOC -libor_extra_source=OpenBSD_malloc_Linux.c -else -libor_extra_source= -endif - -libor_a_SOURCES = \ - address.c \ - compat.c \ - container.c \ - di_ops.c \ - log.c \ - memarea.c \ - mempool.c \ - procmon.c \ - util.c \ - util_codedigest.c \ - $(libor_extra_source) - -libor_crypto_a_SOURCES = \ - aes.c \ - crypto.c \ - torgzip.c \ - tortls.c - -libor_event_a_SOURCES = compat_libevent.c - -noinst_HEADERS = \ - address.h \ - aes.h \ - ciphers.inc \ - compat.h \ - compat_libevent.h \ - container.h \ - crypto.h \ - di_ops.h \ - ht.h \ - memarea.h \ - mempool.h \ - procmon.h \ - strlcat.c \ - strlcpy.c \ - torgzip.h \ - torint.h \ - torlog.h \ - tortls.h \ - util.h - -common_sha1.i: $(libor_SOURCES) $(libor_crypto_a_SOURCES) $(noinst_HEADERS) - if test "@SHA1SUM@" != none; then \ - (cd "$(srcdir)" && "@SHA1SUM@" $(libor_SOURCES) $(libor_crypto_a_SOURCES) $(noinst_HEADERS)) | "@SED@" -n 's/^\(.*\)$$/"\1\\n"/p' > common_sha1.i; \ - elif test "@OPENSSL@" != none; then \ - (cd "$(srcdir)" && "@OPENSSL@" sha1 $(libor_SOURCES) $(libor_crypto_a_SOURCES) $(noinst_HEADERS)) | "@SED@" -n 's/SHA1(\(.*\))= \(.*\)/"\2 \1\\n"/p' > common_sha1.i; \ - else \ - rm common_sha1.i; \ - touch common_sha1.i; \ - fi - -util_codedigest.o: common_sha1.i -crypto.o: sha256.c diff --git a/src/common/OpenBSD_malloc_Linux.c b/src/common/OpenBSD_malloc_Linux.c deleted file mode 100644 index da82729811..0000000000 --- a/src/common/OpenBSD_malloc_Linux.c +++ /dev/null @@ -1,2057 +0,0 @@ -/* Version 1.83 for Linux. - * Compilation: gcc -shared -fPIC -O2 OpenBSD_malloc_Linux.c -o malloc.so - * Launching: LD_PRELOAD=/path/to/malloc.so firefox - */ - -/* $OpenBSD: malloc.c,v 1.83 2006/05/14 19:53:40 otto Exp $ */ - -/* - * ---------------------------------------------------------------------------- - * "THE BEER-WARE LICENSE" (Revision 42): - * <phk@FreeBSD.ORG> wrote this file. As long as you retain this notice you - * can do whatever you want with this stuff. If we meet some day, and you think - * this stuff is worth it, you can buy me a beer in return. Poul-Henning Kamp - * ---------------------------------------------------------------------------- - */ - -/* We use this macro to remove some code that we don't actually want, - * rather than to fix its warnings. */ -#define BUILDING_FOR_TOR - -/* - * Defining MALLOC_EXTRA_SANITY will enable extra checks which are - * related to internal conditions and consistency in malloc.c. This has - * a noticeable runtime performance hit, and generally will not do you - * any good unless you fiddle with the internals of malloc or want - * to catch random pointer corruption as early as possible. - */ -#ifndef MALLOC_EXTRA_SANITY -#undef MALLOC_EXTRA_SANITY -#endif - -/* - * Defining MALLOC_STATS will enable you to call malloc_dump() and set - * the [dD] options in the MALLOC_OPTIONS environment variable. - * It has no run-time performance hit, but does pull in stdio... - */ -#ifndef MALLOC_STATS -#undef MALLOC_STATS -#endif - -/* - * What to use for Junk. This is the byte value we use to fill with - * when the 'J' option is enabled. - */ -#define SOME_JUNK 0xd0 /* as in "Duh" :-) */ - -#include <sys/types.h> -#include <sys/time.h> -#include <sys/resource.h> -#include <sys/param.h> -#include <sys/mman.h> -#include <sys/uio.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <unistd.h> -#include <fcntl.h> -#include <limits.h> -#include <errno.h> -#include <err.h> -/* For SIZE_T_MAX */ -#include "torint.h" - -//#include "thread_private.h" - -/* - * The basic parameters you can tweak. - * - * malloc_pageshift pagesize = 1 << malloc_pageshift - * It's probably best if this is the native - * page size, but it shouldn't have to be. - * - * malloc_minsize minimum size of an allocation in bytes. - * If this is too small it's too much work - * to manage them. This is also the smallest - * unit of alignment used for the storage - * returned by malloc/realloc. - * - */ - -static int align = 0; -static size_t g_alignment = 0; - -extern int __libc_enable_secure; - -#ifndef HAVE_ISSETUGID -static int issetugid(void) -{ - if (__libc_enable_secure) return 1; - if (getuid() != geteuid()) return 1; - if (getgid() != getegid()) return 1; - return 0; -} -#endif - -#define PGSHIFT 12 -#undef MADV_FREE -#define MADV_FREE MADV_DONTNEED -#include <pthread.h> -static pthread_mutex_t gen_mutex = PTHREAD_MUTEX_INITIALIZER; - -#define _MALLOC_LOCK_INIT() {;} -#define _MALLOC_LOCK() {pthread_mutex_lock(&gen_mutex);} -#define _MALLOC_UNLOCK() {pthread_mutex_unlock(&gen_mutex);} - -#if defined(__sparc__) || defined(__alpha__) -#define malloc_pageshift 13U -#endif -#if defined(__ia64__) -#define malloc_pageshift 14U -#endif - -#ifndef malloc_pageshift -#define malloc_pageshift (PGSHIFT) -#endif - -/* - * No user serviceable parts behind this point. - * - * This structure describes a page worth of chunks. - */ -struct pginfo { - struct pginfo *next; /* next on the free list */ - void *page; /* Pointer to the page */ - u_short size; /* size of this page's chunks */ - u_short shift; /* How far to shift for this size chunks */ - u_short free; /* How many free chunks */ - u_short total; /* How many chunk */ - u_long bits[1];/* Which chunks are free */ -}; - -/* How many bits per u_long in the bitmap */ -#define MALLOC_BITS (int)((NBBY * sizeof(u_long))) - -/* - * This structure describes a number of free pages. - */ -struct pgfree { - struct pgfree *next; /* next run of free pages */ - struct pgfree *prev; /* prev run of free pages */ - void *page; /* pointer to free pages */ - void *pdir; /* pointer to the base page's dir */ - size_t size; /* number of bytes free */ -}; - -/* - * Magic values to put in the page_directory - */ -#define MALLOC_NOT_MINE ((struct pginfo*) 0) -#define MALLOC_FREE ((struct pginfo*) 1) -#define MALLOC_FIRST ((struct pginfo*) 2) -#define MALLOC_FOLLOW ((struct pginfo*) 3) -#define MALLOC_MAGIC ((struct pginfo*) 4) - -#ifndef malloc_minsize -#define malloc_minsize 16UL -#endif - -#if !defined(malloc_pagesize) -#define malloc_pagesize (1UL<<malloc_pageshift) -#endif - -#if ((1UL<<malloc_pageshift) != malloc_pagesize) -#error "(1UL<<malloc_pageshift) != malloc_pagesize" -#endif - -#ifndef malloc_maxsize -#define malloc_maxsize ((malloc_pagesize)>>1) -#endif - -/* A mask for the offset inside a page. */ -#define malloc_pagemask ((malloc_pagesize)-1) - -#define pageround(foo) (((foo) + (malloc_pagemask)) & ~malloc_pagemask) -#define ptr2index(foo) (((u_long)(foo) >> malloc_pageshift)+malloc_pageshift) -#define index2ptr(idx) ((void*)(((idx)-malloc_pageshift)<<malloc_pageshift)) - -/* Set when initialization has been done */ -static unsigned int malloc_started; - -/* Number of free pages we cache */ -static unsigned int malloc_cache = 16; - -/* Structure used for linking discrete directory pages. */ -struct pdinfo { - struct pginfo **base; - struct pdinfo *prev; - struct pdinfo *next; - u_long dirnum; -}; -static struct pdinfo *last_dir; /* Caches to the last and previous */ -static struct pdinfo *prev_dir; /* referenced directory pages. */ - -static size_t pdi_off; -static u_long pdi_mod; -#define PD_IDX(num) ((num) / (malloc_pagesize/sizeof(struct pginfo *))) -#define PD_OFF(num) ((num) & ((malloc_pagesize/sizeof(struct pginfo *))-1)) -#define PI_IDX(index) ((index) / pdi_mod) -#define PI_OFF(index) ((index) % pdi_mod) - -/* The last index in the page directory we care about */ -static u_long last_index; - -/* Pointer to page directory. Allocated "as if with" malloc */ -static struct pginfo **page_dir; - -/* Free pages line up here */ -static struct pgfree free_list; - -/* Abort(), user doesn't handle problems. */ -static int malloc_abort = 2; - -/* Are we trying to die ? */ -static int suicide; - -#ifdef MALLOC_STATS -/* dump statistics */ -static int malloc_stats; -#endif - -/* avoid outputting warnings? */ -static int malloc_silent; - -/* always realloc ? */ -static int malloc_realloc; - -/* mprotect free pages PROT_NONE? */ -static int malloc_freeprot; - -/* use guard pages after allocations? */ -static size_t malloc_guard = 0; -static size_t malloc_guarded; -/* align pointers to end of page? */ -static int malloc_ptrguard; - -static int malloc_hint = 1; - -/* xmalloc behaviour ? */ -static int malloc_xmalloc; - -/* zero fill ? */ -static int malloc_zero; - -/* junk fill ? */ -static int malloc_junk; - -#ifdef __FreeBSD__ -/* utrace ? */ -static int malloc_utrace; - -struct ut { - void *p; - size_t s; - void *r; -}; - -void utrace(struct ut *, int); - -#define UTRACE(a, b, c) \ - if (malloc_utrace) \ - {struct ut u; u.p=a; u.s = b; u.r=c; utrace(&u, sizeof u);} -#else /* !__FreeBSD__ */ -#define UTRACE(a,b,c) -#endif - -/* Status of malloc. */ -static int malloc_active; - -/* Allocated memory. */ -static size_t malloc_used; - -/* My last break. */ -static caddr_t malloc_brk; - -/* One location cache for free-list holders. */ -static struct pgfree *px; - -/* Compile-time options. */ -char *malloc_options; - -/* Name of the current public function. */ -static const char *malloc_func; - -#define MMAP(size) \ - mmap((void *)0, (size), PROT_READ|PROT_WRITE, MAP_ANON|MAP_PRIVATE, \ - -1, (off_t)0) - -/* - * Necessary function declarations. - */ -static void *imalloc(size_t size); -static void ifree(void *ptr); -static void *irealloc(void *ptr, size_t size); -static void *malloc_bytes(size_t size); -void *memalign(size_t boundary, size_t size); -size_t malloc_good_size(size_t size); - -/* - * Function for page directory lookup. - */ -static int -pdir_lookup(u_long index, struct pdinfo ** pdi) -{ - struct pdinfo *spi; - u_long pidx = PI_IDX(index); - - if (last_dir != NULL && PD_IDX(last_dir->dirnum) == pidx) - *pdi = last_dir; - else if (prev_dir != NULL && PD_IDX(prev_dir->dirnum) == pidx) - *pdi = prev_dir; - else if (last_dir != NULL && prev_dir != NULL) { - if ((PD_IDX(last_dir->dirnum) > pidx) ? - (PD_IDX(last_dir->dirnum) - pidx) : - (pidx - PD_IDX(last_dir->dirnum)) - < (PD_IDX(prev_dir->dirnum) > pidx) ? - (PD_IDX(prev_dir->dirnum) - pidx) : - (pidx - PD_IDX(prev_dir->dirnum))) - *pdi = last_dir; - else - *pdi = prev_dir; - - if (PD_IDX((*pdi)->dirnum) > pidx) { - for (spi = (*pdi)->prev; - spi != NULL && PD_IDX(spi->dirnum) > pidx; - spi = spi->prev) - *pdi = spi; - if (spi != NULL) - *pdi = spi; - } else - for (spi = (*pdi)->next; - spi != NULL && PD_IDX(spi->dirnum) <= pidx; - spi = spi->next) - *pdi = spi; - } else { - *pdi = (struct pdinfo *) ((caddr_t) page_dir + pdi_off); - for (spi = *pdi; - spi != NULL && PD_IDX(spi->dirnum) <= pidx; - spi = spi->next) - *pdi = spi; - } - - return ((PD_IDX((*pdi)->dirnum) == pidx) ? 0 : - (PD_IDX((*pdi)->dirnum) > pidx) ? 1 : -1); -} - -#ifdef MALLOC_STATS -void -malloc_dump(int fd) -{ - char buf[1024]; - struct pginfo **pd; - struct pgfree *pf; - struct pdinfo *pi; - u_long j; - - pd = page_dir; - pi = (struct pdinfo *) ((caddr_t) pd + pdi_off); - - /* print out all the pages */ - for (j = 0; j <= last_index;) { - snprintf(buf, sizeof buf, "%08lx %5lu ", j << malloc_pageshift, j); - write(fd, buf, strlen(buf)); - if (pd[PI_OFF(j)] == MALLOC_NOT_MINE) { - for (j++; j <= last_index && pd[PI_OFF(j)] == MALLOC_NOT_MINE;) { - if (!PI_OFF(++j)) { - if ((pi = pi->next) == NULL || - PD_IDX(pi->dirnum) != PI_IDX(j)) - break; - pd = pi->base; - j += pdi_mod; - } - } - j--; - snprintf(buf, sizeof buf, ".. %5lu not mine\n", j); - write(fd, buf, strlen(buf)); - } else if (pd[PI_OFF(j)] == MALLOC_FREE) { - for (j++; j <= last_index && pd[PI_OFF(j)] == MALLOC_FREE;) { - if (!PI_OFF(++j)) { - if ((pi = pi->next) == NULL || - PD_IDX(pi->dirnum) != PI_IDX(j)) - break; - pd = pi->base; - j += pdi_mod; - } - } - j--; - snprintf(buf, sizeof buf, ".. %5lu free\n", j); - write(fd, buf, strlen(buf)); - } else if (pd[PI_OFF(j)] == MALLOC_FIRST) { - for (j++; j <= last_index && pd[PI_OFF(j)] == MALLOC_FOLLOW;) { - if (!PI_OFF(++j)) { - if ((pi = pi->next) == NULL || - PD_IDX(pi->dirnum) != PI_IDX(j)) - break; - pd = pi->base; - j += pdi_mod; - } - } - j--; - snprintf(buf, sizeof buf, ".. %5lu in use\n", j); - write(fd, buf, strlen(buf)); - } else if (pd[PI_OFF(j)] < MALLOC_MAGIC) { - snprintf(buf, sizeof buf, "(%p)\n", pd[PI_OFF(j)]); - write(fd, buf, strlen(buf)); - } else { - snprintf(buf, sizeof buf, "%p %d (of %d) x %d @ %p --> %p\n", - pd[PI_OFF(j)], pd[PI_OFF(j)]->free, - pd[PI_OFF(j)]->total, pd[PI_OFF(j)]->size, - pd[PI_OFF(j)]->page, pd[PI_OFF(j)]->next); - write(fd, buf, strlen(buf)); - } - if (!PI_OFF(++j)) { - if ((pi = pi->next) == NULL) - break; - pd = pi->base; - j += (1 + PD_IDX(pi->dirnum) - PI_IDX(j)) * pdi_mod; - } - } - - for (pf = free_list.next; pf; pf = pf->next) { - snprintf(buf, sizeof buf, "Free: @%p [%p...%p[ %ld ->%p <-%p\n", - pf, pf->page, (char *)pf->page + pf->size, - pf->size, pf->prev, pf->next); - write(fd, buf, strlen(buf)); - if (pf == pf->next) { - snprintf(buf, sizeof buf, "Free_list loops\n"); - write(fd, buf, strlen(buf)); - break; - } - } - - /* print out various info */ - snprintf(buf, sizeof buf, "Minsize\t%lu\n", malloc_minsize); - write(fd, buf, strlen(buf)); - snprintf(buf, sizeof buf, "Maxsize\t%lu\n", malloc_maxsize); - write(fd, buf, strlen(buf)); - snprintf(buf, sizeof buf, "Pagesize\t%lu\n", malloc_pagesize); - write(fd, buf, strlen(buf)); - snprintf(buf, sizeof buf, "Pageshift\t%u\n", malloc_pageshift); - write(fd, buf, strlen(buf)); - snprintf(buf, sizeof buf, "In use\t%lu\n", (u_long) malloc_used); - write(fd, buf, strlen(buf)); - snprintf(buf, sizeof buf, "Guarded\t%lu\n", (u_long) malloc_guarded); - write(fd, buf, strlen(buf)); -} -#endif /* MALLOC_STATS */ - -extern char *__progname; - -static void -wrterror(const char *p) -{ -#ifndef BUILDING_FOR_TOR - const char *q = " error: "; - struct iovec iov[5]; - - iov[0].iov_base = __progname; - iov[0].iov_len = strlen(__progname); - iov[1].iov_base = (char*)malloc_func; - iov[1].iov_len = strlen(malloc_func); - iov[2].iov_base = (char*)q; - iov[2].iov_len = strlen(q); - iov[3].iov_base = (char*)p; - iov[3].iov_len = strlen(p); - iov[4].iov_base = (char*)"\n"; - iov[4].iov_len = 1; - writev(STDERR_FILENO, iov, 5); -#else - (void)p; -#endif - suicide = 1; -#ifdef MALLOC_STATS - if (malloc_stats) - malloc_dump(STDERR_FILENO); -#endif /* MALLOC_STATS */ - malloc_active--; - if (malloc_abort) - abort(); -} - -static void -wrtwarning(const char *p) -{ -#ifndef BUILDING_FOR_TOR - const char *q = " warning: "; - struct iovec iov[5]; -#endif - - if (malloc_abort) - wrterror(p); - else if (malloc_silent) - return; - -#ifndef BUILDING_FOR_TOR - iov[0].iov_base = __progname; - iov[0].iov_len = strlen(__progname); - iov[1].iov_base = (char*)malloc_func; - iov[1].iov_len = strlen(malloc_func); - iov[2].iov_base = (char*)q; - iov[2].iov_len = strlen(q); - iov[3].iov_base = (char*)p; - iov[3].iov_len = strlen(p); - iov[4].iov_base = (char*)"\n"; - iov[4].iov_len = 1; - - (void) writev(STDERR_FILENO, iov, 5); -#else - (void)p; -#endif -} - -#ifdef MALLOC_STATS -static void -malloc_exit(void) -{ - char *q = "malloc() warning: Couldn't dump stats\n"; - int save_errno = errno, fd; - - fd = open("malloc.out", O_RDWR|O_APPEND); - if (fd != -1) { - malloc_dump(fd); - close(fd); - } else - write(STDERR_FILENO, q, strlen(q)); - errno = save_errno; -} -#endif /* MALLOC_STATS */ - -/* - * Allocate aligned mmaped chunk - */ - -static void *MMAP_A(size_t pages, size_t alignment) -{ - void *j, *p; - size_t first_size, rest, begin, end; - if (pages%malloc_pagesize != 0) - pages = pages - pages%malloc_pagesize + malloc_pagesize; - first_size = pages + alignment - malloc_pagesize; - p = MMAP(first_size); - rest = ((size_t)p) % alignment; - j = (rest == 0) ? p : (void*) ((size_t)p + alignment - rest); - begin = (size_t)j - (size_t)p; - if (begin != 0) munmap(p, begin); - end = (size_t)p + first_size - ((size_t)j + pages); - if(end != 0) munmap( (void*) ((size_t)j + pages), end); - - return j; -} - - -/* - * Allocate a number of pages from the OS - */ -static void * -map_pages(size_t pages) -{ - struct pdinfo *pi, *spi; - struct pginfo **pd; - u_long idx, pidx, lidx; - caddr_t result, tail; - u_long index, lindex; - void *pdregion = NULL; - size_t dirs, cnt; - - pages <<= malloc_pageshift; - if (!align) - result = MMAP(pages + malloc_guard); - else { - result = MMAP_A(pages + malloc_guard, g_alignment); - } - if (result == MAP_FAILED) { -#ifdef MALLOC_EXTRA_SANITY - wrtwarning("(ES): map_pages fails"); -#endif /* MALLOC_EXTRA_SANITY */ - errno = ENOMEM; - return (NULL); - } - index = ptr2index(result); - tail = result + pages + malloc_guard; - lindex = ptr2index(tail) - 1; - if (malloc_guard) - mprotect(result + pages, malloc_guard, PROT_NONE); - - pidx = PI_IDX(index); - lidx = PI_IDX(lindex); - - if (tail > malloc_brk) { - malloc_brk = tail; - last_index = lindex; - } - - dirs = lidx - pidx; - - /* Insert directory pages, if needed. */ - if (pdir_lookup(index, &pi) != 0) - dirs++; - - if (dirs > 0) { - pdregion = MMAP(malloc_pagesize * dirs); - if (pdregion == MAP_FAILED) { - munmap(result, tail - result); -#ifdef MALLOC_EXTRA_SANITY - wrtwarning("(ES): map_pages fails"); -#endif - errno = ENOMEM; - return (NULL); - } - } - - cnt = 0; - for (idx = pidx, spi = pi; idx <= lidx; idx++) { - if (pi == NULL || PD_IDX(pi->dirnum) != idx) { - pd = (struct pginfo **)((char *)pdregion + - cnt * malloc_pagesize); - cnt++; - memset(pd, 0, malloc_pagesize); - pi = (struct pdinfo *) ((caddr_t) pd + pdi_off); - pi->base = pd; - pi->prev = spi; - pi->next = spi->next; - pi->dirnum = idx * (malloc_pagesize / - sizeof(struct pginfo *)); - - if (spi->next != NULL) - spi->next->prev = pi; - spi->next = pi; - } - if (idx > pidx && idx < lidx) { - pi->dirnum += pdi_mod; - } else if (idx == pidx) { - if (pidx == lidx) { - pi->dirnum += (u_long)(tail - result) >> - malloc_pageshift; - } else { - pi->dirnum += pdi_mod - PI_OFF(index); - } - } else { - pi->dirnum += PI_OFF(ptr2index(tail - 1)) + 1; - } -#ifdef MALLOC_EXTRA_SANITY - if (PD_OFF(pi->dirnum) > pdi_mod || PD_IDX(pi->dirnum) > idx) { - wrterror("(ES): pages directory overflow"); - errno = EFAULT; - return (NULL); - } -#endif /* MALLOC_EXTRA_SANITY */ - if (idx == pidx && pi != last_dir) { - prev_dir = last_dir; - last_dir = pi; - } - spi = pi; - pi = spi->next; - } -#ifdef MALLOC_EXTRA_SANITY - if (cnt > dirs) - wrtwarning("(ES): cnt > dirs"); -#endif /* MALLOC_EXTRA_SANITY */ - if (cnt < dirs) - munmap((char *)pdregion + cnt * malloc_pagesize, - (dirs - cnt) * malloc_pagesize); - - return (result); -} - -/* - * Initialize the world - */ -static void -malloc_init(void) -{ - char *p, b[64]; - int i, j, save_errno = errno; - - _MALLOC_LOCK_INIT(); - -#ifdef MALLOC_EXTRA_SANITY - malloc_junk = 1; -#endif /* MALLOC_EXTRA_SANITY */ - - for (i = 0; i < 3; i++) { - switch (i) { - case 0: - j = (int) readlink("/etc/malloc.conf", b, sizeof b - 1); - if (j <= 0) - continue; - b[j] = '\0'; - p = b; - break; - case 1: - if (issetugid() == 0) - p = getenv("MALLOC_OPTIONS"); - else - continue; - break; - case 2: - p = malloc_options; - break; - default: - p = NULL; - } - - for (; p != NULL && *p != '\0'; p++) { - switch (*p) { - case '>': - malloc_cache <<= 1; - break; - case '<': - malloc_cache >>= 1; - break; - case 'a': - malloc_abort = 0; - break; - case 'A': - malloc_abort = 1; - break; -#ifdef MALLOC_STATS - case 'd': - malloc_stats = 0; - break; - case 'D': - malloc_stats = 1; - break; -#endif /* MALLOC_STATS */ - case 'f': - malloc_freeprot = 0; - break; - case 'F': - malloc_freeprot = 1; - break; - case 'g': - malloc_guard = 0; - break; - case 'G': - malloc_guard = malloc_pagesize; - break; - case 'h': - malloc_hint = 0; - break; - case 'H': - malloc_hint = 1; - break; - case 'j': - malloc_junk = 0; - break; - case 'J': - malloc_junk = 1; - break; - case 'n': - malloc_silent = 0; - break; - case 'N': - malloc_silent = 1; - break; - case 'p': - malloc_ptrguard = 0; - break; - case 'P': - malloc_ptrguard = 1; - break; - case 'r': - malloc_realloc = 0; - break; - case 'R': - malloc_realloc = 1; - break; -#ifdef __FreeBSD__ - case 'u': - malloc_utrace = 0; - break; - case 'U': - malloc_utrace = 1; - break; -#endif /* __FreeBSD__ */ - case 'x': - malloc_xmalloc = 0; - break; - case 'X': - malloc_xmalloc = 1; - break; - case 'z': - malloc_zero = 0; - break; - case 'Z': - malloc_zero = 1; - break; - default: - j = malloc_abort; - malloc_abort = 0; - wrtwarning("unknown char in MALLOC_OPTIONS"); - malloc_abort = j; - break; - } - } - } - - UTRACE(0, 0, 0); - - /* - * We want junk in the entire allocation, and zero only in the part - * the user asked for. - */ - if (malloc_zero) - malloc_junk = 1; - -#ifdef MALLOC_STATS - if (malloc_stats && (atexit(malloc_exit) == -1)) - wrtwarning("atexit(2) failed." - " Will not be able to dump malloc stats on exit"); -#endif /* MALLOC_STATS */ - - if (malloc_pagesize != getpagesize()) { - wrterror("malloc() replacement compiled with a different " - "page size from what we're running with. Failing."); - errno = ENOMEM; - return; - } - - /* Allocate one page for the page directory. */ - page_dir = (struct pginfo **)MMAP(malloc_pagesize); - - if (page_dir == MAP_FAILED) { - wrterror("mmap(2) failed, check limits"); - errno = ENOMEM; - return; - } - pdi_off = (malloc_pagesize - sizeof(struct pdinfo)) & ~(malloc_minsize - 1); - pdi_mod = pdi_off / sizeof(struct pginfo *); - - last_dir = (struct pdinfo *) ((caddr_t) page_dir + pdi_off); - last_dir->base = page_dir; - last_dir->prev = last_dir->next = NULL; - last_dir->dirnum = malloc_pageshift; - - /* Been here, done that. */ - malloc_started++; - - /* Recalculate the cache size in bytes, and make sure it's nonzero. */ - if (!malloc_cache) - malloc_cache++; - malloc_cache <<= malloc_pageshift; - errno = save_errno; -} - -/* - * Allocate a number of complete pages - */ -static void * -malloc_pages(size_t size) -{ - void *p, *delay_free = NULL, *tp; - size_t i; - struct pginfo **pd; - struct pdinfo *pi; - u_long pidx, index; - struct pgfree *pf; - - size = pageround(size) + malloc_guard; - - p = NULL; - /* Look for free pages before asking for more */ - if (!align) - for (pf = free_list.next; pf; pf = pf->next) { - -#ifdef MALLOC_EXTRA_SANITY - if (pf->size & malloc_pagemask) { - wrterror("(ES): junk length entry on free_list"); - errno = EFAULT; - return (NULL); - } - if (!pf->size) { - wrterror("(ES): zero length entry on free_list"); - errno = EFAULT; - return (NULL); - } - if (pf->page > (pf->page + pf->size)) { - wrterror("(ES): sick entry on free_list"); - errno = EFAULT; - return (NULL); - } - if ((pi = pf->pdir) == NULL) { - wrterror("(ES): invalid page directory on free-list"); - errno = EFAULT; - return (NULL); - } - if ((pidx = PI_IDX(ptr2index(pf->page))) != PD_IDX(pi->dirnum)) { - wrterror("(ES): directory index mismatch on free-list"); - errno = EFAULT; - return (NULL); - } - pd = pi->base; - if (pd[PI_OFF(ptr2index(pf->page))] != MALLOC_FREE) { - wrterror("(ES): non-free first page on free-list"); - errno = EFAULT; - return (NULL); - } - pidx = PI_IDX(ptr2index((pf->page) + (pf->size)) - 1); - for (pi = pf->pdir; pi != NULL && PD_IDX(pi->dirnum) < pidx; - pi = pi->next) - ; - if (pi == NULL || PD_IDX(pi->dirnum) != pidx) { - wrterror("(ES): last page not referenced in page directory"); - errno = EFAULT; - return (NULL); - } - pd = pi->base; - if (pd[PI_OFF(ptr2index((pf->page) + (pf->size)) - 1)] != MALLOC_FREE) { - wrterror("(ES): non-free last page on free-list"); - errno = EFAULT; - return (NULL); - } -#endif /* MALLOC_EXTRA_SANITY */ - - if (pf->size < size) - continue; - - if (pf->size == size) { - p = pf->page; - pi = pf->pdir; - if (pf->next != NULL) - pf->next->prev = pf->prev; - pf->prev->next = pf->next; - delay_free = pf; - break; - } - p = pf->page; - pf->page = (char *) pf->page + size; - pf->size -= size; - pidx = PI_IDX(ptr2index(pf->page)); - for (pi = pf->pdir; pi != NULL && PD_IDX(pi->dirnum) < pidx; - pi = pi->next) - ; - if (pi == NULL || PD_IDX(pi->dirnum) != pidx) { - wrterror("(ES): hole in directories"); - errno = EFAULT; - return (NULL); - } - tp = pf->pdir; - pf->pdir = pi; - pi = tp; - break; - } - - size -= malloc_guard; - -#ifdef MALLOC_EXTRA_SANITY - if (p != NULL && pi != NULL) { - pidx = PD_IDX(pi->dirnum); - pd = pi->base; - } - if (p != NULL && pd[PI_OFF(ptr2index(p))] != MALLOC_FREE) { - wrterror("(ES): allocated non-free page on free-list"); - errno = EFAULT; - return (NULL); - } -#endif /* MALLOC_EXTRA_SANITY */ - - if (p != NULL && (malloc_guard || malloc_freeprot)) - mprotect(p, size, PROT_READ | PROT_WRITE); - - size >>= malloc_pageshift; - - /* Map new pages */ - if (p == NULL) - p = map_pages(size); - - if (p != NULL) { - index = ptr2index(p); - pidx = PI_IDX(index); - pdir_lookup(index, &pi); -#ifdef MALLOC_EXTRA_SANITY - if (pi == NULL || PD_IDX(pi->dirnum) != pidx) { - wrterror("(ES): mapped pages not found in directory"); - errno = EFAULT; - return (NULL); - } -#endif /* MALLOC_EXTRA_SANITY */ - if (pi != last_dir) { - prev_dir = last_dir; - last_dir = pi; - } - pd = pi->base; - pd[PI_OFF(index)] = MALLOC_FIRST; - - for (i = 1; i < size; i++) { - if (!PI_OFF(index + i)) { - pidx++; - pi = pi->next; -#ifdef MALLOC_EXTRA_SANITY - if (pi == NULL || PD_IDX(pi->dirnum) != pidx) { - wrterror("(ES): hole in mapped pages directory"); - errno = EFAULT; - return (NULL); - } -#endif /* MALLOC_EXTRA_SANITY */ - pd = pi->base; - } - pd[PI_OFF(index + i)] = MALLOC_FOLLOW; - } - if (malloc_guard) { - if (!PI_OFF(index + i)) { - pidx++; - pi = pi->next; -#ifdef MALLOC_EXTRA_SANITY - if (pi == NULL || PD_IDX(pi->dirnum) != pidx) { - wrterror("(ES): hole in mapped pages directory"); - errno = EFAULT; - return (NULL); - } -#endif /* MALLOC_EXTRA_SANITY */ - pd = pi->base; - } - pd[PI_OFF(index + i)] = MALLOC_FIRST; - } - - malloc_used += size << malloc_pageshift; - malloc_guarded += malloc_guard; - - if (malloc_junk) - memset(p, SOME_JUNK, size << malloc_pageshift); - } - if (delay_free) { - if (px == NULL) - px = delay_free; - else - ifree(delay_free); - } - return (p); -} - -/* - * Allocate a page of fragments - */ - -static __inline__ int -malloc_make_chunks(int bits) -{ - struct pginfo *bp, **pd; - struct pdinfo *pi; -#ifdef MALLOC_EXTRA_SANITY - u_long pidx; -#endif /* MALLOC_EXTRA_SANITY */ - void *pp; - long i, k; - size_t l; - - /* Allocate a new bucket */ - pp = malloc_pages((size_t) malloc_pagesize); - if (pp == NULL) - return (0); - - /* Find length of admin structure */ - l = sizeof *bp - sizeof(u_long); - l += sizeof(u_long) * - (((malloc_pagesize >> bits) + MALLOC_BITS - 1) / MALLOC_BITS); - - /* Don't waste more than two chunks on this */ - - /* - * If we are to allocate a memory protected page for the malloc(0) - * case (when bits=0), it must be from a different page than the - * pginfo page. - * --> Treat it like the big chunk alloc, get a second data page. - */ - if (bits != 0 && (1UL << (bits)) <= l + l) { - bp = (struct pginfo *) pp; - } else { - bp = (struct pginfo *) imalloc(l); - if (bp == NULL) { - ifree(pp); - return (0); - } - } - - /* memory protect the page allocated in the malloc(0) case */ - if (bits == 0) { - bp->size = 0; - bp->shift = 1; - i = malloc_minsize - 1; - while (i >>= 1) - bp->shift++; - bp->total = bp->free = malloc_pagesize >> bp->shift; - bp->page = pp; - - k = mprotect(pp, malloc_pagesize, PROT_NONE); - if (k < 0) { - ifree(pp); - ifree(bp); - return (0); - } - } else { - bp->size = (1UL << bits); - bp->shift = bits; - bp->total = bp->free = malloc_pagesize >> bits; - bp->page = pp; - } - - /* set all valid bits in the bitmap */ - k = bp->total; - i = 0; - - /* Do a bunch at a time */ - for (; (k - i) >= MALLOC_BITS; i += MALLOC_BITS) - bp->bits[i / MALLOC_BITS] = ~0UL; - - for (; i < k; i++) - bp->bits[i / MALLOC_BITS] |= 1UL << (i % MALLOC_BITS); - - k = (long)l; - if (bp == bp->page) { - /* Mark the ones we stole for ourselves */ - for (i = 0; k > 0; i++) { - bp->bits[i / MALLOC_BITS] &= ~(1UL << (i % MALLOC_BITS)); - bp->free--; - bp->total--; - k -= (1 << bits); - } - } - /* MALLOC_LOCK */ - - pdir_lookup(ptr2index(pp), &pi); -#ifdef MALLOC_EXTRA_SANITY - pidx = PI_IDX(ptr2index(pp)); - if (pi == NULL || PD_IDX(pi->dirnum) != pidx) { - wrterror("(ES): mapped pages not found in directory"); - errno = EFAULT; - return (0); - } -#endif /* MALLOC_EXTRA_SANITY */ - if (pi != last_dir) { - prev_dir = last_dir; - last_dir = pi; - } - pd = pi->base; - pd[PI_OFF(ptr2index(pp))] = bp; - - bp->next = page_dir[bits]; - page_dir[bits] = bp; - - /* MALLOC_UNLOCK */ - return (1); -} - -/* - * Allocate a fragment - */ -static void * -malloc_bytes(size_t size) -{ - int i, j; - size_t k; - u_long u, *lp; - struct pginfo *bp; - - /* Don't bother with anything less than this */ - /* unless we have a malloc(0) requests */ - if (size != 0 && size < malloc_minsize) - size = malloc_minsize; - - /* Find the right bucket */ - if (size == 0) - j = 0; - else { - size_t ii; - j = 1; - ii = size - 1; - while (ii >>= 1) - j++; - } - - /* If it's empty, make a page more of that size chunks */ - if (page_dir[j] == NULL && !malloc_make_chunks(j)) - return (NULL); - - bp = page_dir[j]; - - /* Find first word of bitmap which isn't empty */ - for (lp = bp->bits; !*lp; lp++); - - /* Find that bit, and tweak it */ - u = 1; - k = 0; - while (!(*lp & u)) { - u += u; - k++; - } - - if (malloc_guard) { - /* Walk to a random position. */ -// i = arc4random() % bp->free; - i = rand() % bp->free; - while (i > 0) { - u += u; - k++; - if (k >= MALLOC_BITS) { - lp++; - u = 1; - k = 0; - } -#ifdef MALLOC_EXTRA_SANITY - if (lp - bp->bits > (bp->total - 1) / MALLOC_BITS) { - wrterror("chunk overflow"); - errno = EFAULT; - return (NULL); - } -#endif /* MALLOC_EXTRA_SANITY */ - if (*lp & u) - i--; - } - } - *lp ^= u; - - /* If there are no more free, remove from free-list */ - if (!--bp->free) { - page_dir[j] = bp->next; - bp->next = NULL; - } - /* Adjust to the real offset of that chunk */ - k += (lp - bp->bits) * MALLOC_BITS; - k <<= bp->shift; - - if (malloc_junk && bp->size != 0) - memset((char *)bp->page + k, SOME_JUNK, (size_t)bp->size); - - return ((u_char *) bp->page + k); -} - -/* - * Magic so that malloc(sizeof(ptr)) is near the end of the page. - */ -#define PTR_GAP (malloc_pagesize - sizeof(void *)) -#define PTR_SIZE (sizeof(void *)) -#define PTR_ALIGNED(p) (((unsigned long)p & malloc_pagemask) == PTR_GAP) - -/* - * Allocate a piece of memory - */ -static void * -imalloc(size_t size) -{ - void *result; - int ptralloc = 0; - - if (!malloc_started) - malloc_init(); - - if (suicide) - abort(); - - /* does not matter if malloc_bytes fails */ - if (px == NULL) - px = malloc_bytes(sizeof *px); - - if (malloc_ptrguard && size == PTR_SIZE) { - ptralloc = 1; - size = malloc_pagesize; - } - if (size > SIZE_MAX - malloc_pagesize) { /* Check for overflow */ - result = NULL; - errno = ENOMEM; - } else if (size <= malloc_maxsize) - result = malloc_bytes(size); - else - result = malloc_pages(size); - - if (malloc_abort == 1 && result == NULL) - wrterror("allocation failed"); - - if (malloc_zero && result != NULL) - memset(result, 0, size); - - if (result && ptralloc) - return ((char *) result + PTR_GAP); - return (result); -} - -/* - * Change the size of an allocation. - */ -static void * -irealloc(void *ptr, size_t size) -{ - void *p; - size_t osize; - u_long index, i; - struct pginfo **mp; - struct pginfo **pd; - struct pdinfo *pi; -#ifdef MALLOC_EXTRA_SANITY - u_long pidx; -#endif /* MALLOC_EXTRA_SANITY */ - - if (suicide) - abort(); - - if (!malloc_started) { - wrtwarning("malloc() has never been called"); - return (NULL); - } - if (malloc_ptrguard && PTR_ALIGNED(ptr)) { - if (size <= PTR_SIZE) - return (ptr); - - p = imalloc(size); - if (p) - memcpy(p, ptr, PTR_SIZE); - ifree(ptr); - return (p); - } - index = ptr2index(ptr); - - if (index < malloc_pageshift) { - wrtwarning("junk pointer, too low to make sense"); - return (NULL); - } - if (index > last_index) { - wrtwarning("junk pointer, too high to make sense"); - return (NULL); - } - pdir_lookup(index, &pi); -#ifdef MALLOC_EXTRA_SANITY - pidx = PI_IDX(index); - if (pi == NULL || PD_IDX(pi->dirnum) != pidx) { - wrterror("(ES): mapped pages not found in directory"); - errno = EFAULT; - return (NULL); - } -#endif /* MALLOC_EXTRA_SANITY */ - if (pi != last_dir) { - prev_dir = last_dir; - last_dir = pi; - } - pd = pi->base; - mp = &pd[PI_OFF(index)]; - - if (*mp == MALLOC_FIRST) { /* Page allocation */ - - /* Check the pointer */ - if ((u_long) ptr & malloc_pagemask) { - wrtwarning("modified (page-) pointer"); - return (NULL); - } - /* Find the size in bytes */ - i = index; - if (!PI_OFF(++i)) { - pi = pi->next; - if (pi != NULL && PD_IDX(pi->dirnum) != PI_IDX(i)) - pi = NULL; - if (pi != NULL) - pd = pi->base; - } - for (osize = malloc_pagesize; - pi != NULL && pd[PI_OFF(i)] == MALLOC_FOLLOW;) { - osize += malloc_pagesize; - if (!PI_OFF(++i)) { - pi = pi->next; - if (pi != NULL && PD_IDX(pi->dirnum) != PI_IDX(i)) - pi = NULL; - if (pi != NULL) - pd = pi->base; - } - } - - if (!malloc_realloc && size <= osize && - size > osize - malloc_pagesize) { - if (malloc_junk) - memset((char *)ptr + size, SOME_JUNK, osize - size); - return (ptr); /* ..don't do anything else. */ - } - } else if (*mp >= MALLOC_MAGIC) { /* Chunk allocation */ - - /* Check the pointer for sane values */ - if ((u_long) ptr & ((1UL << ((*mp)->shift)) - 1)) { - wrtwarning("modified (chunk-) pointer"); - return (NULL); - } - /* Find the chunk index in the page */ - i = ((u_long) ptr & malloc_pagemask) >> (*mp)->shift; - - /* Verify that it isn't a free chunk already */ - if ((*mp)->bits[i / MALLOC_BITS] & (1UL << (i % MALLOC_BITS))) { - wrtwarning("chunk is already free"); - return (NULL); - } - osize = (*mp)->size; - - if (!malloc_realloc && size <= osize && - (size > osize / 2 || osize == malloc_minsize)) { - if (malloc_junk) - memset((char *) ptr + size, SOME_JUNK, osize - size); - return (ptr); /* ..don't do anything else. */ - } - } else { - wrtwarning("irealloc: pointer to wrong page"); - return (NULL); - } - - p = imalloc(size); - - if (p != NULL) { - /* copy the lesser of the two sizes, and free the old one */ - /* Don't move from/to 0 sized region !!! */ - if (osize != 0 && size != 0) { - if (osize < size) - memcpy(p, ptr, osize); - else - memcpy(p, ptr, size); - } - ifree(ptr); - } - return (p); -} - -/* - * Free a sequence of pages - */ -static __inline__ void -free_pages(void *ptr, u_long index, struct pginfo * info) -{ - u_long i, pidx, lidx; - size_t l, cachesize = 0; - struct pginfo **pd; - struct pdinfo *pi, *spi; - struct pgfree *pf, *pt = NULL; - caddr_t tail; - - if (info == MALLOC_FREE) { - wrtwarning("page is already free"); - return; - } - if (info != MALLOC_FIRST) { - wrtwarning("free_pages: pointer to wrong page"); - return; - } - if ((u_long) ptr & malloc_pagemask) { - wrtwarning("modified (page-) pointer"); - return; - } - /* Count how many pages and mark them free at the same time */ - pidx = PI_IDX(index); - pdir_lookup(index, &pi); -#ifdef MALLOC_EXTRA_SANITY - if (pi == NULL || PD_IDX(pi->dirnum) != pidx) { - wrterror("(ES): mapped pages not found in directory"); - errno = EFAULT; - return; - } -#endif /* MALLOC_EXTRA_SANITY */ - - spi = pi; /* Save page index for start of region. */ - - pd = pi->base; - pd[PI_OFF(index)] = MALLOC_FREE; - i = 1; - if (!PI_OFF(index + i)) { - pi = pi->next; - if (pi == NULL || PD_IDX(pi->dirnum) != PI_IDX(index + i)) - pi = NULL; - else - pd = pi->base; - } - while (pi != NULL && pd[PI_OFF(index + i)] == MALLOC_FOLLOW) { - pd[PI_OFF(index + i)] = MALLOC_FREE; - i++; - if (!PI_OFF(index + i)) { - if ((pi = pi->next) == NULL || - PD_IDX(pi->dirnum) != PI_IDX(index + i)) - pi = NULL; - else - pd = pi->base; - } - } - - l = i << malloc_pageshift; - - if (malloc_junk) - memset(ptr, SOME_JUNK, l); - - malloc_used -= l; - malloc_guarded -= malloc_guard; - if (malloc_guard) { -#ifdef MALLOC_EXTRA_SANITY - if (pi == NULL || PD_IDX(pi->dirnum) != PI_IDX(index + i)) { - wrterror("(ES): hole in mapped pages directory"); - errno = EFAULT; - return; - } -#endif /* MALLOC_EXTRA_SANITY */ - pd[PI_OFF(index + i)] = MALLOC_FREE; - l += malloc_guard; - } - tail = (caddr_t)ptr + l; - - if (malloc_hint) - madvise(ptr, l, MADV_FREE); - - if (malloc_freeprot) - mprotect(ptr, l, PROT_NONE); - - /* Add to free-list. */ - if (px == NULL && (px = malloc_bytes(sizeof *px)) == NULL) - goto not_return; - px->page = ptr; - px->pdir = spi; - px->size = l; - - if (free_list.next == NULL) { - /* Nothing on free list, put this at head. */ - px->next = NULL; - px->prev = &free_list; - free_list.next = px; - pf = px; - px = NULL; - } else { - /* - * Find the right spot, leave pf pointing to the modified - * entry. - */ - - /* Race ahead here, while calculating cache size. */ - for (pf = free_list.next; - (caddr_t)ptr > ((caddr_t)pf->page + pf->size) - && pf->next != NULL; - pf = pf->next) - cachesize += pf->size; - - /* Finish cache size calculation. */ - pt = pf; - while (pt) { - cachesize += pt->size; - pt = pt->next; - } - - if ((caddr_t)pf->page > tail) { - /* Insert before entry */ - px->next = pf; - px->prev = pf->prev; - pf->prev = px; - px->prev->next = px; - pf = px; - px = NULL; - } else if (((caddr_t)pf->page + pf->size) == ptr) { - /* Append to the previous entry. */ - cachesize -= pf->size; - pf->size += l; - if (pf->next != NULL && - pf->next->page == ((caddr_t)pf->page + pf->size)) { - /* And collapse the next too. */ - pt = pf->next; - pf->size += pt->size; - pf->next = pt->next; - if (pf->next != NULL) - pf->next->prev = pf; - } - } else if (pf->page == tail) { - /* Prepend to entry. */ - cachesize -= pf->size; - pf->size += l; - pf->page = ptr; - pf->pdir = spi; - } else if (pf->next == NULL) { - /* Append at tail of chain. */ - px->next = NULL; - px->prev = pf; - pf->next = px; - pf = px; - px = NULL; - } else { - wrterror("freelist is destroyed"); - errno = EFAULT; - return; - } - } - - if (pf->pdir != last_dir) { - prev_dir = last_dir; - last_dir = pf->pdir; - } - - /* Return something to OS ? */ - if (pf->size > (malloc_cache - cachesize)) { - - /* - * Keep the cache intact. Notice that the '>' above guarantees that - * the pf will always have at least one page afterwards. - */ - if (munmap((char *) pf->page + (malloc_cache - cachesize), - pf->size - (malloc_cache - cachesize)) != 0) - goto not_return; - tail = (caddr_t)pf->page + pf->size; - lidx = ptr2index(tail) - 1; - pf->size = malloc_cache - cachesize; - - index = ptr2index((caddr_t)pf->page + pf->size); - - pidx = PI_IDX(index); - if (prev_dir != NULL && PD_IDX(prev_dir->dirnum) >= pidx) - prev_dir = NULL; /* Will be wiped out below ! */ - - for (pi = pf->pdir; pi != NULL && PD_IDX(pi->dirnum) < pidx; - pi = pi->next) - ; - - spi = pi; - if (pi != NULL && PD_IDX(pi->dirnum) == pidx) { - pd = pi->base; - - for (i = index; i <= lidx;) { - if (pd[PI_OFF(i)] != MALLOC_NOT_MINE) { - pd[PI_OFF(i)] = MALLOC_NOT_MINE; -#ifdef MALLOC_EXTRA_SANITY - if (!PD_OFF(pi->dirnum)) { - wrterror("(ES): pages directory underflow"); - errno = EFAULT; - return; - } -#endif /* MALLOC_EXTRA_SANITY */ - pi->dirnum--; - } -#ifdef MALLOC_EXTRA_SANITY - else - wrtwarning("(ES): page already unmapped"); -#endif /* MALLOC_EXTRA_SANITY */ - i++; - if (!PI_OFF(i)) { - /* - * If no page in that dir, free - * directory page. - */ - if (!PD_OFF(pi->dirnum)) { - /* Remove from list. */ - if (spi == pi) - spi = pi->prev; - if (pi->prev != NULL) - pi->prev->next = pi->next; - if (pi->next != NULL) - pi->next->prev = pi->prev; - pi = pi->next; - munmap(pd, malloc_pagesize); - } else - pi = pi->next; - if (pi == NULL || - PD_IDX(pi->dirnum) != PI_IDX(i)) - break; - pd = pi->base; - } - } - if (pi && !PD_OFF(pi->dirnum)) { - /* Resulting page dir is now empty. */ - /* Remove from list. */ - if (spi == pi) /* Update spi only if first. */ - spi = pi->prev; - if (pi->prev != NULL) - pi->prev->next = pi->next; - if (pi->next != NULL) - pi->next->prev = pi->prev; - pi = pi->next; - munmap(pd, malloc_pagesize); - } - } - if (pi == NULL && malloc_brk == tail) { - /* Resize down the malloc upper boundary. */ - last_index = index - 1; - malloc_brk = index2ptr(index); - } - - /* XXX: We could realloc/shrink the pagedir here I guess. */ - if (pf->size == 0) { /* Remove from free-list as well. */ - if (px) - ifree(px); - if ((px = pf->prev) != &free_list) { - if (pi == NULL && last_index == (index - 1)) { - if (spi == NULL) { - malloc_brk = NULL; - i = 11; - } else { - pd = spi->base; - if (PD_IDX(spi->dirnum) < pidx) - index = - ((PD_IDX(spi->dirnum) + 1) * - pdi_mod) - 1; - for (pi = spi, i = index; - pd[PI_OFF(i)] == MALLOC_NOT_MINE; - i--) -#ifdef MALLOC_EXTRA_SANITY - if (!PI_OFF(i)) { - pi = pi->prev; - if (pi == NULL || i == 0) - break; - pd = pi->base; - i = (PD_IDX(pi->dirnum) + 1) * pdi_mod; - } -#else /* !MALLOC_EXTRA_SANITY */ - { - } -#endif /* MALLOC_EXTRA_SANITY */ - malloc_brk = index2ptr(i + 1); - } - last_index = i; - } - if ((px->next = pf->next) != NULL) - px->next->prev = px; - } else { - if ((free_list.next = pf->next) != NULL) - free_list.next->prev = &free_list; - } - px = pf; - last_dir = prev_dir; - prev_dir = NULL; - } - } -not_return: - if (pt != NULL) - ifree(pt); -} - -/* - * Free a chunk, and possibly the page it's on, if the page becomes empty. - */ - -/* ARGSUSED */ -static __inline__ void -free_bytes(void *ptr, u_long index, struct pginfo * info) -{ - struct pginfo **mp, **pd; - struct pdinfo *pi; -#ifdef MALLOC_EXTRA_SANITY - u_long pidx; -#endif /* MALLOC_EXTRA_SANITY */ - void *vp; - long i; - (void) index; - - /* Find the chunk number on the page */ - i = ((u_long) ptr & malloc_pagemask) >> info->shift; - - if ((u_long) ptr & ((1UL << (info->shift)) - 1)) { - wrtwarning("modified (chunk-) pointer"); - return; - } - if (info->bits[i / MALLOC_BITS] & (1UL << (i % MALLOC_BITS))) { - wrtwarning("chunk is already free"); - return; - } - if (malloc_junk && info->size != 0) - memset(ptr, SOME_JUNK, (size_t)info->size); - - info->bits[i / MALLOC_BITS] |= 1UL << (i % MALLOC_BITS); - info->free++; - - if (info->size != 0) - mp = page_dir + info->shift; - else - mp = page_dir; - - if (info->free == 1) { - /* Page became non-full */ - - /* Insert in address order */ - while (*mp != NULL && (*mp)->next != NULL && - (*mp)->next->page < info->page) - mp = &(*mp)->next; - info->next = *mp; - *mp = info; - return; - } - if (info->free != info->total) - return; - - /* Find & remove this page in the queue */ - while (*mp != info) { - mp = &((*mp)->next); -#ifdef MALLOC_EXTRA_SANITY - if (!*mp) { - wrterror("(ES): Not on queue"); - errno = EFAULT; - return; - } -#endif /* MALLOC_EXTRA_SANITY */ - } - *mp = info->next; - - /* Free the page & the info structure if need be */ - pdir_lookup(ptr2index(info->page), &pi); -#ifdef MALLOC_EXTRA_SANITY - pidx = PI_IDX(ptr2index(info->page)); - if (pi == NULL || PD_IDX(pi->dirnum) != pidx) { - wrterror("(ES): mapped pages not found in directory"); - errno = EFAULT; - return; - } -#endif /* MALLOC_EXTRA_SANITY */ - if (pi != last_dir) { - prev_dir = last_dir; - last_dir = pi; - } - pd = pi->base; - pd[PI_OFF(ptr2index(info->page))] = MALLOC_FIRST; - - /* If the page was mprotected, unprotect it before releasing it */ - if (info->size == 0) - mprotect(info->page, malloc_pagesize, PROT_READ | PROT_WRITE); - - vp = info->page; /* Order is important ! */ - if (vp != (void *) info) - ifree(info); - ifree(vp); -} - -static void -ifree(void *ptr) -{ - struct pginfo *info, **pd; - u_long index; -#ifdef MALLOC_EXTRA_SANITY - u_long pidx; -#endif /* MALLOC_EXTRA_SANITY */ - struct pdinfo *pi; - - if (!malloc_started) { - wrtwarning("malloc() has never been called"); - return; - } - /* If we're already sinking, don't make matters any worse. */ - if (suicide) - return; - - if (malloc_ptrguard && PTR_ALIGNED(ptr)) - ptr = (char *) ptr - PTR_GAP; - - index = ptr2index(ptr); - - if (index < malloc_pageshift) { - warnx("(%p)", ptr); - wrtwarning("ifree: junk pointer, too low to make sense"); - return; - } - if (index > last_index) { - warnx("(%p)", ptr); - wrtwarning("ifree: junk pointer, too high to make sense"); - return; - } - pdir_lookup(index, &pi); -#ifdef MALLOC_EXTRA_SANITY - pidx = PI_IDX(index); - if (pi == NULL || PD_IDX(pi->dirnum) != pidx) { - wrterror("(ES): mapped pages not found in directory"); - errno = EFAULT; - return; - } -#endif /* MALLOC_EXTRA_SANITY */ - if (pi != last_dir) { - prev_dir = last_dir; - last_dir = pi; - } - pd = pi->base; - info = pd[PI_OFF(index)]; - - if (info < MALLOC_MAGIC) - free_pages(ptr, index, info); - else - free_bytes(ptr, index, info); - - /* does not matter if malloc_bytes fails */ - if (px == NULL) - px = malloc_bytes(sizeof *px); - - return; -} - -/* - * Common function for handling recursion. Only - * print the error message once, to avoid making the problem - * potentially worse. - */ -static void -malloc_recurse(void) -{ - static int noprint; - - if (noprint == 0) { - noprint = 1; - wrtwarning("recursive call"); - } - malloc_active--; - _MALLOC_UNLOCK(); - errno = EDEADLK; -} - -/* - * These are the public exported interface routines. - */ -void * -malloc(size_t size) -{ - void *r; - - if (!align) - _MALLOC_LOCK(); - malloc_func = " in malloc():"; - if (malloc_active++) { - malloc_recurse(); - return (NULL); - } - r = imalloc(size); - UTRACE(0, size, r); - malloc_active--; - if (!align) - _MALLOC_UNLOCK(); - if (malloc_xmalloc && r == NULL) { - wrterror("out of memory"); - errno = ENOMEM; - } - return (r); -} - -void -free(void *ptr) -{ - /* This is legal. XXX quick path */ - if (ptr == NULL) - return; - - _MALLOC_LOCK(); - malloc_func = " in free():"; - if (malloc_active++) { - malloc_recurse(); - return; - } - ifree(ptr); - UTRACE(ptr, 0, 0); - malloc_active--; - _MALLOC_UNLOCK(); - return; -} - -void * -realloc(void *ptr, size_t size) -{ - void *r; - - _MALLOC_LOCK(); - malloc_func = " in realloc():"; - if (malloc_active++) { - malloc_recurse(); - return (NULL); - } - - if (ptr == NULL) - r = imalloc(size); - else - r = irealloc(ptr, size); - - UTRACE(ptr, size, r); - malloc_active--; - _MALLOC_UNLOCK(); - if (malloc_xmalloc && r == NULL) { - wrterror("out of memory"); - errno = ENOMEM; - } - return (r); -} - -#ifndef SIZE_MAX -//#if defined(__i386__)||defined(__arm__)||defined(__powerpc__) -//#define SIZE_MAX 0xffffffff -//#endif -//#if defined(__x86_64__) -//#define SIZE_MAX 0xffffffffffffffff -//#endif -#define SIZE_MAX SIZE_T_MAX -#endif - -void * -calloc(size_t num, size_t size) -{ - void *p; - - if (num && SIZE_MAX / num < size) { - fprintf(stderr,"OOOOPS"); - errno = ENOMEM; - return NULL; - } - size *= num; - p = malloc(size); - if (p) - memset(p, 0, size); - return(p); -} - -#ifndef BUILDING_FOR_TOR -static int ispowerof2 (size_t a) { - size_t b; - for (b = 1ULL << (sizeof(size_t)*NBBY - 1); b > 1; b >>= 1) - if (b == a) - return 1; - return 0; -} -#endif - -#ifndef BUILDING_FOR_TOR -int posix_memalign(void **memptr, size_t alignment, size_t size) -{ - void *r; - size_t max; - if ((alignment < PTR_SIZE) || (alignment%PTR_SIZE != 0)) return EINVAL; - if (!ispowerof2(alignment)) return EINVAL; - if (alignment < malloc_minsize) alignment = malloc_minsize; - max = alignment > size ? alignment : size; - if (alignment <= malloc_pagesize) - r = malloc(max); - else { - _MALLOC_LOCK(); - align = 1; - g_alignment = alignment; - r = malloc(size); - align=0; - _MALLOC_UNLOCK(); - } - *memptr = r; - if (!r) return ENOMEM; - return 0; -} - -void *memalign(size_t boundary, size_t size) -{ - void *r; - posix_memalign(&r, boundary, size); - return r; -} - -void *valloc(size_t size) -{ - void *r; - posix_memalign(&r, malloc_pagesize, size); - return r; -} -#endif - -size_t malloc_good_size(size_t size) -{ - if (size == 0) { - return 1; - } else if (size <= malloc_maxsize) { - int j; - size_t ii; - /* round up to the nearest power of 2, with same approach - * as malloc_bytes() uses. */ - j = 1; - ii = size - 1; - while (ii >>= 1) - j++; - return ((size_t)1) << j; - } else { - return pageround(size); - } -} diff --git a/src/common/address.c b/src/common/address.c index e88869f1d8..a714ead5e6 100644 --- a/src/common/address.c +++ b/src/common/address.c @@ -305,7 +305,8 @@ tor_addr_lookup(const char *name, uint16_t family, tor_addr_t *addr) * also treated as internal for now.) */ int -tor_addr_is_internal(const tor_addr_t *addr, int for_listening) +tor_addr_is_internal_(const tor_addr_t *addr, int for_listening, + const char *filename, int lineno) { uint32_t iph4 = 0; uint32_t iph6[4]; @@ -355,8 +356,8 @@ tor_addr_is_internal(const tor_addr_t *addr, int for_listening) /* unknown address family... assume it's not safe for external use */ /* rather than tor_assert(0) */ - log_warn(LD_BUG, "tor_addr_is_internal() called with a non-IP address of " - "type %d", (int)v_family); + log_warn(LD_BUG, "tor_addr_is_internal() called from %s:%d with a " + "non-IP address of type %d", filename, lineno, (int)v_family); tor_fragile_assert(); return 1; } @@ -1006,6 +1007,19 @@ fmt_addr_impl(const tor_addr_t *addr, int decorate) return "???"; } +/** Return a string representing the pair <b>addr</b> and <b>port</b>. + * This calls fmt_and_decorate_addr internally, so IPv6 addresses will + * have brackets, and the caveats of fmt_addr_impl apply. + */ +const char * +fmt_addrport(const tor_addr_t *addr, uint16_t port) +{ + /* Add space for a colon and up to 5 digits. */ + static char buf[TOR_ADDR_BUF_LEN + 6]; + tor_snprintf(buf, sizeof(buf), "%s:%u", fmt_and_decorate_addr(addr), port); + return buf; +} + /** Like fmt_addr(), but takes <b>addr</b> as a host-order IPv4 * addresses. Also not thread-safe, also clobbers its return buffer on * repeated calls. */ @@ -1408,17 +1422,17 @@ addr_port_lookup(int severity, const char *addrport, char **address, uint32_t *addr, uint16_t *port_out) { const char *colon; - char *_address = NULL; - int _port; + char *address_ = NULL; + int port_; int ok = 1; tor_assert(addrport); colon = strrchr(addrport, ':'); if (colon) { - _address = tor_strndup(addrport, colon-addrport); - _port = (int) tor_parse_long(colon+1,10,1,65535,NULL,NULL); - if (!_port) { + address_ = tor_strndup(addrport, colon-addrport); + port_ = (int) tor_parse_long(colon+1,10,1,65535,NULL,NULL); + if (!port_) { log_fn(severity, LD_GENERAL, "Port %s out of range", escaped(colon+1)); ok = 0; } @@ -1431,28 +1445,28 @@ addr_port_lookup(int severity, const char *addrport, char **address, ok = 0; } } else { - _address = tor_strdup(addrport); - _port = 0; + address_ = tor_strdup(addrport); + port_ = 0; } if (addr) { /* There's an addr pointer, so we need to resolve the hostname. */ - if (tor_lookup_hostname(_address,addr)) { - log_fn(severity, LD_NET, "Couldn't look up %s", escaped(_address)); + if (tor_lookup_hostname(address_,addr)) { + log_fn(severity, LD_NET, "Couldn't look up %s", escaped(address_)); ok = 0; *addr = 0; } } if (address && ok) { - *address = _address; + *address = address_; } else { if (address) *address = NULL; - tor_free(_address); + tor_free(address_); } if (port_out) - *port_out = ok ? ((uint16_t) _port) : 0; + *port_out = ok ? ((uint16_t) port_) : 0; return ok ? 0 : -1; } @@ -1697,3 +1711,15 @@ tor_addr_hostname_is_local(const char *name) !strcasecmpend(name, ".local"); } +/** Return a newly allocated tor_addr_port_t with <b>addr</b> and + <b>port</b> filled in. */ +tor_addr_port_t * +tor_addr_port_new(const tor_addr_t *addr, uint16_t port) +{ + tor_addr_port_t *ap = tor_malloc_zero(sizeof(tor_addr_port_t)); + if (addr) + tor_addr_copy(&ap->addr, addr); + ap->port = port; + return ap; +} + diff --git a/src/common/address.h b/src/common/address.h index c6c126862a..067b7a0ca6 100644 --- a/src/common/address.h +++ b/src/common/address.h @@ -8,8 +8,8 @@ * \brief Headers for address.h **/ -#ifndef _TOR_ADDRESS_H -#define _TOR_ADDRESS_H +#ifndef TOR_ADDRESS_H +#define TOR_ADDRESS_H #include "orconfig.h" #include "torint.h" @@ -40,7 +40,7 @@ typedef struct tor_addr_port_t uint16_t port; } tor_addr_port_t; -#define TOR_ADDR_NULL {AF_UNSPEC, {0}}; +#define TOR_ADDR_NULL {AF_UNSPEC, {0}} static INLINE const struct in6_addr *tor_addr_to_in6(const tor_addr_t *a); static INLINE uint32_t tor_addr_to_ipv4n(const tor_addr_t *a); @@ -145,6 +145,7 @@ char *tor_dup_addr(const tor_addr_t *addr) ATTR_MALLOC; * addresses. */ #define fmt_and_decorate_addr(a) fmt_addr_impl((a), 1) const char *fmt_addr_impl(const tor_addr_t *addr, int decorate); +const char *fmt_addrport(const tor_addr_t *addr, uint16_t port); const char * fmt_addr32(uint32_t addr); int get_interface_address6(int severity, sa_family_t family, tor_addr_t *addr); @@ -167,7 +168,10 @@ int tor_addr_compare_masked(const tor_addr_t *addr1, const tor_addr_t *addr2, unsigned int tor_addr_hash(const tor_addr_t *addr); int tor_addr_is_v4(const tor_addr_t *addr); -int tor_addr_is_internal(const tor_addr_t *ip, int for_listening); +int tor_addr_is_internal_(const tor_addr_t *ip, int for_listening, + const char *filename, int lineno); +#define tor_addr_is_internal(addr, for_listening) \ + tor_addr_is_internal_((addr), (for_listening), SHORT_FILE__, __LINE__) /** Longest length that can be required for a reverse lookup name. */ /* 32 nybbles, 32 dots, 8 characters of "ip6.arpa", 1 NUL: 73 characters. */ @@ -221,5 +225,7 @@ int tor_inet_ntoa(const struct in_addr *in, char *buf, size_t buf_len); char *tor_dup_ip(uint32_t addr) ATTR_MALLOC; int get_interface_address(int severity, uint32_t *addr); +tor_addr_port_t *tor_addr_port_new(const tor_addr_t *addr, uint16_t port); + #endif diff --git a/src/common/aes.c b/src/common/aes.c index 59d864a3d0..8e489baae1 100644 --- a/src/common/aes.c +++ b/src/common/aes.c @@ -134,8 +134,8 @@ int evaluate_evp_for_aes(int force_val) { (void) force_val; - log_notice(LD_CRYPTO, "This version of OpenSSL has a known-good EVP " - "counter-mode implementation. Using it."); + log_info(LD_CRYPTO, "This version of OpenSSL has a known-good EVP " + "counter-mode implementation. Using it."); return 0; } int @@ -212,11 +212,11 @@ evaluate_evp_for_aes(int force_val) e = ENGINE_get_cipher_engine(NID_aes_128_ecb); if (e) { - log_notice(LD_CRYPTO, "AES engine \"%s\" found; using EVP_* functions.", + log_info(LD_CRYPTO, "AES engine \"%s\" found; using EVP_* functions.", ENGINE_get_name(e)); should_use_EVP = 1; } else { - log_notice(LD_CRYPTO, "No AES engine found; using AES_* functions."); + log_info(LD_CRYPTO, "No AES engine found; using AES_* functions."); should_use_EVP = 0; } #endif @@ -263,12 +263,12 @@ evaluate_ctr_for_aes(void) "not using it."); } else { /* Counter mode is okay */ - log_notice(LD_CRYPTO, "This OpenSSL has a good implementation of counter " + log_info(LD_CRYPTO, "This OpenSSL has a good implementation of counter " "mode; using it."); should_use_openssl_CTR = 1; } #else - log_notice(LD_CRYPTO, "This version of OpenSSL has a slow implementation of " + log_info(LD_CRYPTO, "This version of OpenSSL has a slow implementation of " "counter mode; not using it."); #endif return 0; @@ -285,7 +285,7 @@ evaluate_ctr_for_aes(void) * value of the current counter. */ static INLINE void -_aes_fill_buf(aes_cnt_cipher_t *cipher) +aes_fill_buf_(aes_cnt_cipher_t *cipher) { /* We don't currently use OpenSSL's counter mode implementation because: * 1) some versions have known bugs @@ -340,7 +340,7 @@ aes_set_key(aes_cnt_cipher_t *cipher, const char *key, int key_bits) EVP_EncryptInit(&cipher->key.evp, c, (const unsigned char*)key, NULL); cipher->using_evp = 1; } else { - AES_set_encrypt_key((const unsigned char *)key, key_bits, &cipher->key.aes); + AES_set_encrypt_key((const unsigned char *)key, key_bits,&cipher->key.aes); cipher->using_evp = 0; } @@ -360,7 +360,7 @@ aes_set_key(aes_cnt_cipher_t *cipher, const char *key, int key_bits) memset(cipher->buf, 0, sizeof(cipher->buf)); else #endif - _aes_fill_buf(cipher); + aes_fill_buf_(cipher); } /** Release storage held by <b>cipher</b> @@ -387,9 +387,10 @@ aes_cipher_free(aes_cnt_cipher_t *cipher) #ifdef CAN_USE_OPENSSL_CTR /* Helper function to use EVP with openssl's counter-mode wrapper. */ -static void evp_block128_fn(const uint8_t in[16], - uint8_t out[16], - const void *key) +static void +evp_block128_fn(const uint8_t in[16], + uint8_t out[16], + const void *key) { EVP_CIPHER_CTX *ctx = (void*)key; int inl=16, outl=16; @@ -429,8 +430,7 @@ aes_crypt(aes_cnt_cipher_t *cipher, const char *input, size_t len, &cipher->pos); } return; - } - else + } else #endif { int c = cipher->pos; @@ -453,7 +453,7 @@ aes_crypt(aes_cnt_cipher_t *cipher, const char *input, size_t len, UPDATE_CTR_BUF(cipher, 1); } UPDATE_CTR_BUF(cipher, 0); - _aes_fill_buf(cipher); + aes_fill_buf_(cipher); } } } @@ -469,8 +469,7 @@ aes_crypt_inplace(aes_cnt_cipher_t *cipher, char *data, size_t len) if (should_use_openssl_CTR) { aes_crypt(cipher, data, len, data); return; - } - else + } else #endif { int c = cipher->pos; @@ -493,7 +492,7 @@ aes_crypt_inplace(aes_cnt_cipher_t *cipher, char *data, size_t len) UPDATE_CTR_BUF(cipher, 1); } UPDATE_CTR_BUF(cipher, 0); - _aes_fill_buf(cipher); + aes_fill_buf_(cipher); } } } @@ -515,7 +514,8 @@ aes_set_iv(aes_cnt_cipher_t *cipher, const char *iv) #ifdef CAN_USE_OPENSSL_CTR if (!should_use_openssl_CTR) #endif - _aes_fill_buf(cipher); + aes_fill_buf_(cipher); } #endif + diff --git a/src/common/aes.h b/src/common/aes.h index bde567f87f..fadeacc7ad 100644 --- a/src/common/aes.h +++ b/src/common/aes.h @@ -5,8 +5,8 @@ /* Implements a minimal interface to counter-mode AES. */ -#ifndef _TOR_AES_H -#define _TOR_AES_H +#ifndef TOR_AES_H +#define TOR_AES_H /** * \file aes.h diff --git a/src/common/compat.c b/src/common/compat.c index ca850a3038..b8674a2f5f 100644 --- a/src/common/compat.c +++ b/src/common/compat.c @@ -18,7 +18,7 @@ /* XXXX024 We should just use AC_USE_SYSTEM_EXTENSIONS in our autoconf, * and get this (and other important stuff!) automatically. Once we do that, * make sure to also change the extern char **environ detection in - * configure.in, because whether that is declared or not depends on whether + * configure.ac, because whether that is declared or not depends on whether * we have _GNU_SOURCE defined! Maybe that means that once we take this out, * we can also take out the configure check. */ #define _GNU_SOURCE @@ -1256,7 +1256,7 @@ tor_socketpair(int family, int type, int protocol, tor_socket_t fd[2]) /** Number of extra file descriptors to keep in reserve beyond those that we * tell Tor it's allowed to use. */ -#define ULIMIT_BUFFER 32 /* keep 32 extra fd's beyond _ConnLimit */ +#define ULIMIT_BUFFER 32 /* keep 32 extra fd's beyond ConnLimit_ */ /** Learn the maximum allowed number of file descriptors, and tell the system * we want to use up to that number. (Some systems have a low soft limit, and diff --git a/src/common/compat.h b/src/common/compat.h index 42648bb04b..9ad03d33c5 100644 --- a/src/common/compat.h +++ b/src/common/compat.h @@ -3,8 +3,8 @@ * Copyright (c) 2007-2012, The Tor Project, Inc. */ /* See LICENSE for licensing information */ -#ifndef _TOR_COMPAT_H -#define _TOR_COMPAT_H +#ifndef TOR_COMPAT_H +#define TOR_COMPAT_H #include "orconfig.h" #include "torint.h" @@ -308,10 +308,10 @@ char *tor_strtok_r_impl(char *str, const char *sep, char **lasts); #endif #ifdef _WIN32 -#define _SHORT_FILE_ (tor_fix_source_file(__FILE__)) +#define SHORT_FILE__ (tor_fix_source_file(__FILE__)) const char *tor_fix_source_file(const char *fname); #else -#define _SHORT_FILE_ (__FILE__) +#define SHORT_FILE__ (__FILE__) #define tor_fix_source_file(s) (s) #endif diff --git a/src/common/compat_libevent.c b/src/common/compat_libevent.c index 6655ca87d3..0d06c49c9f 100644 --- a/src/common/compat_libevent.c +++ b/src/common/compat_libevent.c @@ -266,7 +266,7 @@ tor_libevent_initialize(tor_libevent_cfg *torcfg) #if defined(HAVE_EVENT_GET_VERSION) && defined(HAVE_EVENT_GET_METHOD) /* Making this a NOTICE for now so we can link bugs to a libevent versions * or methods better. */ - log(LOG_NOTICE, LD_GENERAL, + log(LOG_INFO, LD_GENERAL, "Initialized libevent version %s using method %s. Good.", event_get_version(), tor_libevent_get_method()); #else diff --git a/src/common/compat_libevent.h b/src/common/compat_libevent.h index 56285ef80d..68da472cfc 100644 --- a/src/common/compat_libevent.h +++ b/src/common/compat_libevent.h @@ -1,8 +1,8 @@ /* Copyright (c) 2009-2012, The Tor Project, Inc. */ /* See LICENSE for licensing information */ -#ifndef _TOR_COMPAT_LIBEVENT_H -#define _TOR_COMPAT_LIBEVENT_H +#ifndef TOR_COMPAT_LIBEVENT_H +#define TOR_COMPAT_LIBEVENT_H #include "orconfig.h" diff --git a/src/common/container.c b/src/common/container.c index ede98eca5a..d4a2f89c90 100644 --- a/src/common/container.c +++ b/src/common/container.c @@ -571,59 +571,116 @@ smartlist_bsearch_idx(const smartlist_t *sl, const void *key, int (*compare)(const void *key, const void **member), int *found_out) { - const int len = smartlist_len(sl); - int hi, lo, cmp, mid; + int hi, lo, cmp, mid, len, diff; + tor_assert(sl); + tor_assert(compare); + tor_assert(found_out); + + len = smartlist_len(sl); + + /* Check for the trivial case of a zero-length list */ if (len == 0) { *found_out = 0; + /* We already know smartlist_len(sl) is 0 in this case */ return 0; - } else if (len == 1) { - cmp = compare(key, (const void **) &sl->list[0]); - if (cmp == 0) { - *found_out = 1; - return 0; - } else if (cmp < 0) { - *found_out = 0; - return 0; - } else { - *found_out = 0; - return 1; - } } - hi = smartlist_len(sl) - 1; + /* Okay, we have a real search to do */ + tor_assert(len > 0); lo = 0; + hi = len - 1; + + /* + * These invariants are always true: + * + * For all i such that 0 <= i < lo, sl[i] < key + * For all i such that hi < i <= len, sl[i] > key + */ while (lo <= hi) { - mid = (lo + hi) / 2; + diff = hi - lo; + /* + * We want mid = (lo + hi) / 2, but that could lead to overflow, so + * instead diff = hi - lo (non-negative because of loop condition), and + * then hi = lo + diff, mid = (lo + lo + diff) / 2 = lo + (diff / 2). + */ + mid = lo + (diff / 2); cmp = compare(key, (const void**) &(sl->list[mid])); - if (cmp>0) { /* key > sl[mid] */ - lo = mid+1; - } else if (cmp<0) { /* key < sl[mid] */ - hi = mid-1; - } else { /* key == sl[mid] */ + if (cmp == 0) { + /* sl[mid] == key; we found it */ *found_out = 1; return mid; - } - } - /* lo > hi. */ - { - tor_assert(lo >= 0); - if (lo < smartlist_len(sl)) { - cmp = compare(key, (const void**) &(sl->list[lo])); + } else if (cmp > 0) { + /* + * key > sl[mid] and an index i such that sl[i] == key must + * have i > mid if it exists. + */ + + /* + * Since lo <= mid <= hi, hi can only decrease on each iteration (by + * being set to mid - 1) and hi is initially len - 1, mid < len should + * always hold, and this is not symmetric with the left end of list + * mid > 0 test below. A key greater than the right end of the list + * should eventually lead to lo == hi == mid == len - 1, and then + * we set lo to len below and fall out to the same exit we hit for + * a key in the middle of the list but not matching. Thus, we just + * assert for consistency here rather than handle a mid == len case. + */ + tor_assert(mid < len); + /* Move lo to the element immediately after sl[mid] */ + lo = mid + 1; + } else { + /* This should always be true in this case */ tor_assert(cmp < 0); - } else if (smartlist_len(sl)) { - cmp = compare(key, (const void**) &(sl->list[smartlist_len(sl)-1])); - tor_assert(cmp > 0); + + /* + * key < sl[mid] and an index i such that sl[i] == key must + * have i < mid if it exists. + */ + + if (mid > 0) { + /* Normal case, move hi to the element immediately before sl[mid] */ + hi = mid - 1; + } else { + /* These should always be true in this case */ + tor_assert(mid == lo); + tor_assert(mid == 0); + /* + * We were at the beginning of the list and concluded that every + * element e compares e > key. + */ + *found_out = 0; + return 0; + } } } + + /* + * lo > hi; we have no element matching key but we have elements falling + * on both sides of it. The lo index points to the first element > key. + */ + tor_assert(lo == hi + 1); /* All other cases should have been handled */ + tor_assert(lo >= 0); + tor_assert(lo <= len); + tor_assert(hi >= 0); + tor_assert(hi <= len); + + if (lo < len) { + cmp = compare(key, (const void **) &(sl->list[lo])); + tor_assert(cmp < 0); + } else { + cmp = compare(key, (const void **) &(sl->list[len-1])); + tor_assert(cmp > 0); + } + *found_out = 0; return lo; } /** Helper: compare two const char **s. */ static int -_compare_string_ptrs(const void **_a, const void **_b) +compare_string_ptrs_(const void **_a, const void **_b) { return strcmp((const char*)*_a, (const char*)*_b); } @@ -633,14 +690,14 @@ _compare_string_ptrs(const void **_a, const void **_b) void smartlist_sort_strings(smartlist_t *sl) { - smartlist_sort(sl, _compare_string_ptrs); + smartlist_sort(sl, compare_string_ptrs_); } /** Return the most frequent string in the sorted list <b>sl</b> */ char * smartlist_get_most_frequent_string(smartlist_t *sl) { - return smartlist_get_most_frequent(sl, _compare_string_ptrs); + return smartlist_get_most_frequent(sl, compare_string_ptrs_); } /** Remove duplicate strings from a sorted list, and free them with tor_free(). @@ -648,7 +705,7 @@ smartlist_get_most_frequent_string(smartlist_t *sl) void smartlist_uniq_strings(smartlist_t *sl) { - smartlist_uniq(sl, _compare_string_ptrs, _tor_free); + smartlist_uniq(sl, compare_string_ptrs_, tor_free_); } /* Heap-based priority queue implementation for O(lg N) insert and remove. @@ -849,7 +906,7 @@ smartlist_pqueue_assert_ok(smartlist_t *sl, /** Helper: compare two DIGEST_LEN digests. */ static int -_compare_digests(const void **_a, const void **_b) +compare_digests_(const void **_a, const void **_b) { return tor_memcmp((const char*)*_a, (const char*)*_b, DIGEST_LEN); } @@ -858,7 +915,7 @@ _compare_digests(const void **_a, const void **_b) void smartlist_sort_digests(smartlist_t *sl) { - smartlist_sort(sl, _compare_digests); + smartlist_sort(sl, compare_digests_); } /** Remove duplicate digests from a sorted list, and free them with tor_free(). @@ -866,12 +923,12 @@ smartlist_sort_digests(smartlist_t *sl) void smartlist_uniq_digests(smartlist_t *sl) { - smartlist_uniq(sl, _compare_digests, _tor_free); + smartlist_uniq(sl, compare_digests_, tor_free_); } /** Helper: compare two DIGEST256_LEN digests. */ static int -_compare_digests256(const void **_a, const void **_b) +compare_digests256_(const void **_a, const void **_b) { return tor_memcmp((const char*)*_a, (const char*)*_b, DIGEST256_LEN); } @@ -880,7 +937,7 @@ _compare_digests256(const void **_a, const void **_b) void smartlist_sort_digests256(smartlist_t *sl) { - smartlist_sort(sl, _compare_digests256); + smartlist_sort(sl, compare_digests256_); } /** Return the most frequent member of the sorted list of DIGEST256_LEN @@ -888,7 +945,7 @@ smartlist_sort_digests256(smartlist_t *sl) char * smartlist_get_most_frequent_digest256(smartlist_t *sl) { - return smartlist_get_most_frequent(sl, _compare_digests256); + return smartlist_get_most_frequent(sl, compare_digests256_); } /** Remove duplicate 256-bit digests from a sorted list, and free them with @@ -897,7 +954,7 @@ smartlist_get_most_frequent_digest256(smartlist_t *sl) void smartlist_uniq_digests256(smartlist_t *sl) { - smartlist_uniq(sl, _compare_digests256, _tor_free); + smartlist_uniq(sl, compare_digests256_, tor_free_); } /** Helper: Declare an entry type and a map type to implement a mapping using diff --git a/src/common/container.h b/src/common/container.h index dab3b83f37..0b3a3d1412 100644 --- a/src/common/container.h +++ b/src/common/container.h @@ -3,8 +3,8 @@ * Copyright (c) 2007-2012, The Tor Project, Inc. */ /* See LICENSE for licensing information */ -#ifndef _TOR_CONTAINER_H -#define _TOR_CONTAINER_H +#ifndef TOR_CONTAINER_H +#define TOR_CONTAINER_H #include "util.h" diff --git a/src/common/crypto.c b/src/common/crypto.c index a69e6c5cb8..c5844046e8 100644 --- a/src/common/crypto.c +++ b/src/common/crypto.c @@ -57,8 +57,8 @@ #include "container.h" #include "compat.h" -#if OPENSSL_VERSION_NUMBER < OPENSSL_V_SERIES(0,9,7) -#error "We require OpenSSL >= 0.9.7" +#if OPENSSL_VERSION_NUMBER < OPENSSL_V_SERIES(0,9,8) +#error "We require OpenSSL >= 0.9.8" #endif #ifdef ANDROID @@ -69,31 +69,6 @@ /** Longest recognized */ #define MAX_DNS_LABEL_SIZE 63 -#if OPENSSL_VERSION_NUMBER < OPENSSL_V_SERIES(0,9,8) && \ - !defined(RUNNING_DOXYGEN) -/** @{ */ -/** On OpenSSL versions before 0.9.8, there is no working SHA256 - * implementation, so we use Tom St Denis's nice speedy one, slightly adapted - * to our needs. These macros make it usable by us. */ -#define SHA256_CTX sha256_state -#define SHA256_Init sha256_init -#define SHA256_Update sha256_process -#define LTC_ARGCHK(x) tor_assert(x) -/** @} */ -#include "sha256.c" -#define SHA256_Final(a,b) sha256_done(b,a) - -static unsigned char * -SHA256(const unsigned char *m, size_t len, unsigned char *d) -{ - SHA256_CTX ctx; - SHA256_Init(&ctx); - SHA256_Update(&ctx, m, len); - SHA256_Final(d, &ctx); - return d; -} -#endif - /** Macro: is k a valid RSA public or private key? */ #define PUBLIC_KEY_OK(k) ((k) && (k)->key && (k)->key->n) /** Macro: is k a valid RSA private key? */ @@ -101,9 +76,9 @@ SHA256(const unsigned char *m, size_t len, unsigned char *d) #ifdef TOR_IS_MULTITHREADED /** A number of preallocated mutexes for use by OpenSSL. */ -static tor_mutex_t **_openssl_mutexes = NULL; +static tor_mutex_t **openssl_mutexes_ = NULL; /** How many mutexes have we allocated for use by OpenSSL? */ -static int _n_openssl_mutexes = 0; +static int n_openssl_mutexes_ = 0; #endif /** A public key, or a public/private key-pair. */ @@ -158,7 +133,7 @@ crypto_get_rsa_padding(int padding) } /** Boolean: has OpenSSL's crypto been initialized? */ -static int _crypto_global_initialized = 0; +static int crypto_global_initialized_ = 0; /** Log all pending crypto errors at level <b>severity</b>. Use * <b>doing</b> to describe our current activities. @@ -221,16 +196,60 @@ try_load_engine(const char *path, const char *engine) } #endif +static char *crypto_openssl_version_str = NULL; +/* Return a human-readable version of the run-time openssl version number. */ +const char * +crypto_openssl_get_version_str(void) +{ + if (crypto_openssl_version_str == NULL) { + const char *raw_version = SSLeay_version(SSLEAY_VERSION); + const char *end_of_version = NULL; + /* The output should be something like "OpenSSL 1.0.0b 10 May 2012. Let's + trim that down. */ + if (!strcmpstart(raw_version, "OpenSSL ")) { + raw_version += strlen("OpenSSL "); + end_of_version = strchr(raw_version, ' '); + } + + if (end_of_version) + crypto_openssl_version_str = tor_strndup(raw_version, + end_of_version-raw_version); + else + crypto_openssl_version_str = tor_strdup(raw_version); + } + return crypto_openssl_version_str; +} + /** Initialize the crypto library. Return 0 on success, -1 on failure. */ int crypto_global_init(int useAccel, const char *accelName, const char *accelDir) { - if (!_crypto_global_initialized) { + if (!crypto_global_initialized_) { ERR_load_crypto_strings(); OpenSSL_add_all_algorithms(); - _crypto_global_initialized = 1; + crypto_global_initialized_ = 1; setup_openssl_threading(); + + if (SSLeay() == OPENSSL_VERSION_NUMBER && + !strcmp(SSLeay_version(SSLEAY_VERSION), OPENSSL_VERSION_TEXT)) { + log_info(LD_CRYPTO, "OpenSSL version matches version from headers " + "(%lx: %s).", SSLeay(), SSLeay_version(SSLEAY_VERSION)); + } else { + log_warn(LD_CRYPTO, "OpenSSL version from headers does not match the " + "version we're running with. If you get weird crashes, that " + "might be why. (Compiled with %lx: %s; running with %lx: %s).", + (unsigned long)OPENSSL_VERSION_NUMBER, OPENSSL_VERSION_TEXT, + SSLeay(), SSLeay_version(SSLEAY_VERSION)); + } + + if (SSLeay() < OPENSSL_V_SERIES(1,0,0)) { + log_notice(LD_CRYPTO, + "Your OpenSSL version seems to be %s. We recommend 1.0.0 " + "or later.", + crypto_openssl_get_version_str()); + } + if (useAccel > 0) { #ifdef DISABLE_ENGINES (void)accelName; @@ -294,7 +313,7 @@ crypto_thread_cleanup(void) /** used by tortls.c: wrap an RSA* in a crypto_pk_t. */ crypto_pk_t * -_crypto_new_pk_from_rsa(RSA *rsa) +crypto_new_pk_from_rsa_(RSA *rsa) { crypto_pk_t *env; tor_assert(rsa); @@ -307,7 +326,7 @@ _crypto_new_pk_from_rsa(RSA *rsa) /** Helper, used by tor-checkkey.c and tor-gencert.c. Return the RSA from a * crypto_pk_t. */ RSA * -_crypto_pk_get_rsa(crypto_pk_t *env) +crypto_pk_get_rsa_(crypto_pk_t *env) { return env->key; } @@ -315,7 +334,7 @@ _crypto_pk_get_rsa(crypto_pk_t *env) /** used by tortls.c: get an equivalent EVP_PKEY* for a crypto_pk_t. Iff * private is set, include the private-key portion of the key. */ EVP_PKEY * -_crypto_pk_get_evp_pkey(crypto_pk_t *env, int private) +crypto_pk_get_evp_pkey_(crypto_pk_t *env, int private) { RSA *key = NULL; EVP_PKEY *pkey = NULL; @@ -343,7 +362,7 @@ _crypto_pk_get_evp_pkey(crypto_pk_t *env, int private) /** Used by tortls.c: Get the DH* from a crypto_dh_t. */ DH * -_crypto_dh_get_dh(crypto_dh_t *dh) +crypto_dh_get_dh_(crypto_dh_t *dh) { return dh->dh; } @@ -358,7 +377,7 @@ crypto_pk_new(void) rsa = RSA_new(); tor_assert(rsa); - return _crypto_new_pk_from_rsa(rsa); + return crypto_new_pk_from_rsa_(rsa); } /** Release a reference to an asymmetric key; when all the references @@ -441,11 +460,7 @@ crypto_pk_generate_key_with_bits(crypto_pk_t *env, int bits) if (env->key) RSA_free(env->key); -#if OPENSSL_VERSION_NUMBER < OPENSSL_V_SERIES(0,9,8) - /* In OpenSSL 0.9.7, RSA_generate_key is all we have. */ - env->key = RSA_generate_key(bits, 65537, NULL, NULL); -#else - /* In OpenSSL 0.9.8, RSA_generate_key is deprecated. */ + { BIGNUM *e = BN_new(); RSA *r = NULL; @@ -466,8 +481,8 @@ crypto_pk_generate_key_with_bits(crypto_pk_t *env, int bits) BN_free(e); if (r) RSA_free(r); - } -#endif + } + if (!env->key) { crypto_log_errors(LOG_WARN, "generating RSA key"); return -1; @@ -711,19 +726,23 @@ crypto_pk_public_exponent_ok(crypto_pk_t *env) return BN_is_word(env->key->e, 65537); } -/** Compare the public-key components of a and b. Return -1 if a\<b, 0 - * if a==b, and 1 if a\>b. +/** Compare the public-key components of a and b. Return less than 0 + * if a\<b, 0 if a==b, and greater than 0 if a\>b. A NULL key is + * considered to be less than all non-NULL keys, and equal to itself. + * + * Note that this may leak information about the keys through timing. */ int crypto_pk_cmp_keys(crypto_pk_t *a, crypto_pk_t *b) { int result; + char a_is_non_null = (a != NULL) && (a->key != NULL); + char b_is_non_null = (b != NULL) && (b->key != NULL); + char an_argument_is_null = !a_is_non_null | !b_is_non_null; - if (!a || !b) - return -1; - - if (!a->key || !b->key) - return -1; + result = tor_memcmp(&a_is_non_null, &b_is_non_null, sizeof(a_is_non_null)); + if (an_argument_is_null) + return result; tor_assert(PUBLIC_KEY_OK(a)); tor_assert(PUBLIC_KEY_OK(b)); @@ -733,6 +752,18 @@ crypto_pk_cmp_keys(crypto_pk_t *a, crypto_pk_t *b) return BN_cmp((a->key)->e, (b->key)->e); } +/** Compare the public-key components of a and b. Return non-zero iff + * a==b. A NULL key is considered to be distinct from all non-NULL + * keys, and equal to itself. + * + * Note that this may leak information about the keys through timing. + */ +int +crypto_pk_eq_keys(crypto_pk_t *a, crypto_pk_t *b) +{ + return (crypto_pk_cmp_keys(a, b) == 0); +} + /** Return the size of the public key modulus in <b>env</b>, in bytes. */ size_t crypto_pk_keysize(crypto_pk_t *env) @@ -791,7 +822,7 @@ crypto_pk_copy_full(crypto_pk_t *env) return NULL; } - return _crypto_new_pk_from_rsa(new_key); + return crypto_new_pk_from_rsa_(new_key); } /** Encrypt <b>fromlen</b> bytes from <b>from</b> with the public key @@ -1158,7 +1189,7 @@ crypto_pk_asn1_decode(const char *str, size_t len) crypto_log_errors(LOG_WARN,"decoding public key"); return NULL; } - return _crypto_new_pk_from_rsa(rsa); + return crypto_new_pk_from_rsa_(rsa); } /** Given a private or public key <b>pk</b>, put a SHA1 hash of the @@ -1623,63 +1654,11 @@ crypto_hmac_sha256(char *hmac_out, const char *key, size_t key_len, const char *msg, size_t msg_len) { -#if OPENSSL_VERSION_NUMBER >= OPENSSL_V_SERIES(0,9,8) /* If we've got OpenSSL >=0.9.8 we can use its hmac implementation. */ tor_assert(key_len < INT_MAX); tor_assert(msg_len < INT_MAX); HMAC(EVP_sha256(), key, (int)key_len, (unsigned char*)msg, (int)msg_len, (unsigned char*)hmac_out, NULL); -#else - /* OpenSSL doesn't have an EVP implementation for SHA256. We'll need - to do HMAC on our own. - - HMAC isn't so hard: To compute HMAC(key, msg): - 1. If len(key) > blocksize, key = H(key). - 2. If len(key) < blocksize, right-pad key up to blocksize with 0 bytes. - 3. let ipad = key xor 0x363636363636....36 - let opad = key xor 0x5c5c5c5c5c5c....5c - The result is H(opad | H( ipad | msg ) ) - */ -#define BLOCKSIZE 64 -#define DIGESTSIZE 32 - uint8_t k[BLOCKSIZE]; - uint8_t pad[BLOCKSIZE]; - uint8_t d[DIGESTSIZE]; - int i; - SHA256_CTX st; - - tor_assert(key_len < INT_MAX); - tor_assert(msg_len < INT_MAX); - - if (key_len <= BLOCKSIZE) { - memset(k, 0, sizeof(k)); - memcpy(k, key, key_len); /* not time invariant in key_len */ - } else { - SHA256((const uint8_t *)key, key_len, k); - memset(k+DIGESTSIZE, 0, sizeof(k)-DIGESTSIZE); - } - for (i = 0; i < BLOCKSIZE; ++i) - pad[i] = k[i] ^ 0x36; - SHA256_Init(&st); - SHA256_Update(&st, pad, BLOCKSIZE); - SHA256_Update(&st, (uint8_t*)msg, msg_len); - SHA256_Final(d, &st); - - for (i = 0; i < BLOCKSIZE; ++i) - pad[i] = k[i] ^ 0x5c; - SHA256_Init(&st); - SHA256_Update(&st, pad, BLOCKSIZE); - SHA256_Update(&st, d, DIGESTSIZE); - SHA256_Final((uint8_t*)hmac_out, &st); - - /* Now clear everything. */ - memset(k, 0, sizeof(k)); - memset(pad, 0, sizeof(pad)); - memset(d, 0, sizeof(d)); - memset(&st, 0, sizeof(st)); -#undef BLOCKSIZE -#undef DIGESTSIZE -#endif } /* DH */ @@ -2282,9 +2261,7 @@ crypto_dh_free(crypto_dh_t *dh) * that fd without checking whether it fit in the fd_set. Thus, if the * system has not just been started up, it is unsafe to call */ #define RAND_POLL_IS_SAFE \ - ((OPENSSL_VERSION_NUMBER >= OPENSSL_V(0,9,7,'j') && \ - OPENSSL_VERSION_NUMBER < OPENSSL_V_SERIES(0,9,8)) || \ - OPENSSL_VERSION_NUMBER >= OPENSSL_V(0,9,8,'c')) + (OPENSSL_VERSION_NUMBER >= OPENSSL_V(0,9,8,'c')) /** Set the seed of the weak RNG to a random value. */ static void @@ -2896,19 +2873,19 @@ secret_to_key(char *key_out, size_t key_out_len, const char *secret, #ifdef TOR_IS_MULTITHREADED /** Helper: OpenSSL uses this callback to manipulate mutexes. */ static void -_openssl_locking_cb(int mode, int n, const char *file, int line) +openssl_locking_cb_(int mode, int n, const char *file, int line) { (void)file; (void)line; - if (!_openssl_mutexes) + if (!openssl_mutexes_) /* This is not a really good fix for the * "release-freed-lock-from-separate-thread-on-shutdown" problem, but * it can't hurt. */ return; if (mode & CRYPTO_LOCK) - tor_mutex_acquire(_openssl_mutexes[n]); + tor_mutex_acquire(openssl_mutexes_[n]); else - tor_mutex_release(_openssl_mutexes[n]); + tor_mutex_release(openssl_mutexes_[n]); } /** OpenSSL helper type: wraps a Tor mutex so that OpenSSL can use it @@ -2920,7 +2897,7 @@ struct CRYPTO_dynlock_value { /** OpenSSL callback function to allocate a lock: see CRYPTO_set_dynlock_* * documentation in OpenSSL's docs for more info. */ static struct CRYPTO_dynlock_value * -_openssl_dynlock_create_cb(const char *file, int line) +openssl_dynlock_create_cb_(const char *file, int line) { struct CRYPTO_dynlock_value *v; (void)file; @@ -2933,7 +2910,7 @@ _openssl_dynlock_create_cb(const char *file, int line) /** OpenSSL callback function to acquire or release a lock: see * CRYPTO_set_dynlock_* documentation in OpenSSL's docs for more info. */ static void -_openssl_dynlock_lock_cb(int mode, struct CRYPTO_dynlock_value *v, +openssl_dynlock_lock_cb_(int mode, struct CRYPTO_dynlock_value *v, const char *file, int line) { (void)file; @@ -2947,7 +2924,7 @@ _openssl_dynlock_lock_cb(int mode, struct CRYPTO_dynlock_value *v, /** OpenSSL callback function to free a lock: see CRYPTO_set_dynlock_* * documentation in OpenSSL's docs for more info. */ static void -_openssl_dynlock_destroy_cb(struct CRYPTO_dynlock_value *v, +openssl_dynlock_destroy_cb_(struct CRYPTO_dynlock_value *v, const char *file, int line) { (void)file; @@ -2964,15 +2941,15 @@ setup_openssl_threading(void) { int i; int n = CRYPTO_num_locks(); - _n_openssl_mutexes = n; - _openssl_mutexes = tor_malloc(n*sizeof(tor_mutex_t *)); + n_openssl_mutexes_ = n; + openssl_mutexes_ = tor_malloc(n*sizeof(tor_mutex_t *)); for (i=0; i < n; ++i) - _openssl_mutexes[i] = tor_mutex_new(); - CRYPTO_set_locking_callback(_openssl_locking_cb); + openssl_mutexes_[i] = tor_mutex_new(); + CRYPTO_set_locking_callback(openssl_locking_cb_); CRYPTO_set_id_callback(tor_get_thread_id); - CRYPTO_set_dynlock_create_callback(_openssl_dynlock_create_cb); - CRYPTO_set_dynlock_lock_callback(_openssl_dynlock_lock_cb); - CRYPTO_set_dynlock_destroy_callback(_openssl_dynlock_destroy_cb); + CRYPTO_set_dynlock_create_callback(openssl_dynlock_create_cb_); + CRYPTO_set_dynlock_lock_callback(openssl_dynlock_lock_cb_); + CRYPTO_set_dynlock_destroy_callback(openssl_dynlock_destroy_cb_); return 0; } #else @@ -3006,18 +2983,19 @@ crypto_global_cleanup(void) CONF_modules_unload(1); CRYPTO_cleanup_all_ex_data(); #ifdef TOR_IS_MULTITHREADED - if (_n_openssl_mutexes) { - int n = _n_openssl_mutexes; - tor_mutex_t **ms = _openssl_mutexes; + if (n_openssl_mutexes_) { + int n = n_openssl_mutexes_; + tor_mutex_t **ms = openssl_mutexes_; int i; - _openssl_mutexes = NULL; - _n_openssl_mutexes = 0; + openssl_mutexes_ = NULL; + n_openssl_mutexes_ = 0; for (i=0;i<n;++i) { tor_mutex_free(ms[i]); } tor_free(ms); } #endif + tor_free(crypto_openssl_version_str); return 0; } diff --git a/src/common/crypto.h b/src/common/crypto.h index 76bcbf7d43..0782ee57f1 100644 --- a/src/common/crypto.h +++ b/src/common/crypto.h @@ -10,8 +10,8 @@ * \brief Headers for crypto.c **/ -#ifndef _TOR_CRYPTO_H -#define _TOR_CRYPTO_H +#ifndef TOR_CRYPTO_H +#define TOR_CRYPTO_H #include <stdio.h> #include "torint.h" @@ -51,7 +51,7 @@ /** Length of the output of our message digest. */ #define DIGEST_LEN 20 /** Length of the output of our second (improved) message digests. (For now - * this is just sha256, but any it can be any other 256-byte digest). */ + * this is just sha256, but it could be any other 256-bit digest.) */ #define DIGEST256_LEN 32 /** Length of our symmetric cipher's keys. */ #define CIPHER_KEY_LEN 16 @@ -111,6 +111,7 @@ typedef struct crypto_digest_t crypto_digest_t; typedef struct crypto_dh_t crypto_dh_t; /* global state */ +const char * crypto_openssl_get_version_str(void); int crypto_global_init(int hardwareAccel, const char *accelName, const char *accelPath); @@ -147,6 +148,7 @@ int crypto_pk_write_private_key_to_filename(crypto_pk_t *env, int crypto_pk_check_key(crypto_pk_t *env); int crypto_pk_cmp_keys(crypto_pk_t *a, crypto_pk_t *b); +int crypto_pk_eq_keys(crypto_pk_t *a, crypto_pk_t *b); size_t crypto_pk_keysize(crypto_pk_t *env); int crypto_pk_num_bits(crypto_pk_t *env); crypto_pk_t *crypto_pk_dup_key(crypto_pk_t *orig); @@ -277,11 +279,11 @@ void secret_to_key(char *key_out, size_t key_out_len, const char *secret, struct rsa_st; struct evp_pkey_st; struct dh_st; -struct rsa_st *_crypto_pk_get_rsa(crypto_pk_t *env); -crypto_pk_t *_crypto_new_pk_from_rsa(struct rsa_st *rsa); -struct evp_pkey_st *_crypto_pk_get_evp_pkey(crypto_pk_t *env, +struct rsa_st *crypto_pk_get_rsa_(crypto_pk_t *env); +crypto_pk_t *crypto_new_pk_from_rsa_(struct rsa_st *rsa); +struct evp_pkey_st *crypto_pk_get_evp_pkey_(crypto_pk_t *env, int private); -struct dh_st *_crypto_dh_get_dh(crypto_dh_t *dh); +struct dh_st *crypto_dh_get_dh_(crypto_dh_t *dh); /* Prototypes for private functions only used by crypto.c and test.c*/ void add_spaces_to_fp(char *out, size_t outlen, const char *in); #endif diff --git a/src/common/di_ops.c b/src/common/di_ops.c index 7683c59dee..418d6e3dca 100644 --- a/src/common/di_ops.c +++ b/src/common/di_ops.c @@ -123,7 +123,7 @@ tor_memeq(const void *a, const void *b, size_t sz) * * If any_difference != 0: * 0 < any_difference < 256, so - * 0 < any_difference - 1 < 255 + * 0 <= any_difference - 1 < 255 * (any_difference - 1) >> 8 == 0 * 1 & ((any_difference - 1) >> 8) == 0 */ diff --git a/src/common/ht.h b/src/common/ht.h deleted file mode 100644 index 25156c4165..0000000000 --- a/src/common/ht.h +++ /dev/null @@ -1,490 +0,0 @@ -/* Copyright (c) 2002, Christopher Clark. - * Copyright (c) 2005-2006, Nick Mathewson. - * Copyright (c) 2007-2012, The Tor Project, Inc. */ -/* See license at end. */ - -/* Based on ideas by Christopher Clark and interfaces from Niels Provos. */ - -#ifndef _TOR_HT_H -#define _TOR_HT_H - -#define HT_HEAD(name, type) \ - struct name { \ - /* The hash table itself. */ \ - struct type **hth_table; \ - /* How long is the hash table? */ \ - unsigned hth_table_length; \ - /* How many elements does the table contain? */ \ - unsigned hth_n_entries; \ - /* How many elements will we allow in the table before resizing it? */ \ - unsigned hth_load_limit; \ - /* Position of hth_table_length in the primes table. */ \ - int hth_prime_idx; \ - } - -#define HT_INITIALIZER() \ - { NULL, 0, 0, 0, -1 } - -#ifdef HT_NO_CACHE_HASH_VALUES -#define HT_ENTRY(type) \ - struct { \ - struct type *hte_next; \ - } -#else -#define HT_ENTRY(type) \ - struct { \ - struct type *hte_next; \ - unsigned hte_hash; \ - } -#endif - -#define HT_EMPTY(head) \ - ((head)->hth_n_entries == 0) - -/* How many elements in 'head'? */ -#define HT_SIZE(head) \ - ((head)->hth_n_entries) - -/* Return memory usage for a hashtable (not counting the entries themselves) */ -#define HT_MEM_USAGE(head) \ - (sizeof(*head) + (head)->hth_table_length * sizeof(void*)) - -#define HT_FIND(name, head, elm) name##_HT_FIND((head), (elm)) -#define HT_INSERT(name, head, elm) name##_HT_INSERT((head), (elm)) -#define HT_REPLACE(name, head, elm) name##_HT_REPLACE((head), (elm)) -#define HT_REMOVE(name, head, elm) name##_HT_REMOVE((head), (elm)) -#define HT_START(name, head) name##_HT_START(head) -#define HT_NEXT(name, head, elm) name##_HT_NEXT((head), (elm)) -#define HT_NEXT_RMV(name, head, elm) name##_HT_NEXT_RMV((head), (elm)) -#define HT_CLEAR(name, head) name##_HT_CLEAR(head) -#define HT_INIT(name, head) name##_HT_INIT(head) -/* Helper: */ -static INLINE unsigned -ht_improve_hash(unsigned h) -{ - /* Aim to protect against poor hash functions by adding logic here - * - logic taken from java 1.4 hashtable source */ - h += ~(h << 9); - h ^= ((h >> 14) | (h << 18)); /* >>> */ - h += (h << 4); - h ^= ((h >> 10) | (h << 22)); /* >>> */ - return h; -} - -#if 0 -/** Basic string hash function, from Java standard String.hashCode(). */ -static INLINE unsigned -ht_string_hash(const char *s) -{ - unsigned h = 0; - int m = 1; - while (*s) { - h += ((signed char)*s++)*m; - m = (m<<5)-1; /* m *= 31 */ - } - return h; -} -#endif - -/** Basic string hash function, from Python's str.__hash__() */ -static INLINE unsigned -ht_string_hash(const char *s) -{ - unsigned h; - const unsigned char *cp = (const unsigned char *)s; - h = *cp << 7; - while (*cp) { - h = (1000003*h) ^ *cp++; - } - /* This conversion truncates the length of the string, but that's ok. */ - h ^= (unsigned)(cp-(const unsigned char*)s); - return h; -} - -#ifndef HT_NO_CACHE_HASH_VALUES -#define HT_SET_HASH_(elm, field, hashfn) \ - do { (elm)->field.hte_hash = hashfn(elm); } while (0) -#define HT_SET_HASHVAL_(elm, field, val) \ - do { (elm)->field.hte_hash = (val); } while (0) -#define HT_ELT_HASH_(elm, field, hashfn) \ - ((elm)->field.hte_hash) -#else -#define HT_SET_HASH_(elm, field, hashfn) \ - ((void)0) -#define HT_ELT_HASH_(elm, field, hashfn) \ - (hashfn(elm)) -#define HT_SET_HASHVAL_(elm, field, val) \ - ((void)0) -#endif - -/* Helper: alias for the bucket containing 'elm'. */ -#define HT_BUCKET_(head, field, elm, hashfn) \ - ((head)->hth_table[HT_ELT_HASH_(elm,field,hashfn) \ - % head->hth_table_length]) - -#define HT_FOREACH(x, name, head) \ - for ((x) = HT_START(name, head); \ - (x) != NULL; \ - (x) = HT_NEXT(name, head, x)) - -#define HT_PROTOTYPE(name, type, field, hashfn, eqfn) \ - int name##_HT_GROW(struct name *ht, unsigned min_capacity); \ - void name##_HT_CLEAR(struct name *ht); \ - int name##_HT_REP_IS_BAD_(const struct name *ht); \ - static INLINE void \ - name##_HT_INIT(struct name *head) { \ - head->hth_table_length = 0; \ - head->hth_table = NULL; \ - head->hth_n_entries = 0; \ - head->hth_load_limit = 0; \ - head->hth_prime_idx = -1; \ - } \ - /* Helper: returns a pointer to the right location in the table \ - * 'head' to find or insert the element 'elm'. */ \ - static INLINE struct type ** \ - name##_HT_FIND_P_(struct name *head, struct type *elm) \ - { \ - struct type **p; \ - if (!head->hth_table) \ - return NULL; \ - p = &HT_BUCKET_(head, field, elm, hashfn); \ - while (*p) { \ - if (eqfn(*p, elm)) \ - return p; \ - p = &(*p)->field.hte_next; \ - } \ - return p; \ - } \ - /* Return a pointer to the element in the table 'head' matching 'elm', \ - * or NULL if no such element exists */ \ - static INLINE struct type * \ - name##_HT_FIND(const struct name *head, struct type *elm) \ - { \ - struct type **p; \ - struct name *h = (struct name *) head; \ - HT_SET_HASH_(elm, field, hashfn); \ - p = name##_HT_FIND_P_(h, elm); \ - return p ? *p : NULL; \ - } \ - /* Insert the element 'elm' into the table 'head'. Do not call this \ - * function if the table might already contain a matching element. */ \ - static INLINE void \ - name##_HT_INSERT(struct name *head, struct type *elm) \ - { \ - struct type **p; \ - if (!head->hth_table || head->hth_n_entries >= head->hth_load_limit) \ - name##_HT_GROW(head, head->hth_n_entries+1); \ - ++head->hth_n_entries; \ - HT_SET_HASH_(elm, field, hashfn); \ - p = &HT_BUCKET_(head, field, elm, hashfn); \ - elm->field.hte_next = *p; \ - *p = elm; \ - } \ - /* Insert the element 'elm' into the table 'head'. If there already \ - * a matching element in the table, replace that element and return \ - * it. */ \ - static INLINE struct type * \ - name##_HT_REPLACE(struct name *head, struct type *elm) \ - { \ - struct type **p, *r; \ - if (!head->hth_table || head->hth_n_entries >= head->hth_load_limit) \ - name##_HT_GROW(head, head->hth_n_entries+1); \ - HT_SET_HASH_(elm, field, hashfn); \ - p = name##_HT_FIND_P_(head, elm); \ - r = *p; \ - *p = elm; \ - if (r && (r!=elm)) { \ - elm->field.hte_next = r->field.hte_next; \ - r->field.hte_next = NULL; \ - return r; \ - } else { \ - ++head->hth_n_entries; \ - return NULL; \ - } \ - } \ - /* Remove any element matching 'elm' from the table 'head'. If such \ - * an element is found, return it; otherwise return NULL. */ \ - static INLINE struct type * \ - name##_HT_REMOVE(struct name *head, struct type *elm) \ - { \ - struct type **p, *r; \ - HT_SET_HASH_(elm, field, hashfn); \ - p = name##_HT_FIND_P_(head,elm); \ - if (!p || !*p) \ - return NULL; \ - r = *p; \ - *p = r->field.hte_next; \ - r->field.hte_next = NULL; \ - --head->hth_n_entries; \ - return r; \ - } \ - /* Invoke the function 'fn' on every element of the table 'head', \ - * using 'data' as its second argument. If the function returns \ - * nonzero, remove the most recently examined element before invoking \ - * the function again. */ \ - static INLINE void \ - name##_HT_FOREACH_FN(struct name *head, \ - int (*fn)(struct type *, void *), \ - void *data) \ - { \ - unsigned idx; \ - struct type **p, **nextp, *next; \ - if (!head->hth_table) \ - return; \ - for (idx=0; idx < head->hth_table_length; ++idx) { \ - p = &head->hth_table[idx]; \ - while (*p) { \ - nextp = &(*p)->field.hte_next; \ - next = *nextp; \ - if (fn(*p, data)) { \ - --head->hth_n_entries; \ - *p = next; \ - } else { \ - p = nextp; \ - } \ - } \ - } \ - } \ - /* Return a pointer to the first element in the table 'head', under \ - * an arbitrary order. This order is stable under remove operations, \ - * but not under others. If the table is empty, return NULL. */ \ - static INLINE struct type ** \ - name##_HT_START(struct name *head) \ - { \ - unsigned b = 0; \ - while (b < head->hth_table_length) { \ - if (head->hth_table[b]) \ - return &head->hth_table[b]; \ - ++b; \ - } \ - return NULL; \ - } \ - /* Return the next element in 'head' after 'elm', under the arbitrary \ - * order used by HT_START. If there are no more elements, return \ - * NULL. If 'elm' is to be removed from the table, you must call \ - * this function for the next value before you remove it. \ - */ \ - static INLINE struct type ** \ - name##_HT_NEXT(struct name *head, struct type **elm) \ - { \ - if ((*elm)->field.hte_next) { \ - return &(*elm)->field.hte_next; \ - } else { \ - unsigned b = (HT_ELT_HASH_(*elm, field, hashfn) \ - % head->hth_table_length)+1; \ - while (b < head->hth_table_length) { \ - if (head->hth_table[b]) \ - return &head->hth_table[b]; \ - ++b; \ - } \ - return NULL; \ - } \ - } \ - static INLINE struct type ** \ - name##_HT_NEXT_RMV(struct name *head, struct type **elm) \ - { \ - unsigned h = HT_ELT_HASH_(*elm, field, hashfn); \ - *elm = (*elm)->field.hte_next; \ - --head->hth_n_entries; \ - if (*elm) { \ - return elm; \ - } else { \ - unsigned b = (h % head->hth_table_length)+1; \ - while (b < head->hth_table_length) { \ - if (head->hth_table[b]) \ - return &head->hth_table[b]; \ - ++b; \ - } \ - return NULL; \ - } \ - } - -#define HT_GENERATE(name, type, field, hashfn, eqfn, load, mallocfn, \ - reallocfn, freefn) \ - static unsigned name##_PRIMES[] = { \ - 53, 97, 193, 389, \ - 769, 1543, 3079, 6151, \ - 12289, 24593, 49157, 98317, \ - 196613, 393241, 786433, 1572869, \ - 3145739, 6291469, 12582917, 25165843, \ - 50331653, 100663319, 201326611, 402653189, \ - 805306457, 1610612741 \ - }; \ - static unsigned name##_N_PRIMES = \ - (unsigned)(sizeof(name##_PRIMES)/sizeof(name##_PRIMES[0])); \ - /* Expand the internal table of 'head' until it is large enough to \ - * hold 'size' elements. Return 0 on success, -1 on allocation \ - * failure. */ \ - int \ - name##_HT_GROW(struct name *head, unsigned size) \ - { \ - unsigned new_len, new_load_limit; \ - int prime_idx; \ - struct type **new_table; \ - if (head->hth_prime_idx == (int)name##_N_PRIMES - 1) \ - return 0; \ - if (head->hth_load_limit > size) \ - return 0; \ - prime_idx = head->hth_prime_idx; \ - do { \ - new_len = name##_PRIMES[++prime_idx]; \ - new_load_limit = (unsigned)(load*new_len); \ - } while (new_load_limit <= size && \ - prime_idx < (int)name##_N_PRIMES); \ - if ((new_table = mallocfn(new_len*sizeof(struct type*)))) { \ - unsigned b; \ - memset(new_table, 0, new_len*sizeof(struct type*)); \ - for (b = 0; b < head->hth_table_length; ++b) { \ - struct type *elm, *next; \ - unsigned b2; \ - elm = head->hth_table[b]; \ - while (elm) { \ - next = elm->field.hte_next; \ - b2 = HT_ELT_HASH_(elm, field, hashfn) % new_len; \ - elm->field.hte_next = new_table[b2]; \ - new_table[b2] = elm; \ - elm = next; \ - } \ - } \ - if (head->hth_table) \ - freefn(head->hth_table); \ - head->hth_table = new_table; \ - } else { \ - unsigned b, b2; \ - new_table = reallocfn(head->hth_table, new_len*sizeof(struct type*)); \ - if (!new_table) return -1; \ - memset(new_table + head->hth_table_length, 0, \ - (new_len - head->hth_table_length)*sizeof(struct type*)); \ - for (b=0; b < head->hth_table_length; ++b) { \ - struct type *e, **pE; \ - for (pE = &new_table[b], e = *pE; e != NULL; e = *pE) { \ - b2 = HT_ELT_HASH_(e, field, hashfn) % new_len; \ - if (b2 == b) { \ - pE = &e->field.hte_next; \ - } else { \ - *pE = e->field.hte_next; \ - e->field.hte_next = new_table[b2]; \ - new_table[b2] = e; \ - } \ - } \ - } \ - head->hth_table = new_table; \ - } \ - head->hth_table_length = new_len; \ - head->hth_prime_idx = prime_idx; \ - head->hth_load_limit = new_load_limit; \ - return 0; \ - } \ - /* Free all storage held by 'head'. Does not free 'head' itself, or \ - * individual elements. */ \ - void \ - name##_HT_CLEAR(struct name *head) \ - { \ - if (head->hth_table) \ - freefn(head->hth_table); \ - head->hth_table_length = 0; \ - name##_HT_INIT(head); \ - } \ - /* Debugging helper: return false iff the representation of 'head' is \ - * internally consistent. */ \ - int \ - name##_HT_REP_IS_BAD_(const struct name *head) \ - { \ - unsigned n, i; \ - struct type *elm; \ - if (!head->hth_table_length) { \ - if (!head->hth_table && !head->hth_n_entries && \ - !head->hth_load_limit && head->hth_prime_idx == -1) \ - return 0; \ - else \ - return 1; \ - } \ - if (!head->hth_table || head->hth_prime_idx < 0 || \ - !head->hth_load_limit) \ - return 2; \ - if (head->hth_n_entries > head->hth_load_limit) \ - return 3; \ - if (head->hth_table_length != name##_PRIMES[head->hth_prime_idx]) \ - return 4; \ - if (head->hth_load_limit != (unsigned)(load*head->hth_table_length)) \ - return 5; \ - for (n = i = 0; i < head->hth_table_length; ++i) { \ - for (elm = head->hth_table[i]; elm; elm = elm->field.hte_next) { \ - if (HT_ELT_HASH_(elm, field, hashfn) != hashfn(elm)) \ - return 1000 + i; \ - if ((HT_ELT_HASH_(elm, field, hashfn) % head->hth_table_length) != i) \ - return 10000 + i; \ - ++n; \ - } \ - } \ - if (n != head->hth_n_entries) \ - return 6; \ - return 0; \ - } - -/** Implements an over-optimized "find and insert if absent" block; - * not meant for direct usage by typical code, or usage outside the critical - * path.*/ -#define HT_FIND_OR_INSERT_(name, field, hashfn, head, eltype, elm, var, y, n) \ - { \ - struct name *var##_head_ = head; \ - struct eltype **var; \ - if (!var##_head_->hth_table || \ - var##_head_->hth_n_entries >= var##_head_->hth_load_limit) \ - name##_HT_GROW(var##_head_, var##_head_->hth_n_entries+1); \ - HT_SET_HASH_((elm), field, hashfn); \ - var = name##_HT_FIND_P_(var##_head_, (elm)); \ - if (*var) { \ - y; \ - } else { \ - n; \ - } \ - } -#define HT_FOI_INSERT_(field, head, elm, newent, var) \ - { \ - HT_SET_HASHVAL_(newent, field, (elm)->field.hte_hash); \ - newent->field.hte_next = NULL; \ - *var = newent; \ - ++((head)->hth_n_entries); \ - } - -/* - * Copyright 2005, Nick Mathewson. Implementation logic is adapted from code - * by Christopher Clark, retrofit to allow drop-in memory management, and to - * use the same interface as Niels Provos's tree.h. This is probably still - * a derived work, so the original license below still applies. - * - * Copyright (c) 2002, Christopher Clark - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * * Neither the name of the original author; nor the names of any contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER - * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ - -#endif - diff --git a/src/common/include.am b/src/common/include.am new file mode 100644 index 0000000000..0fdc72057f --- /dev/null +++ b/src/common/include.am @@ -0,0 +1,71 @@ + +noinst_LIBRARIES+= src/common/libor.a src/common/libor-crypto.a src/common/libor-event.a + +EXTRA_DIST+= \ + src/common/common_sha1.i \ + src/common/Makefile.nmake + +#CFLAGS = -Wall -Wpointer-arith -O2 +AM_CPPFLAGS += -I$(srcdir)/src/common -Isrc/common + +if USE_OPENBSD_MALLOC +libor_extra_source=src/ext/OpenBSD_malloc_Linux.c +else +libor_extra_source= +endif + +src_common_libor_a_SOURCES = \ + src/common/address.c \ + src/common/compat.c \ + src/common/container.c \ + src/common/di_ops.c \ + src/common/log.c \ + src/common/memarea.c \ + src/common/mempool.c \ + src/common/procmon.c \ + src/common/util.c \ + src/common/util_codedigest.c \ + $(libor_extra_source) + +src_common_libor_crypto_a_SOURCES = \ + src/common/aes.c \ + src/common/crypto.c \ + src/common/torgzip.c \ + src/common/tortls.c + +src_common_libor_event_a_SOURCES = src/common/compat_libevent.c + +COMMONHEADERS = \ + src/common/address.h \ + src/common/aes.h \ + src/common/ciphers.inc \ + src/common/compat.h \ + src/common/compat_libevent.h \ + src/common/container.h \ + src/common/crypto.h \ + src/common/di_ops.h \ + src/common/memarea.h \ + src/common/mempool.h \ + src/common/procmon.h \ + src/common/torgzip.h \ + src/common/torint.h \ + src/common/torlog.h \ + src/common/tortls.h \ + src/common/util.h + +noinst_HEADERS+= $(COMMONHEADERS) + +DISTCLEANFILES+= src/common/common_sha1.i + +src/common/common_sha1.i: $(libor_SOURCES) $(libor_crypto_a_SOURCES) $(COMMONHEADERS) + $(AM_V_GEN)if test "@SHA1SUM@" != none; then \ + (cd "$(srcdir)" && "@SHA1SUM@" $(src_common_libor_SOURCES) $(src_common_libor_crypto_a_SOURCES) $(COMMONHEADERS)) | "@SED@" -n 's/^\(.*\)$$/"\1\\n"/p' > $@; \ + elif test "@OPENSSL@" != none; then \ + (cd "$(srcdir)" && "@OPENSSL@" sha1 $(src_common_libor_SOURCES) $(src_Common_libor_crypto_a_SOURCES) $(COMMONHEADERS)) | "@SED@" -n 's/SHA1(\(.*\))= \(.*\)/"\2 \1\\n"/p' > $@; \ + else \ + rm $@; \ + touch $@; \ + fi + +src/common/util_codedigest.o: src/common/common_sha1.i + diff --git a/src/common/log.c b/src/common/log.c index 5e2e6b5b50..5bf12cfe9c 100644 --- a/src/common/log.c +++ b/src/common/log.c @@ -131,7 +131,7 @@ static smartlist_t *pending_cb_messages = NULL; /** What's the lowest log level anybody cares about? Checking this lets us * bail out early from log_debug if we aren't debugging. */ -int _log_global_min_severity = LOG_NOTICE; +int log_global_min_severity_ = LOG_NOTICE; static void delete_log(logfile_t *victim); static void close_log(logfile_t *victim); @@ -177,7 +177,7 @@ set_log_time_granularity(int granularity_msec) * <b>buf_len</b> character buffer in <b>buf</b>. */ static INLINE size_t -_log_prefix(char *buf, size_t buf_len, int severity) +log_prefix_(char *buf, size_t buf_len, int severity) { time_t t; struct timeval now; @@ -230,7 +230,7 @@ log_tor_version(logfile_t *lf, int reset) /* We are resetting, but we aren't at the start of the file; no * need to log again. */ return 0; - n = _log_prefix(buf, sizeof(buf), LOG_NOTICE); + n = log_prefix_(buf, sizeof(buf), LOG_NOTICE); if (appname) { tor_snprintf(buf+n, sizeof(buf)-n, "%s opening %slog file.\n", appname, is_new?"new ":""); @@ -262,7 +262,7 @@ format_msg(char *buf, size_t buf_len, buf_len -= 2; /* subtract 2 characters so we have room for \n\0 */ buf_end = buf+buf_len; /* point *after* the last char we can write to */ - n = _log_prefix(buf, buf_len, severity); + n = log_prefix_(buf, buf_len, severity); end_of_prefix = buf+n; if (log_domains_are_logged) { @@ -423,7 +423,7 @@ void tor_log(int severity, log_domain_mask_t domain, const char *format, ...) { va_list ap; - if (severity > _log_global_min_severity) + if (severity > log_global_min_severity_) return; va_start(ap,format); logv(severity, domain, NULL, format, ap); @@ -436,11 +436,11 @@ tor_log(int severity, log_domain_mask_t domain, const char *format, ...) * variadic macros. All arguments are as for log_fn, except for * <b>fn</b>, which is the name of the calling functions. */ void -_log_fn(int severity, log_domain_mask_t domain, const char *fn, +log_fn_(int severity, log_domain_mask_t domain, const char *fn, const char *format, ...) { va_list ap; - if (severity > _log_global_min_severity) + if (severity > log_global_min_severity_) return; va_start(ap,format); logv(severity, domain, fn, format, ap); @@ -450,75 +450,75 @@ _log_fn(int severity, log_domain_mask_t domain, const char *fn, /** @{ */ /** Variant implementation of log_fn, log_debug, log_info,... for C compilers * without variadic macros. In this case, the calling function sets - * _log_fn_function_name to the name of the function, then invokes the - * appropriate _log_fn, _log_debug, etc. */ -const char *_log_fn_function_name=NULL; + * log_fn_function_name_ to the name of the function, then invokes the + * appropriate log_fn_, log_debug_, etc. */ +const char *log_fn_function_name_=NULL; void -_log_fn(int severity, log_domain_mask_t domain, const char *format, ...) +log_fn_(int severity, log_domain_mask_t domain, const char *format, ...) { va_list ap; - if (severity > _log_global_min_severity) + if (severity > log_global_min_severity_) return; va_start(ap,format); - logv(severity, domain, _log_fn_function_name, format, ap); + logv(severity, domain, log_fn_function_name_, format, ap); va_end(ap); - _log_fn_function_name = NULL; + log_fn_function_name_ = NULL; } void -_log_debug(log_domain_mask_t domain, const char *format, ...) +log_debug_(log_domain_mask_t domain, const char *format, ...) { va_list ap; /* For GCC we do this check in the macro. */ - if (PREDICT_LIKELY(LOG_DEBUG > _log_global_min_severity)) + if (PREDICT_LIKELY(LOG_DEBUG > log_global_min_severity_)) return; va_start(ap,format); - logv(LOG_DEBUG, domain, _log_fn_function_name, format, ap); + logv(LOG_DEBUG, domain, log_fn_function_name_, format, ap); va_end(ap); - _log_fn_function_name = NULL; + log_fn_function_name_ = NULL; } void -_log_info(log_domain_mask_t domain, const char *format, ...) +log_info_(log_domain_mask_t domain, const char *format, ...) { va_list ap; - if (LOG_INFO > _log_global_min_severity) + if (LOG_INFO > log_global_min_severity_) return; va_start(ap,format); - logv(LOG_INFO, domain, _log_fn_function_name, format, ap); + logv(LOG_INFO, domain, log_fn_function_name_, format, ap); va_end(ap); - _log_fn_function_name = NULL; + log_fn_function_name_ = NULL; } void -_log_notice(log_domain_mask_t domain, const char *format, ...) +log_notice_(log_domain_mask_t domain, const char *format, ...) { va_list ap; - if (LOG_NOTICE > _log_global_min_severity) + if (LOG_NOTICE > log_global_min_severity_) return; va_start(ap,format); - logv(LOG_NOTICE, domain, _log_fn_function_name, format, ap); + logv(LOG_NOTICE, domain, log_fn_function_name_, format, ap); va_end(ap); - _log_fn_function_name = NULL; + log_fn_function_name_ = NULL; } void -_log_warn(log_domain_mask_t domain, const char *format, ...) +log_warn_(log_domain_mask_t domain, const char *format, ...) { va_list ap; - if (LOG_WARN > _log_global_min_severity) + if (LOG_WARN > log_global_min_severity_) return; va_start(ap,format); - logv(LOG_WARN, domain, _log_fn_function_name, format, ap); + logv(LOG_WARN, domain, log_fn_function_name_, format, ap); va_end(ap); - _log_fn_function_name = NULL; + log_fn_function_name_ = NULL; } void -_log_err(log_domain_mask_t domain, const char *format, ...) +log_err_(log_domain_mask_t domain, const char *format, ...) { va_list ap; - if (LOG_ERR > _log_global_min_severity) + if (LOG_ERR > log_global_min_severity_) return; va_start(ap,format); - logv(LOG_ERR, domain, _log_fn_function_name, format, ap); + logv(LOG_ERR, domain, log_fn_function_name_, format, ap); va_end(ap); - _log_fn_function_name = NULL; + log_fn_function_name_ = NULL; } /** @} */ #endif @@ -638,7 +638,7 @@ add_stream_log_impl(const log_severity_list_t *severity, lf->next = logfiles; logfiles = lf; - _log_global_min_severity = get_min_log_level(); + log_global_min_severity_ = get_min_log_level(); } /** Add a log handler named <b>name</b> to send all messages in <b>severity</b> @@ -706,7 +706,7 @@ add_callback_log(const log_severity_list_t *severity, log_callback cb) LOCK_LOGS(); logfiles = lf; - _log_global_min_severity = get_min_log_level(); + log_global_min_severity_ = get_min_log_level(); UNLOCK_LOGS(); return 0; } @@ -726,7 +726,7 @@ change_callback_log_severity(int loglevelMin, int loglevelMax, memcpy(lf->severities, &severities, sizeof(severities)); } } - _log_global_min_severity = get_min_log_level(); + log_global_min_severity_ = get_min_log_level(); UNLOCK_LOGS(); } @@ -792,7 +792,7 @@ close_temp_logs(void) } } - _log_global_min_severity = get_min_log_level(); + log_global_min_severity_ = get_min_log_level(); UNLOCK_LOGS(); } @@ -840,7 +840,7 @@ add_file_log(const log_severity_list_t *severity, const char *filename) add_stream_log_impl(severity, filename, fd); logfiles->needs_close = 1; lf = logfiles; - _log_global_min_severity = get_min_log_level(); + log_global_min_severity_ = get_min_log_level(); if (log_tor_version(lf, 0) < 0) { delete_log(lf); @@ -871,7 +871,7 @@ add_syslog_log(const log_severity_list_t *severity) LOCK_LOGS(); lf->next = logfiles; logfiles = lf; - _log_global_min_severity = get_min_log_level(); + log_global_min_severity_ = get_min_log_level(); UNLOCK_LOGS(); return 0; } @@ -907,7 +907,7 @@ log_level_to_string(int level) static const char *domain_list[] = { "GENERAL", "CRYPTO", "NET", "CONFIG", "FS", "PROTOCOL", "MM", "HTTP", "APP", "CONTROL", "CIRC", "REND", "BUG", "DIR", "DIRSERV", - "OR", "EDGE", "ACCT", "HIST", "HANDSHAKE", "HEARTBEAT", NULL + "OR", "EDGE", "ACCT", "HIST", "HANDSHAKE", "HEARTBEAT", "CHANNEL", NULL }; /** Return a bitmask for the log domain for which <b>domain</b> is the name, @@ -1106,7 +1106,7 @@ switch_logs_debug(void) for (i = LOG_DEBUG; i >= LOG_ERR; --i) lf->severities->masks[SEVERITY_MASK_IDX(i)] = ~0u; } - _log_global_min_severity = get_min_log_level(); + log_global_min_severity_ = get_min_log_level(); UNLOCK_LOGS(); } diff --git a/src/common/memarea.c b/src/common/memarea.c index 07bd593cc9..ef8a8d76bc 100644 --- a/src/common/memarea.c +++ b/src/common/memarea.c @@ -77,7 +77,7 @@ typedef struct memarea_chunk_t { * full. */ union { char mem[1]; /**< Memory space in this chunk. */ - void *_void_for_alignment; /**< Dummy; used to make sure mem is aligned. */ + void *void_for_alignment_; /**< Dummy; used to make sure mem is aligned. */ } u; } memarea_chunk_t; @@ -118,7 +118,7 @@ alloc_chunk(size_t sz, int freelist_ok) size_t chunk_size = freelist_ok ? CHUNK_SIZE : sz; memarea_chunk_t *res; chunk_size += SENTINEL_LEN; - res = tor_malloc_roundup(&chunk_size); + res = tor_malloc(chunk_size); res->next_chunk = NULL; res->mem_size = chunk_size - CHUNK_HEADER_SIZE - SENTINEL_LEN; res->next_mem = res->u.mem; diff --git a/src/common/memarea.h b/src/common/memarea.h index b3c76d8d0c..26c3e6dfe3 100644 --- a/src/common/memarea.h +++ b/src/common/memarea.h @@ -2,8 +2,8 @@ /* See LICENSE for licensing information */ /* Tor dependencies */ -#ifndef _TOR_MEMAREA_H -#define _TOR_MEMAREA_H +#ifndef TOR_MEMAREA_H +#define TOR_MEMAREA_H typedef struct memarea_t memarea_t; diff --git a/src/common/mempool.c b/src/common/mempool.c index 2416bce473..0d2580dcaf 100644 --- a/src/common/mempool.c +++ b/src/common/mempool.c @@ -70,7 +70,6 @@ #define ASSERT(x) tor_assert(x) #undef ALLOC_CAN_RETURN_NULL #define TOR -//#define ALLOC_ROUNDUP(p) tor_malloc_roundup(p) /* End Tor dependencies */ #else /* If you're not building this as part of Tor, you'll want to define the @@ -114,7 +113,7 @@ struct mp_allocated_t { * (Not actual size.) */ char mem[1]; /** An extra element to the union to insure correct alignment. */ - ALIGNMENT_TYPE _dummy; + ALIGNMENT_TYPE dummy_; } u; }; @@ -165,25 +164,16 @@ static mp_chunk_t * mp_chunk_new(mp_pool_t *pool) { size_t sz = pool->new_chunk_capacity * pool->item_alloc_size; -#ifdef ALLOC_ROUNDUP - size_t alloc_size = CHUNK_OVERHEAD + sz; - mp_chunk_t *chunk = ALLOC_ROUNDUP(&alloc_size); -#else mp_chunk_t *chunk = ALLOC(CHUNK_OVERHEAD + sz); -#endif + #ifdef MEMPOOL_STATS ++pool->total_chunks_allocated; #endif CHECK_ALLOC(chunk); memset(chunk, 0, sizeof(mp_chunk_t)); /* Doesn't clear the whole thing. */ chunk->magic = MP_CHUNK_MAGIC; -#ifdef ALLOC_ROUNDUP - chunk->mem_size = alloc_size - CHUNK_OVERHEAD; - chunk->capacity = chunk->mem_size / pool->item_alloc_size; -#else chunk->capacity = pool->new_chunk_capacity; chunk->mem_size = sz; -#endif chunk->next_mem = chunk->mem; chunk->pool = pool; return chunk; diff --git a/src/common/mempool.h b/src/common/mempool.h index d0a7bc2f36..b01277df86 100644 --- a/src/common/mempool.h +++ b/src/common/mempool.h @@ -6,8 +6,8 @@ * \brief Headers for mempool.c **/ -#ifndef _TOR_MEMPOOL_H -#define _TOR_MEMPOOL_H +#ifndef TOR_MEMPOOL_H +#define TOR_MEMPOOL_H /** A memory pool is a context in which a large number of fixed-sized * objects can be allocated efficiently. See mempool.c for implementation diff --git a/src/common/sha256.c b/src/common/sha256.c deleted file mode 100644 index 813c68d2a3..0000000000 --- a/src/common/sha256.c +++ /dev/null @@ -1,331 +0,0 @@ -/* Copyright (c) 2009-2012, The Tor Project, Inc. */ -/* See LICENSE for licensing information */ -/* This SHA256 implementation is adapted from the public domain one in - LibTomCrypt, version 1.6. Tor uses it on platforms where OpenSSL doesn't - have a SHA256. */ - - -typedef struct sha256_state { - uint64_t length; - uint32_t state[8], curlen; - unsigned char buf[64]; -} sha256_state; - -#define CRYPT_OK 0 -#define CRYPT_NOP -1 -#define CRYPT_INVALID_ARG -2 - -#define LOAD32H(x,y) STMT_BEGIN x = ntohl(get_uint32((const char*)y)); STMT_END -#define STORE32H(x,y) STMT_BEGIN set_uint32((char*)y, htonl(x)); STMT_END -#define STORE64H(x,y) STMT_BEGIN \ - set_uint32((char*)y, htonl((uint32_t)((x)>>32))); \ - set_uint32(((char*)y)+4, htonl((uint32_t)((x)&0xffffffff))); \ - STMT_END -#define RORc(x, y) ( ((((unsigned long)(x)&0xFFFFFFFFUL)>>(unsigned long)((y)&31)) | ((unsigned long)(x)<<(unsigned long)(32-((y)&31)))) & 0xFFFFFFFFUL) -#ifndef MIN - #define MIN(x, y) ( ((x)<(y))?(x):(y) ) -#endif - - -/* LibTomCrypt, modular cryptographic library -- Tom St Denis - * - * LibTomCrypt is a library that provides various cryptographic - * algorithms in a highly modular and flexible manner. - * - * The library is free for all purposes without any express - * guarantee it works. - * - * Tom St Denis, tomstdenis@gmail.com, http://libtomcrypt.com - */ - -/** - @file sha256.c - SHA256 by Tom St Denis -*/ - - -#ifdef LTC_SMALL_CODE -/* the K array */ -static const uint32_t K[64] = { - 0x428a2f98UL, 0x71374491UL, 0xb5c0fbcfUL, 0xe9b5dba5UL, 0x3956c25bUL, - 0x59f111f1UL, 0x923f82a4UL, 0xab1c5ed5UL, 0xd807aa98UL, 0x12835b01UL, - 0x243185beUL, 0x550c7dc3UL, 0x72be5d74UL, 0x80deb1feUL, 0x9bdc06a7UL, - 0xc19bf174UL, 0xe49b69c1UL, 0xefbe4786UL, 0x0fc19dc6UL, 0x240ca1ccUL, - 0x2de92c6fUL, 0x4a7484aaUL, 0x5cb0a9dcUL, 0x76f988daUL, 0x983e5152UL, - 0xa831c66dUL, 0xb00327c8UL, 0xbf597fc7UL, 0xc6e00bf3UL, 0xd5a79147UL, - 0x06ca6351UL, 0x14292967UL, 0x27b70a85UL, 0x2e1b2138UL, 0x4d2c6dfcUL, - 0x53380d13UL, 0x650a7354UL, 0x766a0abbUL, 0x81c2c92eUL, 0x92722c85UL, - 0xa2bfe8a1UL, 0xa81a664bUL, 0xc24b8b70UL, 0xc76c51a3UL, 0xd192e819UL, - 0xd6990624UL, 0xf40e3585UL, 0x106aa070UL, 0x19a4c116UL, 0x1e376c08UL, - 0x2748774cUL, 0x34b0bcb5UL, 0x391c0cb3UL, 0x4ed8aa4aUL, 0x5b9cca4fUL, - 0x682e6ff3UL, 0x748f82eeUL, 0x78a5636fUL, 0x84c87814UL, 0x8cc70208UL, - 0x90befffaUL, 0xa4506cebUL, 0xbef9a3f7UL, 0xc67178f2UL -}; -#endif - -/* Various logical functions */ -#define Ch(x,y,z) (z ^ (x & (y ^ z))) -#define Maj(x,y,z) (((x | y) & z) | (x & y)) -#define S(x, n) RORc((x),(n)) -#define R(x, n) (((x)&0xFFFFFFFFUL)>>(n)) -#define Sigma0(x) (S(x, 2) ^ S(x, 13) ^ S(x, 22)) -#define Sigma1(x) (S(x, 6) ^ S(x, 11) ^ S(x, 25)) -#define Gamma0(x) (S(x, 7) ^ S(x, 18) ^ R(x, 3)) -#define Gamma1(x) (S(x, 17) ^ S(x, 19) ^ R(x, 10)) - -/* compress 512-bits */ -#ifdef LTC_CLEAN_STACK -static int _sha256_compress(sha256_state * md, unsigned char *buf) -#else -static int sha256_compress(sha256_state * md, unsigned char *buf) -#endif -{ - uint32_t S[8], W[64], t0, t1; -#ifdef LTC_SMALL_CODE - uint32_t t; -#endif - int i; - - /* copy state into S */ - for (i = 0; i < 8; i++) { - S[i] = md->state[i]; - } - - /* copy the state into 512-bits into W[0..15] */ - for (i = 0; i < 16; i++) { - LOAD32H(W[i], buf + (4*i)); - } - - /* fill W[16..63] */ - for (i = 16; i < 64; i++) { - W[i] = Gamma1(W[i - 2]) + W[i - 7] + Gamma0(W[i - 15]) + W[i - 16]; - } - - /* Compress */ -#ifdef LTC_SMALL_CODE -#define RND(a,b,c,d,e,f,g,h,i) \ - t0 = h + Sigma1(e) + Ch(e, f, g) + K[i] + W[i]; \ - t1 = Sigma0(a) + Maj(a, b, c); \ - d += t0; \ - h = t0 + t1; - - for (i = 0; i < 64; ++i) { - RND(S[0],S[1],S[2],S[3],S[4],S[5],S[6],S[7],i); - t = S[7]; S[7] = S[6]; S[6] = S[5]; S[5] = S[4]; - S[4] = S[3]; S[3] = S[2]; S[2] = S[1]; S[1] = S[0]; S[0] = t; - } -#else -#define RND(a,b,c,d,e,f,g,h,i,ki) \ - t0 = h + Sigma1(e) + Ch(e, f, g) + ki + W[i]; \ - t1 = Sigma0(a) + Maj(a, b, c); \ - d += t0; \ - h = t0 + t1; - - RND(S[0],S[1],S[2],S[3],S[4],S[5],S[6],S[7],0,0x428a2f98); - RND(S[7],S[0],S[1],S[2],S[3],S[4],S[5],S[6],1,0x71374491); - RND(S[6],S[7],S[0],S[1],S[2],S[3],S[4],S[5],2,0xb5c0fbcf); - RND(S[5],S[6],S[7],S[0],S[1],S[2],S[3],S[4],3,0xe9b5dba5); - RND(S[4],S[5],S[6],S[7],S[0],S[1],S[2],S[3],4,0x3956c25b); - RND(S[3],S[4],S[5],S[6],S[7],S[0],S[1],S[2],5,0x59f111f1); - RND(S[2],S[3],S[4],S[5],S[6],S[7],S[0],S[1],6,0x923f82a4); - RND(S[1],S[2],S[3],S[4],S[5],S[6],S[7],S[0],7,0xab1c5ed5); - RND(S[0],S[1],S[2],S[3],S[4],S[5],S[6],S[7],8,0xd807aa98); - RND(S[7],S[0],S[1],S[2],S[3],S[4],S[5],S[6],9,0x12835b01); - RND(S[6],S[7],S[0],S[1],S[2],S[3],S[4],S[5],10,0x243185be); - RND(S[5],S[6],S[7],S[0],S[1],S[2],S[3],S[4],11,0x550c7dc3); - RND(S[4],S[5],S[6],S[7],S[0],S[1],S[2],S[3],12,0x72be5d74); - RND(S[3],S[4],S[5],S[6],S[7],S[0],S[1],S[2],13,0x80deb1fe); - RND(S[2],S[3],S[4],S[5],S[6],S[7],S[0],S[1],14,0x9bdc06a7); - RND(S[1],S[2],S[3],S[4],S[5],S[6],S[7],S[0],15,0xc19bf174); - RND(S[0],S[1],S[2],S[3],S[4],S[5],S[6],S[7],16,0xe49b69c1); - RND(S[7],S[0],S[1],S[2],S[3],S[4],S[5],S[6],17,0xefbe4786); - RND(S[6],S[7],S[0],S[1],S[2],S[3],S[4],S[5],18,0x0fc19dc6); - RND(S[5],S[6],S[7],S[0],S[1],S[2],S[3],S[4],19,0x240ca1cc); - RND(S[4],S[5],S[6],S[7],S[0],S[1],S[2],S[3],20,0x2de92c6f); - RND(S[3],S[4],S[5],S[6],S[7],S[0],S[1],S[2],21,0x4a7484aa); - RND(S[2],S[3],S[4],S[5],S[6],S[7],S[0],S[1],22,0x5cb0a9dc); - RND(S[1],S[2],S[3],S[4],S[5],S[6],S[7],S[0],23,0x76f988da); - RND(S[0],S[1],S[2],S[3],S[4],S[5],S[6],S[7],24,0x983e5152); - RND(S[7],S[0],S[1],S[2],S[3],S[4],S[5],S[6],25,0xa831c66d); - RND(S[6],S[7],S[0],S[1],S[2],S[3],S[4],S[5],26,0xb00327c8); - RND(S[5],S[6],S[7],S[0],S[1],S[2],S[3],S[4],27,0xbf597fc7); - RND(S[4],S[5],S[6],S[7],S[0],S[1],S[2],S[3],28,0xc6e00bf3); - RND(S[3],S[4],S[5],S[6],S[7],S[0],S[1],S[2],29,0xd5a79147); - RND(S[2],S[3],S[4],S[5],S[6],S[7],S[0],S[1],30,0x06ca6351); - RND(S[1],S[2],S[3],S[4],S[5],S[6],S[7],S[0],31,0x14292967); - RND(S[0],S[1],S[2],S[3],S[4],S[5],S[6],S[7],32,0x27b70a85); - RND(S[7],S[0],S[1],S[2],S[3],S[4],S[5],S[6],33,0x2e1b2138); - RND(S[6],S[7],S[0],S[1],S[2],S[3],S[4],S[5],34,0x4d2c6dfc); - RND(S[5],S[6],S[7],S[0],S[1],S[2],S[3],S[4],35,0x53380d13); - RND(S[4],S[5],S[6],S[7],S[0],S[1],S[2],S[3],36,0x650a7354); - RND(S[3],S[4],S[5],S[6],S[7],S[0],S[1],S[2],37,0x766a0abb); - RND(S[2],S[3],S[4],S[5],S[6],S[7],S[0],S[1],38,0x81c2c92e); - RND(S[1],S[2],S[3],S[4],S[5],S[6],S[7],S[0],39,0x92722c85); - RND(S[0],S[1],S[2],S[3],S[4],S[5],S[6],S[7],40,0xa2bfe8a1); - RND(S[7],S[0],S[1],S[2],S[3],S[4],S[5],S[6],41,0xa81a664b); - RND(S[6],S[7],S[0],S[1],S[2],S[3],S[4],S[5],42,0xc24b8b70); - RND(S[5],S[6],S[7],S[0],S[1],S[2],S[3],S[4],43,0xc76c51a3); - RND(S[4],S[5],S[6],S[7],S[0],S[1],S[2],S[3],44,0xd192e819); - RND(S[3],S[4],S[5],S[6],S[7],S[0],S[1],S[2],45,0xd6990624); - RND(S[2],S[3],S[4],S[5],S[6],S[7],S[0],S[1],46,0xf40e3585); - RND(S[1],S[2],S[3],S[4],S[5],S[6],S[7],S[0],47,0x106aa070); - RND(S[0],S[1],S[2],S[3],S[4],S[5],S[6],S[7],48,0x19a4c116); - RND(S[7],S[0],S[1],S[2],S[3],S[4],S[5],S[6],49,0x1e376c08); - RND(S[6],S[7],S[0],S[1],S[2],S[3],S[4],S[5],50,0x2748774c); - RND(S[5],S[6],S[7],S[0],S[1],S[2],S[3],S[4],51,0x34b0bcb5); - RND(S[4],S[5],S[6],S[7],S[0],S[1],S[2],S[3],52,0x391c0cb3); - RND(S[3],S[4],S[5],S[6],S[7],S[0],S[1],S[2],53,0x4ed8aa4a); - RND(S[2],S[3],S[4],S[5],S[6],S[7],S[0],S[1],54,0x5b9cca4f); - RND(S[1],S[2],S[3],S[4],S[5],S[6],S[7],S[0],55,0x682e6ff3); - RND(S[0],S[1],S[2],S[3],S[4],S[5],S[6],S[7],56,0x748f82ee); - RND(S[7],S[0],S[1],S[2],S[3],S[4],S[5],S[6],57,0x78a5636f); - RND(S[6],S[7],S[0],S[1],S[2],S[3],S[4],S[5],58,0x84c87814); - RND(S[5],S[6],S[7],S[0],S[1],S[2],S[3],S[4],59,0x8cc70208); - RND(S[4],S[5],S[6],S[7],S[0],S[1],S[2],S[3],60,0x90befffa); - RND(S[3],S[4],S[5],S[6],S[7],S[0],S[1],S[2],61,0xa4506ceb); - RND(S[2],S[3],S[4],S[5],S[6],S[7],S[0],S[1],62,0xbef9a3f7); - RND(S[1],S[2],S[3],S[4],S[5],S[6],S[7],S[0],63,0xc67178f2); - -#undef RND - -#endif - - /* feedback */ - for (i = 0; i < 8; i++) { - md->state[i] = md->state[i] + S[i]; - } - return CRYPT_OK; -} - -#ifdef LTC_CLEAN_STACK -static int sha256_compress(sha256_state * md, unsigned char *buf) -{ - int err; - err = _sha256_compress(md, buf); - burn_stack(sizeof(uint32_t) * 74); - return err; -} -#endif - -/** - Initialize the hash state - @param md The hash state you wish to initialize - @return CRYPT_OK if successful -*/ -static int sha256_init(sha256_state * md) -{ - LTC_ARGCHK(md != NULL); - - md->curlen = 0; - md->length = 0; - md->state[0] = 0x6A09E667UL; - md->state[1] = 0xBB67AE85UL; - md->state[2] = 0x3C6EF372UL; - md->state[3] = 0xA54FF53AUL; - md->state[4] = 0x510E527FUL; - md->state[5] = 0x9B05688CUL; - md->state[6] = 0x1F83D9ABUL; - md->state[7] = 0x5BE0CD19UL; - return CRYPT_OK; -} - -/** - Process a block of memory though the hash - @param md The hash state - @param in The data to hash - @param inlen The length of the data (octets) - @return CRYPT_OK if successful -*/ -static int sha256_process (sha256_state * md, const unsigned char *in, unsigned long inlen) -{ - unsigned long n; - int err; - LTC_ARGCHK(md != NULL); - LTC_ARGCHK(in != NULL); - if (md->curlen > sizeof(md->buf)) { - return CRYPT_INVALID_ARG; - } - while (inlen > 0) { - if (md->curlen == 0 && inlen >= 64) { - if ((err = sha256_compress (md, (unsigned char *)in)) != CRYPT_OK) { - return err; - } - md->length += 64 * 8; - in += 64; - inlen -= 64; - } else { - n = MIN(inlen, (64 - md->curlen)); - memcpy(md->buf + md->curlen, in, (size_t)n); - md->curlen += n; - in += n; - inlen -= n; - if (md->curlen == 64) { - if ((err = sha256_compress (md, md->buf)) != CRYPT_OK) { - return err; - } - md->length += 8*64; - md->curlen = 0; - } - } - } - return CRYPT_OK; -} - -/** - Terminate the hash to get the digest - @param md The hash state - @param out [out] The destination of the hash (32 bytes) - @return CRYPT_OK if successful -*/ -static int sha256_done(sha256_state * md, unsigned char *out) -{ - int i; - - LTC_ARGCHK(md != NULL); - LTC_ARGCHK(out != NULL); - - if (md->curlen >= sizeof(md->buf)) { - return CRYPT_INVALID_ARG; - } - - - /* increase the length of the message */ - md->length += md->curlen * 8; - - /* append the '1' bit */ - md->buf[md->curlen++] = (unsigned char)0x80; - - /* if the length is currently above 56 bytes we append zeros - * then compress. Then we can fall back to padding zeros and length - * encoding like normal. - */ - if (md->curlen > 56) { - while (md->curlen < 64) { - md->buf[md->curlen++] = (unsigned char)0; - } - sha256_compress(md, md->buf); - md->curlen = 0; - } - - /* pad upto 56 bytes of zeroes */ - while (md->curlen < 56) { - md->buf[md->curlen++] = (unsigned char)0; - } - - /* store length */ - STORE64H(md->length, md->buf+56); - sha256_compress(md, md->buf); - - /* copy output */ - for (i = 0; i < 8; i++) { - STORE32H(md->state[i], out+(4*i)); - } -#ifdef LTC_CLEAN_STACK - zeromem(md, sizeof(sha256_state)); -#endif - return CRYPT_OK; -} - -/* $Source: /cvs/libtom/libtomcrypt/src/hashes/sha2/sha256.c,v $ */ -/* $Revision: 1.9 $ */ -/* $Date: 2006/11/01 09:28:17 $ */ diff --git a/src/common/strlcat.c b/src/common/strlcat.c deleted file mode 100644 index 316733bccc..0000000000 --- a/src/common/strlcat.c +++ /dev/null @@ -1,70 +0,0 @@ -/* $OpenBSD: strlcat.c,v 1.8 2001/05/13 15:40:15 deraadt Exp $ */ - -/* - * Copyright (c) 1998 Todd C. Miller <Todd.Miller@courtesan.com> - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, - * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY - * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL - * THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; - * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR - * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF - * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#if defined(LIBC_SCCS) && !defined(lint) -static char *rcsid = "$OpenBSD: strlcat.c,v 1.8 2001/05/13 15:40:15 deraadt Exp $"; -#endif /* LIBC_SCCS and not lint */ - -#include <sys/types.h> -#include <string.h> - -/* - * Appends src to string dst of size siz (unlike strncat, siz is the - * full size of dst, not space left). At most siz-1 characters - * will be copied. Always NUL terminates (unless siz <= strlen(dst)). - * Returns strlen(src) + MIN(siz, strlen(initial dst)). - * If retval >= siz, truncation occurred. - */ -size_t -strlcat(char *dst, const char *src, size_t siz) -{ - register char *d = dst; - register const char *s = src; - register size_t n = siz; - size_t dlen; - - /* Find the end of dst and adjust bytes left but don't go past end */ - while (n-- != 0 && *d != '\0') - d++; - dlen = d - dst; - n = siz - dlen; - - if (n == 0) - return(dlen + strlen(s)); - while (*s != '\0') { - if (n != 1) { - *d++ = *s; - n--; - } - s++; - } - *d = '\0'; - - return(dlen + (s - src)); /* count does not include NUL */ -} diff --git a/src/common/strlcpy.c b/src/common/strlcpy.c deleted file mode 100644 index 9fc47903a1..0000000000 --- a/src/common/strlcpy.c +++ /dev/null @@ -1,60 +0,0 @@ -/* $OpenBSD: strlcpy.c,v 1.2 1998/11/06 04:33:16 wvdputte Exp $ */ - -/* - * Copyright (c) 1998 Todd C. Miller <Todd.Miller@courtesan.com> - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, - * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY - * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL - * THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; - * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR - * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF - * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#if defined(LIBC_SCCS) && !defined(lint) -static char *rcsid = "$OpenBSD: strlcpy.c,v 1.2 1998/11/06 04:33:16 wvdputte Exp $"; -#endif /* LIBC_SCCS and not lint */ - -#include <sys/types.h> -#include <string.h> - -/* - * Copy src to string dst of size siz. At most siz-1 characters - * will be copied. Always NUL terminates (unless siz == 0). - * Returns strlen(src); if retval >= siz, truncation occurred. - */ -size_t strlcpy(char *dst, const char *src, size_t siz) -{ - register char *d = dst; - register const char *s = src; - register size_t n = siz; - - if (n == 0) - return(strlen(s)); - while (*s != '\0') { - if (n != 1) { - *d++ = *s; - n--; - } - s++; - } - *d = '\0'; - - return(s - src); /* count does not include NUL */ -} diff --git a/src/common/torgzip.h b/src/common/torgzip.h index d3ded81f9c..921b232b0f 100644 --- a/src/common/torgzip.h +++ b/src/common/torgzip.h @@ -8,8 +8,8 @@ * \brief Headers for torgzip.h **/ -#ifndef _TOR_TORGZIP_H -#define _TOR_TORGZIP_H +#ifndef TOR_TORGZIP_H +#define TOR_TORGZIP_H /** Enumeration of what kind of compression to use. Only ZLIB_METHOD is * guaranteed to be supported by the compress/uncompress functions here; diff --git a/src/common/torint.h b/src/common/torint.h index 8771802d70..0db9cc7e24 100644 --- a/src/common/torint.h +++ b/src/common/torint.h @@ -8,8 +8,8 @@ * \brief Header file to define uint32_t and friends **/ -#ifndef _TOR_TORINT_H -#define _TOR_TORINT_H +#ifndef TOR_TORINT_H +#define TOR_TORINT_H #include "orconfig.h" diff --git a/src/common/torlog.h b/src/common/torlog.h index 28890a44af..ab97f9c9a7 100644 --- a/src/common/torlog.h +++ b/src/common/torlog.h @@ -10,7 +10,7 @@ * \brief Headers for log.c **/ -#ifndef _TOR_LOG_H +#ifndef TOR_TORLOG_H #include "compat.h" @@ -94,8 +94,10 @@ #define LD_HANDSHAKE (1u<<19) /** Heartbeat messages */ #define LD_HEARTBEAT (1u<<20) +/** Abstract channel_t code */ +#define LD_CHANNEL (1u<<21) /** Number of logging domains in the code. */ -#define N_LOGGING_DOMAINS 21 +#define N_LOGGING_DOMAINS 22 /** This log message is not safe to send to a callback-based logger * immediately. Used as a flag, not a log domain. */ @@ -154,63 +156,63 @@ void tor_log(int severity, log_domain_mask_t domain, const char *format, ...) #define log tor_log /* hack it so we don't conflict with log() as much */ #if defined(__GNUC__) || defined(RUNNING_DOXYGEN) -extern int _log_global_min_severity; +extern int log_global_min_severity_; -void _log_fn(int severity, log_domain_mask_t domain, +void log_fn_(int severity, log_domain_mask_t domain, const char *funcname, const char *format, ...) CHECK_PRINTF(4,5); /** Log a message at level <b>severity</b>, using a pretty-printed version * of the current function name. */ #define log_fn(severity, domain, args...) \ - _log_fn(severity, domain, __PRETTY_FUNCTION__, args) + log_fn_(severity, domain, __PRETTY_FUNCTION__, args) #define log_debug(domain, args...) \ STMT_BEGIN \ - if (PREDICT_UNLIKELY(_log_global_min_severity == LOG_DEBUG)) \ - _log_fn(LOG_DEBUG, domain, __PRETTY_FUNCTION__, args); \ + if (PREDICT_UNLIKELY(log_global_min_severity_ == LOG_DEBUG)) \ + log_fn_(LOG_DEBUG, domain, __PRETTY_FUNCTION__, args); \ STMT_END #define log_info(domain, args...) \ - _log_fn(LOG_INFO, domain, __PRETTY_FUNCTION__, args) + log_fn_(LOG_INFO, domain, __PRETTY_FUNCTION__, args) #define log_notice(domain, args...) \ - _log_fn(LOG_NOTICE, domain, __PRETTY_FUNCTION__, args) + log_fn_(LOG_NOTICE, domain, __PRETTY_FUNCTION__, args) #define log_warn(domain, args...) \ - _log_fn(LOG_WARN, domain, __PRETTY_FUNCTION__, args) + log_fn_(LOG_WARN, domain, __PRETTY_FUNCTION__, args) #define log_err(domain, args...) \ - _log_fn(LOG_ERR, domain, __PRETTY_FUNCTION__, args) + log_fn_(LOG_ERR, domain, __PRETTY_FUNCTION__, args) #else /* ! defined(__GNUC__) */ -void _log_fn(int severity, log_domain_mask_t domain, const char *format, ...); -void _log_debug(log_domain_mask_t domain, const char *format, ...); -void _log_info(log_domain_mask_t domain, const char *format, ...); -void _log_notice(log_domain_mask_t domain, const char *format, ...); -void _log_warn(log_domain_mask_t domain, const char *format, ...); -void _log_err(log_domain_mask_t domain, const char *format, ...); +void log_fn_(int severity, log_domain_mask_t domain, const char *format, ...); +void log_debug_(log_domain_mask_t domain, const char *format, ...); +void log_info_(log_domain_mask_t domain, const char *format, ...); +void log_notice_(log_domain_mask_t domain, const char *format, ...); +void log_warn_(log_domain_mask_t domain, const char *format, ...); +void log_err_(log_domain_mask_t domain, const char *format, ...); #if defined(_MSC_VER) && _MSC_VER < 1300 /* MSVC 6 and earlier don't have __func__, or even __LINE__. */ -#define log_fn _log_fn -#define log_debug _log_debug -#define log_info _log_info -#define log_notice _log_notice -#define log_warn _log_warn -#define log_err _log_err +#define log_fn log_fn_ +#define log_debug log_debug_ +#define log_info log_info_ +#define log_notice log_notice_ +#define log_warn log_warn_ +#define log_err log_err_ #else /* We don't have GCC's varargs macros, so use a global variable to pass the * function name to log_fn */ -extern const char *_log_fn_function_name; +extern const char *log_fn_function_name_; /* We abuse the comma operator here, since we can't use the standard * do {...} while (0) trick to wrap this macro, since the macro can't take * arguments. */ -#define log_fn (_log_fn_function_name=__func__),_log_fn -#define log_debug (_log_fn_function_name=__func__),_log_debug -#define log_info (_log_fn_function_name=__func__),_log_info -#define log_notice (_log_fn_function_name=__func__),_log_notice -#define log_warn (_log_fn_function_name=__func__),_log_warn -#define log_err (_log_fn_function_name=__func__),_log_err +#define log_fn (log_fn_function_name_=__func__),log_fn_ +#define log_debug (log_fn_function_name_=__func__),log_debug_ +#define log_info (log_fn_function_name_=__func__),log_info_ +#define log_notice (log_fn_function_name_=__func__),log_notice_ +#define log_warn (log_fn_function_name_=__func__),log_warn_ +#define log_err (log_fn_function_name_=__func__),log_err_ #endif #endif /* !GNUC */ -# define _TOR_LOG_H +# define TOR_TORLOG_H #endif diff --git a/src/common/tortls.c b/src/common/tortls.c index 12eac8deab..3bb0581463 100644 --- a/src/common/tortls.c +++ b/src/common/tortls.c @@ -58,8 +58,8 @@ #include "container.h" #include <string.h> -#if OPENSSL_VERSION_NUMBER < OPENSSL_V_SERIES(0,9,7) -#error "We require OpenSSL >= 0.9.7" +#if OPENSSL_VERSION_NUMBER < OPENSSL_V_SERIES(0,9,8) +#error "We require OpenSSL >= 0.9.8" #endif /* Enable the "v2" TLS handshake. @@ -234,8 +234,8 @@ static tor_tls_context_t *client_tls_context = NULL; static int tls_library_is_initialized = 0; /* Module-internal error codes. */ -#define _TOR_TLS_SYSCALL (_MIN_TOR_TLS_ERROR_VAL - 2) -#define _TOR_TLS_ZERORETURN (_MIN_TOR_TLS_ERROR_VAL - 1) +#define TOR_TLS_SYSCALL_ (MIN_TOR_TLS_ERROR_VAL_ - 2) +#define TOR_TLS_ZERORETURN_ (MIN_TOR_TLS_ERROR_VAL_ - 1) /** Write a description of the current state of <b>tls</b> into the * <b>sz</b>-byte buffer at <b>buf</b>. */ @@ -393,9 +393,9 @@ tor_tls_err_to_string(int err) /** Given a TLS object and the result of an SSL_* call, use * SSL_get_error to determine whether an error has occurred, and if so * which one. Return one of TOR_TLS_{DONE|WANTREAD|WANTWRITE|ERROR}. - * If extra&CATCH_SYSCALL is true, return _TOR_TLS_SYSCALL instead of + * If extra&CATCH_SYSCALL is true, return TOR_TLS_SYSCALL_ instead of * reporting syscall errors. If extra&CATCH_ZERO is true, return - * _TOR_TLS_ZERORETURN instead of reporting zero-return errors. + * TOR_TLS_ZERORETURN_ instead of reporting zero-return errors. * * If an error has occurred, log it at level <b>severity</b> and describe the * current action as <b>doing</b>. @@ -415,7 +415,7 @@ tor_tls_get_error(tor_tls_t *tls, int r, int extra, return TOR_TLS_WANTWRITE; case SSL_ERROR_SYSCALL: if (extra&CATCH_SYSCALL) - return _TOR_TLS_SYSCALL; + return TOR_TLS_SYSCALL_; if (r == 0) { log(severity, LD_NET, "TLS error: unexpected close while %s (%s)", doing, SSL_state_string_long(tls->ssl)); @@ -432,7 +432,7 @@ tor_tls_get_error(tor_tls_t *tls, int r, int extra, return tor_error; case SSL_ERROR_ZERO_RETURN: if (extra&CATCH_ZERO) - return _TOR_TLS_ZERORETURN; + return TOR_TLS_ZERORETURN_; log(severity, LD_NET, "TLS connection closed while %s in state %s", doing, SSL_state_string_long(tls->ssl)); tls_log_errors(tls, severity, domain, doing); @@ -478,7 +478,7 @@ tor_tls_init(void) * a test of intelligence and determination. */ if (version > OPENSSL_V(0,9,8,'k') && version <= OPENSSL_V(0,9,8,'l')) { - log_notice(LD_GENERAL, "OpenSSL %s looks like version 0.9.8l, but " + log_info(LD_GENERAL, "OpenSSL %s looks like version 0.9.8l, but " "some vendors have backported renegotiation code from " "0.9.8m without updating the version number. " "I will try SSL3_FLAGS and SSL_OP to enable renegotation.", @@ -486,12 +486,12 @@ tor_tls_init(void) use_unsafe_renegotiation_flag = 1; use_unsafe_renegotiation_op = 1; } else if (version > OPENSSL_V(0,9,8,'l')) { - log_notice(LD_GENERAL, "OpenSSL %s looks like version 0.9.8m or later; " + log_info(LD_GENERAL, "OpenSSL %s looks like version 0.9.8m or later; " "I will try SSL_OP to enable renegotiation", SSLeay_version(SSLEAY_VERSION)); use_unsafe_renegotiation_op = 1; } else if (version <= OPENSSL_V(0,9,8,'k')) { - log_notice(LD_GENERAL, "OpenSSL %s [%lx] looks like it's older than " + log_info(LD_GENERAL, "OpenSSL %s [%lx] looks like it's older than " "0.9.8l, but some vendors have backported 0.9.8l's " "renegotiation code to earlier versions, and some have " "backported the code from 0.9.8m or 0.9.8n. I'll set both " @@ -597,9 +597,9 @@ tor_tls_create_certificate(crypto_pk_t *rsa, tor_assert(cname); tor_assert(rsa_sign); tor_assert(cname_sign); - if (!(sign_pkey = _crypto_pk_get_evp_pkey(rsa_sign,1))) + if (!(sign_pkey = crypto_pk_get_evp_pkey_(rsa_sign,1))) goto error; - if (!(pkey = _crypto_pk_get_evp_pkey(rsa,0))) + if (!(pkey = crypto_pk_get_evp_pkey_(rsa,0))) goto error; if (!(x509 = X509_new())) goto error; @@ -754,7 +754,7 @@ tor_cert_new(X509 *x509_cert) if ((pkey = X509_get_pubkey(x509_cert)) && (rsa = EVP_PKEY_get1_RSA(pkey))) { - crypto_pk_t *pk = _crypto_new_pk_from_rsa(rsa); + crypto_pk_t *pk = crypto_new_pk_from_rsa_(rsa); crypto_pk_get_all_digests(pk, &cert->pkey_digests); cert->pkey_digests_set = 1; crypto_pk_free(pk); @@ -778,13 +778,8 @@ tor_cert_decode(const uint8_t *certificate, size_t certificate_len) if (certificate_len > INT_MAX) return NULL; -#if OPENSSL_VERSION_NUMBER < OPENSSL_V_SERIES(0,9,8) - /* This ifdef suppresses a type warning. Take out this case once everybody - * is using OpenSSL 0.9.8 or later. */ - x509 = d2i_X509(NULL, (unsigned char**)&cp, (int)certificate_len); -#else x509 = d2i_X509(NULL, &cp, (int)certificate_len); -#endif + if (!x509) return NULL; /* Couldn't decode */ if (cp - certificate != (int)certificate_len) { @@ -901,7 +896,7 @@ tor_tls_cert_get_key(tor_cert_t *cert) EVP_PKEY_free(pkey); return NULL; } - result = _crypto_new_pk_from_rsa(rsa); + result = crypto_new_pk_from_rsa_(rsa); EVP_PKEY_free(pkey); return result; } @@ -1260,7 +1255,7 @@ tor_tls_context_new(crypto_pk_t *identity, unsigned int key_lifetime, SSL_CTX_set_session_cache_mode(result->ctx, SSL_SESS_CACHE_OFF); if (!is_client) { tor_assert(rsa); - if (!(pkey = _crypto_pk_get_evp_pkey(rsa,1))) + if (!(pkey = crypto_pk_get_evp_pkey_(rsa,1))) goto error; if (!SSL_CTX_use_PrivateKey(result->ctx, pkey)) goto error; @@ -1272,7 +1267,7 @@ tor_tls_context_new(crypto_pk_t *identity, unsigned int key_lifetime, { crypto_dh_t *dh = crypto_dh_new(DH_TYPE_TLS); tor_assert(dh); - SSL_CTX_set_tmp_dh(result->ctx, _crypto_dh_get_dh(dh)); + SSL_CTX_set_tmp_dh(result->ctx, crypto_dh_get_dh_(dh)); crypto_dh_free(dh); } SSL_CTX_set_verify(result->ctx, SSL_VERIFY_PEER, @@ -1764,7 +1759,7 @@ tor_tls_read(tor_tls_t *tls, char *cp, size_t len) return r; } err = tor_tls_get_error(tls, r, CATCH_ZERO, "reading", LOG_DEBUG, LD_NET); - if (err == _TOR_TLS_ZERORETURN || err == TOR_TLS_CLOSE) { + if (err == TOR_TLS_ZERORETURN_ || err == TOR_TLS_CLOSE) { log_debug(LD_NET,"read returned r=%d; TLS is closed",r); tls->state = TOR_TLS_ST_CLOSED; return TOR_TLS_CLOSE; @@ -1977,7 +1972,7 @@ tor_tls_shutdown(tor_tls_t *tls) } while (r>0); err = tor_tls_get_error(tls, r, CATCH_ZERO, "reading to shut down", LOG_INFO, LD_NET); - if (err == _TOR_TLS_ZERORETURN) { + if (err == TOR_TLS_ZERORETURN_) { tls->state = TOR_TLS_ST_GOTCLOSE; /* fall through... */ } else { @@ -1993,11 +1988,11 @@ tor_tls_shutdown(tor_tls_t *tls) } err = tor_tls_get_error(tls, r, CATCH_SYSCALL|CATCH_ZERO, "shutting down", LOG_INFO, LD_NET); - if (err == _TOR_TLS_SYSCALL) { + if (err == TOR_TLS_SYSCALL_) { /* The underlying TCP connection closed while we were shutting down. */ tls->state = TOR_TLS_ST_CLOSED; return TOR_TLS_DONE; - } else if (err == _TOR_TLS_ZERORETURN) { + } else if (err == TOR_TLS_ZERORETURN_) { /* The TLS connection says that it sent a shutdown record, but * isn't done shutting down yet. Make sure that this hasn't * happened before, then go back to the start of the function @@ -2167,7 +2162,7 @@ tor_tls_verify(int severity, tor_tls_t *tls, crypto_pk_t **identity_key) rsa = EVP_PKEY_get1_RSA(id_pkey); if (!rsa) goto done; - *identity_key = _crypto_new_pk_from_rsa(rsa); + *identity_key = crypto_new_pk_from_rsa_(rsa); r = 0; @@ -2297,7 +2292,7 @@ tor_tls_get_n_raw_bytes(tor_tls_t *tls, size_t *n_read, size_t *n_written) /** Implement check_no_tls_errors: If there are any pending OpenSSL * errors, log an error message. */ void -_check_no_tls_errors(const char *fname, int line) +check_no_tls_errors_(const char *fname, int line) { if (ERR_peek_error() == 0) return; diff --git a/src/common/tortls.h b/src/common/tortls.h index 491a5419df..7bc6c8e76b 100644 --- a/src/common/tortls.h +++ b/src/common/tortls.h @@ -3,8 +3,8 @@ * Copyright (c) 2007-2012, The Tor Project, Inc. */ /* See LICENSE for licensing information */ -#ifndef _TOR_TORTLS_H -#define _TOR_TORTLS_H +#ifndef TOR_TORTLS_H +#define TOR_TORTLS_H /** * \file tortls.h @@ -21,7 +21,7 @@ typedef struct tor_tls_t tor_tls_t; typedef struct tor_cert_t tor_cert_t; /* Possible return values for most tor_tls_* functions. */ -#define _MIN_TOR_TLS_ERROR_VAL -9 +#define MIN_TOR_TLS_ERROR_VAL_ -9 #define TOR_TLS_ERROR_MISC -9 /* Rename to unexpected close or something. XXXX */ #define TOR_TLS_ERROR_IO -8 @@ -98,9 +98,9 @@ int tor_tls_get_tlssecrets(tor_tls_t *tls, uint8_t *secrets_out); /* Log and abort if there are unhandled TLS errors in OpenSSL's error stack. */ -#define check_no_tls_errors() _check_no_tls_errors(__FILE__,__LINE__) +#define check_no_tls_errors() check_no_tls_errors_(__FILE__,__LINE__) -void _check_no_tls_errors(const char *fname, int line); +void check_no_tls_errors_(const char *fname, int line); void tor_tls_log_one_error(tor_tls_t *tls, unsigned long err, int severity, int domain, const char *doing); diff --git a/src/common/util.c b/src/common/util.c index 6fb597a3a5..75eb233bef 100644 --- a/src/common/util.c +++ b/src/common/util.c @@ -39,8 +39,8 @@ #endif /* math.h needs this on Linux */ -#ifndef __USE_ISOC99 -#define __USE_ISOC99 1 +#ifndef _USE_ISOC99_ +#define _USE_ISOC99_ 1 #endif #include <math.h> #include <stdlib.h> @@ -125,7 +125,7 @@ * ignored otherwise. */ void * -_tor_malloc(size_t size DMALLOC_PARAMS) +tor_malloc_(size_t size DMALLOC_PARAMS) { void *result; @@ -159,7 +159,7 @@ _tor_malloc(size_t size DMALLOC_PARAMS) * the process on error. (Same as calloc(size,1), but never returns NULL.) */ void * -_tor_malloc_zero(size_t size DMALLOC_PARAMS) +tor_malloc_zero_(size_t size DMALLOC_PARAMS) { /* You may ask yourself, "wouldn't it be smart to use calloc instead of * malloc+memset? Perhaps libc's calloc knows some nifty optimization trick @@ -167,7 +167,7 @@ _tor_malloc_zero(size_t size DMALLOC_PARAMS) * we're allocating something very big (it knows if it just got the memory * from the OS in a pre-zeroed state). We don't want to use tor_malloc_zero * for big stuff, so we don't bother with calloc. */ - void *result = _tor_malloc(size DMALLOC_FN_ARGS); + void *result = tor_malloc_(size DMALLOC_FN_ARGS); memset(result, 0, size); return result; } @@ -184,7 +184,7 @@ _tor_malloc_zero(size_t size DMALLOC_PARAMS) * smaller than size). Don't do that then. */ void * -_tor_calloc(size_t nmemb, size_t size DMALLOC_PARAMS) +tor_calloc_(size_t nmemb, size_t size DMALLOC_PARAMS) { /* You may ask yourself, "wouldn't it be smart to use calloc instead of * malloc+memset? Perhaps libc's calloc knows some nifty optimization trick @@ -197,7 +197,7 @@ _tor_calloc(size_t nmemb, size_t size DMALLOC_PARAMS) tor_assert(nmemb < max_nmemb); - result = _tor_malloc_zero((nmemb * size) DMALLOC_FN_ARGS); + result = tor_malloc_zero_((nmemb * size) DMALLOC_FN_ARGS); return result; } @@ -206,7 +206,7 @@ _tor_calloc(size_t nmemb, size_t size DMALLOC_PARAMS) * terminate. (Like realloc(ptr,size), but never returns NULL.) */ void * -_tor_realloc(void *ptr, size_t size DMALLOC_PARAMS) +tor_realloc_(void *ptr, size_t size DMALLOC_PARAMS) { void *result; @@ -230,7 +230,7 @@ _tor_realloc(void *ptr, size_t size DMALLOC_PARAMS) * NULL.) */ char * -_tor_strdup(const char *s DMALLOC_PARAMS) +tor_strdup_(const char *s DMALLOC_PARAMS) { char *dup; tor_assert(s); @@ -254,12 +254,12 @@ _tor_strdup(const char *s DMALLOC_PARAMS) * NULL.) */ char * -_tor_strndup(const char *s, size_t n DMALLOC_PARAMS) +tor_strndup_(const char *s, size_t n DMALLOC_PARAMS) { char *dup; tor_assert(s); tor_assert(n < SIZE_T_CEILING); - dup = _tor_malloc((n+1) DMALLOC_FN_ARGS); + dup = tor_malloc_((n+1) DMALLOC_FN_ARGS); /* Performance note: Ordinarily we prefer strlcpy to strncpy. But * this function gets called a whole lot, and platform strncpy is * much faster than strlcpy when strlen(s) is much longer than n. @@ -272,12 +272,12 @@ _tor_strndup(const char *s, size_t n DMALLOC_PARAMS) /** Allocate a chunk of <b>len</b> bytes, with the same contents as the * <b>len</b> bytes starting at <b>mem</b>. */ void * -_tor_memdup(const void *mem, size_t len DMALLOC_PARAMS) +tor_memdup_(const void *mem, size_t len DMALLOC_PARAMS) { char *dup; tor_assert(len < SIZE_T_CEILING); tor_assert(mem); - dup = _tor_malloc(len DMALLOC_FN_ARGS); + dup = tor_malloc_(len DMALLOC_FN_ARGS); memcpy(dup, mem, len); return dup; } @@ -285,42 +285,11 @@ _tor_memdup(const void *mem, size_t len DMALLOC_PARAMS) /** Helper for places that need to take a function pointer to the right * spelling of "free()". */ void -_tor_free(void *mem) +tor_free_(void *mem) { tor_free(mem); } -#if defined(HAVE_MALLOC_GOOD_SIZE) && !defined(HAVE_MALLOC_GOOD_SIZE_PROTOTYPE) -/* Some version of Mac OSX have malloc_good_size in their libc, but not - * actually defined in malloc/malloc.h. We detect this and work around it by - * prototyping. - */ -extern size_t malloc_good_size(size_t size); -#endif - -/** Allocate and return a chunk of memory of size at least *<b>size</b>, using - * the same resources we would use to malloc *<b>sizep</b>. Set *<b>sizep</b> - * to the number of usable bytes in the chunk of memory. */ -void * -_tor_malloc_roundup(size_t *sizep DMALLOC_PARAMS) -{ -#ifdef HAVE_MALLOC_GOOD_SIZE - tor_assert(*sizep < SIZE_T_CEILING); - *sizep = malloc_good_size(*sizep); - return _tor_malloc(*sizep DMALLOC_FN_ARGS); -#elif 0 && defined(HAVE_MALLOC_USABLE_SIZE) && !defined(USE_DMALLOC) - /* Never use malloc_usable_size(); it makes valgrind really unhappy, - * and doesn't win much in terms of usable space where it exists. */ - void *result; - tor_assert(*sizep < SIZE_T_CEILING); - result = _tor_malloc(*sizep DMALLOC_FN_ARGS); - *sizep = malloc_usable_size(result); - return result; -#else - return _tor_malloc(*sizep DMALLOC_FN_ARGS); -#endif -} - /** Call the platform malloc info function, and dump the results to the log at * level <b>severity</b>. If no such function exists, do nothing. */ void @@ -363,9 +332,9 @@ tor_mathlog(double d) return log(d); } -/** Return the long integer closest to d. We define this wrapper here so - * that not all users of math.h need to use the right incancations to get - * the c99 functions. */ +/** Return the long integer closest to <b>d</b>. We define this wrapper + * here so that not all users of math.h need to use the right incantations + * to get the c99 functions. */ long tor_lround(double d) { @@ -378,6 +347,21 @@ tor_lround(double d) #endif } +/** Return the 64-bit integer closest to d. We define this wrapper here so + * that not all users of math.h need to use the right incantations to get the + * c99 functions. */ +int64_t +tor_llround(double d) +{ +#if defined(HAVE_LLROUND) + return (int64_t)llround(d); +#elif defined(HAVE_RINT) + return (int64_t)rint(d); +#else + return (int64_t)(d > 0 ? d + 0.5 : ceil(d - 0.5)); +#endif +} + /** Returns floor(log2(u64)). If u64 is 0, (incorrectly) returns 0. */ int tor_log2(uint64_t u64) @@ -410,12 +394,24 @@ tor_log2(uint64_t u64) return r; } -/** Return the power of 2 closest to <b>u64</b>. */ +/** Return the power of 2 in range [1,UINT64_MAX] closest to <b>u64</b>. If + * there are two powers of 2 equally close, round down. */ uint64_t round_to_power_of_2(uint64_t u64) { - int lg2 = tor_log2(u64); - uint64_t low = U64_LITERAL(1) << lg2, high = U64_LITERAL(1) << (lg2+1); + int lg2; + uint64_t low; + uint64_t high; + if (u64 == 0) + return 1; + + lg2 = tor_log2(u64); + low = U64_LITERAL(1) << lg2; + + if (lg2 == 63) + return low; + + high = U64_LITERAL(1) << (lg2+1); if (high - u64 < u64 - low) return high; else @@ -655,6 +651,16 @@ fast_memcmpstart(const void *mem, size_t memlen, return fast_memcmp(mem, prefix, plen); } +/** Given a nul-terminated string s, set every character before the nul + * to zero. */ +void +tor_strclear(char *s) +{ + while (*s) { + *s++ = '\0'; + } +} + /** Return a pointer to the first char of s that is not whitespace and * not a comment, or to the terminating NUL if no such character exists. */ @@ -1013,7 +1019,7 @@ base16_encode(char *dest, size_t destlen, const char *src, size_t srclen) /** Helper: given a hex digit, return its value, or -1 if it isn't hex. */ static INLINE int -_hex_decode_digit(char c) +hex_decode_digit_(char c) { switch (c) { case '0': return 0; @@ -1041,7 +1047,7 @@ _hex_decode_digit(char c) int hex_decode_digit(char c) { - return _hex_decode_digit(c); + return hex_decode_digit_(c); } /** Given a hexadecimal string of <b>srclen</b> bytes in <b>src</b>, decode it @@ -1059,8 +1065,8 @@ base16_decode(char *dest, size_t destlen, const char *src, size_t srclen) return -1; end = src+srclen; while (src<end) { - v1 = _hex_decode_digit(*src); - v2 = _hex_decode_digit(*(src+1)); + v1 = hex_decode_digit_(*src); + v2 = hex_decode_digit_(*(src+1)); if (v1<0||v2<0) return -1; *(uint8_t*)dest = (v1<<4)|v2; @@ -1160,15 +1166,15 @@ esc_for_log(const char *s) const char * escaped(const char *s) { - static char *_escaped_val = NULL; - tor_free(_escaped_val); + static char *escaped_val_ = NULL; + tor_free(escaped_val_); if (s) - _escaped_val = esc_for_log(s); + escaped_val_ = esc_for_log(s); else - _escaped_val = NULL; + escaped_val_ = NULL; - return _escaped_val; + return escaped_val_; } /** Rudimentary string wrapping code: given a un-wrapped <b>string</b> (no @@ -1827,6 +1833,10 @@ file_status(const char *fname) return FN_DIR; else if (st.st_mode & S_IFREG) return FN_FILE; +#ifndef _WIN32 + else if (st.st_mode & S_IFIFO) + return FN_FILE; +#endif else return FN_ERROR; } @@ -2257,6 +2267,46 @@ write_bytes_to_new_file(const char *fname, const char *str, size_t len, (bin?O_BINARY:O_TEXT)); } +/** + * Read the contents of the open file <b>fd</b> presuming it is a FIFO + * (or similar) file descriptor for which the size of the file isn't + * known ahead of time. Return NULL on failure, and a NUL-terminated + * string on success. On success, set <b>sz_out</b> to the number of + * bytes read. + */ +char * +read_file_to_str_until_eof(int fd, size_t max_bytes_to_read, size_t *sz_out) +{ + ssize_t r; + size_t pos = 0; + char *string = NULL; + size_t string_max = 0; + + if (max_bytes_to_read+1 >= SIZE_T_CEILING) + return NULL; + + do { + /* XXXX This "add 1K" approach is a little goofy; if we care about + * performance here, we should be doubling. But in practice we shouldn't + * be using this function on big files anyway. */ + string_max = pos + 1024; + if (string_max > max_bytes_to_read) + string_max = max_bytes_to_read + 1; + string = tor_realloc(string, string_max); + r = read(fd, string + pos, string_max - pos - 1); + if (r < 0) { + tor_free(string); + return NULL; + } + + pos += r; + } while (r > 0 && pos < max_bytes_to_read); + + *sz_out = pos; + string[pos] = '\0'; + return string; +} + /** Read the contents of <b>filename</b> into a newly allocated * string; return the string on success or NULL on failure. * @@ -2305,6 +2355,22 @@ read_file_to_str(const char *filename, int flags, struct stat *stat_out) return NULL; } +#ifndef _WIN32 +/** When we detect that we're reading from a FIFO, don't read more than + * this many bytes. It's insane overkill for most uses. */ +#define FIFO_READ_MAX (1024*1024) + if (S_ISFIFO(statbuf.st_mode)) { + size_t sz = 0; + string = read_file_to_str_until_eof(fd, FIFO_READ_MAX, &sz); + if (string && stat_out) { + statbuf.st_size = sz; + memcpy(stat_out, &statbuf, sizeof(struct stat)); + } + close(fd); + return string; + } +#endif + if ((uint64_t)(statbuf.st_size)+1 >= SIZE_T_CEILING) return NULL; @@ -2683,9 +2749,9 @@ digit_to_num(char d) * success, store the result in <b>out</b>, advance bufp to the next * character, and return 0. On failure, return -1. */ static int -scan_unsigned(const char **bufp, unsigned *out, int width, int base) +scan_unsigned(const char **bufp, unsigned long *out, int width, int base) { - unsigned result = 0; + unsigned long result = 0; int scanned_so_far = 0; const int hex = base==16; tor_assert(base == 10 || base == 16); @@ -2697,8 +2763,8 @@ scan_unsigned(const char **bufp, unsigned *out, int width, int base) while (**bufp && (hex?TOR_ISXDIGIT(**bufp):TOR_ISDIGIT(**bufp)) && scanned_so_far < width) { int digit = hex?hex_decode_digit(*(*bufp)++):digit_to_num(*(*bufp)++); - unsigned new_result = result * base + digit; - if (new_result > UINT32_MAX || new_result < result) + unsigned long new_result = result * base + digit; + if (new_result < result) return -1; /* over/underflow. */ result = new_result; ++scanned_so_far; @@ -2711,6 +2777,89 @@ scan_unsigned(const char **bufp, unsigned *out, int width, int base) return 0; } +/** Helper: Read an signed int from *<b>bufp</b> of up to <b>width</b> + * characters. (Handle arbitrary width if <b>width</b> is less than 0.) On + * success, store the result in <b>out</b>, advance bufp to the next + * character, and return 0. On failure, return -1. */ +static int +scan_signed(const char **bufp, long *out, int width) +{ + int neg = 0; + unsigned long result = 0; + + if (!bufp || !*bufp || !out) + return -1; + if (width<0) + width=MAX_SCANF_WIDTH; + + if (**bufp == '-') { + neg = 1; + ++*bufp; + --width; + } + + if (scan_unsigned(bufp, &result, width, 10) < 0) + return -1; + + if (neg) { + if (result > ((unsigned long)LONG_MAX) + 1) + return -1; /* Underflow */ + *out = -(long)result; + } else { + if (result > LONG_MAX) + return -1; /* Overflow */ + *out = (long)result; + } + + return 0; +} + +/** Helper: Read a decimal-formatted double from *<b>bufp</b> of up to + * <b>width</b> characters. (Handle arbitrary width if <b>width</b> is less + * than 0.) On success, store the result in <b>out</b>, advance bufp to the + * next character, and return 0. On failure, return -1. */ +static int +scan_double(const char **bufp, double *out, int width) +{ + int neg = 0; + double result = 0; + int scanned_so_far = 0; + + if (!bufp || !*bufp || !out) + return -1; + if (width<0) + width=MAX_SCANF_WIDTH; + + if (**bufp == '-') { + neg = 1; + ++*bufp; + } + + while (**bufp && TOR_ISDIGIT(**bufp) && scanned_so_far < width) { + const int digit = digit_to_num(*(*bufp)++); + result = result * 10 + digit; + ++scanned_so_far; + } + if (**bufp == '.') { + double fracval = 0, denominator = 1; + ++*bufp; + ++scanned_so_far; + while (**bufp && TOR_ISDIGIT(**bufp) && scanned_so_far < width) { + const int digit = digit_to_num(*(*bufp)++); + fracval = fracval * 10 + digit; + denominator *= 10; + ++scanned_so_far; + } + result += fracval / denominator; + } + + if (!scanned_so_far) /* No actual digits scanned */ + return -1; + + *out = neg ? -result : result; + return 0; +} + /** Helper: copy up to <b>width</b> non-space characters from <b>bufp</b> to * <b>out</b>. Make sure <b>out</b> is nul-terminated. Advance <b>bufp</b> * to the next non-space character or the EOS. */ @@ -2747,6 +2896,7 @@ tor_vsscanf(const char *buf, const char *pattern, va_list ap) } } else { int width = -1; + int longmod = 0; ++pattern; if (TOR_ISDIGIT(*pattern)) { width = digit_to_num(*pattern++); @@ -2759,17 +2909,57 @@ tor_vsscanf(const char *buf, const char *pattern, va_list ap) if (!width) /* No zero-width things. */ return -1; } + if (*pattern == 'l') { + longmod = 1; + ++pattern; + } if (*pattern == 'u' || *pattern == 'x') { - unsigned *u = va_arg(ap, unsigned *); + unsigned long u; const int base = (*pattern == 'u') ? 10 : 16; if (!*buf) return n_matched; - if (scan_unsigned(&buf, u, width, base)<0) + if (scan_unsigned(&buf, &u, width, base)<0) return n_matched; + if (longmod) { + unsigned long *out = va_arg(ap, unsigned long *); + *out = u; + } else { + unsigned *out = va_arg(ap, unsigned *); + if (u > UINT_MAX) + return n_matched; + *out = (unsigned) u; + } + ++pattern; + ++n_matched; + } else if (*pattern == 'f') { + double *d = va_arg(ap, double *); + if (!longmod) + return -1; /* float not supported */ + if (!*buf) + return n_matched; + if (scan_double(&buf, d, width)<0) + return n_matched; + ++pattern; + ++n_matched; + } else if (*pattern == 'd') { + long lng=0; + if (scan_signed(&buf, &lng, width)<0) + return n_matched; + if (longmod) { + long *out = va_arg(ap, long *); + *out = lng; + } else { + int *out = va_arg(ap, int *); + if (lng < INT_MIN || lng > INT_MAX) + return n_matched; + *out = (int)lng; + } ++pattern; ++n_matched; } else if (*pattern == 's') { char *s = va_arg(ap, char *); + if (longmod) + return -1; if (width < 0) return -1; if (scan_string(&buf, s, width)<0) @@ -2778,6 +2968,8 @@ tor_vsscanf(const char *buf, const char *pattern, va_list ap) ++n_matched; } else if (*pattern == 'c') { char *ch = va_arg(ap, char *); + if (longmod) + return -1; if (width != -1) return -1; if (!*buf) @@ -2788,6 +2980,8 @@ tor_vsscanf(const char *buf, const char *pattern, va_list ap) } else if (*pattern == '%') { if (*buf != '%') return n_matched; + if (longmod) + return -1; ++buf; ++pattern; } else { @@ -2801,9 +2995,14 @@ tor_vsscanf(const char *buf, const char *pattern, va_list ap) /** Minimal sscanf replacement: parse <b>buf</b> according to <b>pattern</b> * and store the results in the corresponding argument fields. Differs from - * sscanf in that it: Only handles %u, %x, %c and %Ns. Does not handle - * arbitrarily long widths. %u and %x do not consume any space. Is - * locale-independent. Returns -1 on malformed patterns. + * sscanf in that: + * <ul><li>It only handles %u, %lu, %x, %lx, %<NUM>s, %d, %ld, %lf, and %c. + * <li>It only handles decimal inputs for %lf. (12.3, not 1.23e1) + * <li>It does not handle arbitrarily long widths. + * <li>Numbers do not consume any space characters. + * <li>It is locale-independent. + * <li>%u and %x do not consume any space. + * <li>It returns -1 on malformed patterns.</ul> * * (As with other locale-independent functions, we need this to parse data that * is in ASCII without worrying that the C library's locale-handling will make @@ -3784,10 +3983,17 @@ tor_process_handle_destroy(process_handle_t *process_handle, if (also_terminate_process) { if (tor_terminate_process(process_handle) < 0) { - log_notice(LD_GENERAL, "Failed to terminate process with PID '%d'", - tor_process_get_pid(process_handle)); + const char *errstr = +#ifdef _WIN32 + format_win32_error(GetLastError()); +#else + strerror(errno); +#endif + log_notice(LD_GENERAL, "Failed to terminate process with " + "PID '%d' ('%s').", tor_process_get_pid(process_handle), + errstr); } else { - log_info(LD_GENERAL, "Terminated process with PID '%d'", + log_info(LD_GENERAL, "Terminated process with PID '%d'.", tor_process_get_pid(process_handle)); } } @@ -4256,6 +4462,50 @@ tor_split_lines(smartlist_t *sl, char *buf, int len) } #ifdef _WIN32 + +/** Return a smartlist containing lines outputted from + * <b>handle</b>. Return NULL on error, and set + * <b>stream_status_out</b> appropriately. */ +smartlist_t * +tor_get_lines_from_handle(HANDLE *handle, + enum stream_status *stream_status_out) +{ + int pos; + char stdout_buf[600] = {0}; + smartlist_t *lines = NULL; + + tor_assert(stream_status_out); + + *stream_status_out = IO_STREAM_TERM; + + pos = tor_read_all_handle(handle, stdout_buf, sizeof(stdout_buf) - 1, NULL); + if (pos < 0) { + *stream_status_out = IO_STREAM_TERM; + return NULL; + } + if (pos == 0) { + *stream_status_out = IO_STREAM_EAGAIN; + return NULL; + } + + /* End with a null even if there isn't a \r\n at the end */ + /* TODO: What if this is a partial line? */ + stdout_buf[pos] = '\0'; + + /* Split up the buffer */ + lines = smartlist_new(); + tor_split_lines(lines, stdout_buf, pos); + + /* Currently 'lines' is populated with strings residing on the + stack. Replace them with their exact copies on the heap: */ + SMARTLIST_FOREACH(lines, char *, line, + SMARTLIST_REPLACE_CURRENT(lines, line, tor_strdup(line))); + + *stream_status_out = IO_STREAM_OKAY; + + return lines; +} + /** Read from stream, and send lines to log at the specified log level. * Returns -1 if there is a error reading, and 0 otherwise. * If the generated stream is flushed more often than on new lines, or @@ -4303,6 +4553,33 @@ log_from_handle(HANDLE *pipe, int severity) #else +/** Return a smartlist containing lines outputted from + * <b>handle</b>. Return NULL on error, and set + * <b>stream_status_out</b> appropriately. */ +smartlist_t * +tor_get_lines_from_handle(FILE *handle, enum stream_status *stream_status_out) +{ + enum stream_status stream_status; + char stdout_buf[400]; + smartlist_t *lines = NULL; + + while (1) { + memset(stdout_buf, 0, sizeof(stdout_buf)); + + stream_status = get_string_from_pipe(handle, + stdout_buf, sizeof(stdout_buf) - 1); + if (stream_status != IO_STREAM_OKAY) + goto done; + + if (!lines) lines = smartlist_new(); + smartlist_add(lines, tor_strdup(stdout_buf)); + } + + done: + *stream_status_out = stream_status; + return lines; +} + /** Read from stream, and send lines to log at the specified log level. * Returns 1 if stream is closed normally, -1 if there is a error reading, and * 0 otherwise. Handles lines from tor-fw-helper and @@ -4421,9 +4698,130 @@ get_string_from_pipe(FILE *stream, char *buf_out, size_t count) return IO_STREAM_TERM; } -/* DOCDOC tor_check_port_forwarding */ +/** Parse a <b>line</b> from tor-fw-helper and issue an appropriate + * log message to our user. */ +static void +handle_fw_helper_line(const char *line) +{ + smartlist_t *tokens = smartlist_new(); + char *message = NULL; + char *message_for_log = NULL; + const char *external_port = NULL; + const char *internal_port = NULL; + const char *result = NULL; + int port = 0; + int success = 0; + + smartlist_split_string(tokens, line, NULL, + SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, -1); + + if (smartlist_len(tokens) < 5) + goto err; + + if (strcmp(smartlist_get(tokens, 0), "tor-fw-helper") || + strcmp(smartlist_get(tokens, 1), "tcp-forward")) + goto err; + + external_port = smartlist_get(tokens, 2); + internal_port = smartlist_get(tokens, 3); + result = smartlist_get(tokens, 4); + + if (smartlist_len(tokens) > 5) { + /* If there are more than 5 tokens, they are part of [<message>]. + Let's use a second smartlist to form the whole message; + strncat loops suck. */ + int i; + int message_words_n = smartlist_len(tokens) - 5; + smartlist_t *message_sl = smartlist_new(); + for (i = 0; i < message_words_n; i++) + smartlist_add(message_sl, smartlist_get(tokens, 5+i)); + + tor_assert(smartlist_len(message_sl) > 0); + message = smartlist_join_strings(message_sl, " ", 0, NULL); + + /* wrap the message in log-friendly wrapping */ + tor_asprintf(&message_for_log, " ('%s')", message); + + smartlist_free(message_sl); + } + + port = atoi(external_port); + if (port < 1 || port > 65535) + goto err; + + port = atoi(internal_port); + if (port < 1 || port > 65535) + goto err; + + if (!strcmp(result, "SUCCESS")) + success = 1; + else if (!strcmp(result, "FAIL")) + success = 0; + else + goto err; + + if (!success) { + log_warn(LD_GENERAL, "Tor was unable to forward TCP port '%s' to '%s'%s. " + "Please make sure that your router supports port " + "forwarding protocols (like NAT-PMP). Note that if '%s' is " + "your ORPort, your relay will be unable to receive inbound " + "traffic.", external_port, internal_port, + message_for_log ? message_for_log : "", + internal_port); + } else { + log_info(LD_GENERAL, + "Tor successfully forwarded TCP port '%s' to '%s'%s.", + external_port, internal_port, + message_for_log ? message_for_log : ""); + } + + goto done; + + err: + log_warn(LD_GENERAL, "tor-fw-helper sent us a string we could not " + "parse (%s).", line); + + done: + SMARTLIST_FOREACH(tokens, char *, cp, tor_free(cp)); + smartlist_free(tokens); + tor_free(message); + tor_free(message_for_log); +} + +/** Read what tor-fw-helper has to say in its stdout and handle it + * appropriately */ +static int +handle_fw_helper_output(process_handle_t *process_handle) +{ + smartlist_t *fw_helper_output = NULL; + enum stream_status stream_status = 0; + + fw_helper_output = + tor_get_lines_from_handle(tor_process_get_stdout_pipe(process_handle), + &stream_status); + if (!fw_helper_output) { /* didn't get any output from tor-fw-helper */ + /* if EAGAIN we should retry in the future */ + return (stream_status == IO_STREAM_EAGAIN) ? 0 : -1; + } + + /* Handle the lines we got: */ + SMARTLIST_FOREACH_BEGIN(fw_helper_output, char *, line) { + handle_fw_helper_line(line); + tor_free(line); + } SMARTLIST_FOREACH_END(line); + + smartlist_free(fw_helper_output); + + return 0; +} + +/** Spawn tor-fw-helper and ask it to forward the ports in + * <b>ports_to_forward</b>. <b>ports_to_forward</b> contains strings + * of the form "<external port>:<internal port>", which is the format + * that tor-fw-helper expects. */ void -tor_check_port_forwarding(const char *filename, int dir_port, int or_port, +tor_check_port_forwarding(const char *filename, + smartlist_t *ports_to_forward, time_t now) { /* When fw-helper succeeds, how long do we wait until running it again */ @@ -4437,32 +4835,51 @@ tor_check_port_forwarding(const char *filename, int dir_port, int or_port, static process_handle_t *child_handle=NULL; static time_t time_to_run_helper = 0; - int stdout_status, stderr_status, retval; - const char *argv[10]; - char s_dirport[6], s_orport[6]; + int stderr_status, retval; + int stdout_status = 0; tor_assert(filename); - /* Set up command line for tor-fw-helper */ - snprintf(s_dirport, sizeof s_dirport, "%d", dir_port); - snprintf(s_orport, sizeof s_orport, "%d", or_port); - - /* TODO: Allow different internal and external ports */ - argv[0] = filename; - argv[1] = "--internal-or-port"; - argv[2] = s_orport; - argv[3] = "--external-or-port"; - argv[4] = s_orport; - argv[5] = "--internal-dir-port"; - argv[6] = s_dirport; - argv[7] = "--external-dir-port"; - argv[8] = s_dirport; - argv[9] = NULL; - /* Start the child, if it is not already running */ if ((!child_handle || child_handle->status != PROCESS_STATUS_RUNNING) && time_to_run_helper < now) { - int status; + /*tor-fw-helper cli looks like this: tor_fw_helper -p :5555 -p 4555:1111 */ + const char **argv; /* cli arguments */ + int args_n, status; + int argv_index = 0; /* index inside 'argv' */ + + tor_assert(smartlist_len(ports_to_forward) > 0); + + /* check for overflow during 'argv' allocation: + (len(ports_to_forward)*2 + 2)*sizeof(char*) > SIZE_MAX == + len(ports_to_forward) > (((SIZE_MAX/sizeof(char*)) - 2)/2) */ + if ((size_t) smartlist_len(ports_to_forward) > + (((SIZE_MAX/sizeof(char*)) - 2)/2)) { + log_warn(LD_GENERAL, + "Overflow during argv allocation. This shouldn't happen."); + return; + } + /* check for overflow during 'argv_index' increase: + ((len(ports_to_forward)*2 + 2) > INT_MAX) == + len(ports_to_forward) > (INT_MAX - 2)/2 */ + if (smartlist_len(ports_to_forward) > (INT_MAX - 2)/2) { + log_warn(LD_GENERAL, + "Overflow during argv_index increase. This shouldn't happen."); + return; + } + + /* Calculate number of cli arguments: one for the filename, two + for each smartlist element (one for "-p" and one for the + ports), and one for the final NULL. */ + args_n = 1 + 2*smartlist_len(ports_to_forward) + 1; + argv = tor_malloc_zero(sizeof(char*)*args_n); + + argv[argv_index++] = filename; + SMARTLIST_FOREACH_BEGIN(ports_to_forward, const char *, port) { + argv[argv_index++] = "-p"; + argv[argv_index++] = port; + } SMARTLIST_FOREACH_END(port); + argv[argv_index] = NULL; /* Assume tor-fw-helper will succeed, start it later*/ time_to_run_helper = now + TIME_TO_EXEC_FWHELPER_SUCCESS; @@ -4479,6 +4896,8 @@ tor_check_port_forwarding(const char *filename, int dir_port, int or_port, status = tor_spawn_background(filename, argv, NULL, &child_handle); #endif + tor_free(argv); + if (PROCESS_STATUS_ERROR == status) { log_warn(LD_GENERAL, "Failed to start port forwarding helper %s", filename); @@ -4496,16 +4915,17 @@ tor_check_port_forwarding(const char *filename, int dir_port, int or_port, /* Read from stdout/stderr and log result */ retval = 0; #ifdef _WIN32 - stdout_status = log_from_handle(child_handle->stdout_pipe, LOG_INFO); - stderr_status = log_from_handle(child_handle->stderr_pipe, LOG_WARN); - /* If we got this far (on Windows), the process started */ - retval = 0; + stderr_status = log_from_handle(child_handle->stderr_pipe, LOG_INFO); #else - stdout_status = log_from_pipe(child_handle->stdout_handle, - LOG_INFO, filename, &retval); stderr_status = log_from_pipe(child_handle->stderr_handle, - LOG_WARN, filename, &retval); + LOG_INFO, filename, &retval); #endif + if (handle_fw_helper_output(child_handle) < 0) { + log_warn(LD_GENERAL, "Failed to handle fw helper output."); + stdout_status = -1; + retval = -1; + } + if (retval) { /* There was a problem in the child process */ time_to_run_helper = now + TIME_TO_EXEC_FWHELPER_FAIL; diff --git a/src/common/util.h b/src/common/util.h index 8977d273c5..aa2087b013 100644 --- a/src/common/util.h +++ b/src/common/util.h @@ -8,8 +8,8 @@ * \brief Headers for util.c **/ -#ifndef _TOR_UTIL_H -#define _TOR_UTIL_H +#ifndef TOR_UTIL_H +#define TOR_UTIL_H #include "orconfig.h" #include "torint.h" @@ -49,9 +49,9 @@ #define tor_assert(expr) STMT_BEGIN \ if (PREDICT_UNLIKELY(!(expr))) { \ log_err(LD_BUG, "%s:%d: %s: Assertion %s failed; aborting.", \ - _SHORT_FILE_, __LINE__, __func__, #expr); \ + SHORT_FILE__, __LINE__, __func__, #expr); \ fprintf(stderr,"%s:%d %s: Assertion %s failed; aborting.\n", \ - _SHORT_FILE_, __LINE__, __func__, #expr); \ + SHORT_FILE__, __LINE__, __func__, #expr); \ abort(); \ } STMT_END @@ -62,7 +62,7 @@ * to calls. */ #ifdef USE_DMALLOC #define DMALLOC_PARAMS , const char *file, const int line -#define DMALLOC_ARGS , _SHORT_FILE_, __LINE__ +#define DMALLOC_ARGS , SHORT_FILE__, __LINE__ #else #define DMALLOC_PARAMS #define DMALLOC_ARGS @@ -74,23 +74,22 @@ #define tor_fragile_assert() /* Memory management */ -void *_tor_malloc(size_t size DMALLOC_PARAMS) ATTR_MALLOC; -void *_tor_malloc_zero(size_t size DMALLOC_PARAMS) ATTR_MALLOC; -void *_tor_malloc_roundup(size_t *size DMALLOC_PARAMS) ATTR_MALLOC; -void *_tor_calloc(size_t nmemb, size_t size DMALLOC_PARAMS) ATTR_MALLOC; -void *_tor_realloc(void *ptr, size_t size DMALLOC_PARAMS); -char *_tor_strdup(const char *s DMALLOC_PARAMS) ATTR_MALLOC ATTR_NONNULL((1)); -char *_tor_strndup(const char *s, size_t n DMALLOC_PARAMS) +void *tor_malloc_(size_t size DMALLOC_PARAMS) ATTR_MALLOC; +void *tor_malloc_zero_(size_t size DMALLOC_PARAMS) ATTR_MALLOC; +void *tor_calloc_(size_t nmemb, size_t size DMALLOC_PARAMS) ATTR_MALLOC; +void *tor_realloc_(void *ptr, size_t size DMALLOC_PARAMS); +char *tor_strdup_(const char *s DMALLOC_PARAMS) ATTR_MALLOC ATTR_NONNULL((1)); +char *tor_strndup_(const char *s, size_t n DMALLOC_PARAMS) ATTR_MALLOC ATTR_NONNULL((1)); -void *_tor_memdup(const void *mem, size_t len DMALLOC_PARAMS) +void *tor_memdup_(const void *mem, size_t len DMALLOC_PARAMS) ATTR_MALLOC ATTR_NONNULL((1)); -void _tor_free(void *mem); +void tor_free_(void *mem); #ifdef USE_DMALLOC extern int dmalloc_free(const char *file, const int line, void *pnt, const int func_id); #define tor_free(p) STMT_BEGIN \ if (PREDICT_LIKELY((p)!=NULL)) { \ - dmalloc_free(_SHORT_FILE_, __LINE__, (p), 0); \ + dmalloc_free(SHORT_FILE__, __LINE__, (p), 0); \ (p)=NULL; \ } \ STMT_END @@ -100,7 +99,7 @@ extern int dmalloc_free(const char *file, const int line, void *pnt, * and it sets the pointer value to NULL after freeing it. * * This is a macro. If you need a function pointer to release memory from - * tor_malloc(), use _tor_free(). + * tor_malloc(), use tor_free_(). */ #define tor_free(p) STMT_BEGIN \ if (PREDICT_LIKELY((p)!=NULL)) { \ @@ -110,14 +109,14 @@ extern int dmalloc_free(const char *file, const int line, void *pnt, STMT_END #endif -#define tor_malloc(size) _tor_malloc(size DMALLOC_ARGS) -#define tor_malloc_zero(size) _tor_malloc_zero(size DMALLOC_ARGS) -#define tor_calloc(nmemb,size) _tor_calloc(nmemb, size DMALLOC_ARGS) +#define tor_malloc(size) tor_malloc_(size DMALLOC_ARGS) +#define tor_malloc_zero(size) tor_malloc_zero_(size DMALLOC_ARGS) +#define tor_calloc(nmemb,size) tor_calloc_(nmemb, size DMALLOC_ARGS) #define tor_malloc_roundup(szp) _tor_malloc_roundup(szp DMALLOC_ARGS) -#define tor_realloc(ptr, size) _tor_realloc(ptr, size DMALLOC_ARGS) -#define tor_strdup(s) _tor_strdup(s DMALLOC_ARGS) -#define tor_strndup(s, n) _tor_strndup(s, n DMALLOC_ARGS) -#define tor_memdup(s, n) _tor_memdup(s, n DMALLOC_ARGS) +#define tor_realloc(ptr, size) tor_realloc_(ptr, size DMALLOC_ARGS) +#define tor_strdup(s) tor_strdup_(s DMALLOC_ARGS) +#define tor_strndup(s, n) tor_strndup_(s, n DMALLOC_ARGS) +#define tor_memdup(s, n) tor_memdup_(s, n DMALLOC_ARGS) void tor_log_mallinfo(int severity); @@ -161,6 +160,7 @@ void tor_log_mallinfo(int severity); /* Math functions */ double tor_mathlog(double d) ATTR_CONST; long tor_lround(double d) ATTR_CONST; +int64_t tor_llround(double d) ATTR_CONST; int tor_log2(uint64_t u64) ATTR_CONST; uint64_t round_to_power_of_2(uint64_t u64); unsigned round_to_next_multiple_of(unsigned number, unsigned divisor); @@ -188,6 +188,7 @@ int strcasecmpstart(const char *s1, const char *s2) ATTR_NONNULL((1,2)); int strcmpend(const char *s1, const char *s2) ATTR_NONNULL((1,2)); int strcasecmpend(const char *s1, const char *s2) ATTR_NONNULL((1,2)); int fast_memcmpstart(const void *mem, size_t memlen, const char *prefix); +void tor_strclear(char *s); void tor_strstrip(char *s, const char *strip) ATTR_NONNULL((1,2)); long tor_parse_long(const char *s, int base, long min, @@ -360,6 +361,9 @@ struct stat; #endif char *read_file_to_str(const char *filename, int flags, struct stat *stat_out) ATTR_MALLOC; +char *read_file_to_str_until_eof(int fd, size_t max_bytes_to_read, + size_t *sz_out) + ATTR_MALLOC; const char *parse_config_line_from_str(const char *line, char **key_out, char **value_out); char *expand_filename(const char *filename); @@ -373,7 +377,8 @@ void write_pidfile(char *filename); /* Port forwarding */ void tor_check_port_forwarding(const char *filename, - int dir_port, int or_port, time_t now); + struct smartlist_t *ports_to_forward, + time_t now); typedef struct process_handle_t process_handle_t; typedef struct process_environment_t process_environment_t; @@ -464,6 +469,16 @@ HANDLE tor_process_get_stdout_pipe(process_handle_t *process_handle); FILE *tor_process_get_stdout_pipe(process_handle_t *process_handle); #endif +#ifdef _WIN32 +struct smartlist_t * +tor_get_lines_from_handle(HANDLE *handle, + enum stream_status *stream_status); +#else +struct smartlist_t * +tor_get_lines_from_handle(FILE *handle, + enum stream_status *stream_status); +#endif + int tor_terminate_process(process_handle_t *process_handle); void tor_process_handle_destroy(process_handle_t *process_handle, int also_terminate_process); |