aboutsummaryrefslogtreecommitdiff
path: root/src/common
diff options
context:
space:
mode:
Diffstat (limited to 'src/common')
-rw-r--r--src/common/Makefile.nmake28
-rw-r--r--src/common/address.c2176
-rw-r--r--src/common/address.h379
-rw-r--r--src/common/address_set.c129
-rw-r--r--src/common/address_set.h35
-rw-r--r--src/common/aes.c410
-rw-r--r--src/common/aes.h29
-rw-r--r--src/common/backtrace.c248
-rw-r--r--src/common/backtrace.h21
-rw-r--r--src/common/buffers.c1146
-rw-r--r--src/common/buffers.h131
-rw-r--r--src/common/buffers_tls.c179
-rw-r--r--src/common/buffers_tls.h19
-rw-r--r--src/common/ciphers.inc100
-rw-r--r--src/common/compat.c3531
-rw-r--r--src/common/compat.h757
-rw-r--r--src/common/compat_libevent.c536
-rw-r--r--src/common/compat_libevent.h98
-rw-r--r--src/common/compat_openssl.h51
-rw-r--r--src/common/compat_pthreads.c350
-rw-r--r--src/common/compat_threads.c406
-rw-r--r--src/common/compat_threads.h226
-rw-r--r--src/common/compat_time.c913
-rw-r--r--src/common/compat_time.h234
-rw-r--r--src/common/compat_winthreads.c251
-rw-r--r--src/common/compress.c675
-rw-r--r--src/common/compress.h93
-rw-r--r--src/common/compress_lzma.c361
-rw-r--r--src/common/compress_lzma.h46
-rw-r--r--src/common/compress_none.c53
-rw-r--r--src/common/compress_none.h20
-rw-r--r--src/common/compress_zlib.c304
-rw-r--r--src/common/compress_zlib.h46
-rw-r--r--src/common/compress_zstd.c540
-rw-r--r--src/common/compress_zstd.h53
-rw-r--r--src/common/confline.c538
-rw-r--r--src/common/confline.h61
-rw-r--r--src/common/container.c1542
-rw-r--r--src/common/container.h742
-rw-r--r--src/common/crypto.c1118
-rw-r--r--src/common/crypto.h114
-rw-r--r--src/common/crypto_curve25519.c359
-rw-r--r--src/common/crypto_curve25519.h89
-rw-r--r--src/common/crypto_digest.c583
-rw-r--r--src/common/crypto_digest.h136
-rw-r--r--src/common/crypto_ed25519.c817
-rw-r--r--src/common/crypto_ed25519.h145
-rw-r--r--src/common/crypto_format.c299
-rw-r--r--src/common/crypto_format.h47
-rw-r--r--src/common/crypto_openssl_mgt.c161
-rw-r--r--src/common/crypto_openssl_mgt.h85
-rw-r--r--src/common/crypto_pwbox.c215
-rw-r--r--src/common/crypto_pwbox.h23
-rw-r--r--src/common/crypto_rand.c615
-rw-r--r--src/common/crypto_rand.h52
-rw-r--r--src/common/crypto_rsa.c1183
-rw-r--r--src/common/crypto_rsa.h119
-rw-r--r--src/common/crypto_s2k.c475
-rw-r--r--src/common/crypto_s2k.h73
-rw-r--r--src/common/crypto_util.c107
-rw-r--r--src/common/crypto_util.h27
-rw-r--r--src/common/di_ops.c274
-rw-r--r--src/common/di_ops.h55
-rw-r--r--src/common/handles.h153
-rw-r--r--src/common/include.am213
-rw-r--r--src/common/linux_syscalls.inc1153
-rw-r--r--src/common/log.c1539
-rw-r--r--src/common/memarea.c398
-rw-r--r--src/common/memarea.h29
-rw-r--r--src/common/procmon.c332
-rw-r--r--src/common/procmon.h35
-rw-r--r--src/common/pubsub.c129
-rw-r--r--src/common/pubsub.h179
-rw-r--r--src/common/sandbox.c1977
-rw-r--r--src/common/sandbox.h174
-rw-r--r--src/common/storagedir.c586
-rw-r--r--src/common/storagedir.h54
-rw-r--r--src/common/testsupport.h90
-rw-r--r--src/common/timers.c318
-rw-r--r--src/common/timers.h31
-rw-r--r--src/common/token_bucket.c255
-rw-r--r--src/common/token_bucket.h118
-rw-r--r--src/common/torint.h379
-rw-r--r--src/common/torlog.h275
-rw-r--r--src/common/tortls.c2670
-rw-r--r--src/common/tortls.h295
-rw-r--r--src/common/util.c5378
-rw-r--r--src/common/util.h572
-rw-r--r--src/common/util_bug.c119
-rw-r--r--src/common/util_bug.h238
-rw-r--r--src/common/util_format.c535
-rw-r--r--src/common/util_format.h52
-rw-r--r--src/common/util_process.c158
-rw-r--r--src/common/util_process.h26
-rw-r--r--src/common/workqueue.c678
-rw-r--r--src/common/workqueue.h66
96 files changed, 0 insertions, 43832 deletions
diff --git a/src/common/Makefile.nmake b/src/common/Makefile.nmake
deleted file mode 100644
index a1c819fffa..0000000000
--- a/src/common/Makefile.nmake
+++ /dev/null
@@ -1,28 +0,0 @@
-all: libor.lib libor-crypto.lib libor-event.lib
-
-CFLAGS = /O2 /MT /I ..\win32 /I ..\..\..\build-alpha\include /I ..\common \
- /I ..\ext
-
-LIBOR_OBJECTS = address.obj backtrace.obj compat.obj container.obj di_ops.obj \
- log.obj memarea.obj mempool.obj procmon.obj sandbox.obj util.obj \
- util_codedigest.obj
-
-LIBOR_CRYPTO_OBJECTS = aes.obj crypto.obj crypto_format.obj compress.obj compress_zlib.obj \
- tortls.obj crypto_curve25519.obj curve25519-donna.obj
-
-LIBOR_EVENT_OBJECTS = compat_libevent.obj
-
-curve25519-donna.obj: ..\ext\curve25519_donna\curve25519-donna.c
- $(CC) $(CFLAGS) /D inline=_inline /c ..\ext\curve25519_donna\curve25519-donna.c
-
-libor.lib: $(LIBOR_OBJECTS)
- lib $(LIBOR_OBJECTS) /out:libor.lib
-
-libor-crypto.lib: $(LIBOR_CRYPTO_OBJECTS)
- lib $(LIBOR_CRYPTO_OBJECTS) /out:libor-crypto.lib
-
-libor-event.lib: $(LIBOR_EVENT_OBJECTS)
- lib $(LIBOR_EVENT_OBJECTS) /out:libor-event.lib
-
-clean:
- del *.obj *.lib libor*.lib
diff --git a/src/common/address.c b/src/common/address.c
deleted file mode 100644
index 9446675712..0000000000
--- a/src/common/address.c
+++ /dev/null
@@ -1,2176 +0,0 @@
-/* Copyright (c) 2003-2004, Roger Dingledine
- * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2017, The Tor Project, Inc. */
-/* See LICENSE for licensing information */
-
-/**
- * \file address.c
- * \brief Functions to use and manipulate the tor_addr_t structure.
- **/
-
-#define ADDRESS_PRIVATE
-
-#include "orconfig.h"
-
-#ifdef _WIN32
-/* For access to structs needed by GetAdaptersAddresses */
-#ifndef WIN32_LEAN_AND_MEAN
-#error "orconfig.h didn't define WIN32_LEAN_AND_MEAN"
-#endif
-#ifndef WINVER
-#error "orconfig.h didn't define WINVER"
-#endif
-#ifndef _WIN32_WINNT
-#error "orconfig.h didn't define _WIN32_WINNT"
-#endif
-#if WINVER < 0x0501
-#error "winver too low"
-#endif
-#if _WIN32_WINNT < 0x0501
-#error "winver too low"
-#endif
-#include <winsock2.h>
-#include <process.h>
-#include <windows.h>
-#include <iphlpapi.h>
-#endif /* defined(_WIN32) */
-
-#include "compat.h"
-#include "util.h"
-#include "util_format.h"
-#include "address.h"
-#include "torlog.h"
-#include "container.h"
-#include "sandbox.h"
-
-#ifdef HAVE_SYS_TIME_H
-#include <sys/time.h>
-#endif
-#ifdef HAVE_UNISTD_H
-#include <unistd.h>
-#endif
-#ifdef HAVE_ERRNO_H
-#include <errno.h>
-#endif
-#ifdef HAVE_NETINET_IN_H
-#include <netinet/in.h>
-#endif
-#ifdef HAVE_ARPA_INET_H
-#include <arpa/inet.h>
-#endif
-#ifdef HAVE_SYS_SOCKET_H
-#include <sys/socket.h>
-#endif
-#ifdef HAVE_NETDB_H
-#include <netdb.h>
-#endif
-#ifdef HAVE_SYS_PARAM_H
-#include <sys/param.h> /* FreeBSD needs this to know what version it is */
-#endif
-#ifdef HAVE_SYS_UN_H
-#include <sys/un.h>
-#endif
-#ifdef HAVE_IFADDRS_H
-#include <ifaddrs.h>
-#endif
-#ifdef HAVE_SYS_IOCTL_H
-#include <sys/ioctl.h>
-#endif
-#ifdef HAVE_NET_IF_H
-#include <net/if.h>
-#endif
-#include <stdarg.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <assert.h>
-
-/* tor_addr_is_null() and maybe other functions rely on AF_UNSPEC being 0 to
- * work correctly. Bail out here if we've found a platform where AF_UNSPEC
- * isn't 0. */
-#if AF_UNSPEC != 0
-#error We rely on AF_UNSPEC being 0. Let us know about your platform, please!
-#endif
-
-/** Convert the tor_addr_t in <b>a</b>, with port in <b>port</b>, into a
- * sockaddr object in *<b>sa_out</b> of object size <b>len</b>. If not enough
- * room is available in sa_out, or on error, return 0. On success, return
- * the length of the sockaddr.
- *
- * Interface note: ordinarily, we return -1 for error. We can't do that here,
- * since socklen_t is unsigned on some platforms.
- **/
-socklen_t
-tor_addr_to_sockaddr(const tor_addr_t *a,
- uint16_t port,
- struct sockaddr *sa_out,
- socklen_t len)
-{
- memset(sa_out, 0, len);
-
- sa_family_t family = tor_addr_family(a);
- if (family == AF_INET) {
- struct sockaddr_in *sin;
- if (len < (int)sizeof(struct sockaddr_in))
- return 0;
- sin = (struct sockaddr_in *)sa_out;
-#ifdef HAVE_STRUCT_SOCKADDR_IN_SIN_LEN
- sin->sin_len = sizeof(struct sockaddr_in);
-#endif
- sin->sin_family = AF_INET;
- sin->sin_port = htons(port);
- sin->sin_addr.s_addr = tor_addr_to_ipv4n(a);
- return sizeof(struct sockaddr_in);
- } else if (family == AF_INET6) {
- struct sockaddr_in6 *sin6;
- if (len < (int)sizeof(struct sockaddr_in6))
- return 0;
- sin6 = (struct sockaddr_in6 *)sa_out;
-#ifdef HAVE_STRUCT_SOCKADDR_IN6_SIN6_LEN
- sin6->sin6_len = sizeof(struct sockaddr_in6);
-#endif
- sin6->sin6_family = AF_INET6;
- sin6->sin6_port = htons(port);
- memcpy(&sin6->sin6_addr, tor_addr_to_in6_assert(a),
- sizeof(struct in6_addr));
- return sizeof(struct sockaddr_in6);
- } else {
- return 0;
- }
-}
-
-/** Set address <b>a</b> to zero. This address belongs to
- * the AF_UNIX family. */
-static void
-tor_addr_make_af_unix(tor_addr_t *a)
-{
- memset(a, 0, sizeof(*a));
- a->family = AF_UNIX;
-}
-
-/** Set the tor_addr_t in <b>a</b> to contain the socket address contained in
- * <b>sa</b>. IF <b>port_out</b> is non-NULL and <b>sa</b> contains a port,
- * set *<b>port_out</b> to that port. Return 0 on success and -1 on
- * failure. */
-int
-tor_addr_from_sockaddr(tor_addr_t *a, const struct sockaddr *sa,
- uint16_t *port_out)
-{
- tor_assert(a);
- tor_assert(sa);
-
- /* This memset is redundant; leaving it in to avoid any future accidents,
- however. */
- memset(a, 0, sizeof(*a));
-
- if (sa->sa_family == AF_INET) {
- struct sockaddr_in *sin = (struct sockaddr_in *) sa;
- tor_addr_from_ipv4n(a, sin->sin_addr.s_addr);
- if (port_out)
- *port_out = ntohs(sin->sin_port);
- } else if (sa->sa_family == AF_INET6) {
- struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *) sa;
- tor_addr_from_in6(a, &sin6->sin6_addr);
- if (port_out)
- *port_out = ntohs(sin6->sin6_port);
- } else if (sa->sa_family == AF_UNIX) {
- tor_addr_make_af_unix(a);
- return 0;
- } else {
- tor_addr_make_unspec(a);
- return -1;
- }
- return 0;
-}
-
-/** Return a newly allocated string holding the address described in
- * <b>sa</b>. AF_UNIX, AF_UNSPEC, AF_INET, and AF_INET6 are supported. */
-char *
-tor_sockaddr_to_str(const struct sockaddr *sa)
-{
- char address[TOR_ADDR_BUF_LEN];
- char *result;
- tor_addr_t addr;
- uint16_t port;
-#ifdef HAVE_SYS_UN_H
- if (sa->sa_family == AF_UNIX) {
- struct sockaddr_un *s_un = (struct sockaddr_un *)sa;
- tor_asprintf(&result, "unix:%s", s_un->sun_path);
- return result;
- }
-#endif /* defined(HAVE_SYS_UN_H) */
- if (sa->sa_family == AF_UNSPEC)
- return tor_strdup("unspec");
-
- if (tor_addr_from_sockaddr(&addr, sa, &port) < 0)
- return NULL;
- if (! tor_addr_to_str(address, &addr, sizeof(address), 1))
- return NULL;
- tor_asprintf(&result, "%s:%d", address, (int)port);
- return result;
-}
-
-/** Set address <b>a</b> to the unspecified address. This address belongs to
- * no family. */
-void
-tor_addr_make_unspec(tor_addr_t *a)
-{
- memset(a, 0, sizeof(*a));
- a->family = AF_UNSPEC;
-}
-
-/** Set address <b>a</b> to the null address in address family <b>family</b>.
- * The null address for AF_INET is 0.0.0.0. The null address for AF_INET6 is
- * [::]. AF_UNSPEC is all null. */
-void
-tor_addr_make_null(tor_addr_t *a, sa_family_t family)
-{
- memset(a, 0, sizeof(*a));
- a->family = family;
-}
-
-/** Similar behavior to Unix gethostbyname: resolve <b>name</b>, and set
- * *<b>addr</b> to the proper IP address and family. The <b>family</b>
- * argument (which must be AF_INET, AF_INET6, or AF_UNSPEC) declares a
- * <i>preferred</i> family, though another one may be returned if only one
- * family is implemented for this address.
- *
- * Return 0 on success, -1 on failure; 1 on transient failure.
- */
-MOCK_IMPL(int,
-tor_addr_lookup,(const char *name, uint16_t family, tor_addr_t *addr))
-{
- /* Perhaps eventually this should be replaced by a tor_getaddrinfo or
- * something.
- */
- struct in_addr iaddr;
- struct in6_addr iaddr6;
- tor_assert(name);
- tor_assert(addr);
- tor_assert(family == AF_INET || family == AF_INET6 || family == AF_UNSPEC);
- if (!*name) {
- /* Empty address is an error. */
- return -1;
- } else if (tor_inet_pton(AF_INET, name, &iaddr)) {
- /* It's an IPv4 IP. */
- if (family == AF_INET6)
- return -1;
- tor_addr_from_in(addr, &iaddr);
- return 0;
- } else if (tor_inet_pton(AF_INET6, name, &iaddr6)) {
- if (family == AF_INET)
- return -1;
- tor_addr_from_in6(addr, &iaddr6);
- return 0;
- } else {
-#ifdef HAVE_GETADDRINFO
- int err;
- struct addrinfo *res=NULL, *res_p;
- struct addrinfo *best=NULL;
- struct addrinfo hints;
- int result = -1;
- memset(&hints, 0, sizeof(hints));
- hints.ai_family = family;
- hints.ai_socktype = SOCK_STREAM;
- err = sandbox_getaddrinfo(name, NULL, &hints, &res);
- /* The check for 'res' here shouldn't be necessary, but it makes static
- * analysis tools happy. */
- if (!err && res) {
- best = NULL;
- for (res_p = res; res_p; res_p = res_p->ai_next) {
- if (family == AF_UNSPEC) {
- if (res_p->ai_family == AF_INET) {
- best = res_p;
- break;
- } else if (res_p->ai_family == AF_INET6 && !best) {
- best = res_p;
- }
- } else if (family == res_p->ai_family) {
- best = res_p;
- break;
- }
- }
- if (!best)
- best = res;
- if (best->ai_family == AF_INET) {
- tor_addr_from_in(addr,
- &((struct sockaddr_in*)best->ai_addr)->sin_addr);
- result = 0;
- } else if (best->ai_family == AF_INET6) {
- tor_addr_from_in6(addr,
- &((struct sockaddr_in6*)best->ai_addr)->sin6_addr);
- result = 0;
- }
- sandbox_freeaddrinfo(res);
- return result;
- }
- return (err == EAI_AGAIN) ? 1 : -1;
-#else /* !(defined(HAVE_GETADDRINFO)) */
- struct hostent *ent;
- int err;
-#ifdef HAVE_GETHOSTBYNAME_R_6_ARG
- char buf[2048];
- struct hostent hostent;
- int r;
- r = gethostbyname_r(name, &hostent, buf, sizeof(buf), &ent, &err);
-#elif defined(HAVE_GETHOSTBYNAME_R_5_ARG)
- char buf[2048];
- struct hostent hostent;
- ent = gethostbyname_r(name, &hostent, buf, sizeof(buf), &err);
-#elif defined(HAVE_GETHOSTBYNAME_R_3_ARG)
- struct hostent_data data;
- struct hostent hent;
- memset(&data, 0, sizeof(data));
- err = gethostbyname_r(name, &hent, &data);
- ent = err ? NULL : &hent;
-#else
- ent = gethostbyname(name);
-#ifdef _WIN32
- err = WSAGetLastError();
-#else
- err = h_errno;
-#endif
-#endif /* defined(HAVE_GETHOSTBYNAME_R_6_ARG) || ... */
- if (ent) {
- if (ent->h_addrtype == AF_INET) {
- tor_addr_from_in(addr, (struct in_addr*) ent->h_addr);
- } else if (ent->h_addrtype == AF_INET6) {
- tor_addr_from_in6(addr, (struct in6_addr*) ent->h_addr);
- } else {
- tor_assert(0); // LCOV_EXCL_LINE: gethostbyname() returned bizarre type
- }
- return 0;
- }
-#ifdef _WIN32
- return (err == WSATRY_AGAIN) ? 1 : -1;
-#else
- return (err == TRY_AGAIN) ? 1 : -1;
-#endif
-#endif /* defined(HAVE_GETADDRINFO) */
- }
-}
-
-/** Return true iff <b>ip</b> is an IP reserved to localhost or local networks
- * in RFC1918 or RFC4193 or RFC4291. (fec0::/10, deprecated by RFC3879, is
- * also treated as internal for now.)
- */
-int
-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];
-
- tor_assert(addr);
- sa_family_t v_family = tor_addr_family(addr);
-
- if (v_family == AF_INET) {
- iph4 = tor_addr_to_ipv4h(addr);
- } else if (v_family == AF_INET6) {
- if (tor_addr_is_v4(addr)) { /* v4-mapped */
- uint32_t *addr32 = NULL;
- v_family = AF_INET;
- // Work around an incorrect NULL pointer dereference warning in
- // "clang --analyze" due to limited analysis depth
- addr32 = tor_addr_to_in6_addr32(addr);
- // To improve performance, wrap this assertion in:
- // #if !defined(__clang_analyzer__) || PARANOIA
- tor_assert(addr32);
- iph4 = ntohl(addr32[3]);
- }
- }
-
- if (v_family == AF_INET6) {
- const uint32_t *a32 = tor_addr_to_in6_addr32(addr);
- iph6[0] = ntohl(a32[0]);
- iph6[1] = ntohl(a32[1]);
- iph6[2] = ntohl(a32[2]);
- iph6[3] = ntohl(a32[3]);
- if (for_listening && !iph6[0] && !iph6[1] && !iph6[2] && !iph6[3]) /* :: */
- return 0;
-
- if (((iph6[0] & 0xfe000000) == 0xfc000000) || /* fc00/7 - RFC4193 */
- ((iph6[0] & 0xffc00000) == 0xfe800000) || /* fe80/10 - RFC4291 */
- ((iph6[0] & 0xffc00000) == 0xfec00000)) /* fec0/10 D- RFC3879 */
- return 1;
-
- if (!iph6[0] && !iph6[1] && !iph6[2] &&
- ((iph6[3] & 0xfffffffe) == 0x00000000)) /* ::/127 */
- return 1;
-
- return 0;
- } else if (v_family == AF_INET) {
- if (for_listening && !iph4) /* special case for binding to 0.0.0.0 */
- return 0;
- if (((iph4 & 0xff000000) == 0x0a000000) || /* 10/8 */
- ((iph4 & 0xff000000) == 0x00000000) || /* 0/8 */
- ((iph4 & 0xff000000) == 0x7f000000) || /* 127/8 */
- ((iph4 & 0xffff0000) == 0xa9fe0000) || /* 169.254/16 */
- ((iph4 & 0xfff00000) == 0xac100000) || /* 172.16/12 */
- ((iph4 & 0xffff0000) == 0xc0a80000)) /* 192.168/16 */
- return 1;
- return 0;
- }
-
- /* 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 from %s:%d with a "
- "non-IP address of type %d", filename, lineno, (int)v_family);
- tor_fragile_assert();
- return 1;
-}
-
-/** Convert a tor_addr_t <b>addr</b> into a string, and store it in
- * <b>dest</b> of size <b>len</b>. Returns a pointer to dest on success,
- * or NULL on failure. If <b>decorate</b>, surround IPv6 addresses with
- * brackets.
- */
-const char *
-tor_addr_to_str(char *dest, const tor_addr_t *addr, size_t len, int decorate)
-{
- const char *ptr;
- tor_assert(addr && dest);
-
- switch (tor_addr_family(addr)) {
- case AF_INET:
- /* Shortest addr x.x.x.x + \0 */
- if (len < 8)
- return NULL;
- ptr = tor_inet_ntop(AF_INET, &addr->addr.in_addr, dest, len);
- break;
- case AF_INET6:
- /* Shortest addr [ :: ] + \0 */
- if (len < (3 + (decorate ? 2 : 0)))
- return NULL;
-
- if (decorate)
- ptr = tor_inet_ntop(AF_INET6, &addr->addr.in6_addr, dest+1, len-2);
- else
- ptr = tor_inet_ntop(AF_INET6, &addr->addr.in6_addr, dest, len);
-
- if (ptr && decorate) {
- *dest = '[';
- memcpy(dest+strlen(dest), "]", 2);
- tor_assert(ptr == dest+1);
- ptr = dest;
- }
- break;
- case AF_UNIX:
- tor_snprintf(dest, len, "AF_UNIX");
- ptr = dest;
- break;
- default:
- return NULL;
- }
- return ptr;
-}
-
-/** Parse an .in-addr.arpa or .ip6.arpa address from <b>address</b>. Return 0
- * if this is not an .in-addr.arpa address or an .ip6.arpa address. Return -1
- * if this is an ill-formed .in-addr.arpa address or an .ip6.arpa address.
- * Also return -1 if <b>family</b> is not AF_UNSPEC, and the parsed address
- * family does not match <b>family</b>. On success, return 1, and store the
- * result, if any, into <b>result</b>, if provided.
- *
- * If <b>accept_regular</b> is set and the address is in neither recognized
- * reverse lookup hostname format, try parsing the address as a regular
- * IPv4 or IPv6 address too.
- */
-int
-tor_addr_parse_PTR_name(tor_addr_t *result, const char *address,
- int family, int accept_regular)
-{
- if (!strcasecmpend(address, ".in-addr.arpa")) {
- /* We have an in-addr.arpa address. */
- char buf[INET_NTOA_BUF_LEN];
- size_t len;
- struct in_addr inaddr;
- if (family == AF_INET6)
- return -1;
-
- len = strlen(address) - strlen(".in-addr.arpa");
- if (len >= INET_NTOA_BUF_LEN)
- return -1; /* Too long. */
-
- memcpy(buf, address, len);
- buf[len] = '\0';
- if (tor_inet_aton(buf, &inaddr) == 0)
- return -1; /* malformed. */
-
- /* reverse the bytes */
- inaddr.s_addr = (uint32_t)
- (((inaddr.s_addr & 0x000000ff) << 24)
- |((inaddr.s_addr & 0x0000ff00) << 8)
- |((inaddr.s_addr & 0x00ff0000) >> 8)
- |((inaddr.s_addr & 0xff000000) >> 24));
-
- if (result) {
- tor_addr_from_in(result, &inaddr);
- }
- return 1;
- }
-
- if (!strcasecmpend(address, ".ip6.arpa")) {
- const char *cp;
- int n0, n1;
- struct in6_addr in6;
-
- if (family == AF_INET)
- return -1;
-
- cp = address;
- for (int i = 0; i < 16; ++i) {
- n0 = hex_decode_digit(*cp++); /* The low-order nybble appears first. */
- if (*cp++ != '.') return -1; /* Then a dot. */
- n1 = hex_decode_digit(*cp++); /* The high-order nybble appears first. */
- if (*cp++ != '.') return -1; /* Then another dot. */
- if (n0<0 || n1 < 0) /* Both nybbles must be hex. */
- return -1;
-
- /* We don't check the length of the string in here. But that's okay,
- * since we already know that the string ends with ".ip6.arpa", and
- * there is no way to frameshift .ip6.arpa so it fits into the pattern
- * of hexdigit, period, hexdigit, period that we enforce above.
- */
-
- /* Assign from low-byte to high-byte. */
- in6.s6_addr[15-i] = n0 | (n1 << 4);
- }
- if (strcasecmp(cp, "ip6.arpa"))
- return -1;
-
- if (result) {
- tor_addr_from_in6(result, &in6);
- }
- return 1;
- }
-
- if (accept_regular) {
- tor_addr_t tmp;
- int r = tor_addr_parse(&tmp, address);
- if (r < 0)
- return 0;
- if (r != family && family != AF_UNSPEC)
- return -1;
-
- if (result)
- memcpy(result, &tmp, sizeof(tor_addr_t));
-
- return 1;
- }
-
- return 0;
-}
-
-/** Convert <b>addr</b> to an in-addr.arpa name or a .ip6.arpa name,
- * and store the result in the <b>outlen</b>-byte buffer at
- * <b>out</b>. Returns a non-negative integer on success.
- * Returns -1 on failure. */
-int
-tor_addr_to_PTR_name(char *out, size_t outlen,
- const tor_addr_t *addr)
-{
- tor_assert(out);
- tor_assert(addr);
-
- if (addr->family == AF_INET) {
- uint32_t a = tor_addr_to_ipv4h(addr);
-
- return tor_snprintf(out, outlen, "%d.%d.%d.%d.in-addr.arpa",
- (int)(uint8_t)((a )&0xff),
- (int)(uint8_t)((a>>8 )&0xff),
- (int)(uint8_t)((a>>16)&0xff),
- (int)(uint8_t)((a>>24)&0xff));
- } else if (addr->family == AF_INET6) {
- int i;
- char *cp = out;
- const uint8_t *bytes = tor_addr_to_in6_addr8(addr);
- if (outlen < REVERSE_LOOKUP_NAME_BUF_LEN)
- return -1;
- for (i = 15; i >= 0; --i) {
- uint8_t byte = bytes[i];
- *cp++ = "0123456789abcdef"[byte & 0x0f];
- *cp++ = '.';
- *cp++ = "0123456789abcdef"[byte >> 4];
- *cp++ = '.';
- }
- memcpy(cp, "ip6.arpa", 9); /* 8 characters plus NUL */
- return 32 * 2 + 8;
- }
- return -1;
-}
-
-/** Parse a string <b>s</b> containing an IPv4/IPv6 address, and possibly
- * a mask and port or port range. Store the parsed address in
- * <b>addr_out</b>, a mask (if any) in <b>mask_out</b>, and port(s) (if any)
- * in <b>port_min_out</b> and <b>port_max_out</b>.
- *
- * The syntax is:
- * Address OptMask OptPortRange
- * Address ::= IPv4Address / "[" IPv6Address "]" / "*"
- * OptMask ::= "/" Integer /
- * OptPortRange ::= ":*" / ":" Integer / ":" Integer "-" Integer /
- *
- * - If mask, minport, or maxport are NULL, we do not want these
- * options to be set; treat them as an error if present.
- * - If the string has no mask, the mask is set to /32 (IPv4) or /128 (IPv6).
- * - If the string has one port, it is placed in both min and max port
- * variables.
- * - If the string has no port(s), port_(min|max)_out are set to 1 and 65535.
- *
- * Return an address family on success, or -1 if an invalid address string is
- * provided.
- *
- * If 'flags & TAPMP_EXTENDED_STAR' is false, then the wildcard address '*'
- * yield an IPv4 wildcard.
- *
- * If 'flags & TAPMP_EXTENDED_STAR' is true, then the wildcard address '*'
- * yields an AF_UNSPEC wildcard address, which expands to corresponding
- * wildcard IPv4 and IPv6 rules, and the following change is made
- * in the grammar above:
- * Address ::= IPv4Address / "[" IPv6Address "]" / "*" / "*4" / "*6"
- * with the new "*4" and "*6" productions creating a wildcard to match
- * IPv4 or IPv6 addresses.
- *
- * If 'flags & TAPMP_EXTENDED_STAR' and 'flags & TAPMP_STAR_IPV4_ONLY' are
- * both true, then the wildcard address '*' yields an IPv4 wildcard.
- *
- * If 'flags & TAPMP_EXTENDED_STAR' and 'flags & TAPMP_STAR_IPV6_ONLY' are
- * both true, then the wildcard address '*' yields an IPv6 wildcard.
- *
- * TAPMP_STAR_IPV4_ONLY and TAPMP_STAR_IPV6_ONLY are mutually exclusive. */
-int
-tor_addr_parse_mask_ports(const char *s,
- unsigned flags,
- tor_addr_t *addr_out,
- maskbits_t *maskbits_out,
- uint16_t *port_min_out, uint16_t *port_max_out)
-{
- char *base = NULL, *address, *mask = NULL, *port = NULL, *rbracket = NULL;
- char *endptr;
- int any_flag=0, v4map=0;
- sa_family_t family;
- struct in6_addr in6_tmp;
- struct in_addr in_tmp = { .s_addr = 0 };
-
- tor_assert(s);
- tor_assert(addr_out);
- /* We can either only want an IPv4 address or only want an IPv6 address,
- * but we can't only want IPv4 & IPv6 at the same time. */
- tor_assert(!((flags & TAPMP_STAR_IPV4_ONLY)
- && (flags & TAPMP_STAR_IPV6_ONLY)));
-
- /** Longest possible length for an address, mask, and port-range combination.
- * Includes IP, [], /mask, :, ports */
-#define MAX_ADDRESS_LENGTH (TOR_ADDR_BUF_LEN+2+(1+INET_NTOA_BUF_LEN)+12+1)
-
- if (strlen(s) > MAX_ADDRESS_LENGTH) {
- log_warn(LD_GENERAL, "Impossibly long IP %s; rejecting", escaped(s));
- goto err;
- }
- base = tor_strdup(s);
-
- /* Break 'base' into separate strings. */
- address = base;
- if (*address == '[') { /* Probably IPv6 */
- address++;
- rbracket = strchr(address, ']');
- if (!rbracket) {
- log_warn(LD_GENERAL,
- "No closing IPv6 bracket in address pattern; rejecting.");
- goto err;
- }
- }
- mask = strchr((rbracket?rbracket:address),'/');
- port = strchr((mask?mask:(rbracket?rbracket:address)), ':');
- if (port)
- *port++ = '\0';
- if (mask)
- *mask++ = '\0';
- if (rbracket)
- *rbracket = '\0';
- if (port && mask)
- tor_assert(port > mask);
- if (mask && rbracket)
- tor_assert(mask > rbracket);
-
- /* Now "address" is the a.b.c.d|'*'|abcd::1 part...
- * "mask" is the Mask|Maskbits part...
- * and "port" is the *|port|min-max part.
- */
-
- /* Process the address portion */
- memset(addr_out, 0, sizeof(tor_addr_t));
-
- if (!strcmp(address, "*")) {
- if (flags & TAPMP_EXTENDED_STAR) {
- if (flags & TAPMP_STAR_IPV4_ONLY) {
- family = AF_INET;
- tor_addr_from_ipv4h(addr_out, 0);
- } else if (flags & TAPMP_STAR_IPV6_ONLY) {
- static char nil_bytes[16] = { [0]=0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0 };
- family = AF_INET6;
- tor_addr_from_ipv6_bytes(addr_out, nil_bytes);
- } else {
- family = AF_UNSPEC;
- tor_addr_make_unspec(addr_out);
- log_info(LD_GENERAL,
- "'%s' expands into rules which apply to all IPv4 and IPv6 "
- "addresses. (Use accept/reject *4:* for IPv4 or "
- "accept[6]/reject[6] *6:* for IPv6.)", s);
- }
- } else {
- family = AF_INET;
- tor_addr_from_ipv4h(addr_out, 0);
- }
- any_flag = 1;
- } else if (!strcmp(address, "*4") && (flags & TAPMP_EXTENDED_STAR)) {
- family = AF_INET;
- tor_addr_from_ipv4h(addr_out, 0);
- any_flag = 1;
- } else if (!strcmp(address, "*6") && (flags & TAPMP_EXTENDED_STAR)) {
- static char nil_bytes[16] = { [0]=0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0 };
- family = AF_INET6;
- tor_addr_from_ipv6_bytes(addr_out, nil_bytes);
- any_flag = 1;
- } else if (tor_inet_pton(AF_INET6, address, &in6_tmp) > 0) {
- family = AF_INET6;
- tor_addr_from_in6(addr_out, &in6_tmp);
- } else if (tor_inet_pton(AF_INET, address, &in_tmp) > 0) {
- family = AF_INET;
- tor_addr_from_in(addr_out, &in_tmp);
- } else {
- log_warn(LD_GENERAL, "Malformed IP %s in address pattern; rejecting.",
- escaped(address));
- goto err;
- }
-
- v4map = tor_addr_is_v4(addr_out);
-
- /* Parse mask */
- if (maskbits_out) {
- int bits = 0;
- struct in_addr v4mask;
-
- if (mask) { /* the caller (tried to) specify a mask */
- bits = (int) strtol(mask, &endptr, 10);
- if (!*endptr) { /* strtol converted everything, so it was an integer */
- if ((bits<0 || bits>128) ||
- (family == AF_INET && bits > 32)) {
- log_warn(LD_GENERAL,
- "Bad number of mask bits (%d) on address range; rejecting.",
- bits);
- goto err;
- }
- } else { /* mask might still be an address-style mask */
- if (tor_inet_pton(AF_INET, mask, &v4mask) > 0) {
- bits = addr_mask_get_bits(ntohl(v4mask.s_addr));
- if (bits < 0) {
- log_warn(LD_GENERAL,
- "IPv4-style mask %s is not a prefix address; rejecting.",
- escaped(mask));
- goto err;
- }
- } else { /* Not IPv4; we don't do address-style IPv6 masks. */
- log_warn(LD_GENERAL,
- "Malformed mask on address range %s; rejecting.",
- escaped(s));
- goto err;
- }
- }
- if (family == AF_INET6 && v4map) {
- if (bits > 32 && bits < 96) { /* Crazy */
- log_warn(LD_GENERAL,
- "Bad mask bits %d for V4-mapped V6 address; rejecting.",
- bits);
- goto err;
- }
- /* XXXX_IP6 is this really what we want? */
- bits = 96 + bits%32; /* map v4-mapped masks onto 96-128 bits */
- }
- if (any_flag) {
- log_warn(LD_GENERAL,
- "Found bit prefix with wildcard address; rejecting");
- goto err;
- }
- } else { /* pick an appropriate mask, as none was given */
- if (any_flag)
- bits = 0; /* This is okay whether it's V6 or V4 (FIX V4-mapped V6!) */
- else if (tor_addr_family(addr_out) == AF_INET)
- bits = 32;
- else if (tor_addr_family(addr_out) == AF_INET6)
- bits = 128;
- }
- *maskbits_out = (maskbits_t) bits;
- } else {
- if (mask) {
- log_warn(LD_GENERAL,
- "Unexpected mask in address %s; rejecting", escaped(s));
- goto err;
- }
- }
-
- /* Parse port(s) */
- if (port_min_out) {
- uint16_t port2;
- if (!port_max_out) /* caller specified one port; fake the second one */
- port_max_out = &port2;
-
- if (parse_port_range(port, port_min_out, port_max_out) < 0) {
- goto err;
- } else if ((*port_min_out != *port_max_out) && port_max_out == &port2) {
- log_warn(LD_GENERAL,
- "Wanted one port from address range, but there are two.");
-
- port_max_out = NULL; /* caller specified one port, so set this back */
- goto err;
- }
- } else {
- if (port) {
- log_warn(LD_GENERAL,
- "Unexpected ports in address %s; rejecting", escaped(s));
- goto err;
- }
- }
-
- tor_free(base);
- return tor_addr_family(addr_out);
- err:
- tor_free(base);
- return -1;
-}
-
-/** Determine whether an address is IPv4, either native or IPv4-mapped IPv6.
- * Note that this is about representation only, as any decent stack will
- * reject IPv4-mapped addresses received on the wire (and won't use them
- * on the wire either).
- */
-int
-tor_addr_is_v4(const tor_addr_t *addr)
-{
- tor_assert(addr);
-
- if (tor_addr_family(addr) == AF_INET)
- return 1;
-
- if (tor_addr_family(addr) == AF_INET6) {
- /* First two don't need to be ordered */
- uint32_t *a32 = tor_addr_to_in6_addr32(addr);
- if (a32[0] == 0 && a32[1] == 0 && ntohl(a32[2]) == 0x0000ffffu)
- return 1;
- }
-
- return 0; /* Not IPv4 - unknown family or a full-blood IPv6 address */
-}
-
-/** Determine whether an address <b>addr</b> is null, either all zeroes or
- * belonging to family AF_UNSPEC.
- */
-int
-tor_addr_is_null(const tor_addr_t *addr)
-{
- tor_assert(addr);
-
- switch (tor_addr_family(addr)) {
- case AF_INET6: {
- uint32_t *a32 = tor_addr_to_in6_addr32(addr);
- return (a32[0] == 0) && (a32[1] == 0) && (a32[2] == 0) && (a32[3] == 0);
- }
- case AF_INET:
- return (tor_addr_to_ipv4n(addr) == 0);
- case AF_UNIX:
- return 1;
- case AF_UNSPEC:
- return 1;
- default:
- log_warn(LD_BUG, "Called with unknown address family %d",
- (int)tor_addr_family(addr));
- return 0;
- }
- //return 1;
-}
-
-/** Return true iff <b>addr</b> is a loopback address */
-int
-tor_addr_is_loopback(const tor_addr_t *addr)
-{
- tor_assert(addr);
- switch (tor_addr_family(addr)) {
- case AF_INET6: {
- /* ::1 */
- uint32_t *a32 = tor_addr_to_in6_addr32(addr);
- return (a32[0] == 0) && (a32[1] == 0) && (a32[2] == 0) &&
- (ntohl(a32[3]) == 1);
- }
- case AF_INET:
- /* 127.0.0.1 */
- return (tor_addr_to_ipv4h(addr) & 0xff000000) == 0x7f000000;
- case AF_UNSPEC:
- return 0;
- /* LCOV_EXCL_START */
- default:
- tor_fragile_assert();
- return 0;
- /* LCOV_EXCL_STOP */
- }
-}
-
-/* Is addr valid?
- * Checks that addr is non-NULL and not tor_addr_is_null().
- * If for_listening is true, IPv4 addr 0.0.0.0 is allowed.
- * It means "bind to all addresses on the local machine". */
-int
-tor_addr_is_valid(const tor_addr_t *addr, int for_listening)
-{
- /* NULL addresses are invalid regardless of for_listening */
- if (addr == NULL) {
- return 0;
- }
-
- /* Only allow IPv4 0.0.0.0 for_listening. */
- if (for_listening && addr->family == AF_INET
- && tor_addr_to_ipv4h(addr) == 0) {
- return 1;
- }
-
- /* Otherwise, the address is valid if it's not tor_addr_is_null() */
- return !tor_addr_is_null(addr);
-}
-
-/* Is the network-order IPv4 address v4n_addr valid?
- * Checks that addr is not zero.
- * Except if for_listening is true, where IPv4 addr 0.0.0.0 is allowed. */
-int
-tor_addr_is_valid_ipv4n(uint32_t v4n_addr, int for_listening)
-{
- /* Any IPv4 address is valid with for_listening. */
- if (for_listening) {
- return 1;
- }
-
- /* Otherwise, zero addresses are invalid. */
- return v4n_addr != 0;
-}
-
-/* Is port valid?
- * Checks that port is not 0.
- * Except if for_listening is true, where port 0 is allowed.
- * It means "OS chooses a port". */
-int
-tor_port_is_valid(uint16_t port, int for_listening)
-{
- /* Any port value is valid with for_listening. */
- if (for_listening) {
- return 1;
- }
-
- /* Otherwise, zero ports are invalid. */
- return port != 0;
-}
-
-/** Set <b>dest</b> to equal the IPv4 address in <b>v4addr</b> (given in
- * network order). */
-void
-tor_addr_from_ipv4n(tor_addr_t *dest, uint32_t v4addr)
-{
- tor_assert(dest);
- memset(dest, 0, sizeof(tor_addr_t));
- dest->family = AF_INET;
- dest->addr.in_addr.s_addr = v4addr;
-}
-
-/** Set <b>dest</b> to equal the IPv6 address in the 16 bytes at
- * <b>ipv6_bytes</b>. */
-void
-tor_addr_from_ipv6_bytes(tor_addr_t *dest, const char *ipv6_bytes)
-{
- tor_assert(dest);
- tor_assert(ipv6_bytes);
- memset(dest, 0, sizeof(tor_addr_t));
- dest->family = AF_INET6;
- memcpy(dest->addr.in6_addr.s6_addr, ipv6_bytes, 16);
-}
-
-/** Set <b>dest</b> equal to the IPv6 address in the in6_addr <b>in6</b>. */
-void
-tor_addr_from_in6(tor_addr_t *dest, const struct in6_addr *in6)
-{
- tor_addr_from_ipv6_bytes(dest, (const char*)in6->s6_addr);
-}
-
-/** Copy a tor_addr_t from <b>src</b> to <b>dest</b>.
- */
-void
-tor_addr_copy(tor_addr_t *dest, const tor_addr_t *src)
-{
- if (src == dest)
- return;
- tor_assert(src);
- tor_assert(dest);
- memcpy(dest, src, sizeof(tor_addr_t));
-}
-
-/** Copy a tor_addr_t from <b>src</b> to <b>dest</b>, taking extra care to
- * copy only the well-defined portions. Used for computing hashes of
- * addresses.
- */
-void
-tor_addr_copy_tight(tor_addr_t *dest, const tor_addr_t *src)
-{
- tor_assert(src != dest);
- tor_assert(src);
- tor_assert(dest);
- memset(dest, 0, sizeof(tor_addr_t));
- dest->family = src->family;
- switch (tor_addr_family(src))
- {
- case AF_INET:
- dest->addr.in_addr.s_addr = src->addr.in_addr.s_addr;
- break;
- case AF_INET6:
- memcpy(dest->addr.in6_addr.s6_addr, src->addr.in6_addr.s6_addr, 16);
- case AF_UNSPEC:
- break;
- // LCOV_EXCL_START
- default:
- tor_fragile_assert();
- // LCOV_EXCL_STOP
- }
-}
-
-/** Given two addresses <b>addr1</b> and <b>addr2</b>, return 0 if the two
- * addresses are equivalent under the mask mbits, less than 0 if addr1
- * precedes addr2, and greater than 0 otherwise.
- *
- * Different address families (IPv4 vs IPv6) are always considered unequal if
- * <b>how</b> is CMP_EXACT; otherwise, IPv6-mapped IPv4 addresses are
- * considered equivalent to their IPv4 equivalents.
- *
- * As a special case, all pointer-wise distinct AF_UNIX addresses are always
- * considered unequal since tor_addr_t currently does not contain the
- * information required to make the comparison.
- */
-int
-tor_addr_compare(const tor_addr_t *addr1, const tor_addr_t *addr2,
- tor_addr_comparison_t how)
-{
- return tor_addr_compare_masked(addr1, addr2, 128, how);
-}
-
-/** As tor_addr_compare(), but only looks at the first <b>mask</b> bits of
- * the address.
- *
- * Reduce over-specific masks (>128 for ipv6, >32 for ipv4) to 128 or 32.
- *
- * The mask is interpreted relative to <b>addr1</b>, so that if a is
- * \::ffff:1.2.3.4, and b is 3.4.5.6,
- * tor_addr_compare_masked(a,b,100,CMP_SEMANTIC) is the same as
- * -tor_addr_compare_masked(b,a,4,CMP_SEMANTIC).
- *
- * We guarantee that the ordering from tor_addr_compare_masked is a total
- * order on addresses, but not that it is any particular order, or that it
- * will be the same from one version to the next.
- */
-int
-tor_addr_compare_masked(const tor_addr_t *addr1, const tor_addr_t *addr2,
- maskbits_t mbits, tor_addr_comparison_t how)
-{
- /** Helper: Evaluates to -1 if a is less than b, 0 if a equals b, or 1 if a
- * is greater than b. May evaluate a and b more than once. */
-#define TRISTATE(a,b) (((a)<(b))?-1: (((a)==(b))?0:1))
- sa_family_t family1, family2, v_family1, v_family2;
-
- tor_assert(addr1 && addr2);
-
- v_family1 = family1 = tor_addr_family(addr1);
- v_family2 = family2 = tor_addr_family(addr2);
-
- if (family1==family2) {
- /* When the families are the same, there's only one way to do the
- * comparison: exactly. */
- int r;
- switch (family1) {
- case AF_UNSPEC:
- return 0; /* All unspecified addresses are equal */
- case AF_INET: {
- uint32_t a1 = tor_addr_to_ipv4h(addr1);
- uint32_t a2 = tor_addr_to_ipv4h(addr2);
- if (mbits <= 0)
- return 0;
- if (mbits > 32)
- mbits = 32;
- a1 >>= (32-mbits);
- a2 >>= (32-mbits);
- r = TRISTATE(a1, a2);
- return r;
- }
- case AF_INET6: {
- if (mbits > 128)
- mbits = 128;
-
- const uint8_t *a1 = tor_addr_to_in6_addr8(addr1);
- const uint8_t *a2 = tor_addr_to_in6_addr8(addr2);
- const int bytes = mbits >> 3;
- const int leftover_bits = mbits & 7;
- if (bytes && (r = tor_memcmp(a1, a2, bytes))) {
- return r;
- } else if (leftover_bits) {
- uint8_t b1 = a1[bytes] >> (8-leftover_bits);
- uint8_t b2 = a2[bytes] >> (8-leftover_bits);
- return TRISTATE(b1, b2);
- } else {
- return 0;
- }
- }
- case AF_UNIX:
- /* HACKHACKHACKHACKHACK:
- * tor_addr_t doesn't contain a copy of sun_path, so it's not
- * possible to compare this at all.
- *
- * Since the only time we currently actually should be comparing
- * 2 AF_UNIX addresses is when dealing with ISO_CLIENTADDR (which
- * is disabled for AF_UNIX SocksPorts anyway), this just does
- * a pointer comparison.
- *
- * See: #20261.
- */
- if (addr1 < addr2)
- return -1;
- else if (addr1 == addr2)
- return 0;
- else
- return 1;
- /* LCOV_EXCL_START */
- default:
- tor_fragile_assert();
- return 0;
- /* LCOV_EXCL_STOP */
- }
- } else if (how == CMP_EXACT) {
- /* Unequal families and an exact comparison? Stop now! */
- return TRISTATE(family1, family2);
- }
-
- if (mbits == 0)
- return 0;
-
- if (family1 == AF_INET6 && tor_addr_is_v4(addr1))
- v_family1 = AF_INET;
- if (family2 == AF_INET6 && tor_addr_is_v4(addr2))
- v_family2 = AF_INET;
- if (v_family1 == v_family2) {
- /* One or both addresses are a mapped ipv4 address. */
- uint32_t a1, a2;
- if (family1 == AF_INET6) {
- a1 = tor_addr_to_mapped_ipv4h(addr1);
- if (mbits <= 96)
- return 0;
- mbits -= 96; /* We just decided that the first 96 bits of a1 "match". */
- } else {
- a1 = tor_addr_to_ipv4h(addr1);
- }
- if (family2 == AF_INET6) {
- a2 = tor_addr_to_mapped_ipv4h(addr2);
- } else {
- a2 = tor_addr_to_ipv4h(addr2);
- }
- if (mbits > 32) mbits = 32;
- a1 >>= (32-mbits);
- a2 >>= (32-mbits);
- return TRISTATE(a1, a2);
- } else {
- /* Unequal families, and semantic comparison, and no semantic family
- * matches. */
- return TRISTATE(family1, family2);
- }
-}
-
-/** Input for siphash, to produce some output for an unspec value. */
-static const uint32_t unspec_hash_input[] = { 0x4e4df09f, 0x92985342 };
-
-/** Return a hash code based on the address addr. DOCDOC extra */
-uint64_t
-tor_addr_hash(const tor_addr_t *addr)
-{
- switch (tor_addr_family(addr)) {
- case AF_INET:
- return siphash24g(&addr->addr.in_addr.s_addr, 4);
- case AF_UNSPEC:
- return siphash24g(unspec_hash_input, sizeof(unspec_hash_input));
- case AF_INET6:
- return siphash24g(&addr->addr.in6_addr.s6_addr, 16);
- /* LCOV_EXCL_START */
- default:
- tor_fragile_assert();
- return 0;
- /* LCOV_EXCL_STOP */
- }
-}
-
-/** As tor_addr_hash, but use a particular siphash key. */
-uint64_t
-tor_addr_keyed_hash(const struct sipkey *key, const tor_addr_t *addr)
-{
- /* This is duplicate code with tor_addr_hash, since this function needs to
- * be backportable all the way to 0.2.9. */
-
- switch (tor_addr_family(addr)) {
- case AF_INET:
- return siphash24(&addr->addr.in_addr.s_addr, 4, key);
- case AF_UNSPEC:
- return siphash24(unspec_hash_input, sizeof(unspec_hash_input), key);
- case AF_INET6:
- return siphash24(&addr->addr.in6_addr.s6_addr, 16, key);
- default:
- /* LCOV_EXCL_START */
- tor_fragile_assert();
- return 0;
- /* LCOV_EXCL_STOP */
- }
-}
-
-/** Return a newly allocated string with a representation of <b>addr</b>. */
-char *
-tor_addr_to_str_dup(const tor_addr_t *addr)
-{
- char buf[TOR_ADDR_BUF_LEN];
- if (tor_addr_to_str(buf, addr, sizeof(buf), 0)) {
- return tor_strdup(buf);
- } else {
- return tor_strdup("<unknown address type>");
- }
-}
-
-/** Return a string representing the address <b>addr</b>. This string
- * is statically allocated, and must not be freed. Each call to
- * <b>fmt_addr_impl</b> invalidates the last result of the function.
- * This function is not thread-safe. If <b>decorate</b> is set, add
- * brackets to IPv6 addresses.
- *
- * It's better to use the wrapper macros of this function:
- * <b>fmt_addr()</b> and <b>fmt_and_decorate_addr()</b>.
- */
-const char *
-fmt_addr_impl(const tor_addr_t *addr, int decorate)
-{
- static char buf[TOR_ADDR_BUF_LEN];
- if (!addr) return "<null>";
- if (tor_addr_to_str(buf, addr, sizeof(buf), decorate))
- return buf;
- else
- 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. */
-const char *
-fmt_addr32(uint32_t addr)
-{
- static char buf[INET_NTOA_BUF_LEN];
- struct in_addr in;
- in.s_addr = htonl(addr);
- tor_inet_ntoa(&in, buf, sizeof(buf));
- return buf;
-}
-
-/** Convert the string in <b>src</b> to a tor_addr_t <b>addr</b>. The string
- * may be an IPv4 address, an IPv6 address, or an IPv6 address surrounded by
- * square brackets.
- *
- * Return an address family on success, or -1 if an invalid address string is
- * provided. */
-int
-tor_addr_parse(tor_addr_t *addr, const char *src)
-{
- /* Holds substring of IPv6 address after removing square brackets */
- char *tmp = NULL;
- int result;
- struct in_addr in_tmp;
- struct in6_addr in6_tmp;
- tor_assert(addr && src);
- if (src[0] == '[' && src[1])
- src = tmp = tor_strndup(src+1, strlen(src)-2);
-
- if (tor_inet_pton(AF_INET6, src, &in6_tmp) > 0) {
- result = AF_INET6;
- tor_addr_from_in6(addr, &in6_tmp);
- } else if (tor_inet_pton(AF_INET, src, &in_tmp) > 0) {
- result = AF_INET;
- tor_addr_from_in(addr, &in_tmp);
- } else {
- result = -1;
- }
-
- tor_free(tmp);
- return result;
-}
-
-/** Parse an address or address-port combination from <b>s</b>, resolve the
- * address as needed, and put the result in <b>addr_out</b> and (optionally)
- * <b>port_out</b>. Return 0 on success, negative on failure. */
-int
-tor_addr_port_lookup(const char *s, tor_addr_t *addr_out, uint16_t *port_out)
-{
- const char *port;
- tor_addr_t addr;
- uint16_t portval;
- char *tmp = NULL;
-
- tor_assert(s);
- tor_assert(addr_out);
-
- s = eat_whitespace(s);
-
- if (*s == '[') {
- port = strstr(s, "]");
- if (!port)
- goto err;
- tmp = tor_strndup(s+1, port-(s+1));
- port = port+1;
- if (*port == ':')
- port++;
- else
- port = NULL;
- } else {
- port = strchr(s, ':');
- if (port)
- tmp = tor_strndup(s, port-s);
- else
- tmp = tor_strdup(s);
- if (port)
- ++port;
- }
-
- if (tor_addr_lookup(tmp, AF_UNSPEC, &addr) != 0)
- goto err;
- tor_free(tmp);
-
- if (port) {
- portval = (int) tor_parse_long(port, 10, 1, 65535, NULL, NULL);
- if (!portval)
- goto err;
- } else {
- portval = 0;
- }
-
- if (port_out)
- *port_out = portval;
- tor_addr_copy(addr_out, &addr);
-
- return 0;
- err:
- tor_free(tmp);
- return -1;
-}
-
-#ifdef _WIN32
-typedef ULONG (WINAPI *GetAdaptersAddresses_fn_t)(
- ULONG, ULONG, PVOID, PIP_ADAPTER_ADDRESSES, PULONG);
-#endif
-
-#ifdef HAVE_IFADDRS_TO_SMARTLIST
-/*
- * Convert a linked list consisting of <b>ifaddrs</b> structures
- * into smartlist of <b>tor_addr_t</b> structures.
- */
-STATIC smartlist_t *
-ifaddrs_to_smartlist(const struct ifaddrs *ifa, sa_family_t family)
-{
- smartlist_t *result = smartlist_new();
- const struct ifaddrs *i;
-
- for (i = ifa; i; i = i->ifa_next) {
- tor_addr_t tmp;
- if ((i->ifa_flags & (IFF_UP | IFF_RUNNING)) != (IFF_UP | IFF_RUNNING))
- continue;
- if (!i->ifa_addr)
- continue;
- if (i->ifa_addr->sa_family != AF_INET &&
- i->ifa_addr->sa_family != AF_INET6)
- continue;
- if (family != AF_UNSPEC && i->ifa_addr->sa_family != family)
- continue;
- if (tor_addr_from_sockaddr(&tmp, i->ifa_addr, NULL) < 0)
- continue;
- smartlist_add(result, tor_memdup(&tmp, sizeof(tmp)));
- }
-
- return result;
-}
-
-/** Use getiffaddrs() function to get list of current machine
- * network interface addresses. Represent the result by smartlist of
- * <b>tor_addr_t</b> structures.
- */
-STATIC smartlist_t *
-get_interface_addresses_ifaddrs(int severity, sa_family_t family)
-{
-
- /* Most free Unixy systems provide getifaddrs, which gives us a linked list
- * of struct ifaddrs. */
- struct ifaddrs *ifa = NULL;
- smartlist_t *result;
- if (getifaddrs(&ifa) < 0) {
- log_fn(severity, LD_NET, "Unable to call getifaddrs(): %s",
- strerror(errno));
- return NULL;
- }
-
- result = ifaddrs_to_smartlist(ifa, family);
-
- freeifaddrs(ifa);
-
- return result;
-}
-#endif /* defined(HAVE_IFADDRS_TO_SMARTLIST) */
-
-#ifdef HAVE_IP_ADAPTER_TO_SMARTLIST
-
-/** Convert a Windows-specific <b>addresses</b> linked list into smartlist
- * of <b>tor_addr_t</b> structures.
- */
-
-STATIC smartlist_t *
-ip_adapter_addresses_to_smartlist(const IP_ADAPTER_ADDRESSES *addresses)
-{
- smartlist_t *result = smartlist_new();
- const IP_ADAPTER_ADDRESSES *address;
-
- for (address = addresses; address; address = address->Next) {
- const IP_ADAPTER_UNICAST_ADDRESS *a;
- for (a = address->FirstUnicastAddress; a; a = a->Next) {
- /* Yes, it's a linked list inside a linked list */
- const struct sockaddr *sa = a->Address.lpSockaddr;
- tor_addr_t tmp;
- if (sa->sa_family != AF_INET && sa->sa_family != AF_INET6)
- continue;
- if (tor_addr_from_sockaddr(&tmp, sa, NULL) < 0)
- continue;
- smartlist_add(result, tor_memdup(&tmp, sizeof(tmp)));
- }
- }
-
- return result;
-}
-
-/** Windows only: use GetAdaptersInfo() function to retrieve network interface
- * addresses of current machine and return them to caller as smartlist of
- * <b>tor_addr_t</b> structures.
- */
-STATIC smartlist_t *
-get_interface_addresses_win32(int severity, sa_family_t family)
-{
-
- /* Windows XP began to provide GetAdaptersAddresses. Windows 2000 had a
- "GetAdaptersInfo", but that's deprecated; let's just try
- GetAdaptersAddresses and fall back to connect+getsockname.
- */
- HANDLE lib = load_windows_system_library(TEXT("iphlpapi.dll"));
- smartlist_t *result = NULL;
- GetAdaptersAddresses_fn_t fn;
- ULONG size, res;
- IP_ADAPTER_ADDRESSES *addresses = NULL;
-
- (void) severity;
-
-#define FLAGS (GAA_FLAG_SKIP_ANYCAST | \
- GAA_FLAG_SKIP_MULTICAST | \
- GAA_FLAG_SKIP_DNS_SERVER)
-
- if (!lib) {
- log_fn(severity, LD_NET, "Unable to load iphlpapi.dll");
- goto done;
- }
-
- /* Cast through a void function pointer, to silence a spurious compiler
- * warning on 64-bit Windows. This cast is safe, because we are casting to
- * the correct type for GetAdaptersAddresses(). */
- if (!(fn = (GetAdaptersAddresses_fn_t)(void(*)(void))
- GetProcAddress(lib, "GetAdaptersAddresses"))) {
- log_fn(severity, LD_NET, "Unable to obtain pointer to "
- "GetAdaptersAddresses");
- goto done;
- }
-
- /* Guess how much space we need. */
- size = 15*1024;
- addresses = tor_malloc(size);
- res = fn(family, FLAGS, NULL, addresses, &size);
- if (res == ERROR_BUFFER_OVERFLOW) {
- /* we didn't guess that we needed enough space; try again */
- tor_free(addresses);
- addresses = tor_malloc(size);
- res = fn(AF_UNSPEC, FLAGS, NULL, addresses, &size);
- }
- if (res != NO_ERROR) {
- log_fn(severity, LD_NET, "GetAdaptersAddresses failed (result: %lu)", res);
- goto done;
- }
-
- result = ip_adapter_addresses_to_smartlist(addresses);
-
- done:
- if (lib)
- FreeLibrary(lib);
- tor_free(addresses);
- return result;
-}
-
-#endif /* defined(HAVE_IP_ADAPTER_TO_SMARTLIST) */
-
-#ifdef HAVE_IFCONF_TO_SMARTLIST
-
-/* Guess how much space we need. There shouldn't be any struct ifreqs
- * larger than this, even on OS X where the struct's size is dynamic. */
-#define IFREQ_SIZE 4096
-
-/* This is defined on Mac OS X */
-#ifndef _SIZEOF_ADDR_IFREQ
-#define _SIZEOF_ADDR_IFREQ sizeof
-#endif
-
-/* Free ifc->ifc_buf safely. */
-static void
-ifconf_free_ifc_buf(struct ifconf *ifc)
-{
- /* On macOS, tor_free() takes the address of ifc.ifc_buf, which leads to
- * undefined behaviour, because pointer-to-pointers are expected to be
- * aligned at 8-bytes, but the ifconf structure is packed. So we use
- * raw_free() instead. */
- raw_free(ifc->ifc_buf);
- ifc->ifc_buf = NULL;
-}
-
-/** Convert <b>*buf</b>, an ifreq structure array of size <b>buflen</b>,
- * into smartlist of <b>tor_addr_t</b> structures.
- */
-STATIC smartlist_t *
-ifreq_to_smartlist(char *buf, size_t buflen)
-{
- smartlist_t *result = smartlist_new();
- char *end = buf + buflen;
-
- /* These acrobatics are due to alignment issues which trigger
- * undefined behaviour traps on OSX. */
- struct ifreq *r = tor_malloc(IFREQ_SIZE);
-
- while (buf < end) {
- /* Copy up to IFREQ_SIZE bytes into the struct ifreq, but don't overrun
- * buf. */
- memcpy(r, buf, end - buf < IFREQ_SIZE ? end - buf : IFREQ_SIZE);
-
- const struct sockaddr *sa = &r->ifr_addr;
- tor_addr_t tmp;
- int valid_sa_family = (sa->sa_family == AF_INET ||
- sa->sa_family == AF_INET6);
-
- int conversion_success = (tor_addr_from_sockaddr(&tmp, sa, NULL) == 0);
-
- if (valid_sa_family && conversion_success)
- smartlist_add(result, tor_memdup(&tmp, sizeof(tmp)));
-
- buf += _SIZEOF_ADDR_IFREQ(*r);
- }
-
- tor_free(r);
- return result;
-}
-
-/** Use ioctl(.,SIOCGIFCONF,.) to get a list of current machine
- * network interface addresses. Represent the result by smartlist of
- * <b>tor_addr_t</b> structures.
- */
-STATIC smartlist_t *
-get_interface_addresses_ioctl(int severity, sa_family_t family)
-{
- /* Some older unixy systems make us use ioctl(SIOCGIFCONF) */
- struct ifconf ifc;
- ifc.ifc_buf = NULL;
- int fd;
- smartlist_t *result = NULL;
-
- /* This interface, AFAICT, only supports AF_INET addresses,
- * except on AIX. For Solaris, we could use SIOCGLIFCONF. */
-
- /* Bail out if family is neither AF_INET nor AF_UNSPEC since
- * ioctl() technique supports non-IPv4 interface addresses on
- * a small number of niche systems only. If family is AF_UNSPEC,
- * fall back to getting AF_INET addresses only. */
- if (family == AF_UNSPEC)
- family = AF_INET;
- else if (family != AF_INET)
- return NULL;
-
- fd = socket(family, SOCK_DGRAM, 0);
- if (fd < 0) {
- tor_log(severity, LD_NET, "socket failed: %s", strerror(errno));
- goto done;
- }
-
- int mult = 1;
- do {
- mult *= 2;
- ifc.ifc_len = mult * IFREQ_SIZE;
- ifc.ifc_buf = tor_realloc(ifc.ifc_buf, ifc.ifc_len);
-
- tor_assert(ifc.ifc_buf);
-
- if (ioctl(fd, SIOCGIFCONF, &ifc) < 0) {
- tor_log(severity, LD_NET, "ioctl failed: %s", strerror(errno));
- goto done;
- }
- /* Ensure we have least IFREQ_SIZE bytes unused at the end. Otherwise, we
- * don't know if we got everything during ioctl. */
- } while (mult * IFREQ_SIZE - ifc.ifc_len <= IFREQ_SIZE);
- result = ifreq_to_smartlist(ifc.ifc_buf, ifc.ifc_len);
-
- done:
- if (fd >= 0)
- close(fd);
- ifconf_free_ifc_buf(&ifc);
- return result;
-}
-#endif /* defined(HAVE_IFCONF_TO_SMARTLIST) */
-
-/** Try to ask our network interfaces what addresses they are bound to.
- * Return a new smartlist of tor_addr_t on success, and NULL on failure.
- * (An empty smartlist indicates that we successfully learned that we have no
- * addresses.) Log failure messages at <b>severity</b>. Only return the
- * interface addresses of requested <b>family</b> and ignore the addresses
- * of other address families. */
-MOCK_IMPL(smartlist_t *,
-get_interface_addresses_raw,(int severity, sa_family_t family))
-{
- smartlist_t *result = NULL;
-#if defined(HAVE_IFADDRS_TO_SMARTLIST)
- if ((result = get_interface_addresses_ifaddrs(severity, family)))
- return result;
-#endif
-#if defined(HAVE_IP_ADAPTER_TO_SMARTLIST)
- if ((result = get_interface_addresses_win32(severity, family)))
- return result;
-#endif
-#if defined(HAVE_IFCONF_TO_SMARTLIST)
- if ((result = get_interface_addresses_ioctl(severity, family)))
- return result;
-#endif
- (void) severity;
- (void) result;
- return NULL;
-}
-
-/** Return true iff <b>a</b> is a multicast address. */
-int
-tor_addr_is_multicast(const tor_addr_t *a)
-{
- sa_family_t family = tor_addr_family(a);
- if (family == AF_INET) {
- uint32_t ipv4h = tor_addr_to_ipv4h(a);
- if ((ipv4h >> 24) == 0xe0)
- return 1; /* Multicast */
- } else if (family == AF_INET6) {
- const uint8_t *a32 = tor_addr_to_in6_addr8(a);
- if (a32[0] == 0xff)
- return 1;
- }
- return 0;
-}
-
-/** Attempt to retrieve IP address of current host by utilizing some
- * UDP socket trickery. Only look for address of given <b>family</b>
- * (only AF_INET and AF_INET6 are supported). Set result to *<b>addr</b>.
- * Return 0 on success, -1 on failure.
- */
-MOCK_IMPL(int,
-get_interface_address6_via_udp_socket_hack,(int severity,
- sa_family_t family,
- tor_addr_t *addr))
-{
- struct sockaddr_storage target_addr;
- int sock=-1, r=-1;
- socklen_t addr_len;
-
- memset(addr, 0, sizeof(tor_addr_t));
- memset(&target_addr, 0, sizeof(target_addr));
-
- /* Don't worry: no packets are sent. We just need to use a real address
- * on the actual Internet. */
- if (family == AF_INET6) {
- struct sockaddr_in6 *sin6 = (struct sockaddr_in6*)&target_addr;
- /* Use the "discard" service port */
- sin6->sin6_port = htons(9);
- sock = tor_open_socket(PF_INET6,SOCK_DGRAM,IPPROTO_UDP);
- addr_len = (socklen_t)sizeof(struct sockaddr_in6);
- sin6->sin6_family = AF_INET6;
- S6_ADDR16(sin6->sin6_addr)[0] = htons(0x2002); /* 2002:: */
- } else if (family == AF_INET) {
- struct sockaddr_in *sin = (struct sockaddr_in*)&target_addr;
- /* Use the "discard" service port */
- sin->sin_port = htons(9);
- sock = tor_open_socket(PF_INET,SOCK_DGRAM,IPPROTO_UDP);
- addr_len = (socklen_t)sizeof(struct sockaddr_in);
- sin->sin_family = AF_INET;
- sin->sin_addr.s_addr = htonl(0x12000001); /* 18.0.0.1 */
- } else {
- return -1;
- }
-
- if (sock < 0) {
- int e = tor_socket_errno(-1);
- log_fn(severity, LD_NET, "unable to create socket: %s",
- tor_socket_strerror(e));
- goto err;
- }
-
- if (tor_connect_socket(sock,(struct sockaddr *)&target_addr,
- addr_len) < 0) {
- int e = tor_socket_errno(sock);
- log_fn(severity, LD_NET, "connect() failed: %s", tor_socket_strerror(e));
- goto err;
- }
-
- if (tor_addr_from_getsockname(addr, sock) < 0) {
- int e = tor_socket_errno(sock);
- log_fn(severity, LD_NET, "getsockname() to determine interface failed: %s",
- tor_socket_strerror(e));
- goto err;
- }
-
- if (tor_addr_is_loopback(addr) || tor_addr_is_multicast(addr)) {
- log_fn(severity, LD_NET, "Address that we determined via UDP socket"
- " magic is unsuitable for public comms.");
- } else {
- r=0;
- }
-
- err:
- if (sock >= 0)
- tor_close_socket(sock);
- if (r == -1)
- memset(addr, 0, sizeof(tor_addr_t));
- return r;
-}
-
-/** Set *<b>addr</b> to an arbitrary IP address (if any) of an interface that
- * connects to the Internet. Prefer public IP addresses to internal IP
- * addresses. This address should only be used in checking whether our
- * address has changed, as it may be an internal IP address. Return 0 on
- * success, -1 on failure.
- * Prefer get_interface_address6_list for a list of all addresses on all
- * interfaces which connect to the Internet.
- */
-MOCK_IMPL(int,
-get_interface_address6,(int severity, sa_family_t family, tor_addr_t *addr))
-{
- smartlist_t *addrs;
- int rv = -1;
- tor_assert(addr);
-
- memset(addr, 0, sizeof(tor_addr_t));
-
- /* Get a list of public or internal IPs in arbitrary order */
- addrs = get_interface_address6_list(severity, family, 1);
-
- /* Find the first non-internal address, or the last internal address
- * Ideally, we want the default route, see #12377 for details */
- SMARTLIST_FOREACH_BEGIN(addrs, tor_addr_t *, a) {
- tor_addr_copy(addr, a);
- rv = 0;
-
- /* If we found a non-internal address, declare success. Otherwise,
- * keep looking. */
- if (!tor_addr_is_internal(a, 0))
- break;
- } SMARTLIST_FOREACH_END(a);
-
- interface_address6_list_free(addrs);
- return rv;
-}
-
-/** Free a smartlist of IP addresses returned by get_interface_address6_list.
- */
-void
-interface_address6_list_free_(smartlist_t *addrs)
-{
- if (addrs != NULL) {
- SMARTLIST_FOREACH(addrs, tor_addr_t *, a, tor_free(a));
- smartlist_free(addrs);
- }
-}
-
-/** Return a smartlist of the IP addresses of type family from all interfaces
- * on the server. Excludes loopback and multicast addresses. Only includes
- * internal addresses if include_internal is true. (Note that a relay behind
- * NAT may use an internal address to connect to the Internet.)
- * An empty smartlist means that there are no addresses of the selected type
- * matching these criteria.
- * Returns NULL on failure.
- * Use interface_address6_list_free to free the returned list.
- */
-MOCK_IMPL(smartlist_t *,
-get_interface_address6_list,(int severity,
- sa_family_t family,
- int include_internal))
-{
- smartlist_t *addrs;
- tor_addr_t addr;
-
- /* Try to do this the smart way if possible. */
- if ((addrs = get_interface_addresses_raw(severity, family))) {
- SMARTLIST_FOREACH_BEGIN(addrs, tor_addr_t *, a)
- {
- if (tor_addr_is_loopback(a) ||
- tor_addr_is_multicast(a)) {
- SMARTLIST_DEL_CURRENT_KEEPORDER(addrs, a);
- tor_free(a);
- continue;
- }
-
- if (!include_internal && tor_addr_is_internal(a, 0)) {
- SMARTLIST_DEL_CURRENT_KEEPORDER(addrs, a);
- tor_free(a);
- continue;
- }
- } SMARTLIST_FOREACH_END(a);
- }
-
- if (addrs && smartlist_len(addrs) > 0) {
- return addrs;
- }
-
- /* if we removed all entries as unsuitable */
- if (addrs) {
- smartlist_free(addrs);
- }
-
- /* Okay, the smart way is out. */
- addrs = smartlist_new();
-
- if (family == AF_INET || family == AF_UNSPEC) {
- if (get_interface_address6_via_udp_socket_hack(severity,AF_INET,
- &addr) == 0) {
- if (include_internal || !tor_addr_is_internal(&addr, 0)) {
- smartlist_add(addrs, tor_memdup(&addr, sizeof(addr)));
- }
- }
- }
-
- if (family == AF_INET6 || family == AF_UNSPEC) {
- if (get_interface_address6_via_udp_socket_hack(severity,AF_INET6,
- &addr) == 0) {
- if (include_internal || !tor_addr_is_internal(&addr, 0)) {
- smartlist_add(addrs, tor_memdup(&addr, sizeof(addr)));
- }
- }
- }
-
- return addrs;
-}
-
-/* ======
- * IPv4 helpers
- * XXXX IPv6 deprecate some of these.
- */
-
-/** Given an address of the form "ip:port", try to divide it into its
- * ip and port portions, setting *<b>address_out</b> to a newly
- * allocated string holding the address portion and *<b>port_out</b>
- * to the port.
- *
- * Don't do DNS lookups and don't allow domain names in the "ip" field.
- *
- * If <b>default_port</b> is less than 0, don't accept <b>addrport</b> of the
- * form "ip" or "ip:0". Otherwise, accept those forms, and set
- * *<b>port_out</b> to <b>default_port</b>.
- *
- * Return 0 on success, -1 on failure. */
-int
-tor_addr_port_parse(int severity, const char *addrport,
- tor_addr_t *address_out, uint16_t *port_out,
- int default_port)
-{
- int retval = -1;
- int r;
- char *addr_tmp = NULL;
-
- tor_assert(addrport);
- tor_assert(address_out);
- tor_assert(port_out);
-
- r = tor_addr_port_split(severity, addrport, &addr_tmp, port_out);
- if (r < 0)
- goto done;
-
- if (!*port_out) {
- if (default_port >= 0)
- *port_out = default_port;
- else
- goto done;
- }
-
- /* make sure that address_out is an IP address */
- if (tor_addr_parse(address_out, addr_tmp) < 0)
- goto done;
-
- retval = 0;
-
- done:
- tor_free(addr_tmp);
- return retval;
-}
-
-/** Given an address of the form "host[:port]", try to divide it into its host
- * and port portions, setting *<b>address_out</b> to a newly allocated string
- * holding the address portion and *<b>port_out</b> to the port (or 0 if no
- * port is given). Return 0 on success, -1 on failure. */
-int
-tor_addr_port_split(int severity, const char *addrport,
- char **address_out, uint16_t *port_out)
-{
- tor_addr_t a_tmp;
- tor_assert(addrport);
- tor_assert(address_out);
- tor_assert(port_out);
- /* We need to check for IPv6 manually because addr_port_lookup() doesn't
- * do a good job on IPv6 addresses that lack a port. */
- if (tor_addr_parse(&a_tmp, addrport) == AF_INET6) {
- *port_out = 0;
- *address_out = tor_strdup(addrport);
- return 0;
- }
-
- return addr_port_lookup(severity, addrport, address_out, NULL, port_out);
-}
-
-/** Parse a string of the form "host[:port]" from <b>addrport</b>. If
- * <b>address</b> is provided, set *<b>address</b> to a copy of the
- * host portion of the string. If <b>addr</b> is provided, try to
- * resolve the host portion of the string and store it into
- * *<b>addr</b> (in host byte order). If <b>port_out</b> is provided,
- * store the port number into *<b>port_out</b>, or 0 if no port is given.
- * If <b>port_out</b> is NULL, then there must be no port number in
- * <b>addrport</b>.
- * Return 0 on success, -1 on failure.
- */
-int
-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_;
- 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_) {
- log_fn(severity, LD_GENERAL, "Port %s out of range", escaped(colon+1));
- ok = 0;
- }
- if (!port_out) {
- char *esc_addrport = esc_for_log(addrport);
- log_fn(severity, LD_GENERAL,
- "Port %s given on %s when not required",
- escaped(colon+1), esc_addrport);
- tor_free(esc_addrport);
- ok = 0;
- }
- } else {
- 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_));
- ok = 0;
- *addr = 0;
- }
- }
-
- if (address && ok) {
- *address = address_;
- } else {
- if (address)
- *address = NULL;
- tor_free(address_);
- }
- if (port_out)
- *port_out = ok ? ((uint16_t) port_) : 0;
-
- return ok ? 0 : -1;
-}
-
-/** If <b>mask</b> is an address mask for a bit-prefix, return the number of
- * bits. Otherwise, return -1. */
-int
-addr_mask_get_bits(uint32_t mask)
-{
- int i;
- if (mask == 0)
- return 0;
- if (mask == 0xFFFFFFFFu)
- return 32;
- for (i=1; i<=32; ++i) {
- if (mask == (uint32_t) ~((1u<<(32-i))-1)) {
- return i;
- }
- }
- return -1;
-}
-
-/** Parse a string <b>s</b> in the format of (*|port(-maxport)?)?, setting the
- * various *out pointers as appropriate. Return 0 on success, -1 on failure.
- */
-int
-parse_port_range(const char *port, uint16_t *port_min_out,
- uint16_t *port_max_out)
-{
- int port_min, port_max, ok;
- tor_assert(port_min_out);
- tor_assert(port_max_out);
-
- if (!port || *port == '\0' || strcmp(port, "*") == 0) {
- port_min = 1;
- port_max = 65535;
- } else {
- char *endptr = NULL;
- port_min = (int)tor_parse_long(port, 10, 0, 65535, &ok, &endptr);
- if (!ok) {
- log_warn(LD_GENERAL,
- "Malformed port %s on address range; rejecting.",
- escaped(port));
- return -1;
- } else if (endptr && *endptr == '-') {
- port = endptr+1;
- endptr = NULL;
- port_max = (int)tor_parse_long(port, 10, 1, 65535, &ok, &endptr);
- if (!ok) {
- log_warn(LD_GENERAL,
- "Malformed port %s on address range; rejecting.",
- escaped(port));
- return -1;
- }
- } else {
- port_max = port_min;
- }
- if (port_min > port_max) {
- log_warn(LD_GENERAL, "Insane port range on address policy; rejecting.");
- return -1;
- }
- }
-
- if (port_min < 1)
- port_min = 1;
- if (port_max > 65535)
- port_max = 65535;
-
- *port_min_out = (uint16_t) port_min;
- *port_max_out = (uint16_t) port_max;
-
- return 0;
-}
-
-/** Given an IPv4 in_addr struct *<b>in</b> (in network order, as usual),
- * write it as a string into the <b>buf_len</b>-byte buffer in
- * <b>buf</b>. Returns a non-negative integer on success.
- * Returns -1 on failure.
- */
-int
-tor_inet_ntoa(const struct in_addr *in, char *buf, size_t buf_len)
-{
- uint32_t a = ntohl(in->s_addr);
- return tor_snprintf(buf, buf_len, "%d.%d.%d.%d",
- (int)(uint8_t)((a>>24)&0xff),
- (int)(uint8_t)((a>>16)&0xff),
- (int)(uint8_t)((a>>8 )&0xff),
- (int)(uint8_t)((a )&0xff));
-}
-
-/** Given a host-order <b>addr</b>, call tor_inet_ntop() on it
- * and return a strdup of the resulting address.
- */
-char *
-tor_dup_ip(uint32_t addr)
-{
- char buf[TOR_ADDR_BUF_LEN];
- struct in_addr in;
-
- in.s_addr = htonl(addr);
- tor_inet_ntop(AF_INET, &in, buf, sizeof(buf));
- return tor_strdup(buf);
-}
-
-/**
- * Set *<b>addr</b> to a host-order IPv4 address (if any) of an
- * interface that connects to the Internet. Prefer public IP addresses to
- * internal IP addresses. This address should only be used in checking
- * whether our address has changed, as it may be an internal IPv4 address.
- * Return 0 on success, -1 on failure.
- * Prefer get_interface_address_list6 for a list of all IPv4 and IPv6
- * addresses on all interfaces which connect to the Internet.
- */
-MOCK_IMPL(int,
-get_interface_address,(int severity, uint32_t *addr))
-{
- tor_addr_t local_addr;
- int r;
-
- memset(addr, 0, sizeof(uint32_t));
-
- r = get_interface_address6(severity, AF_INET, &local_addr);
- if (r>=0)
- *addr = tor_addr_to_ipv4h(&local_addr);
- return r;
-}
-
-/** Return true if we can tell that <b>name</b> is a canonical name for the
- * loopback address. Return true also for *.local hostnames, which are
- * multicast DNS names for hosts on the local network. */
-int
-tor_addr_hostname_is_local(const char *name)
-{
- return !strcasecmp(name, "localhost") ||
- !strcasecmp(name, "local") ||
- !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;
-}
-
-/** Return true iff <a>a</b> and <b>b</b> are the same address and port */
-int
-tor_addr_port_eq(const tor_addr_port_t *a,
- const tor_addr_port_t *b)
-{
- return tor_addr_eq(&a->addr, &b->addr) && a->port == b->port;
-}
-
diff --git a/src/common/address.h b/src/common/address.h
deleted file mode 100644
index c9d9543dee..0000000000
--- a/src/common/address.h
+++ /dev/null
@@ -1,379 +0,0 @@
-/* Copyright (c) 2003-2004, Roger Dingledine
- * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2017, The Tor Project, Inc. */
-/* See LICENSE for licensing information */
-
-/**
- * \file address.h
- * \brief Headers for address.h
- **/
-
-#ifndef TOR_ADDRESS_H
-#define TOR_ADDRESS_H
-
-//#include <sys/sockio.h>
-#include "orconfig.h"
-#include "torint.h"
-#include "compat.h"
-#include "container.h"
-
-#ifdef ADDRESS_PRIVATE
-
-#if defined(HAVE_SYS_IOCTL_H)
-#include <sys/ioctl.h>
-#endif
-
-#ifdef HAVE_GETIFADDRS
-#define HAVE_IFADDRS_TO_SMARTLIST
-#endif
-
-#ifdef _WIN32
-#define HAVE_IP_ADAPTER_TO_SMARTLIST
-#endif
-
-#if defined(SIOCGIFCONF) && defined(HAVE_IOCTL)
-#define HAVE_IFCONF_TO_SMARTLIST
-#endif
-
-#if defined(HAVE_NET_IF_H)
-#include <net/if.h> // for struct ifconf
-#endif
-
-#if defined(HAVE_IFADDRS_TO_SMARTLIST)
-#include <ifaddrs.h>
-#endif
-
-// TODO win32 specific includes
-#endif /* defined(ADDRESS_PRIVATE) */
-
-/** The number of bits from an address to consider while doing a masked
- * comparison. */
-typedef uint8_t maskbits_t;
-
-struct in_addr;
-/** Holds an IPv4 or IPv6 address. (Uses less memory than struct
- * sockaddr_storage.) */
-typedef struct tor_addr_t
-{
- sa_family_t family;
- union {
- uint32_t dummy_; /* This field is here so we have something to initialize
- * with a reliable cross-platform type. */
- struct in_addr in_addr;
- struct in6_addr in6_addr;
- } addr;
-} tor_addr_t;
-
-/** Holds an IP address and a TCP/UDP port. */
-typedef struct tor_addr_port_t
-{
- tor_addr_t addr;
- uint16_t port;
-} tor_addr_port_t;
-
-#define TOR_ADDR_NULL {AF_UNSPEC, {0}}
-
-static inline const struct in6_addr *tor_addr_to_in6(const tor_addr_t *a);
-static inline const struct in6_addr *tor_addr_to_in6_assert(
- const tor_addr_t *a);
-static inline uint32_t tor_addr_to_ipv4n(const tor_addr_t *a);
-static inline uint32_t tor_addr_to_ipv4h(const tor_addr_t *a);
-static inline uint32_t tor_addr_to_mapped_ipv4h(const tor_addr_t *a);
-static inline sa_family_t tor_addr_family(const tor_addr_t *a);
-static inline const struct in_addr *tor_addr_to_in(const tor_addr_t *a);
-static inline int tor_addr_eq_ipv4h(const tor_addr_t *a, uint32_t u);
-
-socklen_t tor_addr_to_sockaddr(const tor_addr_t *a, uint16_t port,
- struct sockaddr *sa_out, socklen_t len);
-int tor_addr_from_sockaddr(tor_addr_t *a, const struct sockaddr *sa,
- uint16_t *port_out);
-void tor_addr_make_unspec(tor_addr_t *a);
-void tor_addr_make_null(tor_addr_t *a, sa_family_t family);
-char *tor_sockaddr_to_str(const struct sockaddr *sa);
-
-/** Return an in6_addr* equivalent to <b>a</b>, or NULL if <b>a</b> is not
- * an IPv6 address. */
-static inline const struct in6_addr *
-tor_addr_to_in6(const tor_addr_t *a)
-{
- return a->family == AF_INET6 ? &a->addr.in6_addr : NULL;
-}
-
-/** As tor_addr_to_in6, but assert that the address truly is an IPv6
- * address. */
-static inline const struct in6_addr *
-tor_addr_to_in6_assert(const tor_addr_t *a)
-{
- tor_assert(a->family == AF_INET6);
- return &a->addr.in6_addr;
-}
-
-/** Given an IPv6 address <b>x</b>, yield it as an array of uint8_t.
- *
- * Requires that <b>x</b> is actually an IPv6 address.
- */
-#define tor_addr_to_in6_addr8(x) tor_addr_to_in6_assert(x)->s6_addr
-
-/** Given an IPv6 address <b>x</b>, yield it as an array of uint16_t.
- *
- * Requires that <b>x</b> is actually an IPv6 address.
- */
-#define tor_addr_to_in6_addr16(x) S6_ADDR16(*tor_addr_to_in6_assert(x))
-/** Given an IPv6 address <b>x</b>, yield it as an array of uint32_t.
- *
- * Requires that <b>x</b> is actually an IPv6 address.
- */
-#define tor_addr_to_in6_addr32(x) S6_ADDR32(*tor_addr_to_in6_assert(x))
-
-/** Return an IPv4 address in network order for <b>a</b>, or 0 if
- * <b>a</b> is not an IPv4 address. */
-static inline uint32_t
-tor_addr_to_ipv4n(const tor_addr_t *a)
-{
- return a->family == AF_INET ? a->addr.in_addr.s_addr : 0;
-}
-/** Return an IPv4 address in host order for <b>a</b>, or 0 if
- * <b>a</b> is not an IPv4 address. */
-static inline uint32_t
-tor_addr_to_ipv4h(const tor_addr_t *a)
-{
- return ntohl(tor_addr_to_ipv4n(a));
-}
-/** Given an IPv6 address, return its mapped IPv4 address in host order, or
- * 0 if <b>a</b> is not an IPv6 address.
- *
- * (Does not check whether the address is really a mapped address */
-static inline uint32_t
-tor_addr_to_mapped_ipv4h(const tor_addr_t *a)
-{
- if (a->family == AF_INET6) {
- uint32_t *addr32 = NULL;
- // Work around an incorrect NULL pointer dereference warning in
- // "clang --analyze" due to limited analysis depth
- addr32 = tor_addr_to_in6_addr32(a);
- // To improve performance, wrap this assertion in:
- // #if !defined(__clang_analyzer__) || PARANOIA
- tor_assert(addr32);
- return ntohl(addr32[3]);
- } else {
- return 0;
- }
-}
-/** Return the address family of <b>a</b>. Possible values are:
- * AF_INET6, AF_INET, AF_UNSPEC. */
-static inline sa_family_t
-tor_addr_family(const tor_addr_t *a)
-{
- return a->family;
-}
-/** Return an in_addr* equivalent to <b>a</b>, or NULL if <b>a</b> is not
- * an IPv4 address. */
-static inline const struct in_addr *
-tor_addr_to_in(const tor_addr_t *a)
-{
- return a->family == AF_INET ? &a->addr.in_addr : NULL;
-}
-/** Return true iff <b>a</b> is an IPv4 address equal to the host-ordered
- * address in <b>u</b>. */
-static inline int
-tor_addr_eq_ipv4h(const tor_addr_t *a, uint32_t u)
-{
- return a->family == AF_INET ? (tor_addr_to_ipv4h(a) == u) : 0;
-}
-
-/** Length of a buffer that you need to allocate to be sure you can encode
- * any tor_addr_t.
- *
- * This allows enough space for
- * "[ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255]",
- * plus a terminating NUL.
- */
-#define TOR_ADDR_BUF_LEN 48
-
-MOCK_DECL(int, tor_addr_lookup,(const char *name, uint16_t family,
- tor_addr_t *addr_out));
-char *tor_addr_to_str_dup(const tor_addr_t *addr) ATTR_MALLOC;
-
-/** Wrapper function of fmt_addr_impl(). It does not decorate IPv6
- * addresses. */
-#define fmt_addr(a) fmt_addr_impl((a), 0)
-/** Wrapper function of fmt_addr_impl(). It decorates IPv6
- * 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);
-
-MOCK_DECL(int,get_interface_address6,(int severity, sa_family_t family,
-tor_addr_t *addr));
-void interface_address6_list_free_(smartlist_t * addrs);// XXXX
-#define interface_address6_list_free(addrs) \
- FREE_AND_NULL(smartlist_t, interface_address6_list_free_, (addrs))
-MOCK_DECL(smartlist_t *,get_interface_address6_list,(int severity,
- sa_family_t family,
- int include_internal));
-
-/** Flag to specify how to do a comparison between addresses. In an "exact"
- * comparison, addresses are equivalent only if they are in the same family
- * with the same value. In a "semantic" comparison, IPv4 addresses match all
- * IPv6 encodings of those addresses. */
-typedef enum {
- CMP_EXACT,
- CMP_SEMANTIC,
-} tor_addr_comparison_t;
-
-int tor_addr_compare(const tor_addr_t *addr1, const tor_addr_t *addr2,
- tor_addr_comparison_t how);
-int tor_addr_compare_masked(const tor_addr_t *addr1, const tor_addr_t *addr2,
- maskbits_t mask, tor_addr_comparison_t how);
-/** Return true iff a and b are the same address. The comparison is done
- * "exactly". */
-#define tor_addr_eq(a,b) (0==tor_addr_compare((a),(b),CMP_EXACT))
-
-uint64_t tor_addr_hash(const tor_addr_t *addr);
-struct sipkey;
-uint64_t tor_addr_keyed_hash(const struct sipkey *key, 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,
- const char *filename, int lineno);
-#define tor_addr_is_internal(addr, for_listening) \
- tor_addr_is_internal_((addr), (for_listening), SHORT_FILE__, __LINE__)
-int tor_addr_is_multicast(const tor_addr_t *a);
-
-/** Longest length that can be required for a reverse lookup name. */
-/* 32 nybbles, 32 dots, 8 characters of "ip6.arpa", 1 NUL: 73 characters. */
-#define REVERSE_LOOKUP_NAME_BUF_LEN 73
-int tor_addr_to_PTR_name(char *out, size_t outlen,
- const tor_addr_t *addr);
-int tor_addr_parse_PTR_name(tor_addr_t *result, const char *address,
- int family, int accept_regular);
-
-int tor_addr_port_lookup(const char *s, tor_addr_t *addr_out,
- uint16_t *port_out);
-
-/* Does the address * yield an AF_UNSPEC wildcard address (1),
- * which expands to corresponding wildcard IPv4 and IPv6 rules, and do we
- * allow *4 and *6 for IPv4 and IPv6 wildcards, respectively;
- * or does the address * yield IPv4 wildcard address (0). */
-#define TAPMP_EXTENDED_STAR 1
-/* Does the address * yield an IPv4 wildcard address rule (1);
- * or does it yield wildcard IPv4 and IPv6 rules (0) */
-#define TAPMP_STAR_IPV4_ONLY (1 << 1)
-/* Does the address * yield an IPv6 wildcard address rule (1);
- * or does it yield wildcard IPv4 and IPv6 rules (0) */
-#define TAPMP_STAR_IPV6_ONLY (1 << 2)
-/* TAPMP_STAR_IPV4_ONLY and TAPMP_STAR_IPV6_ONLY are mutually exclusive. */
-int tor_addr_parse_mask_ports(const char *s, unsigned flags,
- tor_addr_t *addr_out, maskbits_t *mask_out,
- uint16_t *port_min_out, uint16_t *port_max_out);
-const char * tor_addr_to_str(char *dest, const tor_addr_t *addr, size_t len,
- int decorate);
-int tor_addr_parse(tor_addr_t *addr, const char *src);
-void tor_addr_copy(tor_addr_t *dest, const tor_addr_t *src);
-void tor_addr_copy_tight(tor_addr_t *dest, const tor_addr_t *src);
-void tor_addr_from_ipv4n(tor_addr_t *dest, uint32_t v4addr);
-/** Set <b>dest</b> to the IPv4 address encoded in <b>v4addr</b> in host
- * order. */
-#define tor_addr_from_ipv4h(dest, v4addr) \
- tor_addr_from_ipv4n((dest), htonl(v4addr))
-void tor_addr_from_ipv6_bytes(tor_addr_t *dest, const char *bytes);
-/** Set <b>dest</b> to the IPv4 address incoded in <b>in</b>. */
-#define tor_addr_from_in(dest, in) \
- tor_addr_from_ipv4n((dest), (in)->s_addr);
-void tor_addr_from_in6(tor_addr_t *dest, const struct in6_addr *in6);
-int tor_addr_is_null(const tor_addr_t *addr);
-int tor_addr_is_loopback(const tor_addr_t *addr);
-
-int tor_addr_is_valid(const tor_addr_t *addr, int for_listening);
-int tor_addr_is_valid_ipv4n(uint32_t v4n_addr, int for_listening);
-#define tor_addr_is_valid_ipv4h(v4h_addr, for_listening) \
- tor_addr_is_valid_ipv4n(htonl(v4h_addr), (for_listening))
-int tor_port_is_valid(uint16_t port, int for_listening);
-/* Are addr and port both valid? */
-#define tor_addr_port_is_valid(addr, port, for_listening) \
- (tor_addr_is_valid((addr), (for_listening)) && \
- tor_port_is_valid((port), (for_listening)))
-/* Are ap->addr and ap->port both valid? */
-#define tor_addr_port_is_valid_ap(ap, for_listening) \
- tor_addr_port_is_valid(&(ap)->addr, (ap)->port, (for_listening))
-/* Are the network-order v4addr and port both valid? */
-#define tor_addr_port_is_valid_ipv4n(v4n_addr, port, for_listening) \
- (tor_addr_is_valid_ipv4n((v4n_addr), (for_listening)) && \
- tor_port_is_valid((port), (for_listening)))
-/* Are the host-order v4addr and port both valid? */
-#define tor_addr_port_is_valid_ipv4h(v4h_addr, port, for_listening) \
- (tor_addr_is_valid_ipv4h((v4h_addr), (for_listening)) && \
- tor_port_is_valid((port), (for_listening)))
-
-int tor_addr_port_split(int severity, const char *addrport,
- char **address_out, uint16_t *port_out);
-
-int tor_addr_port_parse(int severity, const char *addrport,
- tor_addr_t *address_out, uint16_t *port_out,
- int default_port);
-
-int tor_addr_hostname_is_local(const char *name);
-
-/* IPv4 helpers */
-int addr_port_lookup(int severity, const char *addrport, char **address,
- uint32_t *addr, uint16_t *port_out);
-int parse_port_range(const char *port, uint16_t *port_min_out,
- uint16_t *port_max_out);
-int addr_mask_get_bits(uint32_t mask);
-/** Length of a buffer to allocate to hold the results of tor_inet_ntoa.*/
-#define INET_NTOA_BUF_LEN 16
-int tor_inet_ntoa(const struct in_addr *in, char *buf, size_t buf_len);
-char *tor_dup_ip(uint32_t addr) ATTR_MALLOC;
-MOCK_DECL(int,get_interface_address,(int severity, uint32_t *addr));
-#define interface_address_list_free(lst)\
- interface_address6_list_free(lst)
-/** Return a smartlist of the IPv4 addresses of all interfaces on the server.
- * Excludes loopback and multicast addresses. Only includes internal addresses
- * if include_internal is true. (Note that a relay behind NAT may use an
- * internal address to connect to the Internet.)
- * An empty smartlist means that there are no IPv4 addresses.
- * Returns NULL on failure.
- * Use free_interface_address_list to free the returned list.
- */
-static inline smartlist_t *
-get_interface_address_list(int severity, int include_internal)
-{
- return get_interface_address6_list(severity, AF_INET, include_internal);
-}
-
-tor_addr_port_t *tor_addr_port_new(const tor_addr_t *addr, uint16_t port);
-int tor_addr_port_eq(const tor_addr_port_t *a,
- const tor_addr_port_t *b);
-
-#ifdef ADDRESS_PRIVATE
-MOCK_DECL(smartlist_t *,get_interface_addresses_raw,(int severity,
- sa_family_t family));
-MOCK_DECL(int,get_interface_address6_via_udp_socket_hack,(int severity,
- sa_family_t family,
- tor_addr_t *addr));
-
-#ifdef HAVE_IFADDRS_TO_SMARTLIST
-STATIC smartlist_t *ifaddrs_to_smartlist(const struct ifaddrs *ifa,
- sa_family_t family);
-STATIC smartlist_t *get_interface_addresses_ifaddrs(int severity,
- sa_family_t family);
-#endif /* defined(HAVE_IFADDRS_TO_SMARTLIST) */
-
-#ifdef HAVE_IP_ADAPTER_TO_SMARTLIST
-STATIC smartlist_t *ip_adapter_addresses_to_smartlist(
- const IP_ADAPTER_ADDRESSES *addresses);
-STATIC smartlist_t *get_interface_addresses_win32(int severity,
- sa_family_t family);
-#endif /* defined(HAVE_IP_ADAPTER_TO_SMARTLIST) */
-
-#ifdef HAVE_IFCONF_TO_SMARTLIST
-STATIC smartlist_t *ifreq_to_smartlist(char *ifr,
- size_t buflen);
-STATIC smartlist_t *get_interface_addresses_ioctl(int severity,
- sa_family_t family);
-#endif /* defined(HAVE_IFCONF_TO_SMARTLIST) */
-
-#endif /* defined(ADDRESS_PRIVATE) */
-
-#endif /* !defined(TOR_ADDRESS_H) */
-
diff --git a/src/common/address_set.c b/src/common/address_set.c
deleted file mode 100644
index b2f4bb4c95..0000000000
--- a/src/common/address_set.c
+++ /dev/null
@@ -1,129 +0,0 @@
-/* Copyright (c) 2018, The Tor Project, Inc. */
-/* See LICENSE for licensing information */
-
-/**
- * \file address_set.c
- * \brief Implementation for a set of addresses.
- *
- * This module was first written on a semi-emergency basis to improve the
- * robustness of the anti-DoS module. As such, it's written in a pretty
- * conservative way, and should be susceptible to improvement later on.
- **/
-
-#include "orconfig.h"
-#include "address_set.h"
-#include "address.h"
-#include "compat.h"
-#include "container.h"
-#include "crypto_rand.h"
-#include "util.h"
-#include "siphash.h"
-
-/** How many 64-bit siphash values to extract per address */
-#define N_HASHES 2
-/** How many bloom-filter bits we set per address. This is twice the N_HASHES
- * value, since we split the siphash output into two 32-bit values. */
-#define N_BITS_PER_ITEM (N_HASHES * 2)
-
-/* XXXX This code is largely duplicated with digestset_t. We should merge
- * them together into a common bloom-filter implementation. I'm keeping
- * them separate for now, though, since this module needs to be backported
- * all the way to 0.2.9.
- *
- * The main difference between digestset_t and this code is that we use
- * independent siphashes rather than messing around with bit-shifts. The
- * approach here is probably more sound, and we should prefer it if&when we
- * unify the implementations.
- */
-
-struct address_set_t {
- /** siphash keys to make N_HASHES independent hashes for each address. */
- struct sipkey key[N_HASHES];
- int mask; /**< One less than the number of bits in <b>ba</b>; always one less
- * than a power of two. */
- bitarray_t *ba; /**< A bit array to implement the Bloom filter. */
-};
-
-/**
- * Allocate and return an address_set, suitable for holding up to
- * <b>max_address_guess</b> distinct values.
- */
-address_set_t *
-address_set_new(int max_addresses_guess)
-{
- /* See digestset_new() for rationale on this equation. */
- int n_bits = 1u << (tor_log2(max_addresses_guess)+5);
-
- address_set_t *set = tor_malloc_zero(sizeof(address_set_t));
- set->mask = n_bits - 1;
- set->ba = bitarray_init_zero(n_bits);
- crypto_rand((char*) set->key, sizeof(set->key));
-
- return set;
-}
-
-/**
- * Release all storage associated with <b>set</b>.
- */
-void
-address_set_free(address_set_t *set)
-{
- if (! set)
- return;
-
- bitarray_free(set->ba);
- tor_free(set);
-}
-
-/** Yield the bit index corresponding to 'val' for set. */
-#define BIT(set, val) ((val) & (set)->mask)
-
-/**
- * Add <b>addr</b> to <b>set</b>.
- *
- * All future queries for <b>addr</b> in set will return true. Removing
- * items is not possible.
- */
-void
-address_set_add(address_set_t *set, const struct tor_addr_t *addr)
-{
- int i;
- for (i = 0; i < N_HASHES; ++i) {
- uint64_t h = tor_addr_keyed_hash(&set->key[i], addr);
- uint32_t high_bits = (uint32_t)(h >> 32);
- uint32_t low_bits = (uint32_t)(h);
- bitarray_set(set->ba, BIT(set, high_bits));
- bitarray_set(set->ba, BIT(set, low_bits));
- }
-}
-
-/** As address_set_add(), but take an ipv4 address in host order. */
-void
-address_set_add_ipv4h(address_set_t *set, uint32_t addr)
-{
- tor_addr_t a;
- tor_addr_from_ipv4h(&a, addr);
- address_set_add(set, &a);
-}
-
-/**
- * Return true if <b>addr</b> is a member of <b>set</b>. (And probably,
- * return false if <b>addr</b> is not a member of set.)
- */
-int
-address_set_probably_contains(address_set_t *set,
- const struct tor_addr_t *addr)
-{
- int i, matches = 0;
- for (i = 0; i < N_HASHES; ++i) {
- uint64_t h = tor_addr_keyed_hash(&set->key[i], addr);
- uint32_t high_bits = (uint32_t)(h >> 32);
- uint32_t low_bits = (uint32_t)(h);
- // Note that !! is necessary here, since bitarray_is_set does not
- // necessarily return 1 on true.
- matches += !! bitarray_is_set(set->ba, BIT(set, high_bits));
- matches += !! bitarray_is_set(set->ba, BIT(set, low_bits));
- }
- return matches == N_BITS_PER_ITEM;
-}
-
diff --git a/src/common/address_set.h b/src/common/address_set.h
deleted file mode 100644
index 28d29f3fdf..0000000000
--- a/src/common/address_set.h
+++ /dev/null
@@ -1,35 +0,0 @@
-/* Copyright (c) 2018, The Tor Project, Inc. */
-/* See LICENSE for licensing information */
-
-/**
- * \file address_set.h
- * \brief Types to handle sets of addresses.
- *
- * This module was first written on a semi-emergency basis to improve the
- * robustness of the anti-DoS module. As such, it's written in a pretty
- * conservative way, and should be susceptible to improvement later on.
- **/
-
-#ifndef TOR_ADDRESS_SET_H
-#define TOR_ADDRESS_SET_H
-
-#include "orconfig.h"
-#include "torint.h"
-
-/**
- * An address_set_t represents a set of tor_addr_t values. The implementation
- * is probabilistic: false negatives cannot occur but false positives are
- * possible.
- */
-typedef struct address_set_t address_set_t;
-struct tor_addr_t;
-
-address_set_t *address_set_new(int max_addresses_guess);
-void address_set_free(address_set_t *set);
-void address_set_add(address_set_t *set, const struct tor_addr_t *addr);
-void address_set_add_ipv4h(address_set_t *set, uint32_t addr);
-int address_set_probably_contains(address_set_t *set,
- const struct tor_addr_t *addr);
-
-#endif
-
diff --git a/src/common/aes.c b/src/common/aes.c
deleted file mode 100644
index 49bb54762f..0000000000
--- a/src/common/aes.c
+++ /dev/null
@@ -1,410 +0,0 @@
-/* Copyright (c) 2001, Matej Pfajfar.
- * Copyright (c) 2001-2004, Roger Dingledine.
- * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2017, The Tor Project, Inc. */
-/* See LICENSE for licensing information */
-
-/**
- * \file aes.c
- * \brief Implements a counter-mode stream cipher on top of AES.
- **/
-
-#include "orconfig.h"
-
-#ifdef _WIN32 /*wrkard for dtls1.h >= 0.9.8m of "#include <winsock.h>"*/
- #include <winsock2.h>
- #include <ws2tcpip.h>
-#endif
-
-#include "compat_openssl.h"
-#include <openssl/opensslv.h>
-#include "crypto_openssl_mgt.h"
-
-#if OPENSSL_VERSION_NUMBER < OPENSSL_V_SERIES(1,0,0)
-#error "We require OpenSSL >= 1.0.0"
-#endif
-
-DISABLE_GCC_WARNING(redundant-decls)
-
-#include <assert.h>
-#include <stdlib.h>
-#include <string.h>
-#include <openssl/aes.h>
-#include <openssl/evp.h>
-#include <openssl/engine.h>
-#include <openssl/modes.h>
-
-ENABLE_GCC_WARNING(redundant-decls)
-
-#include "compat.h"
-#include "aes.h"
-#include "util.h"
-#include "torlog.h"
-#include "di_ops.h"
-#include "crypto_util.h"
-
-#ifdef ANDROID
-/* Android's OpenSSL seems to have removed all of its Engine support. */
-#define DISABLE_ENGINES
-#endif
-
-/* We have five strategies for implementing AES counter mode.
- *
- * Best with x86 and x86_64: Use EVP_aes_*_ctr() and EVP_EncryptUpdate().
- * This is possible with OpenSSL 1.0.1, where the counter-mode implementation
- * can use bit-sliced or vectorized AES or AESNI as appropriate.
- *
- * Otherwise: Pick the best possible AES block implementation that OpenSSL
- * gives us, and the best possible counter-mode implementation, and combine
- * them.
- */
-#if OPENSSL_VERSION_NUMBER >= OPENSSL_V_NOPATCH(1,1,0)
-
-/* With newer OpenSSL versions, the older fallback modes don't compile. So
- * don't use them, even if we lack specific acceleration. */
-
-#define USE_EVP_AES_CTR
-
-#elif OPENSSL_VERSION_NUMBER >= OPENSSL_V_NOPATCH(1,0,1) && \
- (defined(__i386) || defined(__i386__) || defined(_M_IX86) || \
- defined(__x86_64) || defined(__x86_64__) || \
- defined(_M_AMD64) || defined(_M_X64) || defined(__INTEL__))
-
-#define USE_EVP_AES_CTR
-
-#endif /* OPENSSL_VERSION_NUMBER >= OPENSSL_V_NOPATCH(1,1,0) || ... */
-
-/* We have 2 strategies for getting the AES block cipher: Via OpenSSL's
- * AES_encrypt function, or via OpenSSL's EVP_EncryptUpdate function.
- *
- * If there's any hardware acceleration in play, we want to be using EVP_* so
- * we can get it. Otherwise, we'll want AES_*, which seems to be about 5%
- * faster than indirecting through the EVP layer.
- */
-
-/* We have 2 strategies for getting a plug-in counter mode: use our own, or
- * use OpenSSL's.
- *
- * Here we have a counter mode that's faster than the one shipping with
- * OpenSSL pre-1.0 (by about 10%!). But OpenSSL 1.0.0 added a counter mode
- * implementation faster than the one here (by about 7%). So we pick which
- * one to used based on the Openssl version above. (OpenSSL 1.0.0a fixed a
- * critical bug in that counter mode implementation, so we need to test to
- * make sure that we have a fixed version.)
- */
-
-#ifdef USE_EVP_AES_CTR
-
-/* We don't actually define the struct here. */
-
-aes_cnt_cipher_t *
-aes_new_cipher(const uint8_t *key, const uint8_t *iv, int key_bits)
-{
- EVP_CIPHER_CTX *cipher = EVP_CIPHER_CTX_new();
- const EVP_CIPHER *c;
- switch (key_bits) {
- case 128: c = EVP_aes_128_ctr(); break;
- case 192: c = EVP_aes_192_ctr(); break;
- case 256: c = EVP_aes_256_ctr(); break;
- default: tor_assert(0); // LCOV_EXCL_LINE
- }
- EVP_EncryptInit(cipher, c, key, iv);
- return (aes_cnt_cipher_t *) cipher;
-}
-void
-aes_cipher_free_(aes_cnt_cipher_t *cipher_)
-{
- if (!cipher_)
- return;
- EVP_CIPHER_CTX *cipher = (EVP_CIPHER_CTX *) cipher_;
-#ifdef OPENSSL_1_1_API
- EVP_CIPHER_CTX_reset(cipher);
-#else
- EVP_CIPHER_CTX_cleanup(cipher);
-#endif
- EVP_CIPHER_CTX_free(cipher);
-}
-void
-aes_crypt_inplace(aes_cnt_cipher_t *cipher_, char *data, size_t len)
-{
- int outl;
- EVP_CIPHER_CTX *cipher = (EVP_CIPHER_CTX *) cipher_;
-
- tor_assert(len < INT_MAX);
-
- EVP_EncryptUpdate(cipher, (unsigned char*)data,
- &outl, (unsigned char*)data, (int)len);
-}
-int
-evaluate_evp_for_aes(int force_val)
-{
- (void) force_val;
- log_info(LD_CRYPTO, "This version of OpenSSL has a known-good EVP "
- "counter-mode implementation. Using it.");
- return 0;
-}
-int
-evaluate_ctr_for_aes(void)
-{
- return 0;
-}
-#else /* !(defined(USE_EVP_AES_CTR)) */
-
-/*======================================================================*/
-/* Interface to AES code, and counter implementation */
-
-/** Implements an AES counter-mode cipher. */
-struct aes_cnt_cipher {
-/** This next element (however it's defined) is the AES key. */
- union {
- EVP_CIPHER_CTX evp;
- AES_KEY aes;
- } key;
-
-#if !defined(WORDS_BIGENDIAN)
-#define USING_COUNTER_VARS
- /** These four values, together, implement a 128-bit counter, with
- * counter0 as the low-order word and counter3 as the high-order word. */
- uint32_t counter3;
- uint32_t counter2;
- uint32_t counter1;
- uint32_t counter0;
-#endif /* !defined(WORDS_BIGENDIAN) */
-
- union {
- /** The counter, in big-endian order, as bytes. */
- uint8_t buf[16];
- /** The counter, in big-endian order, as big-endian words. Note that
- * on big-endian platforms, this is redundant with counter3...0,
- * so we just use these values instead. */
- uint32_t buf32[4];
- } ctr_buf;
-
- /** The encrypted value of ctr_buf. */
- uint8_t buf[16];
- /** Our current stream position within buf. */
- unsigned int pos;
-
- /** True iff we're using the evp implementation of this cipher. */
- uint8_t using_evp;
-};
-
-/** True iff we should prefer the EVP implementation for AES, either because
- * we're testing it or because we have hardware acceleration configured */
-static int should_use_EVP = 0;
-
-/** Check whether we should use the EVP interface for AES. If <b>force_val</b>
- * is nonnegative, we use use EVP iff it is true. Otherwise, we use EVP
- * if there is an engine enabled for aes-ecb. */
-int
-evaluate_evp_for_aes(int force_val)
-{
- ENGINE *e;
-
- if (force_val >= 0) {
- should_use_EVP = force_val;
- return 0;
- }
-#ifdef DISABLE_ENGINES
- should_use_EVP = 0;
-#else
- e = ENGINE_get_cipher_engine(NID_aes_128_ecb);
-
- if (e) {
- log_info(LD_CRYPTO, "AES engine \"%s\" found; using EVP_* functions.",
- ENGINE_get_name(e));
- should_use_EVP = 1;
- } else {
- log_info(LD_CRYPTO, "No AES engine found; using AES_* functions.");
- should_use_EVP = 0;
- }
-#endif /* defined(DISABLE_ENGINES) */
-
- return 0;
-}
-
-/** Test the OpenSSL counter mode implementation to see whether it has the
- * counter-mode bug from OpenSSL 1.0.0. If the implementation works, then
- * we will use it for future encryption/decryption operations.
- *
- * We can't just look at the OpenSSL version, since some distributions update
- * their OpenSSL packages without changing the version number.
- **/
-int
-evaluate_ctr_for_aes(void)
-{
- /* Result of encrypting an all-zero block with an all-zero 128-bit AES key.
- * This should be the same as encrypting an all-zero block with an all-zero
- * 128-bit AES key in counter mode, starting at position 0 of the stream.
- */
- static const unsigned char encrypt_zero[] =
- "\x66\xe9\x4b\xd4\xef\x8a\x2c\x3b\x88\x4c\xfa\x59\xca\x34\x2b\x2e";
- unsigned char zero[16];
- unsigned char output[16];
- unsigned char ivec[16];
- unsigned char ivec_tmp[16];
- unsigned int pos, i;
- AES_KEY key;
- memset(zero, 0, sizeof(zero));
- memset(ivec, 0, sizeof(ivec));
- AES_set_encrypt_key(zero, 128, &key);
-
- pos = 0;
- /* Encrypting a block one byte at a time should make the error manifest
- * itself for known bogus openssl versions. */
- for (i=0; i<16; ++i)
- AES_ctr128_encrypt(&zero[i], &output[i], 1, &key, ivec, ivec_tmp, &pos);
-
- if (fast_memneq(output, encrypt_zero, 16)) {
- /* Counter mode is buggy */
- /* LCOV_EXCL_START */
- log_err(LD_CRYPTO, "This OpenSSL has a buggy version of counter mode; "
- "quitting tor.");
- exit(1); // exit ok: openssl is broken.
- /* LCOV_EXCL_STOP */
- }
- return 0;
-}
-
-#if !defined(USING_COUNTER_VARS)
-#define COUNTER(c, n) ((c)->ctr_buf.buf32[3-(n)])
-#else
-#define COUNTER(c, n) ((c)->counter ## n)
-#endif
-
-static void aes_set_key(aes_cnt_cipher_t *cipher, const uint8_t *key,
- int key_bits);
-static void aes_set_iv(aes_cnt_cipher_t *cipher, const uint8_t *iv);
-
-/**
- * Return a newly allocated counter-mode AES128 cipher implementation,
- * using the 128-bit key <b>key</b> and the 128-bit IV <b>iv</b>.
- */
-aes_cnt_cipher_t*
-aes_new_cipher(const uint8_t *key, const uint8_t *iv, int bits)
-{
- aes_cnt_cipher_t* result = tor_malloc_zero(sizeof(aes_cnt_cipher_t));
-
- aes_set_key(result, key, bits);
- aes_set_iv(result, iv);
-
- return result;
-}
-
-/** Set the key of <b>cipher</b> to <b>key</b>, which is
- * <b>key_bits</b> bits long (must be 128, 192, or 256). Also resets
- * the counter to 0.
- */
-static void
-aes_set_key(aes_cnt_cipher_t *cipher, const uint8_t *key, int key_bits)
-{
- if (should_use_EVP) {
- const EVP_CIPHER *c = 0;
- switch (key_bits) {
- case 128: c = EVP_aes_128_ecb(); break;
- case 192: c = EVP_aes_192_ecb(); break;
- case 256: c = EVP_aes_256_ecb(); break;
- default: tor_assert(0); // LCOV_EXCL_LINE
- }
- EVP_EncryptInit(&cipher->key.evp, c, key, NULL);
- cipher->using_evp = 1;
- } else {
- AES_set_encrypt_key(key, key_bits,&cipher->key.aes);
- cipher->using_evp = 0;
- }
-
-#ifdef USING_COUNTER_VARS
- cipher->counter0 = 0;
- cipher->counter1 = 0;
- cipher->counter2 = 0;
- cipher->counter3 = 0;
-#endif /* defined(USING_COUNTER_VARS) */
-
- memset(cipher->ctr_buf.buf, 0, sizeof(cipher->ctr_buf.buf));
-
- cipher->pos = 0;
-
- memset(cipher->buf, 0, sizeof(cipher->buf));
-}
-
-/** Release storage held by <b>cipher</b>
- */
-void
-aes_cipher_free_(aes_cnt_cipher_t *cipher)
-{
- if (!cipher)
- return;
- if (cipher->using_evp) {
- EVP_CIPHER_CTX_cleanup(&cipher->key.evp);
- }
- memwipe(cipher, 0, sizeof(aes_cnt_cipher_t));
- tor_free(cipher);
-}
-
-#if defined(USING_COUNTER_VARS)
-#define UPDATE_CTR_BUF(c, n) STMT_BEGIN \
- (c)->ctr_buf.buf32[3-(n)] = htonl((c)->counter ## n); \
- STMT_END
-#else
-#define UPDATE_CTR_BUF(c, n)
-#endif /* defined(USING_COUNTER_VARS) */
-
-/* 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)
-{
- EVP_CIPHER_CTX *ctx = (void*)key;
- int inl=16, outl=16;
- EVP_EncryptUpdate(ctx, out, &outl, in, inl);
-}
-
-/** Encrypt <b>len</b> bytes from <b>input</b>, storing the results in place.
- * Uses the key in <b>cipher</b>, and advances the counter by <b>len</b> bytes
- * as it encrypts.
- */
-void
-aes_crypt_inplace(aes_cnt_cipher_t *cipher, char *data, size_t len)
-{
- /* Note that the "128" below refers to the length of the counter,
- * not the length of the AES key. */
- if (cipher->using_evp) {
- /* In openssl 1.0.0, there's an if'd out EVP_aes_128_ctr in evp.h. If
- * it weren't disabled, it might be better just to use that.
- */
- CRYPTO_ctr128_encrypt((const unsigned char *)data,
- (unsigned char *)data,
- len,
- &cipher->key.evp,
- cipher->ctr_buf.buf,
- cipher->buf,
- &cipher->pos,
- evp_block128_fn);
- } else {
- AES_ctr128_encrypt((const unsigned char *)data,
- (unsigned char *)data,
- len,
- &cipher->key.aes,
- cipher->ctr_buf.buf,
- cipher->buf,
- &cipher->pos);
- }
-}
-
-/** Reset the 128-bit counter of <b>cipher</b> to the 16-bit big-endian value
- * in <b>iv</b>. */
-static void
-aes_set_iv(aes_cnt_cipher_t *cipher, const uint8_t *iv)
-{
-#ifdef USING_COUNTER_VARS
- cipher->counter3 = ntohl(get_uint32(iv));
- cipher->counter2 = ntohl(get_uint32(iv+4));
- cipher->counter1 = ntohl(get_uint32(iv+8));
- cipher->counter0 = ntohl(get_uint32(iv+12));
-#endif /* defined(USING_COUNTER_VARS) */
- cipher->pos = 0;
- memcpy(cipher->ctr_buf.buf, iv, 16);
-}
-
-#endif /* defined(USE_EVP_AES_CTR) */
diff --git a/src/common/aes.h b/src/common/aes.h
deleted file mode 100644
index 0b17cd55a4..0000000000
--- a/src/common/aes.h
+++ /dev/null
@@ -1,29 +0,0 @@
-/* Copyright (c) 2003, Roger Dingledine
- * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2017, The Tor Project, Inc. */
-/* See LICENSE for licensing information */
-
-/* Implements a minimal interface to counter-mode AES. */
-
-#ifndef TOR_AES_H
-#define TOR_AES_H
-
-/**
- * \file aes.h
- * \brief Headers for aes.c
- */
-
-typedef struct aes_cnt_cipher aes_cnt_cipher_t;
-
-aes_cnt_cipher_t* aes_new_cipher(const uint8_t *key, const uint8_t *iv,
- int key_bits);
-void aes_cipher_free_(aes_cnt_cipher_t *cipher);
-#define aes_cipher_free(cipher) \
- FREE_AND_NULL(aes_cnt_cipher_t, aes_cipher_free_, (cipher))
-void aes_crypt_inplace(aes_cnt_cipher_t *cipher, char *data, size_t len);
-
-int evaluate_evp_for_aes(int force_value);
-int evaluate_ctr_for_aes(void);
-
-#endif /* !defined(TOR_AES_H) */
-
diff --git a/src/common/backtrace.c b/src/common/backtrace.c
deleted file mode 100644
index f2498b2aa6..0000000000
--- a/src/common/backtrace.c
+++ /dev/null
@@ -1,248 +0,0 @@
-/* Copyright (c) 2013-2017, The Tor Project, Inc. */
-/* See LICENSE for licensing information */
-
-/**
- * \file backtrace.c
- *
- * \brief Functions to produce backtraces on bugs, crashes, or assertion
- * failures.
- *
- * Currently, we've only got an implementation here using the backtrace()
- * family of functions, which are sometimes provided by libc and sometimes
- * provided by libexecinfo. We tie into the sigaction() backend in order to
- * detect crashes.
- */
-
-#include "orconfig.h"
-#include "compat.h"
-#include "util.h"
-#include "torlog.h"
-
-#ifdef HAVE_EXECINFO_H
-#include <execinfo.h>
-#endif
-#ifdef HAVE_FCNTL_H
-#include <fcntl.h>
-#endif
-#ifdef HAVE_UNISTD_H
-#include <unistd.h>
-#endif
-#ifdef HAVE_SIGNAL_H
-#include <signal.h>
-#endif
-
-#ifdef HAVE_CYGWIN_SIGNAL_H
-#include <cygwin/signal.h>
-#elif defined(HAVE_SYS_UCONTEXT_H)
-#include <sys/ucontext.h>
-#elif defined(HAVE_UCONTEXT_H)
-#include <ucontext.h>
-#endif /* defined(HAVE_CYGWIN_SIGNAL_H) || ... */
-
-#define EXPOSE_CLEAN_BACKTRACE
-#include "backtrace.h"
-
-#if defined(HAVE_EXECINFO_H) && defined(HAVE_BACKTRACE) && \
- defined(HAVE_BACKTRACE_SYMBOLS_FD) && defined(HAVE_SIGACTION)
-#define USE_BACKTRACE
-#endif
-
-#if !defined(USE_BACKTRACE)
-#define NO_BACKTRACE_IMPL
-#endif
-
-/** Version of Tor to report in backtrace messages. */
-static char *bt_version = NULL;
-
-#ifdef USE_BACKTRACE
-/** Largest stack depth to try to dump. */
-#define MAX_DEPTH 256
-/** Static allocation of stack to dump. This is static so we avoid stack
- * pressure. */
-static void *cb_buf[MAX_DEPTH];
-/** Protects cb_buf from concurrent access */
-static tor_mutex_t cb_buf_mutex;
-
-/** Change a stacktrace in <b>stack</b> of depth <b>depth</b> so that it will
- * log the correct function from which a signal was received with context
- * <b>ctx</b>. (When we get a signal, the current function will not have
- * called any other function, and will therefore have not pushed its address
- * onto the stack. Fortunately, we usually have the program counter in the
- * ucontext_t structure.
- */
-void
-clean_backtrace(void **stack, size_t depth, const ucontext_t *ctx)
-{
-#ifdef PC_FROM_UCONTEXT
-#if defined(__linux__)
- const size_t n = 1;
-#elif defined(__darwin__) || defined(__APPLE__) || defined(OpenBSD) \
- || defined(__FreeBSD__)
- const size_t n = 2;
-#else
- const size_t n = 1;
-#endif /* defined(__linux__) || ... */
- if (depth <= n)
- return;
-
- stack[n] = (void*) ctx->PC_FROM_UCONTEXT;
-#else /* !(defined(PC_FROM_UCONTEXT)) */
- (void) depth;
- (void) ctx;
- (void) stack;
-#endif /* defined(PC_FROM_UCONTEXT) */
-}
-
-/** Log a message <b>msg</b> at <b>severity</b> in <b>domain</b>, and follow
- * that with a backtrace log. */
-void
-log_backtrace(int severity, int domain, const char *msg)
-{
- size_t depth;
- char **symbols;
- size_t i;
-
- tor_mutex_acquire(&cb_buf_mutex);
-
- depth = backtrace(cb_buf, MAX_DEPTH);
- symbols = backtrace_symbols(cb_buf, (int)depth);
-
- tor_log(severity, domain, "%s. Stack trace:", msg);
- if (!symbols) {
- /* LCOV_EXCL_START -- we can't provoke this. */
- tor_log(severity, domain, " Unable to generate backtrace.");
- goto done;
- /* LCOV_EXCL_STOP */
- }
- for (i=0; i < depth; ++i) {
- tor_log(severity, domain, " %s", symbols[i]);
- }
- raw_free(symbols);
-
- done:
- tor_mutex_release(&cb_buf_mutex);
-}
-
-static void crash_handler(int sig, siginfo_t *si, void *ctx_)
- __attribute__((noreturn));
-
-/** Signal handler: write a crash message with a stack trace, and die. */
-static void
-crash_handler(int sig, siginfo_t *si, void *ctx_)
-{
- char buf[40];
- size_t depth;
- ucontext_t *ctx = (ucontext_t *) ctx_;
- int n_fds, i;
- const int *fds = NULL;
-
- (void) si;
-
- depth = backtrace(cb_buf, MAX_DEPTH);
- /* Clean up the top stack frame so we get the real function
- * name for the most recently failing function. */
- clean_backtrace(cb_buf, depth, ctx);
-
- format_dec_number_sigsafe((unsigned)sig, buf, sizeof(buf));
-
- tor_log_err_sigsafe(bt_version, " died: Caught signal ", buf, "\n",
- NULL);
-
- n_fds = tor_log_get_sigsafe_err_fds(&fds);
- for (i=0; i < n_fds; ++i)
- backtrace_symbols_fd(cb_buf, (int)depth, fds[i]);
-
- abort();
-}
-
-/** Install signal handlers as needed so that when we crash, we produce a
- * useful stack trace. Return 0 on success, -1 on failure. */
-static int
-install_bt_handler(void)
-{
- int trap_signals[] = { SIGSEGV, SIGILL, SIGFPE, SIGBUS, SIGSYS,
- SIGIO, -1 };
- int i, rv=0;
-
- struct sigaction sa;
-
- tor_mutex_init(&cb_buf_mutex);
-
- memset(&sa, 0, sizeof(sa));
- sa.sa_sigaction = crash_handler;
- sa.sa_flags = SA_SIGINFO;
- sigfillset(&sa.sa_mask);
-
- for (i = 0; trap_signals[i] >= 0; ++i) {
- if (sigaction(trap_signals[i], &sa, NULL) == -1) {
- /* LCOV_EXCL_START */
- log_warn(LD_BUG, "Sigaction failed: %s", strerror(errno));
- rv = -1;
- /* LCOV_EXCL_STOP */
- }
- }
-
- {
- /* Now, generate (but do not log) a backtrace. This ensures that
- * libc has pre-loaded the symbols we need to dump things, so that later
- * reads won't be denied by the sandbox code */
- char **symbols;
- size_t depth = backtrace(cb_buf, MAX_DEPTH);
- symbols = backtrace_symbols(cb_buf, (int) depth);
- if (symbols)
- raw_free(symbols);
- }
-
- return rv;
-}
-
-/** Uninstall crash handlers. */
-static void
-remove_bt_handler(void)
-{
- tor_mutex_uninit(&cb_buf_mutex);
-}
-#endif /* defined(USE_BACKTRACE) */
-
-#ifdef NO_BACKTRACE_IMPL
-void
-log_backtrace(int severity, int domain, const char *msg)
-{
- tor_log(severity, domain, "%s. (Stack trace not available)", msg);
-}
-
-static int
-install_bt_handler(void)
-{
- return 0;
-}
-
-static void
-remove_bt_handler(void)
-{
-}
-#endif /* defined(NO_BACKTRACE_IMPL) */
-
-/** Set up code to handle generating error messages on crashes. */
-int
-configure_backtrace_handler(const char *tor_version)
-{
- tor_free(bt_version);
- if (tor_version)
- tor_asprintf(&bt_version, "Tor %s", tor_version);
- else
- tor_asprintf(&bt_version, "Tor");
-
- return install_bt_handler();
-}
-
-/** Perform end-of-process cleanup for code that generates error messages on
- * crashes. */
-void
-clean_up_backtrace_handler(void)
-{
- remove_bt_handler();
-
- tor_free(bt_version);
-}
-
diff --git a/src/common/backtrace.h b/src/common/backtrace.h
deleted file mode 100644
index 3d0ab8a90a..0000000000
--- a/src/common/backtrace.h
+++ /dev/null
@@ -1,21 +0,0 @@
-/* Copyright (c) 2013-2017, The Tor Project, Inc. */
-/* See LICENSE for licensing information */
-
-#ifndef TOR_BACKTRACE_H
-#define TOR_BACKTRACE_H
-
-#include "orconfig.h"
-
-void log_backtrace(int severity, int domain, const char *msg);
-int configure_backtrace_handler(const char *tor_version);
-void clean_up_backtrace_handler(void);
-
-#ifdef EXPOSE_CLEAN_BACKTRACE
-#if defined(HAVE_EXECINFO_H) && defined(HAVE_BACKTRACE) && \
- defined(HAVE_BACKTRACE_SYMBOLS_FD) && defined(HAVE_SIGACTION)
-void clean_backtrace(void **stack, size_t depth, const ucontext_t *ctx);
-#endif
-#endif /* defined(EXPOSE_CLEAN_BACKTRACE) */
-
-#endif /* !defined(TOR_BACKTRACE_H) */
-
diff --git a/src/common/buffers.c b/src/common/buffers.c
deleted file mode 100644
index a01add9bef..0000000000
--- a/src/common/buffers.c
+++ /dev/null
@@ -1,1146 +0,0 @@
-/* Copyright (c) 2001 Matej Pfajfar.
- * Copyright (c) 2001-2004, Roger Dingledine.
- * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2017, The Tor Project, Inc. */
-/* See LICENSE for licensing information */
-
-/**
- * \file buffers.c
- * \brief Implements a generic buffer interface.
- *
- * A buf_t is a (fairly) opaque byte-oriented FIFO that can read to or flush
- * from memory, sockets, file descriptors, TLS connections, or another buf_t.
- * Buffers are implemented as linked lists of memory chunks.
- *
- * All socket-backed and TLS-based connection_t objects have a pair of
- * buffers: one for incoming data, and one for outcoming data. These are fed
- * and drained from functions in connection.c, trigged by events that are
- * monitored in main.c.
- **/
-
-#define BUFFERS_PRIVATE
-#include "orconfig.h"
-#include <stddef.h>
-#include "buffers.h"
-#include "compat.h"
-#include "compress.h"
-#include "util.h"
-#include "torint.h"
-#include "torlog.h"
-#ifdef HAVE_UNISTD_H
-#include <unistd.h>
-#endif
-
-//#define PARANOIA
-
-#ifdef PARANOIA
-/** Helper: If PARANOIA is defined, assert that the buffer in local variable
- * <b>buf</b> is well-formed. */
-#define check() STMT_BEGIN buf_assert_ok(buf); STMT_END
-#else
-#define check() STMT_NIL
-#endif /* defined(PARANOIA) */
-
-/* Implementation notes:
- *
- * After flirting with memmove, and dallying with ring-buffers, we're finally
- * getting up to speed with the 1970s and implementing buffers as a linked
- * list of small chunks. Each buffer has such a list; data is removed from
- * the head of the list, and added at the tail. The list is singly linked,
- * and the buffer keeps a pointer to the head and the tail.
- *
- * Every chunk, except the tail, contains at least one byte of data. Data in
- * each chunk is contiguous.
- *
- * When you need to treat the first N characters on a buffer as a contiguous
- * string, use the buf_pullup function to make them so. Don't do this more
- * than necessary.
- *
- * The major free Unix kernels have handled buffers like this since, like,
- * forever.
- */
-
-/* Chunk manipulation functions */
-
-#define CHUNK_HEADER_LEN offsetof(chunk_t, mem[0])
-
-/* We leave this many NUL bytes at the end of the buffer. */
-#ifdef DISABLE_MEMORY_SENTINELS
-#define SENTINEL_LEN 0
-#else
-#define SENTINEL_LEN 4
-#endif
-
-/* Header size plus NUL bytes at the end */
-#define CHUNK_OVERHEAD (CHUNK_HEADER_LEN + SENTINEL_LEN)
-
-/** Return the number of bytes needed to allocate a chunk to hold
- * <b>memlen</b> bytes. */
-#define CHUNK_ALLOC_SIZE(memlen) (CHUNK_OVERHEAD + (memlen))
-/** Return the number of usable bytes in a chunk allocated with
- * malloc(<b>memlen</b>). */
-#define CHUNK_SIZE_WITH_ALLOC(memlen) ((memlen) - CHUNK_OVERHEAD)
-
-#define DEBUG_SENTINEL
-
-#if defined(DEBUG_SENTINEL) && !defined(DISABLE_MEMORY_SENTINELS)
-#define DBG_S(s) s
-#else
-#define DBG_S(s) (void)0
-#endif
-
-#ifdef DISABLE_MEMORY_SENTINELS
-#define CHUNK_SET_SENTINEL(chunk, alloclen) STMT_NIL
-#else
-#define CHUNK_SET_SENTINEL(chunk, alloclen) do { \
- uint8_t *a = (uint8_t*) &(chunk)->mem[(chunk)->memlen]; \
- DBG_S(uint8_t *b = &((uint8_t*)(chunk))[(alloclen)-SENTINEL_LEN]); \
- DBG_S(tor_assert(a == b)); \
- memset(a,0,SENTINEL_LEN); \
- } while (0)
-#endif /* defined(DISABLE_MEMORY_SENTINELS) */
-
-/** Move all bytes stored in <b>chunk</b> to the front of <b>chunk</b>->mem,
- * to free up space at the end. */
-static inline void
-chunk_repack(chunk_t *chunk)
-{
- if (chunk->datalen && chunk->data != &chunk->mem[0]) {
- memmove(chunk->mem, chunk->data, chunk->datalen);
- }
- chunk->data = &chunk->mem[0];
-}
-
-/** Keep track of total size of allocated chunks for consistency asserts */
-static size_t total_bytes_allocated_in_chunks = 0;
-static void
-buf_chunk_free_unchecked(chunk_t *chunk)
-{
- if (!chunk)
- return;
-#ifdef DEBUG_CHUNK_ALLOC
- tor_assert(CHUNK_ALLOC_SIZE(chunk->memlen) == chunk->DBG_alloc);
-#endif
- tor_assert(total_bytes_allocated_in_chunks >=
- CHUNK_ALLOC_SIZE(chunk->memlen));
- total_bytes_allocated_in_chunks -= CHUNK_ALLOC_SIZE(chunk->memlen);
- tor_free(chunk);
-}
-static inline chunk_t *
-chunk_new_with_alloc_size(size_t alloc)
-{
- chunk_t *ch;
- ch = tor_malloc(alloc);
- ch->next = NULL;
- ch->datalen = 0;
-#ifdef DEBUG_CHUNK_ALLOC
- ch->DBG_alloc = alloc;
-#endif
- ch->memlen = CHUNK_SIZE_WITH_ALLOC(alloc);
- total_bytes_allocated_in_chunks += alloc;
- ch->data = &ch->mem[0];
- CHUNK_SET_SENTINEL(ch, alloc);
- return ch;
-}
-
-/** Expand <b>chunk</b> until it can hold <b>sz</b> bytes, and return a
- * new pointer to <b>chunk</b>. Old pointers are no longer valid. */
-static inline chunk_t *
-chunk_grow(chunk_t *chunk, size_t sz)
-{
- off_t offset;
- const size_t memlen_orig = chunk->memlen;
- const size_t orig_alloc = CHUNK_ALLOC_SIZE(memlen_orig);
- const size_t new_alloc = CHUNK_ALLOC_SIZE(sz);
- tor_assert(sz > chunk->memlen);
- offset = chunk->data - chunk->mem;
- chunk = tor_realloc(chunk, new_alloc);
- chunk->memlen = sz;
- chunk->data = chunk->mem + offset;
-#ifdef DEBUG_CHUNK_ALLOC
- tor_assert(chunk->DBG_alloc == orig_alloc);
- chunk->DBG_alloc = new_alloc;
-#endif
- total_bytes_allocated_in_chunks += new_alloc - orig_alloc;
- CHUNK_SET_SENTINEL(chunk, new_alloc);
- return chunk;
-}
-
-/** Every chunk should take up at least this many bytes. */
-#define MIN_CHUNK_ALLOC 256
-/** No chunk should take up more than this many bytes. */
-#define MAX_CHUNK_ALLOC 65536
-
-/** Return the allocation size we'd like to use to hold <b>target</b>
- * bytes. */
-size_t
-buf_preferred_chunk_size(size_t target)
-{
- tor_assert(target <= SIZE_T_CEILING - CHUNK_OVERHEAD);
- if (CHUNK_ALLOC_SIZE(target) >= MAX_CHUNK_ALLOC)
- return CHUNK_ALLOC_SIZE(target);
- size_t sz = MIN_CHUNK_ALLOC;
- while (CHUNK_SIZE_WITH_ALLOC(sz) < target) {
- sz <<= 1;
- }
- return sz;
-}
-
-/** Collapse data from the first N chunks from <b>buf</b> into buf->head,
- * growing it as necessary, until buf->head has the first <b>bytes</b> bytes
- * of data from the buffer, or until buf->head has all the data in <b>buf</b>.
- *
- * Set *<b>head_out</b> to point to the first byte of available data, and
- * *<b>len_out</b> to the number of bytes of data available at
- * *<b>head_out</b>. Note that *<b>len_out</b> may be more or less than
- * <b>bytes</b>, depending on the number of bytes available.
- */
-void
-buf_pullup(buf_t *buf, size_t bytes, const char **head_out, size_t *len_out)
-{
- chunk_t *dest, *src;
- size_t capacity;
- if (!buf->head) {
- *head_out = NULL;
- *len_out = 0;
- return;
- }
-
- check();
- if (buf->datalen < bytes)
- bytes = buf->datalen;
-
- capacity = bytes;
- if (buf->head->datalen >= bytes) {
- *head_out = buf->head->data;
- *len_out = buf->head->datalen;
- return;
- }
-
- if (buf->head->memlen >= capacity) {
- /* We don't need to grow the first chunk, but we might need to repack it.*/
- size_t needed = capacity - buf->head->datalen;
- if (CHUNK_REMAINING_CAPACITY(buf->head) < needed)
- chunk_repack(buf->head);
- tor_assert(CHUNK_REMAINING_CAPACITY(buf->head) >= needed);
- } else {
- chunk_t *newhead;
- size_t newsize;
- /* We need to grow the chunk. */
- chunk_repack(buf->head);
- newsize = CHUNK_SIZE_WITH_ALLOC(buf_preferred_chunk_size(capacity));
- newhead = chunk_grow(buf->head, newsize);
- tor_assert(newhead->memlen >= capacity);
- if (newhead != buf->head) {
- if (buf->tail == buf->head)
- buf->tail = newhead;
- buf->head = newhead;
- }
- }
-
- dest = buf->head;
- while (dest->datalen < bytes) {
- size_t n = bytes - dest->datalen;
- src = dest->next;
- tor_assert(src);
- if (n >= src->datalen) {
- memcpy(CHUNK_WRITE_PTR(dest), src->data, src->datalen);
- dest->datalen += src->datalen;
- dest->next = src->next;
- if (buf->tail == src)
- buf->tail = dest;
- buf_chunk_free_unchecked(src);
- } else {
- memcpy(CHUNK_WRITE_PTR(dest), src->data, n);
- dest->datalen += n;
- src->data += n;
- src->datalen -= n;
- tor_assert(dest->datalen == bytes);
- }
- }
-
- check();
- *head_out = buf->head->data;
- *len_out = buf->head->datalen;
-}
-
-#ifdef TOR_UNIT_TESTS
-/* Write sz bytes from cp into a newly allocated buffer buf.
- * Returns NULL when passed a NULL cp or zero sz.
- * Asserts on failure: only for use in unit tests.
- * buf must be freed using buf_free(). */
-buf_t *
-buf_new_with_data(const char *cp, size_t sz)
-{
- /* Validate arguments */
- if (!cp || sz <= 0) {
- return NULL;
- }
-
- tor_assert(sz < SSIZE_T_CEILING);
-
- /* Allocate a buffer */
- buf_t *buf = buf_new_with_capacity(sz);
- tor_assert(buf);
- buf_assert_ok(buf);
- tor_assert(!buf->head);
-
- /* Allocate a chunk that is sz bytes long */
- buf->head = chunk_new_with_alloc_size(CHUNK_ALLOC_SIZE(sz));
- buf->tail = buf->head;
- tor_assert(buf->head);
- buf_assert_ok(buf);
- tor_assert(buf_allocation(buf) >= sz);
-
- /* Copy the data and size the buffers */
- tor_assert(sz <= buf_slack(buf));
- tor_assert(sz <= CHUNK_REMAINING_CAPACITY(buf->head));
- memcpy(&buf->head->mem[0], cp, sz);
- buf->datalen = sz;
- buf->head->datalen = sz;
- buf->head->data = &buf->head->mem[0];
- buf_assert_ok(buf);
-
- /* Make sure everything is large enough */
- tor_assert(buf_allocation(buf) >= sz);
- tor_assert(buf_allocation(buf) >= buf_datalen(buf) + buf_slack(buf));
- /* Does the buffer implementation allocate more than the requested size?
- * (for example, by rounding up). If so, these checks will fail. */
- tor_assert(buf_datalen(buf) == sz);
- tor_assert(buf_slack(buf) == 0);
-
- return buf;
-}
-#endif /* defined(TOR_UNIT_TESTS) */
-
-/** Remove the first <b>n</b> bytes from buf. */
-void
-buf_drain(buf_t *buf, size_t n)
-{
- tor_assert(buf->datalen >= n);
- while (n) {
- tor_assert(buf->head);
- if (buf->head->datalen > n) {
- buf->head->datalen -= n;
- buf->head->data += n;
- buf->datalen -= n;
- return;
- } else {
- chunk_t *victim = buf->head;
- n -= victim->datalen;
- buf->datalen -= victim->datalen;
- buf->head = victim->next;
- if (buf->tail == victim)
- buf->tail = NULL;
- buf_chunk_free_unchecked(victim);
- }
- }
- check();
-}
-
-/** Create and return a new buf with default chunk capacity <b>size</b>.
- */
-buf_t *
-buf_new_with_capacity(size_t size)
-{
- buf_t *b = buf_new();
- b->default_chunk_size = buf_preferred_chunk_size(size);
- return b;
-}
-
-/** Allocate and return a new buffer with default capacity. */
-buf_t *
-buf_new(void)
-{
- buf_t *buf = tor_malloc_zero(sizeof(buf_t));
- buf->magic = BUFFER_MAGIC;
- buf->default_chunk_size = 4096;
- return buf;
-}
-
-size_t
-buf_get_default_chunk_size(const buf_t *buf)
-{
- return buf->default_chunk_size;
-}
-
-/** Remove all data from <b>buf</b>. */
-void
-buf_clear(buf_t *buf)
-{
- chunk_t *chunk, *next;
- buf->datalen = 0;
- for (chunk = buf->head; chunk; chunk = next) {
- next = chunk->next;
- buf_chunk_free_unchecked(chunk);
- }
- buf->head = buf->tail = NULL;
-}
-
-/** Return the number of bytes stored in <b>buf</b> */
-MOCK_IMPL(size_t,
-buf_datalen, (const buf_t *buf))
-{
- return buf->datalen;
-}
-
-/** Return the total length of all chunks used in <b>buf</b>. */
-size_t
-buf_allocation(const buf_t *buf)
-{
- size_t total = 0;
- const chunk_t *chunk;
- for (chunk = buf->head; chunk; chunk = chunk->next) {
- total += CHUNK_ALLOC_SIZE(chunk->memlen);
- }
- return total;
-}
-
-/** Return the number of bytes that can be added to <b>buf</b> without
- * performing any additional allocation. */
-size_t
-buf_slack(const buf_t *buf)
-{
- if (!buf->tail)
- return 0;
- else
- return CHUNK_REMAINING_CAPACITY(buf->tail);
-}
-
-/** Release storage held by <b>buf</b>. */
-void
-buf_free_(buf_t *buf)
-{
- if (!buf)
- return;
-
- buf_clear(buf);
- buf->magic = 0xdeadbeef;
- tor_free(buf);
-}
-
-/** Return a new copy of <b>in_chunk</b> */
-static chunk_t *
-chunk_copy(const chunk_t *in_chunk)
-{
- chunk_t *newch = tor_memdup(in_chunk, CHUNK_ALLOC_SIZE(in_chunk->memlen));
- total_bytes_allocated_in_chunks += CHUNK_ALLOC_SIZE(in_chunk->memlen);
-#ifdef DEBUG_CHUNK_ALLOC
- newch->DBG_alloc = CHUNK_ALLOC_SIZE(in_chunk->memlen);
-#endif
- newch->next = NULL;
- if (in_chunk->data) {
- off_t offset = in_chunk->data - in_chunk->mem;
- newch->data = newch->mem + offset;
- }
- return newch;
-}
-
-/** Return a new copy of <b>buf</b> */
-buf_t *
-buf_copy(const buf_t *buf)
-{
- chunk_t *ch;
- buf_t *out = buf_new();
- out->default_chunk_size = buf->default_chunk_size;
- for (ch = buf->head; ch; ch = ch->next) {
- chunk_t *newch = chunk_copy(ch);
- if (out->tail) {
- out->tail->next = newch;
- out->tail = newch;
- } else {
- out->head = out->tail = newch;
- }
- }
- out->datalen = buf->datalen;
- return out;
-}
-
-/** Append a new chunk with enough capacity to hold <b>capacity</b> bytes to
- * the tail of <b>buf</b>. If <b>capped</b>, don't allocate a chunk bigger
- * than MAX_CHUNK_ALLOC. */
-chunk_t *
-buf_add_chunk_with_capacity(buf_t *buf, size_t capacity, int capped)
-{
- chunk_t *chunk;
-
- if (CHUNK_ALLOC_SIZE(capacity) < buf->default_chunk_size) {
- chunk = chunk_new_with_alloc_size(buf->default_chunk_size);
- } else if (capped && CHUNK_ALLOC_SIZE(capacity) > MAX_CHUNK_ALLOC) {
- chunk = chunk_new_with_alloc_size(MAX_CHUNK_ALLOC);
- } else {
- chunk = chunk_new_with_alloc_size(buf_preferred_chunk_size(capacity));
- }
-
- chunk->inserted_time = monotime_coarse_get_stamp();
-
- if (buf->tail) {
- tor_assert(buf->head);
- buf->tail->next = chunk;
- buf->tail = chunk;
- } else {
- tor_assert(!buf->head);
- buf->head = buf->tail = chunk;
- }
- check();
- return chunk;
-}
-
-/** Return the age of the oldest chunk in the buffer <b>buf</b>, in
- * timestamp units. Requires the current monotonic timestamp as its
- * input <b>now</b>.
- */
-uint32_t
-buf_get_oldest_chunk_timestamp(const buf_t *buf, uint32_t now)
-{
- if (buf->head) {
- return now - buf->head->inserted_time;
- } else {
- return 0;
- }
-}
-
-size_t
-buf_get_total_allocation(void)
-{
- return total_bytes_allocated_in_chunks;
-}
-
-/** Read up to <b>at_most</b> bytes from the socket <b>fd</b> into
- * <b>chunk</b> (which must be on <b>buf</b>). If we get an EOF, set
- * *<b>reached_eof</b> to 1. Return -1 on error, 0 on eof or blocking,
- * and the number of bytes read otherwise. */
-static inline int
-read_to_chunk(buf_t *buf, chunk_t *chunk, tor_socket_t fd, size_t at_most,
- int *reached_eof, int *socket_error)
-{
- ssize_t read_result;
- if (at_most > CHUNK_REMAINING_CAPACITY(chunk))
- at_most = CHUNK_REMAINING_CAPACITY(chunk);
- read_result = tor_socket_recv(fd, CHUNK_WRITE_PTR(chunk), at_most, 0);
-
- if (read_result < 0) {
- int e = tor_socket_errno(fd);
- if (!ERRNO_IS_EAGAIN(e)) { /* it's a real error */
-#ifdef _WIN32
- if (e == WSAENOBUFS)
- log_warn(LD_NET,"recv() failed: WSAENOBUFS. Not enough ram?");
-#endif
- *socket_error = e;
- return -1;
- }
- return 0; /* would block. */
- } else if (read_result == 0) {
- log_debug(LD_NET,"Encountered eof on fd %d", (int)fd);
- *reached_eof = 1;
- return 0;
- } else { /* actually got bytes. */
- buf->datalen += read_result;
- chunk->datalen += read_result;
- log_debug(LD_NET,"Read %ld bytes. %d on inbuf.", (long)read_result,
- (int)buf->datalen);
- tor_assert(read_result < INT_MAX);
- return (int)read_result;
- }
-}
-
-/** Read from socket <b>s</b>, writing onto end of <b>buf</b>. Read at most
- * <b>at_most</b> bytes, growing the buffer as necessary. If recv() returns 0
- * (because of EOF), set *<b>reached_eof</b> to 1 and return 0. Return -1 on
- * error; else return the number of bytes read.
- */
-/* XXXX indicate "read blocked" somehow? */
-int
-buf_read_from_socket(buf_t *buf, tor_socket_t s, size_t at_most,
- int *reached_eof,
- int *socket_error)
-{
- /* XXXX It's stupid to overload the return values for these functions:
- * "error status" and "number of bytes read" are not mutually exclusive.
- */
- int r = 0;
- size_t total_read = 0;
-
- check();
- tor_assert(reached_eof);
- tor_assert(SOCKET_OK(s));
-
- if (BUG(buf->datalen >= INT_MAX))
- return -1;
- if (BUG(buf->datalen >= INT_MAX - at_most))
- return -1;
-
- while (at_most > total_read) {
- size_t readlen = at_most - total_read;
- chunk_t *chunk;
- if (!buf->tail || CHUNK_REMAINING_CAPACITY(buf->tail) < MIN_READ_LEN) {
- chunk = buf_add_chunk_with_capacity(buf, at_most, 1);
- if (readlen > chunk->memlen)
- readlen = chunk->memlen;
- } else {
- size_t cap = CHUNK_REMAINING_CAPACITY(buf->tail);
- chunk = buf->tail;
- if (cap < readlen)
- readlen = cap;
- }
-
- r = read_to_chunk(buf, chunk, s, readlen, reached_eof, socket_error);
- check();
- if (r < 0)
- return r; /* Error */
- tor_assert(total_read+r < INT_MAX);
- total_read += r;
- if ((size_t)r < readlen) { /* eof, block, or no more to read. */
- break;
- }
- }
- return (int)total_read;
-}
-
-/** Helper for buf_flush_to_socket(): try to write <b>sz</b> bytes from chunk
- * <b>chunk</b> of buffer <b>buf</b> onto socket <b>s</b>. On success, deduct
- * the bytes written from *<b>buf_flushlen</b>. Return the number of bytes
- * written on success, 0 on blocking, -1 on failure.
- */
-static inline int
-flush_chunk(tor_socket_t s, buf_t *buf, chunk_t *chunk, size_t sz,
- size_t *buf_flushlen)
-{
- ssize_t write_result;
-
- if (sz > chunk->datalen)
- sz = chunk->datalen;
- write_result = tor_socket_send(s, chunk->data, sz, 0);
-
- if (write_result < 0) {
- int e = tor_socket_errno(s);
- if (!ERRNO_IS_EAGAIN(e)) { /* it's a real error */
-#ifdef _WIN32
- if (e == WSAENOBUFS)
- log_warn(LD_NET,"write() failed: WSAENOBUFS. Not enough ram?");
-#endif
- return -1;
- }
- log_debug(LD_NET,"write() would block, returning.");
- return 0;
- } else {
- *buf_flushlen -= write_result;
- buf_drain(buf, write_result);
- tor_assert(write_result < INT_MAX);
- return (int)write_result;
- }
-}
-
-/** Write data from <b>buf</b> to the socket <b>s</b>. Write at most
- * <b>sz</b> bytes, decrement *<b>buf_flushlen</b> by
- * the number of bytes actually written, and remove the written bytes
- * from the buffer. Return the number of bytes written on success,
- * -1 on failure. Return 0 if write() would block.
- */
-int
-buf_flush_to_socket(buf_t *buf, tor_socket_t s, size_t sz,
- size_t *buf_flushlen)
-{
- /* XXXX It's stupid to overload the return values for these functions:
- * "error status" and "number of bytes flushed" are not mutually exclusive.
- */
- int r;
- size_t flushed = 0;
- tor_assert(buf_flushlen);
- tor_assert(SOCKET_OK(s));
- if (BUG(*buf_flushlen > buf->datalen)) {
- *buf_flushlen = buf->datalen;
- }
- if (BUG(sz > *buf_flushlen)) {
- sz = *buf_flushlen;
- }
-
- check();
- while (sz) {
- size_t flushlen0;
- tor_assert(buf->head);
- if (buf->head->datalen >= sz)
- flushlen0 = sz;
- else
- flushlen0 = buf->head->datalen;
-
- r = flush_chunk(s, buf, buf->head, flushlen0, buf_flushlen);
- check();
- if (r < 0)
- return r;
- flushed += r;
- sz -= r;
- if (r == 0 || (size_t)r < flushlen0) /* can't flush any more now. */
- break;
- }
- tor_assert(flushed < INT_MAX);
- return (int)flushed;
-}
-
-/** Append <b>string_len</b> bytes from <b>string</b> to the end of
- * <b>buf</b>.
- *
- * Return the new length of the buffer on success, -1 on failure.
- */
-int
-buf_add(buf_t *buf, const char *string, size_t string_len)
-{
- if (!string_len)
- return (int)buf->datalen;
- check();
-
- if (BUG(buf->datalen >= INT_MAX))
- return -1;
- if (BUG(buf->datalen >= INT_MAX - string_len))
- return -1;
-
- while (string_len) {
- size_t copy;
- if (!buf->tail || !CHUNK_REMAINING_CAPACITY(buf->tail))
- buf_add_chunk_with_capacity(buf, string_len, 1);
-
- copy = CHUNK_REMAINING_CAPACITY(buf->tail);
- if (copy > string_len)
- copy = string_len;
- memcpy(CHUNK_WRITE_PTR(buf->tail), string, copy);
- string_len -= copy;
- string += copy;
- buf->datalen += copy;
- buf->tail->datalen += copy;
- }
-
- check();
- tor_assert(buf->datalen < INT_MAX);
- return (int)buf->datalen;
-}
-
-/** Add a nul-terminated <b>string</b> to <b>buf</b>, not including the
- * terminating NUL. */
-void
-buf_add_string(buf_t *buf, const char *string)
-{
- buf_add(buf, string, strlen(string));
-}
-
-/** As tor_snprintf, but write the results into a buf_t */
-void
-buf_add_printf(buf_t *buf, const char *format, ...)
-{
- va_list ap;
- va_start(ap,format);
- buf_add_vprintf(buf, format, ap);
- va_end(ap);
-}
-
-/** As tor_vsnprintf, but write the results into a buf_t. */
-void
-buf_add_vprintf(buf_t *buf, const char *format, va_list args)
-{
- /* XXXX Faster implementations are easy enough, but let's optimize later */
- char *tmp;
- tor_vasprintf(&tmp, format, args);
- buf_add(buf, tmp, strlen(tmp));
- tor_free(tmp);
-}
-
-/** Return a heap-allocated string containing the contents of <b>buf</b>, plus
- * a NUL byte. If <b>sz_out</b> is provided, set *<b>sz_out</b> to the length
- * of the returned string, not including the terminating NUL. */
-char *
-buf_extract(buf_t *buf, size_t *sz_out)
-{
- tor_assert(buf);
-
- size_t sz = buf_datalen(buf);
- char *result;
- result = tor_malloc(sz+1);
- buf_peek(buf, result, sz);
- result[sz] = 0;
- if (sz_out)
- *sz_out = sz;
- return result;
-}
-
-/** Helper: copy the first <b>string_len</b> bytes from <b>buf</b>
- * onto <b>string</b>.
- */
-void
-buf_peek(const buf_t *buf, char *string, size_t string_len)
-{
- chunk_t *chunk;
-
- tor_assert(string);
- /* make sure we don't ask for too much */
- tor_assert(string_len <= buf->datalen);
- /* buf_assert_ok(buf); */
-
- chunk = buf->head;
- while (string_len) {
- size_t copy = string_len;
- tor_assert(chunk);
- if (chunk->datalen < copy)
- copy = chunk->datalen;
- memcpy(string, chunk->data, copy);
- string_len -= copy;
- string += copy;
- chunk = chunk->next;
- }
-}
-
-/** Remove <b>string_len</b> bytes from the front of <b>buf</b>, and store
- * them into <b>string</b>. Return the new buffer size. <b>string_len</b>
- * must be \<= the number of bytes on the buffer.
- */
-int
-buf_get_bytes(buf_t *buf, char *string, size_t string_len)
-{
- /* There must be string_len bytes in buf; write them onto string,
- * then memmove buf back (that is, remove them from buf).
- *
- * Return the number of bytes still on the buffer. */
-
- check();
- buf_peek(buf, string, string_len);
- buf_drain(buf, string_len);
- check();
- tor_assert(buf->datalen < INT_MAX);
- return (int)buf->datalen;
-}
-
-/** Move up to *<b>buf_flushlen</b> bytes from <b>buf_in</b> to
- * <b>buf_out</b>, and modify *<b>buf_flushlen</b> appropriately.
- * Return the number of bytes actually copied.
- */
-int
-buf_move_to_buf(buf_t *buf_out, buf_t *buf_in, size_t *buf_flushlen)
-{
- /* We can do way better here, but this doesn't turn up in any profiles. */
- char b[4096];
- size_t cp, len;
-
- if (BUG(buf_out->datalen >= INT_MAX))
- return -1;
- if (BUG(buf_out->datalen >= INT_MAX - *buf_flushlen))
- return -1;
-
- len = *buf_flushlen;
- if (len > buf_in->datalen)
- len = buf_in->datalen;
-
- cp = len; /* Remember the number of bytes we intend to copy. */
- tor_assert(cp < INT_MAX);
- while (len) {
- /* This isn't the most efficient implementation one could imagine, since
- * it does two copies instead of 1, but I kinda doubt that this will be
- * critical path. */
- size_t n = len > sizeof(b) ? sizeof(b) : len;
- buf_get_bytes(buf_in, b, n);
- buf_add(buf_out, b, n);
- len -= n;
- }
- *buf_flushlen -= cp;
- return (int)cp;
-}
-
-/** Moves all data from <b>buf_in</b> to <b>buf_out</b>, without copying.
- */
-void
-buf_move_all(buf_t *buf_out, buf_t *buf_in)
-{
- tor_assert(buf_out);
- if (!buf_in)
- return;
-
- if (buf_out->head == NULL) {
- buf_out->head = buf_in->head;
- buf_out->tail = buf_in->tail;
- } else {
- buf_out->tail->next = buf_in->head;
- buf_out->tail = buf_in->tail;
- }
-
- buf_out->datalen += buf_in->datalen;
- buf_in->head = buf_in->tail = NULL;
- buf_in->datalen = 0;
-}
-
-/** Internal structure: represents a position in a buffer. */
-typedef struct buf_pos_t {
- const chunk_t *chunk; /**< Which chunk are we pointing to? */
- int pos;/**< Which character inside the chunk's data are we pointing to? */
- size_t chunk_pos; /**< Total length of all previous chunks. */
-} buf_pos_t;
-
-/** Initialize <b>out</b> to point to the first character of <b>buf</b>.*/
-static void
-buf_pos_init(const buf_t *buf, buf_pos_t *out)
-{
- out->chunk = buf->head;
- out->pos = 0;
- out->chunk_pos = 0;
-}
-
-/** Advance <b>out</b> to the first appearance of <b>ch</b> at the current
- * position of <b>out</b>, or later. Return -1 if no instances are found;
- * otherwise returns the absolute position of the character. */
-static off_t
-buf_find_pos_of_char(char ch, buf_pos_t *out)
-{
- const chunk_t *chunk;
- int pos;
- tor_assert(out);
- if (out->chunk) {
- if (out->chunk->datalen) {
- tor_assert(out->pos < (off_t)out->chunk->datalen);
- } else {
- tor_assert(out->pos == 0);
- }
- }
- pos = out->pos;
- for (chunk = out->chunk; chunk; chunk = chunk->next) {
- char *cp = memchr(chunk->data+pos, ch, chunk->datalen - pos);
- if (cp) {
- out->chunk = chunk;
- tor_assert(cp - chunk->data < INT_MAX);
- out->pos = (int)(cp - chunk->data);
- return out->chunk_pos + out->pos;
- } else {
- out->chunk_pos += chunk->datalen;
- pos = 0;
- }
- }
- return -1;
-}
-
-/** Advance <b>pos</b> by a single character, if there are any more characters
- * in the buffer. Returns 0 on success, -1 on failure. */
-static inline int
-buf_pos_inc(buf_pos_t *pos)
-{
- ++pos->pos;
- if (pos->pos == (off_t)pos->chunk->datalen) {
- if (!pos->chunk->next)
- return -1;
- pos->chunk_pos += pos->chunk->datalen;
- pos->chunk = pos->chunk->next;
- pos->pos = 0;
- }
- return 0;
-}
-
-/** Return true iff the <b>n</b>-character string in <b>s</b> appears
- * (verbatim) at <b>pos</b>. */
-static int
-buf_matches_at_pos(const buf_pos_t *pos, const char *s, size_t n)
-{
- buf_pos_t p;
- if (!n)
- return 1;
-
- memcpy(&p, pos, sizeof(p));
-
- while (1) {
- char ch = p.chunk->data[p.pos];
- if (ch != *s)
- return 0;
- ++s;
- /* If we're out of characters that don't match, we match. Check this
- * _before_ we test incrementing pos, in case we're at the end of the
- * string. */
- if (--n == 0)
- return 1;
- if (buf_pos_inc(&p)<0)
- return 0;
- }
-}
-
-/** Return the first position in <b>buf</b> at which the <b>n</b>-character
- * string <b>s</b> occurs, or -1 if it does not occur. */
-int
-buf_find_string_offset(const buf_t *buf, const char *s, size_t n)
-{
- buf_pos_t pos;
- buf_pos_init(buf, &pos);
- while (buf_find_pos_of_char(*s, &pos) >= 0) {
- if (buf_matches_at_pos(&pos, s, n)) {
- tor_assert(pos.chunk_pos + pos.pos < INT_MAX);
- return (int)(pos.chunk_pos + pos.pos);
- } else {
- if (buf_pos_inc(&pos)<0)
- return -1;
- }
- }
- return -1;
-}
-
-/** Return 1 iff <b>buf</b> starts with <b>cmd</b>. <b>cmd</b> must be a null
- * terminated string, of no more than PEEK_BUF_STARTSWITH_MAX bytes. */
-int
-buf_peek_startswith(const buf_t *buf, const char *cmd)
-{
- char tmp[PEEK_BUF_STARTSWITH_MAX];
- size_t clen = strlen(cmd);
- if (clen == 0)
- return 1;
- if (BUG(clen > sizeof(tmp)))
- return 0;
- if (buf->datalen < clen)
- return 0;
- buf_peek(buf, tmp, clen);
- return fast_memeq(tmp, cmd, clen);
-}
-
-/** Return the index within <b>buf</b> at which <b>ch</b> first appears,
- * or -1 if <b>ch</b> does not appear on buf. */
-static off_t
-buf_find_offset_of_char(buf_t *buf, char ch)
-{
- chunk_t *chunk;
- off_t offset = 0;
- for (chunk = buf->head; chunk; chunk = chunk->next) {
- char *cp = memchr(chunk->data, ch, chunk->datalen);
- if (cp)
- return offset + (cp - chunk->data);
- else
- offset += chunk->datalen;
- }
- return -1;
-}
-
-/** Try to read a single LF-terminated line from <b>buf</b>, and write it
- * (including the LF), NUL-terminated, into the *<b>data_len</b> byte buffer
- * at <b>data_out</b>. Set *<b>data_len</b> to the number of bytes in the
- * line, not counting the terminating NUL. Return 1 if we read a whole line,
- * return 0 if we don't have a whole line yet, and return -1 if the line
- * length exceeds *<b>data_len</b>.
- */
-int
-buf_get_line(buf_t *buf, char *data_out, size_t *data_len)
-{
- size_t sz;
- off_t offset;
-
- if (!buf->head)
- return 0;
-
- offset = buf_find_offset_of_char(buf, '\n');
- if (offset < 0)
- return 0;
- sz = (size_t) offset;
- if (sz+2 > *data_len) {
- *data_len = sz + 2;
- return -1;
- }
- buf_get_bytes(buf, data_out, sz+1);
- data_out[sz+1] = '\0';
- *data_len = sz+1;
- return 1;
-}
-
-/** Compress or uncompress the <b>data_len</b> bytes in <b>data</b> using the
- * compression state <b>state</b>, appending the result to <b>buf</b>. If
- * <b>done</b> is true, flush the data in the state and finish the
- * compression/uncompression. Return -1 on failure, 0 on success. */
-int
-buf_add_compress(buf_t *buf, tor_compress_state_t *state,
- const char *data, size_t data_len,
- const int done)
-{
- char *next;
- size_t old_avail, avail;
- int over = 0;
-
- do {
- int need_new_chunk = 0;
- if (!buf->tail || ! CHUNK_REMAINING_CAPACITY(buf->tail)) {
- size_t cap = data_len / 4;
- buf_add_chunk_with_capacity(buf, cap, 1);
- }
- next = CHUNK_WRITE_PTR(buf->tail);
- avail = old_avail = CHUNK_REMAINING_CAPACITY(buf->tail);
- switch (tor_compress_process(state, &next, &avail,
- &data, &data_len, done)) {
- case TOR_COMPRESS_DONE:
- over = 1;
- break;
- case TOR_COMPRESS_ERROR:
- return -1;
- case TOR_COMPRESS_OK:
- if (data_len == 0) {
- tor_assert_nonfatal(!done);
- over = 1;
- }
- break;
- case TOR_COMPRESS_BUFFER_FULL:
- if (avail) {
- /* The compression module says we need more room
- * (TOR_COMPRESS_BUFFER_FULL). Start a new chunk automatically,
- * whether were going to or not. */
- need_new_chunk = 1;
- }
- if (data_len == 0 && !done) {
- /* We've consumed all the input data, though, so there's no
- * point in forging ahead right now. */
- over = 1;
- }
- break;
- }
- buf->datalen += old_avail - avail;
- buf->tail->datalen += old_avail - avail;
- if (need_new_chunk) {
- buf_add_chunk_with_capacity(buf, data_len/4, 1);
- }
-
- } while (!over);
- check();
- return 0;
-}
-
-/** Set *<b>output</b> to contain a copy of the data in *<b>input</b> */
-int
-buf_set_to_copy(buf_t **output,
- const buf_t *input)
-{
- if (*output)
- buf_free(*output);
- *output = buf_copy(input);
- return 0;
-}
-
-/** Log an error and exit if <b>buf</b> is corrupted.
- */
-void
-buf_assert_ok(buf_t *buf)
-{
- tor_assert(buf);
- tor_assert(buf->magic == BUFFER_MAGIC);
-
- if (! buf->head) {
- tor_assert(!buf->tail);
- tor_assert(buf->datalen == 0);
- } else {
- chunk_t *ch;
- size_t total = 0;
- tor_assert(buf->tail);
- for (ch = buf->head; ch; ch = ch->next) {
- total += ch->datalen;
- tor_assert(ch->datalen <= ch->memlen);
- tor_assert(ch->data >= &ch->mem[0]);
- tor_assert(ch->data <= &ch->mem[0]+ch->memlen);
- if (ch->data == &ch->mem[0]+ch->memlen) {
- /* LCOV_EXCL_START */
- static int warned = 0;
- if (! warned) {
- log_warn(LD_BUG, "Invariant violation in buf.c related to #15083");
- warned = 1;
- }
- /* LCOV_EXCL_STOP */
- }
- tor_assert(ch->data+ch->datalen <= &ch->mem[0] + ch->memlen);
- if (!ch->next)
- tor_assert(ch == buf->tail);
- }
- tor_assert(buf->datalen == total);
- }
-}
-
diff --git a/src/common/buffers.h b/src/common/buffers.h
deleted file mode 100644
index 4275152de2..0000000000
--- a/src/common/buffers.h
+++ /dev/null
@@ -1,131 +0,0 @@
-/* Copyright (c) 2001 Matej Pfajfar.
- * Copyright (c) 2001-2004, Roger Dingledine.
- * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2017, The Tor Project, Inc. */
-/* See LICENSE for licensing information */
-
-/**
- * \file buffers.h
- * \brief Header file for buffers.c.
- **/
-
-#ifndef TOR_BUFFERS_H
-#define TOR_BUFFERS_H
-
-#include "compat.h"
-#include "torint.h"
-#include "testsupport.h"
-
-typedef struct buf_t buf_t;
-
-struct tor_compress_state_t;
-
-buf_t *buf_new(void);
-buf_t *buf_new_with_capacity(size_t size);
-size_t buf_get_default_chunk_size(const buf_t *buf);
-void buf_free_(buf_t *buf);
-#define buf_free(b) FREE_AND_NULL(buf_t, buf_free_, (b))
-void buf_clear(buf_t *buf);
-buf_t *buf_copy(const buf_t *buf);
-
-MOCK_DECL(size_t, buf_datalen, (const buf_t *buf));
-size_t buf_allocation(const buf_t *buf);
-size_t buf_slack(const buf_t *buf);
-
-uint32_t buf_get_oldest_chunk_timestamp(const buf_t *buf, uint32_t now);
-size_t buf_get_total_allocation(void);
-
-int buf_read_from_socket(buf_t *buf, tor_socket_t s, size_t at_most,
- int *reached_eof,
- int *socket_error);
-
-int buf_flush_to_socket(buf_t *buf, tor_socket_t s, size_t sz,
- size_t *buf_flushlen);
-
-int buf_add(buf_t *buf, const char *string, size_t string_len);
-void buf_add_string(buf_t *buf, const char *string);
-void buf_add_printf(buf_t *buf, const char *format, ...)
- CHECK_PRINTF(2, 3);
-void buf_add_vprintf(buf_t *buf, const char *format, va_list args)
- CHECK_PRINTF(2, 0);
-int buf_add_compress(buf_t *buf, struct tor_compress_state_t *state,
- const char *data, size_t data_len, int done);
-int buf_move_to_buf(buf_t *buf_out, buf_t *buf_in, size_t *buf_flushlen);
-void buf_move_all(buf_t *buf_out, buf_t *buf_in);
-void buf_peek(const buf_t *buf, char *string, size_t string_len);
-void buf_drain(buf_t *buf, size_t n);
-int buf_get_bytes(buf_t *buf, char *string, size_t string_len);
-int buf_get_line(buf_t *buf, char *data_out, size_t *data_len);
-
-#define PEEK_BUF_STARTSWITH_MAX 16
-int buf_peek_startswith(const buf_t *buf, const char *cmd);
-
-int buf_set_to_copy(buf_t **output,
- const buf_t *input);
-
-void buf_assert_ok(buf_t *buf);
-
-int buf_find_string_offset(const buf_t *buf, const char *s, size_t n);
-void buf_pullup(buf_t *buf, size_t bytes,
- const char **head_out, size_t *len_out);
-char *buf_extract(buf_t *buf, size_t *sz_out);
-
-#ifdef BUFFERS_PRIVATE
-#ifdef TOR_UNIT_TESTS
-buf_t *buf_new_with_data(const char *cp, size_t sz);
-#endif
-size_t buf_preferred_chunk_size(size_t target);
-
-#define DEBUG_CHUNK_ALLOC
-/** A single chunk on a buffer. */
-typedef struct chunk_t {
- struct chunk_t *next; /**< The next chunk on the buffer. */
- size_t datalen; /**< The number of bytes stored in this chunk */
- size_t memlen; /**< The number of usable bytes of storage in <b>mem</b>. */
-#ifdef DEBUG_CHUNK_ALLOC
- size_t DBG_alloc;
-#endif
- char *data; /**< A pointer to the first byte of data stored in <b>mem</b>. */
- uint32_t inserted_time; /**< Timestamp when this chunk was inserted. */
- char mem[FLEXIBLE_ARRAY_MEMBER]; /**< The actual memory used for storage in
- * this chunk. */
-} chunk_t;
-
-/** Magic value for buf_t.magic, to catch pointer errors. */
-#define BUFFER_MAGIC 0xB0FFF312u
-/** A resizeable buffer, optimized for reading and writing. */
-struct buf_t {
- uint32_t magic; /**< Magic cookie for debugging: Must be set to
- * BUFFER_MAGIC. */
- size_t datalen; /**< How many bytes is this buffer holding right now? */
- size_t default_chunk_size; /**< Don't allocate any chunks smaller than
- * this for this buffer. */
- chunk_t *head; /**< First chunk in the list, or NULL for none. */
- chunk_t *tail; /**< Last chunk in the list, or NULL for none. */
-};
-
-chunk_t *buf_add_chunk_with_capacity(buf_t *buf, size_t capacity, int capped);
-/** If a read onto the end of a chunk would be smaller than this number, then
- * just start a new chunk. */
-#define MIN_READ_LEN 8
-
-/** Return the number of bytes that can be written onto <b>chunk</b> without
- * running out of space. */
-static inline size_t
-CHUNK_REMAINING_CAPACITY(const chunk_t *chunk)
-{
- return (chunk->mem + chunk->memlen) - (chunk->data + chunk->datalen);
-}
-
-/** Return the next character in <b>chunk</b> onto which data can be appended.
- * If the chunk is full, this might be off the end of chunk->mem. */
-static inline char *
-CHUNK_WRITE_PTR(chunk_t *chunk)
-{
- return chunk->data + chunk->datalen;
-}
-
-#endif /* defined(BUFFERS_PRIVATE) */
-
-#endif /* !defined(TOR_BUFFERS_H) */
-
diff --git a/src/common/buffers_tls.c b/src/common/buffers_tls.c
deleted file mode 100644
index 041f78b818..0000000000
--- a/src/common/buffers_tls.c
+++ /dev/null
@@ -1,179 +0,0 @@
-/* Copyright (c) 2001 Matej Pfajfar.
- * Copyright (c) 2001-2004, Roger Dingledine.
- * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2017, The Tor Project, Inc. */
-/* See LICENSE for licensing information */
-
-#define BUFFERS_PRIVATE
-#include "orconfig.h"
-#include <stddef.h>
-#include "buffers.h"
-#include "buffers_tls.h"
-#include "compat.h"
-#include "compress.h"
-#include "util.h"
-#include "torint.h"
-#include "torlog.h"
-#include "tortls.h"
-#ifdef HAVE_UNISTD_H
-#include <unistd.h>
-#endif
-
-/** As read_to_chunk(), but return (negative) error code on error, blocking,
- * or TLS, and the number of bytes read otherwise. */
-static inline int
-read_to_chunk_tls(buf_t *buf, chunk_t *chunk, tor_tls_t *tls,
- size_t at_most)
-{
- int read_result;
-
- tor_assert(CHUNK_REMAINING_CAPACITY(chunk) >= at_most);
- read_result = tor_tls_read(tls, CHUNK_WRITE_PTR(chunk), at_most);
- if (read_result < 0)
- return read_result;
- buf->datalen += read_result;
- chunk->datalen += read_result;
- return read_result;
-}
-
-/** As read_to_buf, but reads from a TLS connection, and returns a TLS
- * status value rather than the number of bytes read.
- *
- * Using TLS on OR connections complicates matters in two ways.
- *
- * First, a TLS stream has its own read buffer independent of the
- * connection's read buffer. (TLS needs to read an entire frame from
- * the network before it can decrypt any data. Thus, trying to read 1
- * byte from TLS can require that several KB be read from the network
- * and decrypted. The extra data is stored in TLS's decrypt buffer.)
- * Because the data hasn't been read by Tor (it's still inside the TLS),
- * this means that sometimes a connection "has stuff to read" even when
- * poll() didn't return POLLIN. The tor_tls_get_pending_bytes function is
- * used in connection.c to detect TLS objects with non-empty internal
- * buffers and read from them again.
- *
- * Second, the TLS stream's events do not correspond directly to network
- * events: sometimes, before a TLS stream can read, the network must be
- * ready to write -- or vice versa.
- */
-int
-buf_read_from_tls(buf_t *buf, tor_tls_t *tls, size_t at_most)
-{
- int r = 0;
- size_t total_read = 0;
-
- check_no_tls_errors();
-
- if (BUG(buf->datalen >= INT_MAX))
- return -1;
- if (BUG(buf->datalen >= INT_MAX - at_most))
- return -1;
-
- while (at_most > total_read) {
- size_t readlen = at_most - total_read;
- chunk_t *chunk;
- if (!buf->tail || CHUNK_REMAINING_CAPACITY(buf->tail) < MIN_READ_LEN) {
- chunk = buf_add_chunk_with_capacity(buf, at_most, 1);
- if (readlen > chunk->memlen)
- readlen = chunk->memlen;
- } else {
- size_t cap = CHUNK_REMAINING_CAPACITY(buf->tail);
- chunk = buf->tail;
- if (cap < readlen)
- readlen = cap;
- }
-
- r = read_to_chunk_tls(buf, chunk, tls, readlen);
- if (r < 0)
- return r; /* Error */
- tor_assert(total_read+r < INT_MAX);
- total_read += r;
- if ((size_t)r < readlen) /* eof, block, or no more to read. */
- break;
- }
- return (int)total_read;
-}
-
-/** Helper for buf_flush_to_tls(): try to write <b>sz</b> bytes from chunk
- * <b>chunk</b> of buffer <b>buf</b> onto socket <b>s</b>. (Tries to write
- * more if there is a forced pending write size.) On success, deduct the
- * bytes written from *<b>buf_flushlen</b>. Return the number of bytes
- * written on success, and a TOR_TLS error code on failure or blocking.
- */
-static inline int
-flush_chunk_tls(tor_tls_t *tls, buf_t *buf, chunk_t *chunk,
- size_t sz, size_t *buf_flushlen)
-{
- int r;
- size_t forced;
- char *data;
-
- forced = tor_tls_get_forced_write_size(tls);
- if (forced > sz)
- sz = forced;
- if (chunk) {
- data = chunk->data;
- tor_assert(sz <= chunk->datalen);
- } else {
- data = NULL;
- tor_assert(sz == 0);
- }
- r = tor_tls_write(tls, data, sz);
- if (r < 0)
- return r;
- if (*buf_flushlen > (size_t)r)
- *buf_flushlen -= r;
- else
- *buf_flushlen = 0;
- buf_drain(buf, r);
- log_debug(LD_NET,"flushed %d bytes, %d ready to flush, %d remain.",
- r,(int)*buf_flushlen,(int)buf->datalen);
- return r;
-}
-
-/** As buf_flush_to_socket(), but writes data to a TLS connection. Can write
- * more than <b>flushlen</b> bytes.
- */
-int
-buf_flush_to_tls(buf_t *buf, tor_tls_t *tls, size_t flushlen,
- size_t *buf_flushlen)
-{
- int r;
- size_t flushed = 0;
- ssize_t sz;
- tor_assert(buf_flushlen);
- if (BUG(*buf_flushlen > buf->datalen)) {
- *buf_flushlen = buf->datalen;
- }
- if (BUG(flushlen > *buf_flushlen)) {
- flushlen = *buf_flushlen;
- }
- sz = (ssize_t) flushlen;
-
- /* we want to let tls write even if flushlen is zero, because it might
- * have a partial record pending */
- check_no_tls_errors();
-
- do {
- size_t flushlen0;
- if (buf->head) {
- if ((ssize_t)buf->head->datalen >= sz)
- flushlen0 = sz;
- else
- flushlen0 = buf->head->datalen;
- } else {
- flushlen0 = 0;
- }
-
- r = flush_chunk_tls(tls, buf, buf->head, flushlen0, buf_flushlen);
- if (r < 0)
- return r;
- flushed += r;
- sz -= r;
- if (r == 0) /* Can't flush any more now. */
- break;
- } while (sz > 0);
- tor_assert(flushed < INT_MAX);
- return (int)flushed;
-}
-
diff --git a/src/common/buffers_tls.h b/src/common/buffers_tls.h
deleted file mode 100644
index 2f9fda45a0..0000000000
--- a/src/common/buffers_tls.h
+++ /dev/null
@@ -1,19 +0,0 @@
-/* Copyright (c) 2001 Matej Pfajfar.
- * Copyright (c) 2001-2004, Roger Dingledine.
- * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2017, The Tor Project, Inc. */
-/* See LICENSE for licensing information */
-
-#ifndef TOR_BUFFERS_TLS_H
-#define TOR_BUFFERS_TLS_H
-
-struct buf_t;
-struct tor_tls_t;
-
-int buf_read_from_tls(struct buf_t *buf,
- struct tor_tls_t *tls, size_t at_most);
-int buf_flush_to_tls(struct buf_t *buf, struct tor_tls_t *tls,
- size_t sz, size_t *buf_flushlen);
-
-#endif /* !defined(TOR_BUFFERS_TLS_H) */
-
diff --git a/src/common/ciphers.inc b/src/common/ciphers.inc
deleted file mode 100644
index 0084b3e325..0000000000
--- a/src/common/ciphers.inc
+++ /dev/null
@@ -1,100 +0,0 @@
-/* This is an include file used to define the list of ciphers clients should
- * advertise. Before including it, you should define the CIPHER and XCIPHER
- * macros.
- *
- * This file was automatically generated by get_mozilla_ciphers.py;
- * TLSv1.3 ciphers were added manually.
- */
-
-/* Here are the TLS1.3 ciphers. Note that we don't have XCIPHER instances
- * here, since we don't want to ever fake them.
- */
-#ifdef TLS1_3_TXT_AES_128_GCM_SHA256
- CIPHER(0x1301, TLS1_3_TXT_AES_128_GCM_SHA256)
-#endif
-#ifdef TLS1_3_TXT_AES_256_GCM_SHA384
- CIPHER(0x1302, TLS1_3_TXT_AES_256_GCM_SHA384)
-#endif
-#ifdef TLS1_3_TXT_CHACHA20_POLY1305_SHA256
- CIPHER(0x1303, TLS1_3_TXT_CHACHA20_POLY1305_SHA256)
-#endif
-#ifdef TLS1_3_TXT_AES_128_CCM_SHA256
- CIPHER(0x1304, TLS1_3_TXT_AES_128_CCM_SHA256)
-#endif
-
-/* Here's the machine-generated list. */
-#ifdef TLS1_TXT_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256
- CIPHER(0xc02b, TLS1_TXT_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256)
-#else
- XCIPHER(0xc02b, TLS1_TXT_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256)
-#endif
-#ifdef TLS1_TXT_ECDHE_RSA_WITH_AES_128_GCM_SHA256
- CIPHER(0xc02f, TLS1_TXT_ECDHE_RSA_WITH_AES_128_GCM_SHA256)
-#else
- XCIPHER(0xc02f, TLS1_TXT_ECDHE_RSA_WITH_AES_128_GCM_SHA256)
-#endif
-#ifdef TLS1_TXT_ECDHE_ECDSA_WITH_CHACHA20_POLY1305
- CIPHER(0xcca9, TLS1_TXT_ECDHE_ECDSA_WITH_CHACHA20_POLY1305)
-#else
- XCIPHER(0xcca9, TLS1_TXT_ECDHE_ECDSA_WITH_CHACHA20_POLY1305)
-#endif
-#ifdef TLS1_TXT_ECDHE_RSA_WITH_CHACHA20_POLY1305
- CIPHER(0xcca8, TLS1_TXT_ECDHE_RSA_WITH_CHACHA20_POLY1305)
-#else
- XCIPHER(0xcca8, TLS1_TXT_ECDHE_RSA_WITH_CHACHA20_POLY1305)
-#endif
-#ifdef TLS1_TXT_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384
- CIPHER(0xc02c, TLS1_TXT_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384)
-#else
- XCIPHER(0xc02c, TLS1_TXT_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384)
-#endif
-#ifdef TLS1_TXT_ECDHE_RSA_WITH_AES_256_GCM_SHA384
- CIPHER(0xc030, TLS1_TXT_ECDHE_RSA_WITH_AES_256_GCM_SHA384)
-#else
- XCIPHER(0xc030, TLS1_TXT_ECDHE_RSA_WITH_AES_256_GCM_SHA384)
-#endif
-#ifdef TLS1_TXT_ECDHE_ECDSA_WITH_AES_256_CBC_SHA
- CIPHER(0xc00a, TLS1_TXT_ECDHE_ECDSA_WITH_AES_256_CBC_SHA)
-#else
- XCIPHER(0xc00a, TLS1_TXT_ECDHE_ECDSA_WITH_AES_256_CBC_SHA)
-#endif
-#ifdef TLS1_TXT_ECDHE_ECDSA_WITH_AES_128_CBC_SHA
- CIPHER(0xc009, TLS1_TXT_ECDHE_ECDSA_WITH_AES_128_CBC_SHA)
-#else
- XCIPHER(0xc009, TLS1_TXT_ECDHE_ECDSA_WITH_AES_128_CBC_SHA)
-#endif
-#ifdef TLS1_TXT_ECDHE_RSA_WITH_AES_128_CBC_SHA
- CIPHER(0xc013, TLS1_TXT_ECDHE_RSA_WITH_AES_128_CBC_SHA)
-#else
- XCIPHER(0xc013, TLS1_TXT_ECDHE_RSA_WITH_AES_128_CBC_SHA)
-#endif
-#ifdef TLS1_TXT_ECDHE_RSA_WITH_AES_256_CBC_SHA
- CIPHER(0xc014, TLS1_TXT_ECDHE_RSA_WITH_AES_256_CBC_SHA)
-#else
- XCIPHER(0xc014, TLS1_TXT_ECDHE_RSA_WITH_AES_256_CBC_SHA)
-#endif
-#ifdef TLS1_TXT_DHE_RSA_WITH_AES_128_SHA
- CIPHER(0x0033, TLS1_TXT_DHE_RSA_WITH_AES_128_SHA)
-#else
- XCIPHER(0x0033, TLS1_TXT_DHE_RSA_WITH_AES_128_SHA)
-#endif
-#ifdef TLS1_TXT_DHE_RSA_WITH_AES_256_SHA
- CIPHER(0x0039, TLS1_TXT_DHE_RSA_WITH_AES_256_SHA)
-#else
- XCIPHER(0x0039, TLS1_TXT_DHE_RSA_WITH_AES_256_SHA)
-#endif
-#ifdef TLS1_TXT_RSA_WITH_AES_128_SHA
- CIPHER(0x002f, TLS1_TXT_RSA_WITH_AES_128_SHA)
-#else
- XCIPHER(0x002f, TLS1_TXT_RSA_WITH_AES_128_SHA)
-#endif
-#ifdef TLS1_TXT_RSA_WITH_AES_256_SHA
- CIPHER(0x0035, TLS1_TXT_RSA_WITH_AES_256_SHA)
-#else
- XCIPHER(0x0035, TLS1_TXT_RSA_WITH_AES_256_SHA)
-#endif
-#ifdef SSL3_TXT_RSA_DES_192_CBC3_SHA
- CIPHER(0x000a, SSL3_TXT_RSA_DES_192_CBC3_SHA)
-#else
- XCIPHER(0x000a, SSL3_TXT_RSA_DES_192_CBC3_SHA)
-#endif
diff --git a/src/common/compat.c b/src/common/compat.c
deleted file mode 100644
index 6fdd6ecf00..0000000000
--- a/src/common/compat.c
+++ /dev/null
@@ -1,3531 +0,0 @@
-/* Copyright (c) 2003-2004, Roger Dingledine
- * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2017, The Tor Project, Inc. */
-/* See LICENSE for licensing information */
-
-/**
- * \file compat.c
- * \brief Wrappers to make calls more portable. This code defines
- * functions such as tor_snprintf, get/set various data types,
- * renaming, setting socket options, switching user IDs. It is basically
- * where the non-portable items are conditionally included depending on
- * the platform.
- **/
-
-#define COMPAT_PRIVATE
-#include "compat.h"
-
-#ifdef _WIN32
-#include <winsock2.h>
-#include <windows.h>
-#include <sys/locking.h>
-#endif
-
-#ifdef HAVE_UNAME
-#include <sys/utsname.h>
-#endif
-#ifdef HAVE_SYS_TYPES_H
-#include <sys/types.h>
-#endif
-#ifdef HAVE_SYS_SYSCTL_H
-#include <sys/sysctl.h>
-#endif
-#ifdef HAVE_SYS_STAT_H
-#include <sys/stat.h>
-#endif
-#ifdef HAVE_UTIME_H
-#include <utime.h>
-#endif
-#ifdef HAVE_SYS_UTIME_H
-#include <sys/utime.h>
-#endif
-#ifdef HAVE_UNISTD_H
-#include <unistd.h>
-#endif
-#ifdef HAVE_SYS_FCNTL_H
-#include <sys/fcntl.h>
-#endif
-#ifdef HAVE_PWD_H
-#include <pwd.h>
-#endif
-#ifdef HAVE_GRP_H
-#include <grp.h>
-#endif
-#ifdef HAVE_FCNTL_H
-#include <fcntl.h>
-#endif
-#ifdef HAVE_ERRNO_H
-#include <errno.h>
-#endif
-#ifdef HAVE_ARPA_INET_H
-#include <arpa/inet.h>
-#endif
-#ifdef HAVE_CRT_EXTERNS_H
-#include <crt_externs.h>
-#endif
-#ifdef HAVE_SYS_STATVFS_H
-#include <sys/statvfs.h>
-#endif
-#ifdef HAVE_SYS_CAPABILITY_H
-#include <sys/capability.h>
-#endif
-
-#ifdef _WIN32
-#include <conio.h>
-#include <wchar.h>
-/* Some mingw headers lack these. :p */
-#if defined(HAVE_DECL__GETWCH) && !HAVE_DECL__GETWCH
-wint_t _getwch(void);
-#endif
-#ifndef WEOF
-#define WEOF (wchar_t)(0xFFFF)
-#endif
-#if defined(HAVE_DECL_SECUREZEROMEMORY) && !HAVE_DECL_SECUREZEROMEMORY
-static inline void
-SecureZeroMemory(PVOID ptr, SIZE_T cnt)
-{
- volatile char *vcptr = (volatile char*)ptr;
- while (cnt--)
- *vcptr++ = 0;
-}
-#endif /* defined(HAVE_DECL_SECUREZEROMEMORY) && !HAVE_DECL_SECUREZEROMEMORY */
-#elif defined(HAVE_READPASSPHRASE_H)
-#include <readpassphrase.h>
-#else
-#include "tor_readpassphrase.h"
-#endif /* defined(_WIN32) || ... */
-
-/* Includes for the process attaching prevention */
-#if defined(HAVE_SYS_PRCTL_H) && defined(__linux__)
-/* Only use the linux prctl; the IRIX prctl is totally different */
-#include <sys/prctl.h>
-#elif defined(__APPLE__)
-#include <sys/ptrace.h>
-#endif /* defined(HAVE_SYS_PRCTL_H) && defined(__linux__) || ... */
-
-#ifdef HAVE_NETDB_H
-#include <netdb.h>
-#endif
-#ifdef HAVE_SYS_PARAM_H
-#include <sys/param.h> /* FreeBSD needs this to know what version it is */
-#endif
-#include <stdio.h>
-#include <stdlib.h>
-#include <assert.h>
-#ifdef HAVE_SIGNAL_H
-#include <signal.h>
-#endif
-#ifdef HAVE_MMAP
-#include <sys/mman.h>
-#endif
-#ifdef HAVE_SYS_SYSLIMITS_H
-#include <sys/syslimits.h>
-#endif
-#ifdef HAVE_SYS_FILE_H
-#include <sys/file.h>
-#endif
-
-#include "torlog.h"
-#include "util.h"
-#include "container.h"
-#include "address.h"
-#include "sandbox.h"
-
-/* Inline the strl functions if the platform doesn't have them. */
-#ifndef HAVE_STRLCPY
-#include "strlcpy.c"
-#endif
-#ifndef HAVE_STRLCAT
-#include "strlcat.c"
-#endif
-
-/* When set_max_file_descriptors() is called, update this with the max file
- * descriptor value so we can use it to check the limit when opening a new
- * socket. Default value is what Debian sets as the default hard limit. */
-static int max_sockets = 1024;
-
-/** As open(path, flags, mode), but return an fd with the close-on-exec mode
- * set. */
-int
-tor_open_cloexec(const char *path, int flags, unsigned mode)
-{
- int fd;
- const char *p = sandbox_intern_string(path);
-#ifdef O_CLOEXEC
- fd = open(p, flags|O_CLOEXEC, mode);
- if (fd >= 0)
- return fd;
- /* If we got an error, see if it is EINVAL. EINVAL might indicate that,
- * even though we were built on a system with O_CLOEXEC support, we
- * are running on one without. */
- if (errno != EINVAL)
- return -1;
-#endif /* defined(O_CLOEXEC) */
-
- log_debug(LD_FS, "Opening %s with flags %x", p, flags);
- fd = open(p, flags, mode);
-#ifdef FD_CLOEXEC
- if (fd >= 0) {
- if (fcntl(fd, F_SETFD, FD_CLOEXEC) == -1) {
- log_warn(LD_FS,"Couldn't set FD_CLOEXEC: %s", strerror(errno));
- close(fd);
- return -1;
- }
- }
-#endif /* defined(FD_CLOEXEC) */
- return fd;
-}
-
-/** As fopen(path,mode), but ensures that the O_CLOEXEC bit is set on the
- * underlying file handle. */
-FILE *
-tor_fopen_cloexec(const char *path, const char *mode)
-{
- FILE *result = fopen(path, mode);
-#ifdef FD_CLOEXEC
- if (result != NULL) {
- if (fcntl(fileno(result), F_SETFD, FD_CLOEXEC) == -1) {
- log_warn(LD_FS,"Couldn't set FD_CLOEXEC: %s", strerror(errno));
- fclose(result);
- return NULL;
- }
- }
-#endif /* defined(FD_CLOEXEC) */
- return result;
-}
-
-/** As rename(), but work correctly with the sandbox. */
-int
-tor_rename(const char *path_old, const char *path_new)
-{
- log_debug(LD_FS, "Renaming %s to %s", path_old, path_new);
- return rename(sandbox_intern_string(path_old),
- sandbox_intern_string(path_new));
-}
-
-#if defined(HAVE_MMAP) || defined(RUNNING_DOXYGEN)
-/** Try to create a memory mapping for <b>filename</b> and return it. On
- * failure, return NULL. Sets errno properly, using ERANGE to mean
- * "empty file". Must only be called on trusted Tor-owned files, as changing
- * the underlying file's size causes unspecified behavior. */
-tor_mmap_t *
-tor_mmap_file(const char *filename)
-{
- int fd; /* router file */
- char *string;
- int result;
- tor_mmap_t *res;
- size_t size, filesize;
- struct stat st;
-
- tor_assert(filename);
-
- fd = tor_open_cloexec(filename, O_RDONLY, 0);
- if (fd<0) {
- int save_errno = errno;
- int severity = (errno == ENOENT) ? LOG_INFO : LOG_WARN;
- log_fn(severity, LD_FS,"Could not open \"%s\" for mmap(): %s",filename,
- strerror(errno));
- errno = save_errno;
- return NULL;
- }
-
- /* Get the size of the file */
- result = fstat(fd, &st);
- if (result != 0) {
- int save_errno = errno;
- log_warn(LD_FS,
- "Couldn't fstat opened descriptor for \"%s\" during mmap: %s",
- filename, strerror(errno));
- close(fd);
- errno = save_errno;
- return NULL;
- }
- size = filesize = (size_t)(st.st_size);
-
- if (st.st_size > SSIZE_T_CEILING || (off_t)size < st.st_size) {
- log_warn(LD_FS, "File \"%s\" is too large. Ignoring.",filename);
- errno = EFBIG;
- close(fd);
- return NULL;
- }
- if (!size) {
- /* Zero-length file. If we call mmap on it, it will succeed but
- * return NULL, and bad things will happen. So just fail. */
- log_info(LD_FS,"File \"%s\" is empty. Ignoring.",filename);
- errno = ERANGE;
- close(fd);
- return NULL;
- }
-
- string = mmap(0, size, PROT_READ, MAP_PRIVATE, fd, 0);
- close(fd);
- if (string == MAP_FAILED) {
- int save_errno = errno;
- log_warn(LD_FS,"Could not mmap file \"%s\": %s", filename,
- strerror(errno));
- errno = save_errno;
- return NULL;
- }
-
- res = tor_malloc_zero(sizeof(tor_mmap_t));
- res->data = string;
- res->size = filesize;
- res->mapping_size = size;
-
- return res;
-}
-/** Release storage held for a memory mapping; returns 0 on success,
- * or -1 on failure (and logs a warning). */
-int
-tor_munmap_file(tor_mmap_t *handle)
-{
- int res;
-
- if (handle == NULL)
- return 0;
-
- res = munmap((char*)handle->data, handle->mapping_size);
- if (res == 0) {
- /* munmap() succeeded */
- tor_free(handle);
- } else {
- log_warn(LD_FS, "Failed to munmap() in tor_munmap_file(): %s",
- strerror(errno));
- res = -1;
- }
-
- return res;
-}
-#elif defined(_WIN32)
-tor_mmap_t *
-tor_mmap_file(const char *filename)
-{
- TCHAR tfilename[MAX_PATH]= {0};
- tor_mmap_t *res = tor_malloc_zero(sizeof(tor_mmap_t));
- int empty = 0;
- HANDLE file_handle = INVALID_HANDLE_VALUE;
- DWORD size_low, size_high;
- uint64_t real_size;
- res->mmap_handle = NULL;
-#ifdef UNICODE
- mbstowcs(tfilename,filename,MAX_PATH);
-#else
- strlcpy(tfilename,filename,MAX_PATH);
-#endif
- file_handle = CreateFile(tfilename,
- GENERIC_READ, FILE_SHARE_READ,
- NULL,
- OPEN_EXISTING,
- FILE_ATTRIBUTE_NORMAL,
- 0);
-
- if (file_handle == INVALID_HANDLE_VALUE)
- goto win_err;
-
- size_low = GetFileSize(file_handle, &size_high);
-
- if (size_low == INVALID_FILE_SIZE && GetLastError() != NO_ERROR) {
- log_warn(LD_FS,"Error getting size of \"%s\".",filename);
- goto win_err;
- }
- if (size_low == 0 && size_high == 0) {
- log_info(LD_FS,"File \"%s\" is empty. Ignoring.",filename);
- empty = 1;
- goto err;
- }
- real_size = (((uint64_t)size_high)<<32) | size_low;
- if (real_size > SIZE_MAX) {
- log_warn(LD_FS,"File \"%s\" is too big to map; not trying.",filename);
- goto err;
- }
- res->size = real_size;
-
- res->mmap_handle = CreateFileMapping(file_handle,
- NULL,
- PAGE_READONLY,
- size_high,
- size_low,
- NULL);
- if (res->mmap_handle == NULL)
- goto win_err;
- res->data = (char*) MapViewOfFile(res->mmap_handle,
- FILE_MAP_READ,
- 0, 0, 0);
- if (!res->data)
- goto win_err;
-
- CloseHandle(file_handle);
- return res;
- win_err: {
- DWORD e = GetLastError();
- int severity = (e == ERROR_FILE_NOT_FOUND || e == ERROR_PATH_NOT_FOUND) ?
- LOG_INFO : LOG_WARN;
- char *msg = format_win32_error(e);
- log_fn(severity, LD_FS, "Couldn't mmap file \"%s\": %s", filename, msg);
- tor_free(msg);
- if (e == ERROR_FILE_NOT_FOUND || e == ERROR_PATH_NOT_FOUND)
- errno = ENOENT;
- else
- errno = EINVAL;
- }
- err:
- if (empty)
- errno = ERANGE;
- if (file_handle != INVALID_HANDLE_VALUE)
- CloseHandle(file_handle);
- tor_munmap_file(res);
- return NULL;
-}
-
-/* Unmap the file, and return 0 for success or -1 for failure */
-int
-tor_munmap_file(tor_mmap_t *handle)
-{
- if (handle == NULL)
- return 0;
-
- if (handle->data) {
- /* This is an ugly cast, but without it, "data" in struct tor_mmap_t would
- have to be redefined as non-const. */
- BOOL ok = UnmapViewOfFile( (LPVOID) handle->data);
- if (!ok) {
- log_warn(LD_FS, "Failed to UnmapViewOfFile() in tor_munmap_file(): %d",
- (int)GetLastError());
- }
- }
-
- if (handle->mmap_handle != NULL)
- CloseHandle(handle->mmap_handle);
- tor_free(handle);
-
- return 0;
-}
-#else
-#error "cannot implement tor_mmap_file"
-#endif /* defined(HAVE_MMAP) || ... || ... */
-
-/** Replacement for snprintf. Differs from platform snprintf in two
- * ways: First, always NUL-terminates its output. Second, always
- * returns -1 if the result is truncated. (Note that this return
- * behavior does <i>not</i> conform to C99; it just happens to be
- * easier to emulate "return -1" with conformant implementations than
- * it is to emulate "return number that would be written" with
- * non-conformant implementations.) */
-int
-tor_snprintf(char *str, size_t size, const char *format, ...)
-{
- va_list ap;
- int r;
- va_start(ap,format);
- r = tor_vsnprintf(str,size,format,ap);
- va_end(ap);
- return r;
-}
-
-/** Replacement for vsnprintf; behavior differs as tor_snprintf differs from
- * snprintf.
- */
-int
-tor_vsnprintf(char *str, size_t size, const char *format, va_list args)
-{
- int r;
- if (size == 0)
- return -1; /* no place for the NUL */
- if (size > SIZE_T_CEILING)
- return -1;
-#ifdef _WIN32
- r = _vsnprintf(str, size, format, args);
-#else
- r = vsnprintf(str, size, format, args);
-#endif
- str[size-1] = '\0';
- if (r < 0 || r >= (ssize_t)size)
- return -1;
- return r;
-}
-
-/**
- * Portable asprintf implementation. Does a printf() into a newly malloc'd
- * string. Sets *<b>strp</b> to this string, and returns its length (not
- * including the terminating NUL character).
- *
- * You can treat this function as if its implementation were something like
- <pre>
- char buf[_INFINITY_];
- tor_snprintf(buf, sizeof(buf), fmt, args);
- *strp = tor_strdup(buf);
- return strlen(*strp):
- </pre>
- * Where _INFINITY_ is an imaginary constant so big that any string can fit
- * into it.
- */
-int
-tor_asprintf(char **strp, const char *fmt, ...)
-{
- int r;
- va_list args;
- va_start(args, fmt);
- r = tor_vasprintf(strp, fmt, args);
- va_end(args);
- if (!*strp || r < 0) {
- /* LCOV_EXCL_START */
- log_err(LD_BUG, "Internal error in asprintf");
- tor_assert(0);
- /* LCOV_EXCL_STOP */
- }
- return r;
-}
-
-/**
- * Portable vasprintf implementation. Does a printf() into a newly malloc'd
- * string. Differs from regular vasprintf in the same ways that
- * tor_asprintf() differs from regular asprintf.
- */
-int
-tor_vasprintf(char **strp, const char *fmt, va_list args)
-{
- /* use a temporary variable in case *strp is in args. */
- char *strp_tmp=NULL;
-#ifdef HAVE_VASPRINTF
- /* If the platform gives us one, use it. */
- int r = vasprintf(&strp_tmp, fmt, args);
- if (r < 0)
- *strp = NULL;
- else
- *strp = strp_tmp;
- return r;
-#elif defined(HAVE__VSCPRINTF)
- /* On Windows, _vsnprintf won't tell us the length of the string if it
- * overflows, so we need to use _vcsprintf to tell how much to allocate */
- int len, r;
- va_list tmp_args;
- va_copy(tmp_args, args);
- len = _vscprintf(fmt, tmp_args);
- va_end(tmp_args);
- if (len < 0) {
- *strp = NULL;
- return -1;
- }
- strp_tmp = tor_malloc(len + 1);
- r = _vsnprintf(strp_tmp, len+1, fmt, args);
- if (r != len) {
- tor_free(strp_tmp);
- *strp = NULL;
- return -1;
- }
- *strp = strp_tmp;
- return len;
-#else
- /* Everywhere else, we have a decent vsnprintf that tells us how many
- * characters we need. We give it a try on a short buffer first, since
- * it might be nice to avoid the second vsnprintf call.
- */
- char buf[128];
- int len, r;
- va_list tmp_args;
- va_copy(tmp_args, args);
- /* vsnprintf() was properly checked but tor_vsnprintf() available so
- * why not use it? */
- len = tor_vsnprintf(buf, sizeof(buf), fmt, tmp_args);
- va_end(tmp_args);
- if (len < (int)sizeof(buf)) {
- *strp = tor_strdup(buf);
- return len;
- }
- strp_tmp = tor_malloc(len+1);
- /* use of tor_vsnprintf() will ensure string is null terminated */
- r = tor_vsnprintf(strp_tmp, len+1, fmt, args);
- if (r != len) {
- tor_free(strp_tmp);
- *strp = NULL;
- return -1;
- }
- *strp = strp_tmp;
- return len;
-#endif /* defined(HAVE_VASPRINTF) || ... */
-}
-
-/** Given <b>hlen</b> bytes at <b>haystack</b> and <b>nlen</b> bytes at
- * <b>needle</b>, return a pointer to the first occurrence of the needle
- * within the haystack, or NULL if there is no such occurrence.
- *
- * This function is <em>not</em> timing-safe.
- *
- * Requires that <b>nlen</b> be greater than zero.
- */
-const void *
-tor_memmem(const void *_haystack, size_t hlen,
- const void *_needle, size_t nlen)
-{
-#if defined(HAVE_MEMMEM) && (!defined(__GNUC__) || __GNUC__ >= 2)
- tor_assert(nlen);
- return memmem(_haystack, hlen, _needle, nlen);
-#else
- /* This isn't as fast as the GLIBC implementation, but it doesn't need to
- * be. */
- const char *p, *last_possible_start;
- const char *haystack = (const char*)_haystack;
- const char *needle = (const char*)_needle;
- char first;
- tor_assert(nlen);
-
- if (nlen > hlen)
- return NULL;
-
- p = haystack;
- /* Last position at which the needle could start. */
- last_possible_start = haystack + hlen - nlen;
- first = *(const char*)needle;
- while ((p = memchr(p, first, last_possible_start + 1 - p))) {
- if (fast_memeq(p, needle, nlen))
- return p;
- if (++p > last_possible_start) {
- /* This comparison shouldn't be necessary, since if p was previously
- * equal to last_possible_start, the next memchr call would be
- * "memchr(p, first, 0)", which will return NULL. But it clarifies the
- * logic. */
- return NULL;
- }
- }
- return NULL;
-#endif /* defined(HAVE_MEMMEM) && (!defined(__GNUC__) || __GNUC__ >= 2) */
-}
-
-/**
- * Tables to implement ctypes-replacement TOR_IS*() functions. Each table
- * has 256 bits to look up whether a character is in some set or not. This
- * fails on non-ASCII platforms, but it is hard to find a platform whose
- * character set is not a superset of ASCII nowadays. */
-
-/**@{*/
-const uint32_t TOR_ISALPHA_TABLE[8] =
- { 0, 0, 0x7fffffe, 0x7fffffe, 0, 0, 0, 0 };
-const uint32_t TOR_ISALNUM_TABLE[8] =
- { 0, 0x3ff0000, 0x7fffffe, 0x7fffffe, 0, 0, 0, 0 };
-const uint32_t TOR_ISSPACE_TABLE[8] = { 0x3e00, 0x1, 0, 0, 0, 0, 0, 0 };
-const uint32_t TOR_ISXDIGIT_TABLE[8] =
- { 0, 0x3ff0000, 0x7e, 0x7e, 0, 0, 0, 0 };
-const uint32_t TOR_ISDIGIT_TABLE[8] = { 0, 0x3ff0000, 0, 0, 0, 0, 0, 0 };
-const uint32_t TOR_ISPRINT_TABLE[8] =
- { 0, 0xffffffff, 0xffffffff, 0x7fffffff, 0, 0, 0, 0x0 };
-const uint32_t TOR_ISUPPER_TABLE[8] = { 0, 0, 0x7fffffe, 0, 0, 0, 0, 0 };
-const uint32_t TOR_ISLOWER_TABLE[8] = { 0, 0, 0, 0x7fffffe, 0, 0, 0, 0 };
-
-/** Upper-casing and lowercasing tables to map characters to upper/lowercase
- * equivalents. Used by tor_toupper() and tor_tolower(). */
-/**@{*/
-const uint8_t TOR_TOUPPER_TABLE[256] = {
- 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,
- 16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,
- 32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,
- 48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,
- 64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,
- 80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,
- 96,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,
- 80,81,82,83,84,85,86,87,88,89,90,123,124,125,126,127,
- 128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,
- 144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,
- 160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175,
- 176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191,
- 192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,
- 208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,
- 224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,
- 240,241,242,243,244,245,246,247,248,249,250,251,252,253,254,255,
-};
-const uint8_t TOR_TOLOWER_TABLE[256] = {
- 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,
- 16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,
- 32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,
- 48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,
- 64,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,
- 112,113,114,115,116,117,118,119,120,121,122,91,92,93,94,95,
- 96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,
- 112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,
- 128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,
- 144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,
- 160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175,
- 176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191,
- 192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,
- 208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,
- 224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,
- 240,241,242,243,244,245,246,247,248,249,250,251,252,253,254,255,
-};
-/**@}*/
-
-/** Helper for tor_strtok_r_impl: Advances cp past all characters in
- * <b>sep</b>, and returns its new value. */
-static char *
-strtok_helper(char *cp, const char *sep)
-{
- if (sep[1]) {
- while (*cp && strchr(sep, *cp))
- ++cp;
- } else {
- while (*cp && *cp == *sep)
- ++cp;
- }
- return cp;
-}
-
-/** Implementation of strtok_r for platforms whose coders haven't figured out
- * how to write one. Hey, retrograde libc developers! You can use this code
- * here for free! */
-char *
-tor_strtok_r_impl(char *str, const char *sep, char **lasts)
-{
- char *cp, *start;
- tor_assert(*sep);
- if (str) {
- str = strtok_helper(str, sep);
- if (!*str)
- return NULL;
- start = cp = *lasts = str;
- } else if (!*lasts || !**lasts) {
- return NULL;
- } else {
- start = cp = *lasts;
- }
-
- if (sep[1]) {
- while (*cp && !strchr(sep, *cp))
- ++cp;
- } else {
- cp = strchr(cp, *sep);
- }
-
- if (!cp || !*cp) {
- *lasts = NULL;
- } else {
- *cp++ = '\0';
- *lasts = strtok_helper(cp, sep);
- }
- return start;
-}
-
-#ifdef _WIN32
-/** Take a filename and return a pointer to its final element. This
- * function is called on __FILE__ to fix a MSVC nit where __FILE__
- * contains the full path to the file. This is bad, because it
- * confuses users to find the home directory of the person who
- * compiled the binary in their warning messages.
- */
-const char *
-tor_fix_source_file(const char *fname)
-{
- const char *cp1, *cp2, *r;
- cp1 = strrchr(fname, '/');
- cp2 = strrchr(fname, '\\');
- if (cp1 && cp2) {
- r = (cp1<cp2)?(cp2+1):(cp1+1);
- } else if (cp1) {
- r = cp1+1;
- } else if (cp2) {
- r = cp2+1;
- } else {
- r = fname;
- }
- return r;
-}
-#endif /* defined(_WIN32) */
-
-/**
- * Read a 16-bit value beginning at <b>cp</b>. Equivalent to
- * *(uint16_t*)(cp), but will not cause segfaults on platforms that forbid
- * unaligned memory access.
- */
-uint16_t
-get_uint16(const void *cp)
-{
- uint16_t v;
- memcpy(&v,cp,2);
- return v;
-}
-/**
- * Read a 32-bit value beginning at <b>cp</b>. Equivalent to
- * *(uint32_t*)(cp), but will not cause segfaults on platforms that forbid
- * unaligned memory access.
- */
-uint32_t
-get_uint32(const void *cp)
-{
- uint32_t v;
- memcpy(&v,cp,4);
- return v;
-}
-/**
- * Read a 64-bit value beginning at <b>cp</b>. Equivalent to
- * *(uint64_t*)(cp), but will not cause segfaults on platforms that forbid
- * unaligned memory access.
- */
-uint64_t
-get_uint64(const void *cp)
-{
- uint64_t v;
- memcpy(&v,cp,8);
- return v;
-}
-
-/**
- * Set a 16-bit value beginning at <b>cp</b> to <b>v</b>. Equivalent to
- * *(uint16_t*)(cp) = v, but will not cause segfaults on platforms that forbid
- * unaligned memory access. */
-void
-set_uint16(void *cp, uint16_t v)
-{
- memcpy(cp,&v,2);
-}
-/**
- * Set a 32-bit value beginning at <b>cp</b> to <b>v</b>. Equivalent to
- * *(uint32_t*)(cp) = v, but will not cause segfaults on platforms that forbid
- * unaligned memory access. */
-void
-set_uint32(void *cp, uint32_t v)
-{
- memcpy(cp,&v,4);
-}
-/**
- * Set a 64-bit value beginning at <b>cp</b> to <b>v</b>. Equivalent to
- * *(uint64_t*)(cp) = v, but will not cause segfaults on platforms that forbid
- * unaligned memory access. */
-void
-set_uint64(void *cp, uint64_t v)
-{
- memcpy(cp,&v,8);
-}
-
-/**
- * Rename the file <b>from</b> to the file <b>to</b>. On Unix, this is
- * the same as rename(2). On windows, this removes <b>to</b> first if
- * it already exists.
- * Returns 0 on success. Returns -1 and sets errno on failure.
- */
-int
-replace_file(const char *from, const char *to)
-{
-#ifndef _WIN32
- return tor_rename(from, to);
-#else
- switch (file_status(to))
- {
- case FN_NOENT:
- break;
- case FN_FILE:
- case FN_EMPTY:
- if (unlink(to)) return -1;
- break;
- case FN_ERROR:
- return -1;
- case FN_DIR:
- errno = EISDIR;
- return -1;
- }
- return tor_rename(from,to);
-#endif /* !defined(_WIN32) */
-}
-
-/** Change <b>fname</b>'s modification time to now. */
-int
-touch_file(const char *fname)
-{
- if (utime(fname, NULL)!=0)
- return -1;
- return 0;
-}
-
-/** Represents a lockfile on which we hold the lock. */
-struct tor_lockfile_t {
- /** Name of the file */
- char *filename;
- /** File descriptor used to hold the file open */
- int fd;
-};
-
-/** Try to get a lock on the lockfile <b>filename</b>, creating it as
- * necessary. If someone else has the lock and <b>blocking</b> is true,
- * wait until the lock is available. Otherwise return immediately whether
- * we succeeded or not.
- *
- * Set *<b>locked_out</b> to true if somebody else had the lock, and to false
- * otherwise.
- *
- * Return a <b>tor_lockfile_t</b> on success, NULL on failure.
- *
- * (Implementation note: because we need to fall back to fcntl on some
- * platforms, these locks are per-process, not per-thread. If you want
- * to do in-process locking, use tor_mutex_t like a normal person.
- * On Windows, when <b>blocking</b> is true, the maximum time that
- * is actually waited is 10 seconds, after which NULL is returned
- * and <b>locked_out</b> is set to 1.)
- */
-tor_lockfile_t *
-tor_lockfile_lock(const char *filename, int blocking, int *locked_out)
-{
- tor_lockfile_t *result;
- int fd;
- *locked_out = 0;
-
- log_info(LD_FS, "Locking \"%s\"", filename);
- fd = tor_open_cloexec(filename, O_RDWR|O_CREAT|O_TRUNC, 0600);
- if (fd < 0) {
- log_warn(LD_FS,"Couldn't open \"%s\" for locking: %s", filename,
- strerror(errno));
- return NULL;
- }
-
-#ifdef _WIN32
- _lseek(fd, 0, SEEK_SET);
- if (_locking(fd, blocking ? _LK_LOCK : _LK_NBLCK, 1) < 0) {
- if (errno != EACCES && errno != EDEADLOCK)
- log_warn(LD_FS,"Couldn't lock \"%s\": %s", filename, strerror(errno));
- else
- *locked_out = 1;
- close(fd);
- return NULL;
- }
-#elif defined(HAVE_FLOCK)
- if (flock(fd, LOCK_EX|(blocking ? 0 : LOCK_NB)) < 0) {
- if (errno != EWOULDBLOCK)
- log_warn(LD_FS,"Couldn't lock \"%s\": %s", filename, strerror(errno));
- else
- *locked_out = 1;
- close(fd);
- return NULL;
- }
-#else
- {
- struct flock lock;
- memset(&lock, 0, sizeof(lock));
- lock.l_type = F_WRLCK;
- lock.l_whence = SEEK_SET;
- if (fcntl(fd, blocking ? F_SETLKW : F_SETLK, &lock) < 0) {
- if (errno != EACCES && errno != EAGAIN)
- log_warn(LD_FS, "Couldn't lock \"%s\": %s", filename, strerror(errno));
- else
- *locked_out = 1;
- close(fd);
- return NULL;
- }
- }
-#endif /* defined(_WIN32) || ... */
-
- result = tor_malloc(sizeof(tor_lockfile_t));
- result->filename = tor_strdup(filename);
- result->fd = fd;
- return result;
-}
-
-/** Release the lock held as <b>lockfile</b>. */
-void
-tor_lockfile_unlock(tor_lockfile_t *lockfile)
-{
- tor_assert(lockfile);
-
- log_info(LD_FS, "Unlocking \"%s\"", lockfile->filename);
-#ifdef _WIN32
- _lseek(lockfile->fd, 0, SEEK_SET);
- if (_locking(lockfile->fd, _LK_UNLCK, 1) < 0) {
- log_warn(LD_FS,"Error unlocking \"%s\": %s", lockfile->filename,
- strerror(errno));
- }
-#elif defined(HAVE_FLOCK)
- if (flock(lockfile->fd, LOCK_UN) < 0) {
- log_warn(LD_FS, "Error unlocking \"%s\": %s", lockfile->filename,
- strerror(errno));
- }
-#else
- /* Closing the lockfile is sufficient. */
-#endif /* defined(_WIN32) || ... */
-
- close(lockfile->fd);
- lockfile->fd = -1;
- tor_free(lockfile->filename);
- tor_free(lockfile);
-}
-
-/** @{ */
-/** Some old versions of Unix didn't define constants for these values,
- * and instead expect you to say 0, 1, or 2. */
-#ifndef SEEK_SET
-#define SEEK_SET 0
-#endif
-#ifndef SEEK_CUR
-#define SEEK_CUR 1
-#endif
-#ifndef SEEK_END
-#define SEEK_END 2
-#endif
-/** @} */
-
-/** Return the position of <b>fd</b> with respect to the start of the file. */
-off_t
-tor_fd_getpos(int fd)
-{
-#ifdef _WIN32
- return (off_t) _lseek(fd, 0, SEEK_CUR);
-#else
- return (off_t) lseek(fd, 0, SEEK_CUR);
-#endif
-}
-
-/** Move <b>fd</b> to the end of the file. Return -1 on error, 0 on success.
- * If the file is a pipe, do nothing and succeed.
- **/
-int
-tor_fd_seekend(int fd)
-{
-#ifdef _WIN32
- return _lseek(fd, 0, SEEK_END) < 0 ? -1 : 0;
-#else
- off_t rc = lseek(fd, 0, SEEK_END) < 0 ? -1 : 0;
-#ifdef ESPIPE
- /* If we get an error and ESPIPE, then it's a pipe or a socket of a fifo:
- * no need to worry. */
- if (rc < 0 && errno == ESPIPE)
- rc = 0;
-#endif /* defined(ESPIPE) */
- return (rc < 0) ? -1 : 0;
-#endif /* defined(_WIN32) */
-}
-
-/** Move <b>fd</b> to position <b>pos</b> in the file. Return -1 on error, 0
- * on success. */
-int
-tor_fd_setpos(int fd, off_t pos)
-{
-#ifdef _WIN32
- return _lseek(fd, pos, SEEK_SET) < 0 ? -1 : 0;
-#else
- return lseek(fd, pos, SEEK_SET) < 0 ? -1 : 0;
-#endif
-}
-
-/** Replacement for ftruncate(fd, 0): move to the front of the file and remove
- * all the rest of the file. Return -1 on error, 0 on success. */
-int
-tor_ftruncate(int fd)
-{
- /* Rumor has it that some versions of ftruncate do not move the file pointer.
- */
- if (tor_fd_setpos(fd, 0) < 0)
- return -1;
-
-#ifdef _WIN32
- return _chsize(fd, 0);
-#else
- return ftruncate(fd, 0);
-#endif
-}
-
-#undef DEBUG_SOCKET_COUNTING
-#ifdef DEBUG_SOCKET_COUNTING
-/** A bitarray of all fds that should be passed to tor_socket_close(). Only
- * used if DEBUG_SOCKET_COUNTING is defined. */
-static bitarray_t *open_sockets = NULL;
-/** The size of <b>open_sockets</b>, in bits. */
-static int max_socket = -1;
-#endif /* defined(DEBUG_SOCKET_COUNTING) */
-
-/** Count of number of sockets currently open. (Undercounts sockets opened by
- * eventdns and libevent.) */
-static int n_sockets_open = 0;
-
-/** Mutex to protect open_sockets, max_socket, and n_sockets_open. */
-static tor_mutex_t *socket_accounting_mutex = NULL;
-
-/** Helper: acquire the socket accounting lock. */
-static inline void
-socket_accounting_lock(void)
-{
- if (PREDICT_UNLIKELY(!socket_accounting_mutex))
- socket_accounting_mutex = tor_mutex_new();
- tor_mutex_acquire(socket_accounting_mutex);
-}
-
-/** Helper: release the socket accounting lock. */
-static inline void
-socket_accounting_unlock(void)
-{
- tor_mutex_release(socket_accounting_mutex);
-}
-
-/** As close(), but guaranteed to work for sockets across platforms (including
- * Windows, where close()ing a socket doesn't work. Returns 0 on success and
- * the socket error code on failure. */
-int
-tor_close_socket_simple(tor_socket_t s)
-{
- int r = 0;
-
- /* On Windows, you have to call close() on fds returned by open(),
- * and closesocket() on fds returned by socket(). On Unix, everything
- * gets close()'d. We abstract this difference by always using
- * tor_close_socket to close sockets, and always using close() on
- * files.
- */
- #if defined(_WIN32)
- r = closesocket(s);
- #else
- r = close(s);
- #endif
-
- if (r != 0) {
- int err = tor_socket_errno(-1);
- log_info(LD_NET, "Close returned an error: %s", tor_socket_strerror(err));
- return err;
- }
-
- return r;
-}
-
-/** As tor_close_socket_simple(), but keeps track of the number
- * of open sockets. Returns 0 on success, -1 on failure. */
-MOCK_IMPL(int,
-tor_close_socket,(tor_socket_t s))
-{
- int r = tor_close_socket_simple(s);
-
- socket_accounting_lock();
-#ifdef DEBUG_SOCKET_COUNTING
- if (s > max_socket || ! bitarray_is_set(open_sockets, s)) {
- log_warn(LD_BUG, "Closing a socket (%d) that wasn't returned by tor_open_"
- "socket(), or that was already closed or something.", s);
- } else {
- tor_assert(open_sockets && s <= max_socket);
- bitarray_clear(open_sockets, s);
- }
-#endif /* defined(DEBUG_SOCKET_COUNTING) */
- if (r == 0) {
- --n_sockets_open;
- } else {
-#ifdef _WIN32
- if (r != WSAENOTSOCK)
- --n_sockets_open;
-#else
- if (r != EBADF)
- --n_sockets_open; // LCOV_EXCL_LINE -- EIO and EINTR too hard to force.
-#endif /* defined(_WIN32) */
- r = -1;
- }
-
- tor_assert_nonfatal(n_sockets_open >= 0);
- socket_accounting_unlock();
- return r;
-}
-
-/** @{ */
-#ifdef DEBUG_SOCKET_COUNTING
-/** Helper: if DEBUG_SOCKET_COUNTING is enabled, remember that <b>s</b> is
- * now an open socket. */
-static inline void
-mark_socket_open(tor_socket_t s)
-{
- /* XXXX This bitarray business will NOT work on windows: sockets aren't
- small ints there. */
- if (s > max_socket) {
- if (max_socket == -1) {
- open_sockets = bitarray_init_zero(s+128);
- max_socket = s+128;
- } else {
- open_sockets = bitarray_expand(open_sockets, max_socket, s+128);
- max_socket = s+128;
- }
- }
- if (bitarray_is_set(open_sockets, s)) {
- log_warn(LD_BUG, "I thought that %d was already open, but socket() just "
- "gave it to me!", s);
- }
- bitarray_set(open_sockets, s);
-}
-#else /* !(defined(DEBUG_SOCKET_COUNTING)) */
-#define mark_socket_open(s) ((void) (s))
-#endif /* defined(DEBUG_SOCKET_COUNTING) */
-/** @} */
-
-/** As socket(), but counts the number of open sockets. */
-MOCK_IMPL(tor_socket_t,
-tor_open_socket,(int domain, int type, int protocol))
-{
- return tor_open_socket_with_extensions(domain, type, protocol, 1, 0);
-}
-
-/** Mockable wrapper for connect(). */
-MOCK_IMPL(tor_socket_t,
-tor_connect_socket,(tor_socket_t sock, const struct sockaddr *address,
- socklen_t address_len))
-{
- return connect(sock,address,address_len);
-}
-
-/** As socket(), but creates a nonblocking socket and
- * counts the number of open sockets. */
-tor_socket_t
-tor_open_socket_nonblocking(int domain, int type, int protocol)
-{
- return tor_open_socket_with_extensions(domain, type, protocol, 1, 1);
-}
-
-/** As socket(), but counts the number of open sockets and handles
- * socket creation with either of SOCK_CLOEXEC and SOCK_NONBLOCK specified.
- * <b>cloexec</b> and <b>nonblock</b> should be either 0 or 1 to indicate
- * if the corresponding extension should be used.*/
-tor_socket_t
-tor_open_socket_with_extensions(int domain, int type, int protocol,
- int cloexec, int nonblock)
-{
- tor_socket_t s;
-
- /* We are about to create a new file descriptor so make sure we have
- * enough of them. */
- if (get_n_open_sockets() >= max_sockets - 1) {
-#ifdef _WIN32
- WSASetLastError(WSAEMFILE);
-#else
- errno = EMFILE;
-#endif
- return TOR_INVALID_SOCKET;
- }
-
-#if defined(SOCK_CLOEXEC) && defined(SOCK_NONBLOCK)
- int ext_flags = (cloexec ? SOCK_CLOEXEC : 0) |
- (nonblock ? SOCK_NONBLOCK : 0);
- s = socket(domain, type|ext_flags, protocol);
- if (SOCKET_OK(s))
- goto socket_ok;
- /* If we got an error, see if it is EINVAL. EINVAL might indicate that,
- * even though we were built on a system with SOCK_CLOEXEC and SOCK_NONBLOCK
- * support, we are running on one without. */
- if (errno != EINVAL)
- return s;
-#endif /* defined(SOCK_CLOEXEC) && defined(SOCK_NONBLOCK) */
-
- s = socket(domain, type, protocol);
- if (! SOCKET_OK(s))
- return s;
-
-#if defined(FD_CLOEXEC)
- if (cloexec) {
- if (fcntl(s, F_SETFD, FD_CLOEXEC) == -1) {
- log_warn(LD_FS,"Couldn't set FD_CLOEXEC: %s", strerror(errno));
- tor_close_socket_simple(s);
- return TOR_INVALID_SOCKET;
- }
- }
-#else /* !(defined(FD_CLOEXEC)) */
- (void)cloexec;
-#endif /* defined(FD_CLOEXEC) */
-
- if (nonblock) {
- if (set_socket_nonblocking(s) == -1) {
- tor_close_socket_simple(s);
- return TOR_INVALID_SOCKET;
- }
- }
-
- goto socket_ok; /* So that socket_ok will not be unused. */
-
- socket_ok:
- tor_take_socket_ownership(s);
- return s;
-}
-
-/**
- * For socket accounting: remember that we are the owner of the socket
- * <b>s</b>. This will prevent us from overallocating sockets, and prevent us
- * from asserting later when we close the socket <b>s</b>.
- */
-void
-tor_take_socket_ownership(tor_socket_t s)
-{
- socket_accounting_lock();
- ++n_sockets_open;
- mark_socket_open(s);
- socket_accounting_unlock();
-}
-
-/** As accept(), but counts the number of open sockets. */
-tor_socket_t
-tor_accept_socket(tor_socket_t sockfd, struct sockaddr *addr, socklen_t *len)
-{
- return tor_accept_socket_with_extensions(sockfd, addr, len, 1, 0);
-}
-
-/** As accept(), but returns a nonblocking socket and
- * counts the number of open sockets. */
-tor_socket_t
-tor_accept_socket_nonblocking(tor_socket_t sockfd, struct sockaddr *addr,
- socklen_t *len)
-{
- return tor_accept_socket_with_extensions(sockfd, addr, len, 1, 1);
-}
-
-/** As accept(), but counts the number of open sockets and handles
- * socket creation with either of SOCK_CLOEXEC and SOCK_NONBLOCK specified.
- * <b>cloexec</b> and <b>nonblock</b> should be either 0 or 1 to indicate
- * if the corresponding extension should be used.*/
-tor_socket_t
-tor_accept_socket_with_extensions(tor_socket_t sockfd, struct sockaddr *addr,
- socklen_t *len, int cloexec, int nonblock)
-{
- tor_socket_t s;
-
- /* We are about to create a new file descriptor so make sure we have
- * enough of them. */
- if (get_n_open_sockets() >= max_sockets - 1) {
-#ifdef _WIN32
- WSASetLastError(WSAEMFILE);
-#else
- errno = EMFILE;
-#endif
- return TOR_INVALID_SOCKET;
- }
-
-#if defined(HAVE_ACCEPT4) && defined(SOCK_CLOEXEC) \
- && defined(SOCK_NONBLOCK)
- int ext_flags = (cloexec ? SOCK_CLOEXEC : 0) |
- (nonblock ? SOCK_NONBLOCK : 0);
- s = accept4(sockfd, addr, len, ext_flags);
- if (SOCKET_OK(s))
- goto socket_ok;
- /* If we got an error, see if it is ENOSYS. ENOSYS indicates that,
- * even though we were built on a system with accept4 support, we
- * are running on one without. Also, check for EINVAL, which indicates that
- * we are missing SOCK_CLOEXEC/SOCK_NONBLOCK support. */
- if (errno != EINVAL && errno != ENOSYS)
- return s;
-#endif /* defined(HAVE_ACCEPT4) && defined(SOCK_CLOEXEC) ... */
-
- s = accept(sockfd, addr, len);
- if (!SOCKET_OK(s))
- return s;
-
-#if defined(FD_CLOEXEC)
- if (cloexec) {
- if (fcntl(s, F_SETFD, FD_CLOEXEC) == -1) {
- log_warn(LD_NET, "Couldn't set FD_CLOEXEC: %s", strerror(errno));
- tor_close_socket_simple(s);
- return TOR_INVALID_SOCKET;
- }
- }
-#else /* !(defined(FD_CLOEXEC)) */
- (void)cloexec;
-#endif /* defined(FD_CLOEXEC) */
-
- if (nonblock) {
- if (set_socket_nonblocking(s) == -1) {
- tor_close_socket_simple(s);
- return TOR_INVALID_SOCKET;
- }
- }
-
- goto socket_ok; /* So that socket_ok will not be unused. */
-
- socket_ok:
- tor_take_socket_ownership(s);
- return s;
-}
-
-/** Return the number of sockets we currently have opened. */
-int
-get_n_open_sockets(void)
-{
- int n;
- socket_accounting_lock();
- n = n_sockets_open;
- socket_accounting_unlock();
- return n;
-}
-
-/** Mockable wrapper for getsockname(). */
-MOCK_IMPL(int,
-tor_getsockname,(tor_socket_t sock, struct sockaddr *address,
- socklen_t *address_len))
-{
- return getsockname(sock, address, address_len);
-}
-
-/**
- * Find the local address associated with the socket <b>sock</b>, and
- * place it in *<b>addr_out</b>. Return 0 on success, -1 on failure.
- *
- * (As tor_getsockname, but instead places the result in a tor_addr_t.) */
-int
-tor_addr_from_getsockname(tor_addr_t *addr_out, tor_socket_t sock)
-{
- struct sockaddr_storage ss;
- socklen_t ss_len = sizeof(ss);
- memset(&ss, 0, sizeof(ss));
-
- if (tor_getsockname(sock, (struct sockaddr *) &ss, &ss_len) < 0)
- return -1;
-
- return tor_addr_from_sockaddr(addr_out, (struct sockaddr *)&ss, NULL);
-}
-
-/** Turn <b>socket</b> into a nonblocking socket. Return 0 on success, -1
- * on failure.
- */
-int
-set_socket_nonblocking(tor_socket_t sock)
-{
-#if defined(_WIN32)
- unsigned long nonblocking = 1;
- ioctlsocket(sock, FIONBIO, (unsigned long*) &nonblocking);
-#else
- int flags;
-
- flags = fcntl(sock, F_GETFL, 0);
- if (flags == -1) {
- log_warn(LD_NET, "Couldn't get file status flags: %s", strerror(errno));
- return -1;
- }
- flags |= O_NONBLOCK;
- if (fcntl(sock, F_SETFL, flags) == -1) {
- log_warn(LD_NET, "Couldn't set file status flags: %s", strerror(errno));
- return -1;
- }
-#endif /* defined(_WIN32) */
-
- return 0;
-}
-
-/**
- * Allocate a pair of connected sockets. (Like socketpair(family,
- * type,protocol,fd), but works on systems that don't have
- * socketpair.)
- *
- * Currently, only (AF_UNIX, SOCK_STREAM, 0) sockets are supported.
- *
- * Note that on systems without socketpair, this call will fail if
- * localhost is inaccessible (for example, if the networking
- * stack is down). And even if it succeeds, the socket pair will not
- * be able to read while localhost is down later (the socket pair may
- * even close, depending on OS-specific timeouts).
- *
- * Returns 0 on success and -errno on failure; do not rely on the value
- * of errno or WSAGetLastError().
- **/
-/* It would be nicer just to set errno, but that won't work for windows. */
-int
-tor_socketpair(int family, int type, int protocol, tor_socket_t fd[2])
-{
-//don't use win32 socketpairs (they are always bad)
-#if defined(HAVE_SOCKETPAIR) && !defined(_WIN32)
- int r;
-
-#ifdef SOCK_CLOEXEC
- r = socketpair(family, type|SOCK_CLOEXEC, protocol, fd);
- if (r == 0)
- goto sockets_ok;
- /* If we got an error, see if it is EINVAL. EINVAL might indicate that,
- * even though we were built on a system with SOCK_CLOEXEC support, we
- * are running on one without. */
- if (errno != EINVAL)
- return -errno;
-#endif /* defined(SOCK_CLOEXEC) */
-
- r = socketpair(family, type, protocol, fd);
- if (r < 0)
- return -errno;
-
-#if defined(FD_CLOEXEC)
- if (SOCKET_OK(fd[0])) {
- r = fcntl(fd[0], F_SETFD, FD_CLOEXEC);
- if (r == -1) {
- close(fd[0]);
- close(fd[1]);
- return -errno;
- }
- }
- if (SOCKET_OK(fd[1])) {
- r = fcntl(fd[1], F_SETFD, FD_CLOEXEC);
- if (r == -1) {
- close(fd[0]);
- close(fd[1]);
- return -errno;
- }
- }
-#endif /* defined(FD_CLOEXEC) */
- goto sockets_ok; /* So that sockets_ok will not be unused. */
-
- sockets_ok:
- socket_accounting_lock();
- if (SOCKET_OK(fd[0])) {
- ++n_sockets_open;
- mark_socket_open(fd[0]);
- }
- if (SOCKET_OK(fd[1])) {
- ++n_sockets_open;
- mark_socket_open(fd[1]);
- }
- socket_accounting_unlock();
-
- return 0;
-#else /* !(defined(HAVE_SOCKETPAIR) && !defined(_WIN32)) */
- return tor_ersatz_socketpair(family, type, protocol, fd);
-#endif /* defined(HAVE_SOCKETPAIR) && !defined(_WIN32) */
-}
-
-#ifdef NEED_ERSATZ_SOCKETPAIR
-
-static inline socklen_t
-SIZEOF_SOCKADDR(int domain)
-{
- switch (domain) {
- case AF_INET:
- return sizeof(struct sockaddr_in);
- case AF_INET6:
- return sizeof(struct sockaddr_in6);
- default:
- return 0;
- }
-}
-
-/**
- * Helper used to implement socketpair on systems that lack it, by
- * making a direct connection to localhost.
- */
-STATIC int
-tor_ersatz_socketpair(int family, int type, int protocol, tor_socket_t fd[2])
-{
- /* This socketpair does not work when localhost is down. So
- * it's really not the same thing at all. But it's close enough
- * for now, and really, when localhost is down sometimes, we
- * have other problems too.
- */
- tor_socket_t listener = TOR_INVALID_SOCKET;
- tor_socket_t connector = TOR_INVALID_SOCKET;
- tor_socket_t acceptor = TOR_INVALID_SOCKET;
- tor_addr_t listen_tor_addr;
- struct sockaddr_storage connect_addr_ss, listen_addr_ss;
- struct sockaddr *listen_addr = (struct sockaddr *) &listen_addr_ss;
- uint16_t listen_port = 0;
- tor_addr_t connect_tor_addr;
- uint16_t connect_port = 0;
- struct sockaddr *connect_addr = (struct sockaddr *) &connect_addr_ss;
- socklen_t size;
- int saved_errno = -1;
- int ersatz_domain = AF_INET;
-
- memset(&connect_tor_addr, 0, sizeof(connect_tor_addr));
- memset(&connect_addr_ss, 0, sizeof(connect_addr_ss));
- memset(&listen_tor_addr, 0, sizeof(listen_tor_addr));
- memset(&listen_addr_ss, 0, sizeof(listen_addr_ss));
-
- if (protocol
-#ifdef AF_UNIX
- || family != AF_UNIX
-#endif
- ) {
-#ifdef _WIN32
- return -WSAEAFNOSUPPORT;
-#else
- return -EAFNOSUPPORT;
-#endif
- }
- if (!fd) {
- return -EINVAL;
- }
-
- listener = tor_open_socket(ersatz_domain, type, 0);
- if (!SOCKET_OK(listener)) {
- int first_errno = tor_socket_errno(-1);
- if (first_errno == SOCK_ERRNO(EPROTONOSUPPORT)
- && ersatz_domain == AF_INET) {
- /* Assume we're on an IPv6-only system */
- ersatz_domain = AF_INET6;
- listener = tor_open_socket(ersatz_domain, type, 0);
- if (!SOCKET_OK(listener)) {
- /* Keep the previous behaviour, which was to return the IPv4 error.
- * (This may be less informative on IPv6-only systems.)
- * XX/teor - is there a better way to decide which errno to return?
- * (I doubt we care much either way, once there is an error.)
- */
- return -first_errno;
- }
- }
- }
- /* If there is no 127.0.0.1 or ::1, this will and must fail. Otherwise, we
- * risk exposing a socketpair on a routable IP address. (Some BSD jails
- * use a routable address for localhost. Fortunately, they have the real
- * AF_UNIX socketpair.) */
- if (ersatz_domain == AF_INET) {
- tor_addr_from_ipv4h(&listen_tor_addr, INADDR_LOOPBACK);
- } else {
- tor_addr_parse(&listen_tor_addr, "[::1]");
- }
- tor_assert(tor_addr_is_loopback(&listen_tor_addr));
- size = tor_addr_to_sockaddr(&listen_tor_addr,
- 0 /* kernel chooses port. */,
- listen_addr,
- sizeof(listen_addr_ss));
- if (bind(listener, listen_addr, size) == -1)
- goto tidy_up_and_fail;
- if (listen(listener, 1) == -1)
- goto tidy_up_and_fail;
-
- connector = tor_open_socket(ersatz_domain, type, 0);
- if (!SOCKET_OK(connector))
- goto tidy_up_and_fail;
- /* We want to find out the port number to connect to. */
- size = sizeof(connect_addr_ss);
- if (getsockname(listener, connect_addr, &size) == -1)
- goto tidy_up_and_fail;
- if (size != SIZEOF_SOCKADDR (connect_addr->sa_family))
- goto abort_tidy_up_and_fail;
- if (connect(connector, connect_addr, size) == -1)
- goto tidy_up_and_fail;
-
- size = sizeof(listen_addr_ss);
- acceptor = tor_accept_socket(listener, listen_addr, &size);
- if (!SOCKET_OK(acceptor))
- goto tidy_up_and_fail;
- if (size != SIZEOF_SOCKADDR(listen_addr->sa_family))
- goto abort_tidy_up_and_fail;
- /* Now check we are talking to ourself by matching port and host on the
- two sockets. */
- if (getsockname(connector, connect_addr, &size) == -1)
- goto tidy_up_and_fail;
- /* Set *_tor_addr and *_port to the address and port that was used */
- tor_addr_from_sockaddr(&listen_tor_addr, listen_addr, &listen_port);
- tor_addr_from_sockaddr(&connect_tor_addr, connect_addr, &connect_port);
- if (size != SIZEOF_SOCKADDR (connect_addr->sa_family)
- || tor_addr_compare(&listen_tor_addr, &connect_tor_addr, CMP_SEMANTIC)
- || listen_port != connect_port) {
- goto abort_tidy_up_and_fail;
- }
- tor_close_socket(listener);
- fd[0] = connector;
- fd[1] = acceptor;
-
- return 0;
-
- abort_tidy_up_and_fail:
-#ifdef _WIN32
- saved_errno = WSAECONNABORTED;
-#else
- saved_errno = ECONNABORTED; /* I hope this is portable and appropriate. */
-#endif
- tidy_up_and_fail:
- if (saved_errno < 0)
- saved_errno = errno;
- if (SOCKET_OK(listener))
- tor_close_socket(listener);
- if (SOCKET_OK(connector))
- tor_close_socket(connector);
- if (SOCKET_OK(acceptor))
- tor_close_socket(acceptor);
- return -saved_errno;
-}
-
-#undef SIZEOF_SOCKADDR
-
-#endif /* defined(NEED_ERSATZ_SOCKETPAIR) */
-
-/* Return the maximum number of allowed sockets. */
-int
-get_max_sockets(void)
-{
- return max_sockets;
-}
-
-/** 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_ */
-
-/** 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 let us set it higher.) We compute this by finding the largest
- * number that we can use.
- *
- * If the limit is below the reserved file descriptor value (ULIMIT_BUFFER),
- * return -1 and <b>max_out</b> is untouched.
- *
- * If we can't find a number greater than or equal to <b>limit</b>, then we
- * fail by returning -1 and <b>max_out</b> is untouched.
- *
- * If we are unable to set the limit value because of setrlimit() failing,
- * return 0 and <b>max_out</b> is set to the current maximum value returned
- * by getrlimit().
- *
- * Otherwise, return 0 and store the maximum we found inside <b>max_out</b>
- * and set <b>max_sockets</b> with that value as well.*/
-int
-set_max_file_descriptors(rlim_t limit, int *max_out)
-{
- if (limit < ULIMIT_BUFFER) {
- log_warn(LD_CONFIG,
- "ConnLimit must be at least %d. Failing.", ULIMIT_BUFFER);
- return -1;
- }
-
- /* Define some maximum connections values for systems where we cannot
- * automatically determine a limit. Re Cygwin, see
- * http://archives.seul.org/or/talk/Aug-2006/msg00210.html
- * For an iPhone, 9999 should work. For Windows and all other unknown
- * systems we use 15000 as the default. */
-#ifndef HAVE_GETRLIMIT
-#if defined(CYGWIN) || defined(__CYGWIN__)
- const char *platform = "Cygwin";
- const unsigned long MAX_CONNECTIONS = 3200;
-#elif defined(_WIN32)
- const char *platform = "Windows";
- const unsigned long MAX_CONNECTIONS = 15000;
-#else
- const char *platform = "unknown platforms with no getrlimit()";
- const unsigned long MAX_CONNECTIONS = 15000;
-#endif /* defined(CYGWIN) || defined(__CYGWIN__) || ... */
- log_fn(LOG_INFO, LD_NET,
- "This platform is missing getrlimit(). Proceeding.");
- if (limit > MAX_CONNECTIONS) {
- log_warn(LD_CONFIG,
- "We do not support more than %lu file descriptors "
- "on %s. Tried to raise to %lu.",
- (unsigned long)MAX_CONNECTIONS, platform, (unsigned long)limit);
- return -1;
- }
- limit = MAX_CONNECTIONS;
-#else /* !(!defined(HAVE_GETRLIMIT)) */
- struct rlimit rlim;
-
- if (getrlimit(RLIMIT_NOFILE, &rlim) != 0) {
- log_warn(LD_NET, "Could not get maximum number of file descriptors: %s",
- strerror(errno));
- return -1;
- }
- if (rlim.rlim_max < limit) {
- log_warn(LD_CONFIG,"We need %lu file descriptors available, and we're "
- "limited to %lu. Please change your ulimit -n.",
- (unsigned long)limit, (unsigned long)rlim.rlim_max);
- return -1;
- }
-
- if (rlim.rlim_max > rlim.rlim_cur) {
- log_info(LD_NET,"Raising max file descriptors from %lu to %lu.",
- (unsigned long)rlim.rlim_cur, (unsigned long)rlim.rlim_max);
- }
- /* Set the current limit value so if the attempt to set the limit to the
- * max fails at least we'll have a valid value of maximum sockets. */
- *max_out = max_sockets = (int)rlim.rlim_cur - ULIMIT_BUFFER;
- rlim.rlim_cur = rlim.rlim_max;
-
- if (setrlimit(RLIMIT_NOFILE, &rlim) != 0) {
- int couldnt_set = 1;
- const int setrlimit_errno = errno;
-#ifdef OPEN_MAX
- uint64_t try_limit = OPEN_MAX - ULIMIT_BUFFER;
- if (errno == EINVAL && try_limit < (uint64_t) rlim.rlim_cur) {
- /* On some platforms, OPEN_MAX is the real limit, and getrlimit() is
- * full of nasty lies. I'm looking at you, OSX 10.5.... */
- rlim.rlim_cur = MIN((rlim_t) try_limit, rlim.rlim_cur);
- if (setrlimit(RLIMIT_NOFILE, &rlim) == 0) {
- if (rlim.rlim_cur < (rlim_t)limit) {
- log_warn(LD_CONFIG, "We are limited to %lu file descriptors by "
- "OPEN_MAX (%lu), and ConnLimit is %lu. Changing "
- "ConnLimit; sorry.",
- (unsigned long)try_limit, (unsigned long)OPEN_MAX,
- (unsigned long)limit);
- } else {
- log_info(LD_CONFIG, "Dropped connection limit to %lu based on "
- "OPEN_MAX (%lu); Apparently, %lu was too high and rlimit "
- "lied to us.",
- (unsigned long)try_limit, (unsigned long)OPEN_MAX,
- (unsigned long)rlim.rlim_max);
- }
- couldnt_set = 0;
- }
- }
-#endif /* defined(OPEN_MAX) */
- if (couldnt_set) {
- log_warn(LD_CONFIG,"Couldn't set maximum number of file descriptors: %s",
- strerror(setrlimit_errno));
- }
- }
- /* leave some overhead for logs, etc, */
- limit = rlim.rlim_cur;
-#endif /* !defined(HAVE_GETRLIMIT) */
-
- if (limit > INT_MAX)
- limit = INT_MAX;
- tor_assert(max_out);
- *max_out = max_sockets = (int)limit - ULIMIT_BUFFER;
- return 0;
-}
-
-#ifndef _WIN32
-/** Log details of current user and group credentials. Return 0 on
- * success. Logs and return -1 on failure.
- */
-static int
-log_credential_status(void)
-{
-/** Log level to use when describing non-error UID/GID status. */
-#define CREDENTIAL_LOG_LEVEL LOG_INFO
- /* Real, effective and saved UIDs */
- uid_t ruid, euid, suid;
- /* Read, effective and saved GIDs */
- gid_t rgid, egid, sgid;
- /* Supplementary groups */
- gid_t *sup_gids = NULL;
- int sup_gids_size;
- /* Number of supplementary groups */
- int ngids;
-
- /* log UIDs */
-#ifdef HAVE_GETRESUID
- if (getresuid(&ruid, &euid, &suid) != 0 ) {
- log_warn(LD_GENERAL, "Error getting changed UIDs: %s", strerror(errno));
- return -1;
- } else {
- log_fn(CREDENTIAL_LOG_LEVEL, LD_GENERAL,
- "UID is %u (real), %u (effective), %u (saved)",
- (unsigned)ruid, (unsigned)euid, (unsigned)suid);
- }
-#else /* !(defined(HAVE_GETRESUID)) */
- /* getresuid is not present on MacOS X, so we can't get the saved (E)UID */
- ruid = getuid();
- euid = geteuid();
- (void)suid;
-
- log_fn(CREDENTIAL_LOG_LEVEL, LD_GENERAL,
- "UID is %u (real), %u (effective), unknown (saved)",
- (unsigned)ruid, (unsigned)euid);
-#endif /* defined(HAVE_GETRESUID) */
-
- /* log GIDs */
-#ifdef HAVE_GETRESGID
- if (getresgid(&rgid, &egid, &sgid) != 0 ) {
- log_warn(LD_GENERAL, "Error getting changed GIDs: %s", strerror(errno));
- return -1;
- } else {
- log_fn(CREDENTIAL_LOG_LEVEL, LD_GENERAL,
- "GID is %u (real), %u (effective), %u (saved)",
- (unsigned)rgid, (unsigned)egid, (unsigned)sgid);
- }
-#else /* !(defined(HAVE_GETRESGID)) */
- /* getresgid is not present on MacOS X, so we can't get the saved (E)GID */
- rgid = getgid();
- egid = getegid();
- (void)sgid;
- log_fn(CREDENTIAL_LOG_LEVEL, LD_GENERAL,
- "GID is %u (real), %u (effective), unknown (saved)",
- (unsigned)rgid, (unsigned)egid);
-#endif /* defined(HAVE_GETRESGID) */
-
- /* log supplementary groups */
- sup_gids_size = 64;
- sup_gids = tor_calloc(64, sizeof(gid_t));
- while ((ngids = getgroups(sup_gids_size, sup_gids)) < 0 &&
- errno == EINVAL &&
- sup_gids_size < NGROUPS_MAX) {
- sup_gids_size *= 2;
- sup_gids = tor_reallocarray(sup_gids, sizeof(gid_t), sup_gids_size);
- }
-
- if (ngids < 0) {
- log_warn(LD_GENERAL, "Error getting supplementary GIDs: %s",
- strerror(errno));
- tor_free(sup_gids);
- return -1;
- } else {
- int i, retval = 0;
- char *s = NULL;
- smartlist_t *elts = smartlist_new();
-
- for (i = 0; i<ngids; i++) {
- smartlist_add_asprintf(elts, "%u", (unsigned)sup_gids[i]);
- }
-
- s = smartlist_join_strings(elts, " ", 0, NULL);
-
- log_fn(CREDENTIAL_LOG_LEVEL, LD_GENERAL, "Supplementary groups are: %s",s);
-
- tor_free(s);
- SMARTLIST_FOREACH(elts, char *, cp, tor_free(cp));
- smartlist_free(elts);
- tor_free(sup_gids);
-
- return retval;
- }
-
- return 0;
-}
-#endif /* !defined(_WIN32) */
-
-#ifndef _WIN32
-/** Cached struct from the last getpwname() call we did successfully. */
-static struct passwd *passwd_cached = NULL;
-
-/** Helper: copy a struct passwd object.
- *
- * We only copy the fields pw_uid, pw_gid, pw_name, pw_dir. Tor doesn't use
- * any others, and I don't want to run into incompatibilities.
- */
-static struct passwd *
-tor_passwd_dup(const struct passwd *pw)
-{
- struct passwd *new_pw = tor_malloc_zero(sizeof(struct passwd));
- if (pw->pw_name)
- new_pw->pw_name = tor_strdup(pw->pw_name);
- if (pw->pw_dir)
- new_pw->pw_dir = tor_strdup(pw->pw_dir);
- new_pw->pw_uid = pw->pw_uid;
- new_pw->pw_gid = pw->pw_gid;
-
- return new_pw;
-}
-
-#define tor_passwd_free(pw) \
- FREE_AND_NULL(struct passwd, tor_passwd_free_, (pw))
-
-/** Helper: free one of our cached 'struct passwd' values. */
-static void
-tor_passwd_free_(struct passwd *pw)
-{
- if (!pw)
- return;
-
- tor_free(pw->pw_name);
- tor_free(pw->pw_dir);
- tor_free(pw);
-}
-
-/** Wrapper around getpwnam() that caches result. Used so that we don't need
- * to give the sandbox access to /etc/passwd.
- *
- * The following fields alone will definitely be copied in the output: pw_uid,
- * pw_gid, pw_name, pw_dir. Other fields are not present in cached values.
- *
- * When called with a NULL argument, this function clears storage associated
- * with static variables it uses.
- **/
-const struct passwd *
-tor_getpwnam(const char *username)
-{
- struct passwd *pw;
-
- if (username == NULL) {
- tor_passwd_free(passwd_cached);
- passwd_cached = NULL;
- return NULL;
- }
-
- if ((pw = getpwnam(username))) {
- tor_passwd_free(passwd_cached);
- passwd_cached = tor_passwd_dup(pw);
- log_info(LD_GENERAL, "Caching new entry %s for %s",
- passwd_cached->pw_name, username);
- return pw;
- }
-
- /* Lookup failed */
- if (! passwd_cached || ! passwd_cached->pw_name)
- return NULL;
-
- if (! strcmp(username, passwd_cached->pw_name))
- return passwd_cached; // LCOV_EXCL_LINE - would need to make getpwnam flaky
-
- return NULL;
-}
-
-/** Wrapper around getpwnam() that can use cached result from
- * tor_getpwnam(). Used so that we don't need to give the sandbox access to
- * /etc/passwd.
- *
- * The following fields alone will definitely be copied in the output: pw_uid,
- * pw_gid, pw_name, pw_dir. Other fields are not present in cached values.
- */
-const struct passwd *
-tor_getpwuid(uid_t uid)
-{
- struct passwd *pw;
-
- if ((pw = getpwuid(uid))) {
- return pw;
- }
-
- /* Lookup failed */
- if (! passwd_cached)
- return NULL;
-
- if (uid == passwd_cached->pw_uid)
- return passwd_cached; // LCOV_EXCL_LINE - would need to make getpwnam flaky
-
- return NULL;
-}
-#endif /* !defined(_WIN32) */
-
-/** Return true iff we were compiled with capability support, and capabilities
- * seem to work. **/
-int
-have_capability_support(void)
-{
-#ifdef HAVE_LINUX_CAPABILITIES
- cap_t caps = cap_get_proc();
- if (caps == NULL)
- return 0;
- cap_free(caps);
- return 1;
-#else /* !(defined(HAVE_LINUX_CAPABILITIES)) */
- return 0;
-#endif /* defined(HAVE_LINUX_CAPABILITIES) */
-}
-
-#ifdef HAVE_LINUX_CAPABILITIES
-/** Helper. Drop all capabilities but a small set, and set PR_KEEPCAPS as
- * appropriate.
- *
- * If pre_setuid, retain only CAP_NET_BIND_SERVICE, CAP_SETUID, and
- * CAP_SETGID, and use PR_KEEPCAPS to ensure that capabilities persist across
- * setuid().
- *
- * If not pre_setuid, retain only CAP_NET_BIND_SERVICE, and disable
- * PR_KEEPCAPS.
- *
- * Return 0 on success, and -1 on failure.
- */
-static int
-drop_capabilities(int pre_setuid)
-{
- /* We keep these three capabilities, and these only, as we setuid.
- * After we setuid, we drop all but the first. */
- const cap_value_t caplist[] = {
- CAP_NET_BIND_SERVICE, CAP_SETUID, CAP_SETGID
- };
- const char *where = pre_setuid ? "pre-setuid" : "post-setuid";
- const int n_effective = pre_setuid ? 3 : 1;
- const int n_permitted = pre_setuid ? 3 : 1;
- const int n_inheritable = 1;
- const int keepcaps = pre_setuid ? 1 : 0;
-
- /* Sets whether we keep capabilities across a setuid. */
- if (prctl(PR_SET_KEEPCAPS, keepcaps) < 0) {
- log_warn(LD_CONFIG, "Unable to call prctl() %s: %s",
- where, strerror(errno));
- return -1;
- }
-
- cap_t caps = cap_get_proc();
- if (!caps) {
- log_warn(LD_CONFIG, "Unable to call cap_get_proc() %s: %s",
- where, strerror(errno));
- return -1;
- }
- cap_clear(caps);
-
- cap_set_flag(caps, CAP_EFFECTIVE, n_effective, caplist, CAP_SET);
- cap_set_flag(caps, CAP_PERMITTED, n_permitted, caplist, CAP_SET);
- cap_set_flag(caps, CAP_INHERITABLE, n_inheritable, caplist, CAP_SET);
-
- int r = cap_set_proc(caps);
- cap_free(caps);
- if (r < 0) {
- log_warn(LD_CONFIG, "No permission to set capabilities %s: %s",
- where, strerror(errno));
- return -1;
- }
-
- return 0;
-}
-#endif /* defined(HAVE_LINUX_CAPABILITIES) */
-
-/** Call setuid and setgid to run as <b>user</b> and switch to their
- * primary group. Return 0 on success. On failure, log and return -1.
- *
- * If SWITCH_ID_KEEP_BINDLOW is set in 'flags', try to use the capability
- * system to retain the abilitity to bind low ports.
- *
- * If SWITCH_ID_WARN_IF_NO_CAPS is set in flags, also warn if we have
- * don't have capability support.
- */
-int
-switch_id(const char *user, const unsigned flags)
-{
-#ifndef _WIN32
- const struct passwd *pw = NULL;
- uid_t old_uid;
- gid_t old_gid;
- static int have_already_switched_id = 0;
- const int keep_bindlow = !!(flags & SWITCH_ID_KEEP_BINDLOW);
- const int warn_if_no_caps = !!(flags & SWITCH_ID_WARN_IF_NO_CAPS);
-
- tor_assert(user);
-
- if (have_already_switched_id)
- return 0;
-
- /* Log the initial credential state */
- if (log_credential_status())
- return -1;
-
- log_fn(CREDENTIAL_LOG_LEVEL, LD_GENERAL, "Changing user and groups");
-
- /* Get old UID/GID to check if we changed correctly */
- old_uid = getuid();
- old_gid = getgid();
-
- /* Lookup the user and group information, if we have a problem, bail out. */
- pw = tor_getpwnam(user);
- if (pw == NULL) {
- log_warn(LD_CONFIG, "Error setting configured user: %s not found", user);
- return -1;
- }
-
-#ifdef HAVE_LINUX_CAPABILITIES
- (void) warn_if_no_caps;
- if (keep_bindlow) {
- if (drop_capabilities(1))
- return -1;
- }
-#else /* !(defined(HAVE_LINUX_CAPABILITIES)) */
- (void) keep_bindlow;
- if (warn_if_no_caps) {
- log_warn(LD_CONFIG, "KeepBindCapabilities set, but no capability support "
- "on this system.");
- }
-#endif /* defined(HAVE_LINUX_CAPABILITIES) */
-
- /* Properly switch egid,gid,euid,uid here or bail out */
- if (setgroups(1, &pw->pw_gid)) {
- log_warn(LD_GENERAL, "Error setting groups to gid %d: \"%s\".",
- (int)pw->pw_gid, strerror(errno));
- if (old_uid == pw->pw_uid) {
- log_warn(LD_GENERAL, "Tor is already running as %s. You do not need "
- "the \"User\" option if you are already running as the user "
- "you want to be. (If you did not set the User option in your "
- "torrc, check whether it was specified on the command line "
- "by a startup script.)", user);
- } else {
- log_warn(LD_GENERAL, "If you set the \"User\" option, you must start Tor"
- " as root.");
- }
- return -1;
- }
-
- if (setegid(pw->pw_gid)) {
- log_warn(LD_GENERAL, "Error setting egid to %d: %s",
- (int)pw->pw_gid, strerror(errno));
- return -1;
- }
-
- if (setgid(pw->pw_gid)) {
- log_warn(LD_GENERAL, "Error setting gid to %d: %s",
- (int)pw->pw_gid, strerror(errno));
- return -1;
- }
-
- if (setuid(pw->pw_uid)) {
- log_warn(LD_GENERAL, "Error setting configured uid to %s (%d): %s",
- user, (int)pw->pw_uid, strerror(errno));
- return -1;
- }
-
- if (seteuid(pw->pw_uid)) {
- log_warn(LD_GENERAL, "Error setting configured euid to %s (%d): %s",
- user, (int)pw->pw_uid, strerror(errno));
- return -1;
- }
-
- /* This is how OpenBSD rolls:
- if (setgroups(1, &pw->pw_gid) || setegid(pw->pw_gid) ||
- setgid(pw->pw_gid) || setuid(pw->pw_uid) || seteuid(pw->pw_uid)) {
- setgid(pw->pw_gid) || seteuid(pw->pw_uid) || setuid(pw->pw_uid)) {
- log_warn(LD_GENERAL, "Error setting configured UID/GID: %s",
- strerror(errno));
- return -1;
- }
- */
-
- /* We've properly switched egid, gid, euid, uid, and supplementary groups if
- * we're here. */
-#ifdef HAVE_LINUX_CAPABILITIES
- if (keep_bindlow) {
- if (drop_capabilities(0))
- return -1;
- }
-#endif /* defined(HAVE_LINUX_CAPABILITIES) */
-
-#if !defined(CYGWIN) && !defined(__CYGWIN__)
- /* If we tried to drop privilege to a group/user other than root, attempt to
- * restore root (E)(U|G)ID, and abort if the operation succeeds */
-
- /* Only check for privilege dropping if we were asked to be non-root */
- if (pw->pw_uid) {
- /* Try changing GID/EGID */
- if (pw->pw_gid != old_gid &&
- (setgid(old_gid) != -1 || setegid(old_gid) != -1)) {
- log_warn(LD_GENERAL, "Was able to restore group credentials even after "
- "switching GID: this means that the setgid code didn't work.");
- return -1;
- }
-
- /* Try changing UID/EUID */
- if (pw->pw_uid != old_uid &&
- (setuid(old_uid) != -1 || seteuid(old_uid) != -1)) {
- log_warn(LD_GENERAL, "Was able to restore user credentials even after "
- "switching UID: this means that the setuid code didn't work.");
- return -1;
- }
- }
-#endif /* !defined(CYGWIN) && !defined(__CYGWIN__) */
-
- /* Check what really happened */
- if (log_credential_status()) {
- return -1;
- }
-
- have_already_switched_id = 1; /* mark success so we never try again */
-
-#if defined(__linux__) && defined(HAVE_SYS_PRCTL_H) && \
- defined(HAVE_PRCTL) && defined(PR_SET_DUMPABLE)
- if (pw->pw_uid) {
- /* Re-enable core dumps if we're not running as root. */
- log_info(LD_CONFIG, "Re-enabling coredumps");
- if (prctl(PR_SET_DUMPABLE, 1)) {
- log_warn(LD_CONFIG, "Unable to re-enable coredumps: %s",strerror(errno));
- }
- }
-#endif /* defined(__linux__) && defined(HAVE_SYS_PRCTL_H) && ... */
- return 0;
-
-#else /* !(!defined(_WIN32)) */
- (void)user;
- (void)flags;
-
- log_warn(LD_CONFIG, "Switching users is unsupported on your OS.");
- return -1;
-#endif /* !defined(_WIN32) */
-}
-
-/* We only use the linux prctl for now. There is no Win32 support; this may
- * also work on various BSD systems and Mac OS X - send testing feedback!
- *
- * On recent Gnu/Linux kernels it is possible to create a system-wide policy
- * that will prevent non-root processes from attaching to other processes
- * unless they are the parent process; thus gdb can attach to programs that
- * they execute but they cannot attach to other processes running as the same
- * user. The system wide policy may be set with the sysctl
- * kernel.yama.ptrace_scope or by inspecting
- * /proc/sys/kernel/yama/ptrace_scope and it is 1 by default on Ubuntu 11.04.
- *
- * This ptrace scope will be ignored on Gnu/Linux for users with
- * CAP_SYS_PTRACE and so it is very likely that root will still be able to
- * attach to the Tor process.
- */
-/** Attempt to disable debugger attachment: return 1 on success, -1 on
- * failure, and 0 if we don't know how to try on this platform. */
-int
-tor_disable_debugger_attach(void)
-{
- int r = -1;
- log_debug(LD_CONFIG,
- "Attemping to disable debugger attachment to Tor for "
- "unprivileged users.");
-#if defined(__linux__) && defined(HAVE_SYS_PRCTL_H) \
- && defined(HAVE_PRCTL) && defined(PR_SET_DUMPABLE)
-#define TRIED_TO_DISABLE
- r = prctl(PR_SET_DUMPABLE, 0);
-#elif defined(__APPLE__) && defined(PT_DENY_ATTACH)
-#define TRIED_TO_ATTACH
- r = ptrace(PT_DENY_ATTACH, 0, 0, 0);
-#endif /* defined(__linux__) && defined(HAVE_SYS_PRCTL_H) ... || ... */
-
- // XXX: TODO - Mac OS X has dtrace and this may be disabled.
- // XXX: TODO - Windows probably has something similar
-#ifdef TRIED_TO_DISABLE
- if (r == 0) {
- log_debug(LD_CONFIG,"Debugger attachment disabled for "
- "unprivileged users.");
- return 1;
- } else {
- log_warn(LD_CONFIG, "Unable to disable debugger attaching: %s",
- strerror(errno));
- }
-#endif /* defined(TRIED_TO_DISABLE) */
-#undef TRIED_TO_DISABLE
- return r;
-}
-
-#ifdef HAVE_PWD_H
-/** Allocate and return a string containing the home directory for the
- * user <b>username</b>. Only works on posix-like systems. */
-char *
-get_user_homedir(const char *username)
-{
- const struct passwd *pw;
- tor_assert(username);
-
- if (!(pw = tor_getpwnam(username))) {
- log_err(LD_CONFIG,"User \"%s\" not found.", username);
- return NULL;
- }
- return tor_strdup(pw->pw_dir);
-}
-#endif /* defined(HAVE_PWD_H) */
-
-/** Modify <b>fname</b> to contain the name of its parent directory. Doesn't
- * actually examine the filesystem; does a purely syntactic modification.
- *
- * The parent of the root director is considered to be iteself.
- *
- * Path separators are the forward slash (/) everywhere and additionally
- * the backslash (\) on Win32.
- *
- * Cuts off any number of trailing path separators but otherwise ignores
- * them for purposes of finding the parent directory.
- *
- * Returns 0 if a parent directory was successfully found, -1 otherwise (fname
- * did not have any path separators or only had them at the end).
- * */
-int
-get_parent_directory(char *fname)
-{
- char *cp;
- int at_end = 1;
- tor_assert(fname);
-#ifdef _WIN32
- /* If we start with, say, c:, then don't consider that the start of the path
- */
- if (fname[0] && fname[1] == ':') {
- fname += 2;
- }
-#endif /* defined(_WIN32) */
- /* Now we want to remove all path-separators at the end of the string,
- * and to remove the end of the string starting with the path separator
- * before the last non-path-separator. In perl, this would be
- * s#[/]*$##; s#/[^/]*$##;
- * on a unixy platform.
- */
- cp = fname + strlen(fname);
- at_end = 1;
- while (--cp >= fname) {
- int is_sep = (*cp == '/'
-#ifdef _WIN32
- || *cp == '\\'
-#endif
- );
- if (is_sep) {
- if (cp == fname) {
- /* This is the first separator in the file name; don't remove it! */
- cp[1] = '\0';
- return 0;
- }
- *cp = '\0';
- if (! at_end)
- return 0;
- } else {
- at_end = 0;
- }
- }
- return -1;
-}
-
-#ifndef _WIN32
-/** Return a newly allocated string containing the output of getcwd(). Return
- * NULL on failure. (We can't just use getcwd() into a PATH_MAX buffer, since
- * Hurd hasn't got a PATH_MAX.)
- */
-static char *
-alloc_getcwd(void)
-{
-#ifdef HAVE_GET_CURRENT_DIR_NAME
- /* Glibc makes this nice and simple for us. */
- char *cwd = get_current_dir_name();
- char *result = NULL;
- if (cwd) {
- /* We make a copy here, in case tor_malloc() is not malloc(). */
- result = tor_strdup(cwd);
- raw_free(cwd); // alias for free to avoid tripping check-spaces.
- }
- return result;
-#else /* !(defined(HAVE_GET_CURRENT_DIR_NAME)) */
- size_t size = 1024;
- char *buf = NULL;
- char *ptr = NULL;
-
- while (ptr == NULL) {
- buf = tor_realloc(buf, size);
- ptr = getcwd(buf, size);
-
- if (ptr == NULL && errno != ERANGE) {
- tor_free(buf);
- return NULL;
- }
-
- size *= 2;
- }
- return buf;
-#endif /* defined(HAVE_GET_CURRENT_DIR_NAME) */
-}
-#endif /* !defined(_WIN32) */
-
-/** Expand possibly relative path <b>fname</b> to an absolute path.
- * Return a newly allocated string, possibly equal to <b>fname</b>. */
-char *
-make_path_absolute(char *fname)
-{
-#ifdef _WIN32
- char *absfname_malloced = _fullpath(NULL, fname, 1);
-
- /* We don't want to assume that tor_free can free a string allocated
- * with malloc. On failure, return fname (it's better than nothing). */
- char *absfname = tor_strdup(absfname_malloced ? absfname_malloced : fname);
- if (absfname_malloced) raw_free(absfname_malloced);
-
- return absfname;
-#else /* !(defined(_WIN32)) */
- char *absfname = NULL, *path = NULL;
-
- tor_assert(fname);
-
- if (fname[0] == '/') {
- absfname = tor_strdup(fname);
- } else {
- path = alloc_getcwd();
- if (path) {
- tor_asprintf(&absfname, "%s/%s", path, fname);
- tor_free(path);
- } else {
- /* LCOV_EXCL_START Can't make getcwd fail. */
- /* If getcwd failed, the best we can do here is keep using the
- * relative path. (Perhaps / isn't readable by this UID/GID.) */
- log_warn(LD_GENERAL, "Unable to find current working directory: %s",
- strerror(errno));
- absfname = tor_strdup(fname);
- /* LCOV_EXCL_STOP */
- }
- }
- return absfname;
-#endif /* defined(_WIN32) */
-}
-
-#ifndef HAVE__NSGETENVIRON
-#ifndef HAVE_EXTERN_ENVIRON_DECLARED
-/* Some platforms declare environ under some circumstances, others don't. */
-#ifndef RUNNING_DOXYGEN
-extern char **environ;
-#endif
-#endif /* !defined(HAVE_EXTERN_ENVIRON_DECLARED) */
-#endif /* !defined(HAVE__NSGETENVIRON) */
-
-/** Return the current environment. This is a portable replacement for
- * 'environ'. */
-char **
-get_environment(void)
-{
-#ifdef HAVE__NSGETENVIRON
- /* This is for compatibility between OSX versions. Otherwise (for example)
- * when we do a mostly-static build on OSX 10.7, the resulting binary won't
- * work on OSX 10.6. */
- return *_NSGetEnviron();
-#else /* !(defined(HAVE__NSGETENVIRON)) */
- return environ;
-#endif /* defined(HAVE__NSGETENVIRON) */
-}
-
-/** Get name of current host and write it to <b>name</b> array, whose
- * length is specified by <b>namelen</b> argument. Return 0 upon
- * successful completion; otherwise return return -1. (Currently,
- * this function is merely a mockable wrapper for POSIX gethostname().)
- */
-MOCK_IMPL(int,
-tor_gethostname,(char *name, size_t namelen))
-{
- return gethostname(name,namelen);
-}
-
-/** Set *addr to the IP address (in dotted-quad notation) stored in *str.
- * Return 1 on success, 0 if *str is badly formatted.
- * (Like inet_aton(str,addr), but works on Windows and Solaris.)
- */
-int
-tor_inet_aton(const char *str, struct in_addr* addr)
-{
- unsigned a,b,c,d;
- char more;
- if (tor_sscanf(str, "%3u.%3u.%3u.%3u%c", &a,&b,&c,&d,&more) != 4)
- return 0;
- if (a > 255) return 0;
- if (b > 255) return 0;
- if (c > 255) return 0;
- if (d > 255) return 0;
- addr->s_addr = htonl((a<<24) | (b<<16) | (c<<8) | d);
- return 1;
-}
-
-/** Given <b>af</b>==AF_INET and <b>src</b> a struct in_addr, or
- * <b>af</b>==AF_INET6 and <b>src</b> a struct in6_addr, try to format the
- * address and store it in the <b>len</b>-byte buffer <b>dst</b>. Returns
- * <b>dst</b> on success, NULL on failure.
- *
- * (Like inet_ntop(af,src,dst,len), but works on platforms that don't have it:
- * Tor sometimes needs to format ipv6 addresses even on platforms without ipv6
- * support.) */
-const char *
-tor_inet_ntop(int af, const void *src, char *dst, size_t len)
-{
- if (af == AF_INET) {
- if (tor_inet_ntoa(src, dst, len) < 0)
- return NULL;
- else
- return dst;
- } else if (af == AF_INET6) {
- const struct in6_addr *addr = src;
- char buf[64], *cp;
- int longestGapLen = 0, longestGapPos = -1, i,
- curGapPos = -1, curGapLen = 0;
- uint16_t words[8];
- for (i = 0; i < 8; ++i) {
- words[i] = (((uint16_t)addr->s6_addr[2*i])<<8) + addr->s6_addr[2*i+1];
- }
- if (words[0] == 0 && words[1] == 0 && words[2] == 0 && words[3] == 0 &&
- words[4] == 0 && ((words[5] == 0 && words[6] && words[7]) ||
- (words[5] == 0xffff))) {
- /* This is an IPv4 address. */
- if (words[5] == 0) {
- tor_snprintf(buf, sizeof(buf), "::%d.%d.%d.%d",
- addr->s6_addr[12], addr->s6_addr[13],
- addr->s6_addr[14], addr->s6_addr[15]);
- } else {
- tor_snprintf(buf, sizeof(buf), "::%x:%d.%d.%d.%d", words[5],
- addr->s6_addr[12], addr->s6_addr[13],
- addr->s6_addr[14], addr->s6_addr[15]);
- }
- if ((strlen(buf) + 1) > len) /* +1 for \0 */
- return NULL;
- strlcpy(dst, buf, len);
- return dst;
- }
- i = 0;
- while (i < 8) {
- if (words[i] == 0) {
- curGapPos = i++;
- curGapLen = 1;
- while (i<8 && words[i] == 0) {
- ++i; ++curGapLen;
- }
- if (curGapLen > longestGapLen) {
- longestGapPos = curGapPos;
- longestGapLen = curGapLen;
- }
- } else {
- ++i;
- }
- }
- if (longestGapLen<=1)
- longestGapPos = -1;
-
- cp = buf;
- for (i = 0; i < 8; ++i) {
- if (words[i] == 0 && longestGapPos == i) {
- if (i == 0)
- *cp++ = ':';
- *cp++ = ':';
- while (i < 8 && words[i] == 0)
- ++i;
- --i; /* to compensate for loop increment. */
- } else {
- tor_snprintf(cp, sizeof(buf)-(cp-buf), "%x", (unsigned)words[i]);
- cp += strlen(cp);
- if (i != 7)
- *cp++ = ':';
- }
- }
- *cp = '\0';
- if ((strlen(buf) + 1) > len) /* +1 for \0 */
- return NULL;
- strlcpy(dst, buf, len);
- return dst;
- } else {
- return NULL;
- }
-}
-
-/** Given <b>af</b>==AF_INET or <b>af</b>==AF_INET6, and a string <b>src</b>
- * encoding an IPv4 address or IPv6 address correspondingly, try to parse the
- * address and store the result in <b>dst</b> (which must have space for a
- * struct in_addr or a struct in6_addr, as appropriate). Return 1 on success,
- * 0 on a bad parse, and -1 on a bad <b>af</b>.
- *
- * (Like inet_pton(af,src,dst) but works on platforms that don't have it: Tor
- * sometimes needs to format ipv6 addresses even on platforms without ipv6
- * support.) */
-int
-tor_inet_pton(int af, const char *src, void *dst)
-{
- if (af == AF_INET) {
- return tor_inet_aton(src, dst);
- } else if (af == AF_INET6) {
- struct in6_addr *out = dst;
- uint16_t words[8];
- int gapPos = -1, i, setWords=0;
- const char *dot = strchr(src, '.');
- const char *eow; /* end of words. */
- memset(words, 0xf8, sizeof(words));
- if (dot == src)
- return 0;
- else if (!dot)
- eow = src+strlen(src);
- else {
- unsigned byte1,byte2,byte3,byte4;
- char more;
- for (eow = dot-1; eow > src && TOR_ISDIGIT(*eow); --eow)
- ;
- if (*eow != ':')
- return 0;
- ++eow;
-
- /* We use "scanf" because some platform inet_aton()s are too lax
- * about IPv4 addresses of the form "1.2.3" */
- if (tor_sscanf(eow, "%3u.%3u.%3u.%3u%c",
- &byte1,&byte2,&byte3,&byte4,&more) != 4)
- return 0;
-
- if (byte1 > 255 || byte2 > 255 || byte3 > 255 || byte4 > 255)
- return 0;
-
- words[6] = (byte1<<8) | byte2;
- words[7] = (byte3<<8) | byte4;
- setWords += 2;
- }
-
- i = 0;
- while (src < eow) {
- if (i > 7)
- return 0;
- if (TOR_ISXDIGIT(*src)) {
- char *next;
- ssize_t len;
- long r = strtol(src, &next, 16);
- if (next == NULL || next == src) {
- /* The 'next == src' error case can happen on versions of openbsd
- * which treat "0xfoo" as an error, rather than as "0" followed by
- * "xfoo". */
- return 0;
- }
-
- len = *next == '\0' ? eow - src : next - src;
- if (len > 4)
- return 0;
- if (len > 1 && !TOR_ISXDIGIT(src[1]))
- return 0; /* 0x is not valid */
-
- tor_assert(r >= 0);
- tor_assert(r < 65536);
- words[i++] = (uint16_t)r;
- setWords++;
- src = next;
- if (*src != ':' && src != eow)
- return 0;
- ++src;
- } else if (*src == ':' && i > 0 && gapPos == -1) {
- gapPos = i;
- ++src;
- } else if (*src == ':' && i == 0 && src+1 < eow && src[1] == ':' &&
- gapPos == -1) {
- gapPos = i;
- src += 2;
- } else {
- return 0;
- }
- }
-
- if (setWords > 8 ||
- (setWords == 8 && gapPos != -1) ||
- (setWords < 8 && gapPos == -1))
- return 0;
-
- if (gapPos >= 0) {
- int nToMove = setWords - (dot ? 2 : 0) - gapPos;
- int gapLen = 8 - setWords;
- tor_assert(nToMove >= 0);
- memmove(&words[gapPos+gapLen], &words[gapPos],
- sizeof(uint16_t)*nToMove);
- memset(&words[gapPos], 0, sizeof(uint16_t)*gapLen);
- }
- for (i = 0; i < 8; ++i) {
- out->s6_addr[2*i ] = words[i] >> 8;
- out->s6_addr[2*i+1] = words[i] & 0xff;
- }
-
- return 1;
- } else {
- return -1;
- }
-}
-
-/** Similar behavior to Unix gethostbyname: resolve <b>name</b>, and set
- * *<b>addr</b> to the proper IP address, in host byte order. Returns 0
- * on success, -1 on failure; 1 on transient failure.
- *
- * (This function exists because standard windows gethostbyname
- * doesn't treat raw IP addresses properly.)
- */
-
-MOCK_IMPL(int,
-tor_lookup_hostname,(const char *name, uint32_t *addr))
-{
- tor_addr_t myaddr;
- int ret;
-
- if ((ret = tor_addr_lookup(name, AF_INET, &myaddr)))
- return ret;
-
- if (tor_addr_family(&myaddr) == AF_INET) {
- *addr = tor_addr_to_ipv4h(&myaddr);
- return ret;
- }
-
- return -1;
-}
-
-/** Hold the result of our call to <b>uname</b>. */
-static char uname_result[256];
-/** True iff uname_result is set. */
-static int uname_result_is_set = 0;
-
-/** Return a pointer to a description of our platform.
- */
-MOCK_IMPL(const char *,
-get_uname,(void))
-{
-#ifdef HAVE_UNAME
- struct utsname u;
-#endif
- if (!uname_result_is_set) {
-#ifdef HAVE_UNAME
- if (uname(&u) != -1) {
- /* (Linux says 0 is success, Solaris says 1 is success) */
- strlcpy(uname_result, u.sysname, sizeof(uname_result));
- } else
-#endif /* defined(HAVE_UNAME) */
- {
-#ifdef _WIN32
- OSVERSIONINFOEX info;
- int i;
- const char *plat = NULL;
- static struct {
- unsigned major; unsigned minor; const char *version;
- } win_version_table[] = {
- { 6, 2, "Windows 8" },
- { 6, 1, "Windows 7" },
- { 6, 0, "Windows Vista" },
- { 5, 2, "Windows Server 2003" },
- { 5, 1, "Windows XP" },
- { 5, 0, "Windows 2000" },
- /* { 4, 0, "Windows NT 4.0" }, */
- { 4, 90, "Windows Me" },
- { 4, 10, "Windows 98" },
- /* { 4, 0, "Windows 95" } */
- { 3, 51, "Windows NT 3.51" },
- { 0, 0, NULL }
- };
- memset(&info, 0, sizeof(info));
- info.dwOSVersionInfoSize = sizeof(info);
- if (! GetVersionEx((LPOSVERSIONINFO)&info)) {
- strlcpy(uname_result, "Bizarre version of Windows where GetVersionEx"
- " doesn't work.", sizeof(uname_result));
- uname_result_is_set = 1;
- return uname_result;
- }
- if (info.dwMajorVersion == 4 && info.dwMinorVersion == 0) {
- if (info.dwPlatformId == VER_PLATFORM_WIN32_NT)
- plat = "Windows NT 4.0";
- else
- plat = "Windows 95";
- } else {
- for (i=0; win_version_table[i].major>0; ++i) {
- if (win_version_table[i].major == info.dwMajorVersion &&
- win_version_table[i].minor == info.dwMinorVersion) {
- plat = win_version_table[i].version;
- break;
- }
- }
- }
- if (plat) {
- strlcpy(uname_result, plat, sizeof(uname_result));
- } else {
- if (info.dwMajorVersion > 6 ||
- (info.dwMajorVersion==6 && info.dwMinorVersion>2))
- tor_snprintf(uname_result, sizeof(uname_result),
- "Very recent version of Windows [major=%d,minor=%d]",
- (int)info.dwMajorVersion,(int)info.dwMinorVersion);
- else
- tor_snprintf(uname_result, sizeof(uname_result),
- "Unrecognized version of Windows [major=%d,minor=%d]",
- (int)info.dwMajorVersion,(int)info.dwMinorVersion);
- }
-#ifdef VER_NT_SERVER
- if (info.wProductType == VER_NT_SERVER ||
- info.wProductType == VER_NT_DOMAIN_CONTROLLER) {
- strlcat(uname_result, " [server]", sizeof(uname_result));
- }
-#endif /* defined(VER_NT_SERVER) */
-#else /* !(defined(_WIN32)) */
- /* LCOV_EXCL_START -- can't provoke uname failure */
- strlcpy(uname_result, "Unknown platform", sizeof(uname_result));
- /* LCOV_EXCL_STOP */
-#endif /* defined(_WIN32) */
- }
- uname_result_is_set = 1;
- }
- return uname_result;
-}
-
-/*
- * Process control
- */
-
-/** Implementation logic for compute_num_cpus(). */
-static int
-compute_num_cpus_impl(void)
-{
-#ifdef _WIN32
- SYSTEM_INFO info;
- memset(&info, 0, sizeof(info));
- GetSystemInfo(&info);
- if (info.dwNumberOfProcessors >= 1 && info.dwNumberOfProcessors < INT_MAX)
- return (int)info.dwNumberOfProcessors;
- else
- return -1;
-#elif defined(HAVE_SYSCONF)
-#ifdef _SC_NPROCESSORS_CONF
- long cpus_conf = sysconf(_SC_NPROCESSORS_CONF);
-#else
- long cpus_conf = -1;
-#endif
-#ifdef _SC_NPROCESSORS_ONLN
- long cpus_onln = sysconf(_SC_NPROCESSORS_ONLN);
-#else
- long cpus_onln = -1;
-#endif
- long cpus = -1;
-
- if (cpus_conf > 0 && cpus_onln < 0) {
- cpus = cpus_conf;
- } else if (cpus_onln > 0 && cpus_conf < 0) {
- cpus = cpus_onln;
- } else if (cpus_onln > 0 && cpus_conf > 0) {
- if (cpus_onln < cpus_conf) {
- log_notice(LD_GENERAL, "I think we have %ld CPUS, but only %ld of them "
- "are available. Telling Tor to only use %ld. You can over"
- "ride this with the NumCPUs option",
- cpus_conf, cpus_onln, cpus_onln);
- }
- cpus = cpus_onln;
- }
-
- if (cpus >= 1 && cpus < INT_MAX)
- return (int)cpus;
- else
- return -1;
-#else
- return -1;
-#endif /* defined(_WIN32) || ... */
-}
-
-#define MAX_DETECTABLE_CPUS 16
-
-/** Return how many CPUs we are running with. We assume that nobody is
- * using hot-swappable CPUs, so we don't recompute this after the first
- * time. Return -1 if we don't know how to tell the number of CPUs on this
- * system.
- */
-int
-compute_num_cpus(void)
-{
- static int num_cpus = -2;
- if (num_cpus == -2) {
- num_cpus = compute_num_cpus_impl();
- tor_assert(num_cpus != -2);
- if (num_cpus > MAX_DETECTABLE_CPUS) {
- /* LCOV_EXCL_START */
- log_notice(LD_GENERAL, "Wow! I detected that you have %d CPUs. I "
- "will not autodetect any more than %d, though. If you "
- "want to configure more, set NumCPUs in your torrc",
- num_cpus, MAX_DETECTABLE_CPUS);
- num_cpus = MAX_DETECTABLE_CPUS;
- /* LCOV_EXCL_STOP */
- }
- }
- return num_cpus;
-}
-
-#if !defined(_WIN32)
-/** Defined iff we need to add locks when defining fake versions of reentrant
- * versions of time-related functions. */
-#define TIME_FNS_NEED_LOCKS
-#endif
-
-/** Helper: Deal with confused or out-of-bounds values from localtime_r and
- * friends. (On some platforms, they can give out-of-bounds values or can
- * return NULL.) If <b>islocal</b>, this is a localtime result; otherwise
- * it's from gmtime. The function returns <b>r</b>, when given <b>timep</b>
- * as its input. If we need to store new results, store them in
- * <b>resultbuf</b>. */
-static struct tm *
-correct_tm(int islocal, const time_t *timep, struct tm *resultbuf,
- struct tm *r)
-{
- const char *outcome;
-
- if (PREDICT_LIKELY(r)) {
- /* We can't strftime dates after 9999 CE, and we want to avoid dates
- * before 1 CE (avoiding the year 0 issue and negative years). */
- if (r->tm_year > 8099) {
- r->tm_year = 8099;
- r->tm_mon = 11;
- r->tm_mday = 31;
- r->tm_yday = 364;
- r->tm_wday = 6;
- r->tm_hour = 23;
- r->tm_min = 59;
- r->tm_sec = 59;
- } else if (r->tm_year < (1-1900)) {
- r->tm_year = (1-1900);
- r->tm_mon = 0;
- r->tm_mday = 1;
- r->tm_yday = 0;
- r->tm_wday = 0;
- r->tm_hour = 0;
- r->tm_min = 0;
- r->tm_sec = 0;
- }
- return r;
- }
-
- /* If we get here, gmtime or localtime returned NULL. It might have done
- * this because of overrun or underrun, or it might have done it because of
- * some other weird issue. */
- if (timep) {
- if (*timep < 0) {
- r = resultbuf;
- r->tm_year = 70; /* 1970 CE */
- r->tm_mon = 0;
- r->tm_mday = 1;
- r->tm_yday = 0;
- r->tm_wday = 0;
- r->tm_hour = 0;
- r->tm_min = 0 ;
- r->tm_sec = 0;
- outcome = "Rounding up to 1970";
- goto done;
- } else if (*timep >= INT32_MAX) {
- /* Rounding down to INT32_MAX isn't so great, but keep in mind that we
- * only do it if gmtime/localtime tells us NULL. */
- r = resultbuf;
- r->tm_year = 137; /* 2037 CE */
- r->tm_mon = 11;
- r->tm_mday = 31;
- r->tm_yday = 364;
- r->tm_wday = 6;
- r->tm_hour = 23;
- r->tm_min = 59;
- r->tm_sec = 59;
- outcome = "Rounding down to 2037";
- goto done;
- }
- }
-
- /* If we get here, then gmtime/localtime failed without getting an extreme
- * value for *timep */
- /* LCOV_EXCL_START */
- tor_fragile_assert();
- r = resultbuf;
- memset(resultbuf, 0, sizeof(struct tm));
- outcome="can't recover";
- /* LCOV_EXCL_STOP */
- done:
- log_warn(LD_BUG, "%s("I64_FORMAT") failed with error %s: %s",
- islocal?"localtime":"gmtime",
- timep?I64_PRINTF_ARG(*timep):0,
- strerror(errno),
- outcome);
- return r;
-}
-
-/** @{ */
-/** As localtime_r, but defined for platforms that don't have it:
- *
- * Convert *<b>timep</b> to a struct tm in local time, and store the value in
- * *<b>result</b>. Return the result on success, or NULL on failure.
- */
-#ifdef HAVE_LOCALTIME_R
-struct tm *
-tor_localtime_r(const time_t *timep, struct tm *result)
-{
- struct tm *r;
- r = localtime_r(timep, result);
- return correct_tm(1, timep, result, r);
-}
-#elif defined(TIME_FNS_NEED_LOCKS)
-struct tm *
-tor_localtime_r(const time_t *timep, struct tm *result)
-{
- struct tm *r;
- static tor_mutex_t *m=NULL;
- if (!m) { m=tor_mutex_new(); }
- tor_assert(result);
- tor_mutex_acquire(m);
- r = localtime(timep);
- if (r)
- memcpy(result, r, sizeof(struct tm));
- tor_mutex_release(m);
- return correct_tm(1, timep, result, r);
-}
-#else
-struct tm *
-tor_localtime_r(const time_t *timep, struct tm *result)
-{
- struct tm *r;
- tor_assert(result);
- r = localtime(timep);
- if (r)
- memcpy(result, r, sizeof(struct tm));
- return correct_tm(1, timep, result, r);
-}
-#endif /* defined(HAVE_LOCALTIME_R) || ... */
-/** @} */
-
-/** @{ */
-/** As gmtime_r, but defined for platforms that don't have it:
- *
- * Convert *<b>timep</b> to a struct tm in UTC, and store the value in
- * *<b>result</b>. Return the result on success, or NULL on failure.
- */
-#ifdef HAVE_GMTIME_R
-struct tm *
-tor_gmtime_r(const time_t *timep, struct tm *result)
-{
- struct tm *r;
- r = gmtime_r(timep, result);
- return correct_tm(0, timep, result, r);
-}
-#elif defined(TIME_FNS_NEED_LOCKS)
-struct tm *
-tor_gmtime_r(const time_t *timep, struct tm *result)
-{
- struct tm *r;
- static tor_mutex_t *m=NULL;
- if (!m) { m=tor_mutex_new(); }
- tor_assert(result);
- tor_mutex_acquire(m);
- r = gmtime(timep);
- if (r)
- memcpy(result, r, sizeof(struct tm));
- tor_mutex_release(m);
- return correct_tm(0, timep, result, r);
-}
-#else
-struct tm *
-tor_gmtime_r(const time_t *timep, struct tm *result)
-{
- struct tm *r;
- tor_assert(result);
- r = gmtime(timep);
- if (r)
- memcpy(result, r, sizeof(struct tm));
- return correct_tm(0, timep, result, r);
-}
-#endif /* defined(HAVE_GMTIME_R) || ... */
-
-#if defined(HAVE_MLOCKALL) && HAVE_DECL_MLOCKALL && defined(RLIMIT_MEMLOCK)
-#define HAVE_UNIX_MLOCKALL
-#endif
-
-#ifdef HAVE_UNIX_MLOCKALL
-/** Attempt to raise the current and max rlimit to infinity for our process.
- * This only needs to be done once and can probably only be done when we have
- * not already dropped privileges.
- */
-static int
-tor_set_max_memlock(void)
-{
- /* Future consideration for Windows is probably SetProcessWorkingSetSize
- * This is similar to setting the memory rlimit of RLIMIT_MEMLOCK
- * http://msdn.microsoft.com/en-us/library/ms686234(VS.85).aspx
- */
-
- struct rlimit limit;
-
- /* RLIM_INFINITY is -1 on some platforms. */
- limit.rlim_cur = RLIM_INFINITY;
- limit.rlim_max = RLIM_INFINITY;
-
- if (setrlimit(RLIMIT_MEMLOCK, &limit) == -1) {
- if (errno == EPERM) {
- log_warn(LD_GENERAL, "You appear to lack permissions to change memory "
- "limits. Are you root?");
- }
- log_warn(LD_GENERAL, "Unable to raise RLIMIT_MEMLOCK: %s",
- strerror(errno));
- return -1;
- }
-
- return 0;
-}
-#endif /* defined(HAVE_UNIX_MLOCKALL) */
-
-/** Attempt to lock all current and all future memory pages.
- * This should only be called once and while we're privileged.
- * Like mlockall() we return 0 when we're successful and -1 when we're not.
- * Unlike mlockall() we return 1 if we've already attempted to lock memory.
- */
-int
-tor_mlockall(void)
-{
- static int memory_lock_attempted = 0;
-
- if (memory_lock_attempted) {
- return 1;
- }
-
- memory_lock_attempted = 1;
-
- /*
- * Future consideration for Windows may be VirtualLock
- * VirtualLock appears to implement mlock() but not mlockall()
- *
- * http://msdn.microsoft.com/en-us/library/aa366895(VS.85).aspx
- */
-
-#ifdef HAVE_UNIX_MLOCKALL
- if (tor_set_max_memlock() == 0) {
- log_debug(LD_GENERAL, "RLIMIT_MEMLOCK is now set to RLIM_INFINITY.");
- }
-
- if (mlockall(MCL_CURRENT|MCL_FUTURE) == 0) {
- log_info(LD_GENERAL, "Insecure OS paging is effectively disabled.");
- return 0;
- } else {
- if (errno == ENOSYS) {
- /* Apple - it's 2009! I'm looking at you. Grrr. */
- log_notice(LD_GENERAL, "It appears that mlockall() is not available on "
- "your platform.");
- } else if (errno == EPERM) {
- log_notice(LD_GENERAL, "It appears that you lack the permissions to "
- "lock memory. Are you root?");
- }
- log_notice(LD_GENERAL, "Unable to lock all current and future memory "
- "pages: %s", strerror(errno));
- return -1;
- }
-#else /* !(defined(HAVE_UNIX_MLOCKALL)) */
- log_warn(LD_GENERAL, "Unable to lock memory pages. mlockall() unsupported?");
- return -1;
-#endif /* defined(HAVE_UNIX_MLOCKALL) */
-}
-
-/**
- * On Windows, WSAEWOULDBLOCK is not always correct: when you see it,
- * you need to ask the socket for its actual errno. Also, you need to
- * get your errors from WSAGetLastError, not errno. (If you supply a
- * socket of -1, we check WSAGetLastError, but don't correct
- * WSAEWOULDBLOCKs.)
- *
- * The upshot of all of this is that when a socket call fails, you
- * should call tor_socket_errno <em>at most once</em> on the failing
- * socket to get the error.
- */
-#if defined(_WIN32)
-int
-tor_socket_errno(tor_socket_t sock)
-{
- int optval, optvallen=sizeof(optval);
- int err = WSAGetLastError();
- if (err == WSAEWOULDBLOCK && SOCKET_OK(sock)) {
- if (getsockopt(sock, SOL_SOCKET, SO_ERROR, (void*)&optval, &optvallen))
- return err;
- if (optval)
- return optval;
- }
- return err;
-}
-#endif /* defined(_WIN32) */
-
-#if defined(_WIN32)
-#define E(code, s) { code, (s " [" #code " ]") }
-struct { int code; const char *msg; } windows_socket_errors[] = {
- E(WSAEINTR, "Interrupted function call"),
- E(WSAEACCES, "Permission denied"),
- E(WSAEFAULT, "Bad address"),
- E(WSAEINVAL, "Invalid argument"),
- E(WSAEMFILE, "Too many open files"),
- E(WSAEWOULDBLOCK, "Resource temporarily unavailable"),
- E(WSAEINPROGRESS, "Operation now in progress"),
- E(WSAEALREADY, "Operation already in progress"),
- E(WSAENOTSOCK, "Socket operation on nonsocket"),
- E(WSAEDESTADDRREQ, "Destination address required"),
- E(WSAEMSGSIZE, "Message too long"),
- E(WSAEPROTOTYPE, "Protocol wrong for socket"),
- E(WSAENOPROTOOPT, "Bad protocol option"),
- E(WSAEPROTONOSUPPORT, "Protocol not supported"),
- E(WSAESOCKTNOSUPPORT, "Socket type not supported"),
- /* What's the difference between NOTSUPP and NOSUPPORT? :) */
- E(WSAEOPNOTSUPP, "Operation not supported"),
- E(WSAEPFNOSUPPORT, "Protocol family not supported"),
- E(WSAEAFNOSUPPORT, "Address family not supported by protocol family"),
- E(WSAEADDRINUSE, "Address already in use"),
- E(WSAEADDRNOTAVAIL, "Cannot assign requested address"),
- E(WSAENETDOWN, "Network is down"),
- E(WSAENETUNREACH, "Network is unreachable"),
- E(WSAENETRESET, "Network dropped connection on reset"),
- E(WSAECONNABORTED, "Software caused connection abort"),
- E(WSAECONNRESET, "Connection reset by peer"),
- E(WSAENOBUFS, "No buffer space available"),
- E(WSAEISCONN, "Socket is already connected"),
- E(WSAENOTCONN, "Socket is not connected"),
- E(WSAESHUTDOWN, "Cannot send after socket shutdown"),
- E(WSAETIMEDOUT, "Connection timed out"),
- E(WSAECONNREFUSED, "Connection refused"),
- E(WSAEHOSTDOWN, "Host is down"),
- E(WSAEHOSTUNREACH, "No route to host"),
- E(WSAEPROCLIM, "Too many processes"),
- /* Yes, some of these start with WSA, not WSAE. No, I don't know why. */
- E(WSASYSNOTREADY, "Network subsystem is unavailable"),
- E(WSAVERNOTSUPPORTED, "Winsock.dll out of range"),
- E(WSANOTINITIALISED, "Successful WSAStartup not yet performed"),
- E(WSAEDISCON, "Graceful shutdown now in progress"),
-#ifdef WSATYPE_NOT_FOUND
- E(WSATYPE_NOT_FOUND, "Class type not found"),
-#endif
- E(WSAHOST_NOT_FOUND, "Host not found"),
- E(WSATRY_AGAIN, "Nonauthoritative host not found"),
- E(WSANO_RECOVERY, "This is a nonrecoverable error"),
- E(WSANO_DATA, "Valid name, no data record of requested type)"),
-
- /* There are some more error codes whose numeric values are marked
- * <b>OS dependent</b>. They start with WSA_, apparently for the same
- * reason that practitioners of some craft traditions deliberately
- * introduce imperfections into their baskets and rugs "to allow the
- * evil spirits to escape." If we catch them, then our binaries
- * might not report consistent results across versions of Windows.
- * Thus, I'm going to let them all fall through.
- */
- { -1, NULL },
-};
-/** There does not seem to be a strerror equivalent for Winsock errors.
- * Naturally, we have to roll our own.
- */
-const char *
-tor_socket_strerror(int e)
-{
- int i;
- for (i=0; windows_socket_errors[i].code >= 0; ++i) {
- if (e == windows_socket_errors[i].code)
- return windows_socket_errors[i].msg;
- }
- return strerror(e);
-}
-#endif /* defined(_WIN32) */
-
-/** Called before we make any calls to network-related functions.
- * (Some operating systems require their network libraries to be
- * initialized.) */
-int
-network_init(void)
-{
-#ifdef _WIN32
- /* This silly exercise is necessary before windows will allow
- * gethostbyname to work. */
- WSADATA WSAData;
- int r;
- r = WSAStartup(0x101,&WSAData);
- if (r) {
- log_warn(LD_NET,"Error initializing windows network layer: code was %d",r);
- return -1;
- }
- if (sizeof(SOCKET) != sizeof(tor_socket_t)) {
- log_warn(LD_BUG,"The tor_socket_t type does not match SOCKET in size; Tor "
- "might not work. (Sizes are %d and %d respectively.)",
- (int)sizeof(tor_socket_t), (int)sizeof(SOCKET));
- }
- /* WSAData.iMaxSockets might show the max sockets we're allowed to use.
- * We might use it to complain if we're trying to be a server but have
- * too few sockets available. */
-#endif /* defined(_WIN32) */
- return 0;
-}
-
-#ifdef _WIN32
-/** Return a newly allocated string describing the windows system error code
- * <b>err</b>. Note that error codes are different from errno. Error codes
- * come from GetLastError() when a winapi call fails. errno is set only when
- * ANSI functions fail. Whee. */
-char *
-format_win32_error(DWORD err)
-{
- TCHAR *str = NULL;
- char *result;
- DWORD n;
-
- /* Somebody once decided that this interface was better than strerror(). */
- n = FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER |
- FORMAT_MESSAGE_FROM_SYSTEM |
- FORMAT_MESSAGE_IGNORE_INSERTS,
- NULL, err,
- MAKELANGID(LANG_ENGLISH, SUBLANG_DEFAULT),
- (LPVOID)&str,
- 0, NULL);
-
- if (str && n) {
-#ifdef UNICODE
- size_t len;
- if (n > 128*1024)
- len = (128 * 1024) * 2 + 1; /* This shouldn't be possible, but let's
- * make sure. */
- else
- len = n * 2 + 1;
- result = tor_malloc(len);
- wcstombs(result,str,len);
- result[len-1] = '\0';
-#else /* !(defined(UNICODE)) */
- result = tor_strdup(str);
-#endif /* defined(UNICODE) */
- } else {
- result = tor_strdup("<unformattable error>");
- }
- if (str) {
- LocalFree(str); /* LocalFree != free() */
- }
- return result;
-}
-#endif /* defined(_WIN32) */
-
-#if defined(HW_PHYSMEM64)
-/* This appears to be an OpenBSD thing */
-#define INT64_HW_MEM HW_PHYSMEM64
-#elif defined(HW_MEMSIZE)
-/* OSX defines this one */
-#define INT64_HW_MEM HW_MEMSIZE
-#endif /* defined(HW_PHYSMEM64) || ... */
-
-/**
- * Helper: try to detect the total system memory, and return it. On failure,
- * return 0.
- */
-static uint64_t
-get_total_system_memory_impl(void)
-{
-#if defined(__linux__)
- /* On linux, sysctl is deprecated. Because proc is so awesome that you
- * shouldn't _want_ to write portable code, I guess? */
- unsigned long long result=0;
- int fd = -1;
- char *s = NULL;
- const char *cp;
- size_t file_size=0;
- if (-1 == (fd = tor_open_cloexec("/proc/meminfo",O_RDONLY,0)))
- return 0;
- s = read_file_to_str_until_eof(fd, 65536, &file_size);
- if (!s)
- goto err;
- cp = strstr(s, "MemTotal:");
- if (!cp)
- goto err;
- /* Use the system sscanf so that space will match a wider number of space */
- if (sscanf(cp, "MemTotal: %llu kB\n", &result) != 1)
- goto err;
-
- close(fd);
- tor_free(s);
- return result * 1024;
-
- /* LCOV_EXCL_START Can't reach this unless proc is broken. */
- err:
- tor_free(s);
- close(fd);
- return 0;
- /* LCOV_EXCL_STOP */
-#elif defined (_WIN32)
- /* Windows has MEMORYSTATUSEX; pretty straightforward. */
- MEMORYSTATUSEX ms;
- memset(&ms, 0, sizeof(ms));
- ms.dwLength = sizeof(ms);
- if (! GlobalMemoryStatusEx(&ms))
- return 0;
-
- return ms.ullTotalPhys;
-
-#elif defined(HAVE_SYSCTL) && defined(INT64_HW_MEM)
- /* On many systems, HW_PYHSMEM is clipped to 32 bits; let's use a better
- * variant if we know about it. */
- uint64_t memsize = 0;
- size_t len = sizeof(memsize);
- int mib[2] = {CTL_HW, INT64_HW_MEM};
- if (sysctl(mib,2,&memsize,&len,NULL,0))
- return 0;
-
- return memsize;
-
-#elif defined(HAVE_SYSCTL) && defined(HW_PHYSMEM)
- /* On some systems (like FreeBSD I hope) you can use a size_t with
- * HW_PHYSMEM. */
- size_t memsize=0;
- size_t len = sizeof(memsize);
- int mib[2] = {CTL_HW, HW_USERMEM};
- if (sysctl(mib,2,&memsize,&len,NULL,0))
- return 0;
-
- return memsize;
-
-#else
- /* I have no clue. */
- return 0;
-#endif /* defined(__linux__) || ... */
-}
-
-/**
- * Try to find out how much physical memory the system has. On success,
- * return 0 and set *<b>mem_out</b> to that value. On failure, return -1.
- */
-MOCK_IMPL(int,
-get_total_system_memory, (size_t *mem_out))
-{
- static size_t mem_cached=0;
- uint64_t m = get_total_system_memory_impl();
- if (0 == m) {
- /* LCOV_EXCL_START -- can't make this happen without mocking. */
- /* We couldn't find our memory total */
- if (0 == mem_cached) {
- /* We have no cached value either */
- *mem_out = 0;
- return -1;
- }
-
- *mem_out = mem_cached;
- return 0;
- /* LCOV_EXCL_STOP */
- }
-
-#if SIZE_MAX != UINT64_MAX
- if (m > SIZE_MAX) {
- /* I think this could happen if we're a 32-bit Tor running on a 64-bit
- * system: we could have more system memory than would fit in a
- * size_t. */
- m = SIZE_MAX;
- }
-#endif /* SIZE_MAX != UINT64_MAX */
-
- *mem_out = mem_cached = (size_t) m;
-
- return 0;
-}
-
-/** Emit the password prompt <b>prompt</b>, then read up to <b>buflen</b>
- * bytes of passphrase into <b>output</b>. Return the number of bytes in
- * the passphrase, excluding terminating NUL.
- */
-ssize_t
-tor_getpass(const char *prompt, char *output, size_t buflen)
-{
- tor_assert(buflen <= SSIZE_MAX);
- tor_assert(buflen >= 1);
-#if defined(HAVE_READPASSPHRASE)
- char *pwd = readpassphrase(prompt, output, buflen, RPP_ECHO_OFF);
- if (pwd == NULL)
- return -1;
- return strlen(pwd);
-#elif defined(_WIN32)
- int r = -1;
- while (*prompt) {
- _putch(*prompt++);
- }
-
- tor_assert(buflen <= INT_MAX);
- wchar_t *buf = tor_calloc(buflen, sizeof(wchar_t));
-
- wchar_t *ptr = buf, *lastch = buf + buflen - 1;
- while (ptr < lastch) {
- wint_t ch = _getwch();
- switch (ch) {
- case '\r':
- case '\n':
- case WEOF:
- goto done_reading;
- case 3:
- goto done; /* Can't actually read ctrl-c this way. */
- case '\b':
- if (ptr > buf)
- --ptr;
- continue;
- case 0:
- case 0xe0:
- ch = _getwch(); /* Ignore; this is a function or arrow key */
- break;
- default:
- *ptr++ = ch;
- break;
- }
- }
- done_reading:
- ;
-
-#ifndef WC_ERR_INVALID_CHARS
-#define WC_ERR_INVALID_CHARS 0x80
-#endif
-
- /* Now convert it to UTF-8 */
- r = WideCharToMultiByte(CP_UTF8,
- WC_NO_BEST_FIT_CHARS|WC_ERR_INVALID_CHARS,
- buf, (int)(ptr-buf),
- output, (int)(buflen-1),
- NULL, NULL);
- if (r <= 0) {
- r = -1;
- goto done;
- }
-
- tor_assert(r < (int)buflen);
-
- output[r] = 0;
-
- done:
- SecureZeroMemory(buf, sizeof(wchar_t)*buflen);
- tor_free(buf);
- return r;
-#else
-#error "No implementation for tor_getpass found!"
-#endif /* defined(HAVE_READPASSPHRASE) || ... */
-}
-
-/** Return the amount of free disk space we have permission to use, in
- * bytes. Return -1 if the amount of free space can't be determined. */
-int64_t
-tor_get_avail_disk_space(const char *path)
-{
-#ifdef HAVE_STATVFS
- struct statvfs st;
- int r;
- memset(&st, 0, sizeof(st));
-
- r = statvfs(path, &st);
- if (r < 0)
- return -1;
-
- int64_t result = st.f_bavail;
- if (st.f_frsize) {
- result *= st.f_frsize;
- } else if (st.f_bsize) {
- result *= st.f_bsize;
- } else {
- return -1;
- }
-
- return result;
-#elif defined(_WIN32)
- ULARGE_INTEGER freeBytesAvail;
- BOOL ok;
-
- ok = GetDiskFreeSpaceEx(path, &freeBytesAvail, NULL, NULL);
- if (!ok) {
- return -1;
- }
- return (int64_t)freeBytesAvail.QuadPart;
-#else
- (void)path;
- errno = ENOSYS;
- return -1;
-#endif /* defined(HAVE_STATVFS) || ... */
-}
-
diff --git a/src/common/compat.h b/src/common/compat.h
deleted file mode 100644
index c7e7f8d9ef..0000000000
--- a/src/common/compat.h
+++ /dev/null
@@ -1,757 +0,0 @@
-/* Copyright (c) 2003-2004, Roger Dingledine
- * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2017, The Tor Project, Inc. */
-/* See LICENSE for licensing information */
-
-#ifndef TOR_COMPAT_H
-#define TOR_COMPAT_H
-
-#include "orconfig.h"
-#ifdef _WIN32
-#include <winsock2.h>
-#include <ws2tcpip.h>
-#ifndef SIO_IDEAL_SEND_BACKLOG_QUERY
-#define SIO_IDEAL_SEND_BACKLOG_QUERY 0x4004747b
-#endif
-#endif
-#include "torint.h"
-#include "testsupport.h"
-#ifdef HAVE_SYS_PARAM_H
-#include <sys/param.h>
-#endif
-#ifdef HAVE_SYS_TYPES_H
-#include <sys/types.h>
-#endif
-#ifdef HAVE_SYS_TIME_H
-#include <sys/time.h>
-#endif
-#ifdef HAVE_TIME_H
-#include <time.h>
-#endif
-#ifdef HAVE_STRING_H
-#include <string.h>
-#endif
-#include <stdarg.h>
-#ifdef HAVE_SYS_RESOURCE_H
-#include <sys/resource.h>
-#endif
-#ifdef HAVE_SYS_SOCKET_H
-#include <sys/socket.h>
-#endif
-#ifdef HAVE_NETINET_IN_H
-#include <netinet/in.h>
-#endif
-#ifdef HAVE_NETINET6_IN6_H
-#include <netinet6/in6.h>
-#endif
-
-#include "compat_time.h"
-
-#if defined(__has_feature)
-# if __has_feature(address_sanitizer)
-/* Some of the fancy glibc strcmp() macros include references to memory that
- * clang rejects because it is off the end of a less-than-3. Clang hates this,
- * even though those references never actually happen. */
-# undef strcmp
-#endif /* __has_feature(address_sanitizer) */
-#endif /* defined(__has_feature) */
-
-#include <stdio.h>
-#include <errno.h>
-
-#ifndef NULL_REP_IS_ZERO_BYTES
-#error "It seems your platform does not represent NULL as zero. We can't cope."
-#endif
-
-#ifndef DOUBLE_0_REP_IS_ZERO_BYTES
-#error "It seems your platform does not represent 0.0 as zeros. We can't cope."
-#endif
-
-#if 'a'!=97 || 'z'!=122 || 'A'!=65 || ' '!=32
-#error "It seems that you encode characters in something other than ASCII."
-#endif
-
-/* ===== Compiler compatibility */
-
-/* GCC can check printf and scanf types on arbitrary functions. */
-#ifdef __GNUC__
-#define CHECK_PRINTF(formatIdx, firstArg) \
- __attribute__ ((format(printf, formatIdx, firstArg)))
-#else
-#define CHECK_PRINTF(formatIdx, firstArg)
-#endif /* defined(__GNUC__) */
-#ifdef __GNUC__
-#define CHECK_SCANF(formatIdx, firstArg) \
- __attribute__ ((format(scanf, formatIdx, firstArg)))
-#else
-#define CHECK_SCANF(formatIdx, firstArg)
-#endif /* defined(__GNUC__) */
-
-/* What GCC do we have? */
-#ifdef __GNUC__
-#define GCC_VERSION (__GNUC__ * 100 + __GNUC_MINOR__)
-#else
-#define GCC_VERSION 0
-#endif
-
-/* Temporarily enable and disable warnings. */
-#ifdef __GNUC__
-# define PRAGMA_STRINGIFY_(s) #s
-# define PRAGMA_JOIN_STRINGIFY_(a,b) PRAGMA_STRINGIFY_(a ## b)
-/* Support for macro-generated pragmas (c99) */
-# define PRAGMA_(x) _Pragma (#x)
-# ifdef __clang__
-# define PRAGMA_DIAGNOSTIC_(x) PRAGMA_(clang diagnostic x)
-# else
-# define PRAGMA_DIAGNOSTIC_(x) PRAGMA_(GCC diagnostic x)
-# endif
-# if defined(__clang__) || GCC_VERSION >= 406
-/* we have push/pop support */
-# define DISABLE_GCC_WARNING(warningopt) \
- PRAGMA_DIAGNOSTIC_(push) \
- PRAGMA_DIAGNOSTIC_(ignored PRAGMA_JOIN_STRINGIFY_(-W,warningopt))
-# define ENABLE_GCC_WARNING(warningopt) \
- PRAGMA_DIAGNOSTIC_(pop)
-#else /* !(defined(__clang__) || GCC_VERSION >= 406) */
-/* older version of gcc: no push/pop support. */
-# define DISABLE_GCC_WARNING(warningopt) \
- PRAGMA_DIAGNOSTIC_(ignored PRAGMA_JOIN_STRINGIFY_(-W,warningopt))
-# define ENABLE_GCC_WARNING(warningopt) \
- PRAGMA_DIAGNOSTIC_(warning PRAGMA_JOIN_STRINGIFY_(-W,warningopt))
-#endif /* defined(__clang__) || GCC_VERSION >= 406 */
-#else /* !(defined(__GNUC__)) */
-/* not gcc at all */
-# define DISABLE_GCC_WARNING(warning)
-# define ENABLE_GCC_WARNING(warning)
-#endif /* defined(__GNUC__) */
-
-/* inline is __inline on windows. */
-#ifdef _WIN32
-#define inline __inline
-#endif
-
-/* Try to get a reasonable __func__ substitute in place. */
-#if defined(_MSC_VER)
-
-#define __func__ __FUNCTION__
-
-#else
-/* For platforms where autoconf works, make sure __func__ is defined
- * sanely. */
-#ifndef HAVE_MACRO__func__
-#ifdef HAVE_MACRO__FUNCTION__
-#define __func__ __FUNCTION__
-#elif HAVE_MACRO__FUNC__
-#define __func__ __FUNC__
-#else
-#define __func__ "???"
-#endif /* defined(HAVE_MACRO__FUNCTION__) || ... */
-#endif /* !defined(HAVE_MACRO__func__) */
-#endif /* defined(_MSC_VER) */
-
-#define U64_TO_DBL(x) ((double) (x))
-#define DBL_TO_U64(x) ((uint64_t) (x))
-
-#ifdef ENUM_VALS_ARE_SIGNED
-#define ENUM_BF(t) unsigned
-#else
-/** Wrapper for having a bitfield of an enumerated type. Where possible, we
- * just use the enumerated type (so the compiler can help us and notice
- * problems), but if enumerated types are unsigned, we must use unsigned,
- * so that the loss of precision doesn't make large values negative. */
-#define ENUM_BF(t) t
-#endif /* defined(ENUM_VALS_ARE_SIGNED) */
-
-/* GCC has several useful attributes. */
-#if defined(__GNUC__) && __GNUC__ >= 3
-#define ATTR_NORETURN __attribute__((noreturn))
-#define ATTR_CONST __attribute__((const))
-#define ATTR_MALLOC __attribute__((malloc))
-#define ATTR_NORETURN __attribute__((noreturn))
-#define ATTR_WUR __attribute__((warn_unused_result))
-/* Alas, nonnull is not at present a good idea for us. We'd like to get
- * warnings when we pass NULL where we shouldn't (which nonnull does, albeit
- * spottily), but we don't want to tell the compiler to make optimizations
- * with the assumption that the argument can't be NULL (since this would make
- * many of our checks go away, and make our code less robust against
- * programming errors). Unfortunately, nonnull currently does both of these
- * things, and there's no good way to split them up.
- *
- * #define ATTR_NONNULL(x) __attribute__((nonnull x)) */
-#define ATTR_NONNULL(x)
-#define ATTR_UNUSED __attribute__ ((unused))
-
-/** Macro: Evaluates to <b>exp</b> and hints the compiler that the value
- * of <b>exp</b> will probably be true.
- *
- * In other words, "if (PREDICT_LIKELY(foo))" is the same as "if (foo)",
- * except that it tells the compiler that the branch will be taken most of the
- * time. This can generate slightly better code with some CPUs.
- */
-#define PREDICT_LIKELY(exp) __builtin_expect(!!(exp), 1)
-/** Macro: Evaluates to <b>exp</b> and hints the compiler that the value
- * of <b>exp</b> will probably be false.
- *
- * In other words, "if (PREDICT_UNLIKELY(foo))" is the same as "if (foo)",
- * except that it tells the compiler that the branch will usually not be
- * taken. This can generate slightly better code with some CPUs.
- */
-#define PREDICT_UNLIKELY(exp) __builtin_expect(!!(exp), 0)
-#else /* !(defined(__GNUC__) && __GNUC__ >= 3) */
-#define ATTR_NORETURN
-#define ATTR_CONST
-#define ATTR_MALLOC
-#define ATTR_NORETURN
-#define ATTR_NONNULL(x)
-#define ATTR_UNUSED
-#define ATTR_WUR
-#define PREDICT_LIKELY(exp) (exp)
-#define PREDICT_UNLIKELY(exp) (exp)
-#endif /* defined(__GNUC__) && __GNUC__ >= 3 */
-
-/** Expands to a syntactically valid empty statement. */
-#define STMT_NIL (void)0
-
-/** Expands to a syntactically valid empty statement, explicitly (void)ing its
- * argument. */
-#define STMT_VOID(a) while (0) { (void)(a); }
-
-#ifdef __GNUC__
-/** STMT_BEGIN and STMT_END are used to wrap blocks inside macros so that
- * the macro can be used as if it were a single C statement. */
-#define STMT_BEGIN (void) ({
-#define STMT_END })
-#elif defined(sun) || defined(__sun__)
-#define STMT_BEGIN if (1) {
-#define STMT_END } else STMT_NIL
-#else
-#define STMT_BEGIN do {
-#define STMT_END } while (0)
-#endif /* defined(__GNUC__) || ... */
-
-/* Some tools (like coccinelle) don't like to see operators as macro
- * arguments. */
-#define OP_LT <
-#define OP_GT >
-#define OP_GE >=
-#define OP_LE <=
-#define OP_EQ ==
-#define OP_NE !=
-
-/* ===== String compatibility */
-#ifdef _WIN32
-/* Windows names string functions differently from most other platforms. */
-#define strncasecmp _strnicmp
-#define strcasecmp _stricmp
-#endif
-
-#if defined __APPLE__
-/* On OSX 10.9 and later, the overlap-checking code for strlcat would
- * appear to have a severe bug that can sometimes cause aborts in Tor.
- * Instead, use the non-checking variants. This is sad.
- *
- * See https://trac.torproject.org/projects/tor/ticket/15205
- */
-#undef strlcat
-#undef strlcpy
-#endif /* defined __APPLE__ */
-
-#ifndef HAVE_STRLCAT
-size_t strlcat(char *dst, const char *src, size_t siz) ATTR_NONNULL((1,2));
-#endif
-#ifndef HAVE_STRLCPY
-size_t strlcpy(char *dst, const char *src, size_t siz) ATTR_NONNULL((1,2));
-#endif
-
-#ifdef _MSC_VER
-/** Casts the uint64_t value in <b>a</b> to the right type for an argument
- * to printf. */
-#define U64_PRINTF_ARG(a) (a)
-/** Casts the uint64_t* value in <b>a</b> to the right type for an argument
- * to scanf. */
-#define U64_SCANF_ARG(a) (a)
-/** Expands to a literal uint64_t-typed constant for the value <b>n</b>. */
-#define U64_LITERAL(n) (n ## ui64)
-#define I64_PRINTF_ARG(a) (a)
-#define I64_SCANF_ARG(a) (a)
-#define I64_LITERAL(n) (n ## i64)
-#else /* !(defined(_MSC_VER)) */
-#define U64_PRINTF_ARG(a) ((long long unsigned int)(a))
-#define U64_SCANF_ARG(a) ((long long unsigned int*)(a))
-#define U64_LITERAL(n) (n ## llu)
-#define I64_PRINTF_ARG(a) ((long long signed int)(a))
-#define I64_SCANF_ARG(a) ((long long signed int*)(a))
-#define I64_LITERAL(n) (n ## ll)
-#endif /* defined(_MSC_VER) */
-
-#if defined(__MINGW32__) || defined(__MINGW64__)
-#define MINGW_ANY
-#endif
-
-#if defined(_MSC_VER) || defined(MINGW_ANY)
-/** The formatting string used to put a uint64_t value in a printf() or
- * scanf() function. See also U64_PRINTF_ARG and U64_SCANF_ARG. */
-#define U64_FORMAT "%I64u"
-#define I64_FORMAT "%I64d"
-#else /* !(defined(_MSC_VER) || defined(MINGW_ANY)) */
-#define U64_FORMAT "%llu"
-#define I64_FORMAT "%lld"
-#endif /* defined(_MSC_VER) || defined(MINGW_ANY) */
-
-#if (SIZEOF_INTPTR_T == SIZEOF_INT)
-#define INTPTR_T_FORMAT "%d"
-#define INTPTR_PRINTF_ARG(x) ((int)(x))
-#elif (SIZEOF_INTPTR_T == SIZEOF_LONG)
-#define INTPTR_T_FORMAT "%ld"
-#define INTPTR_PRINTF_ARG(x) ((long)(x))
-#elif (SIZEOF_INTPTR_T == 8)
-#define INTPTR_T_FORMAT I64_FORMAT
-#define INTPTR_PRINTF_ARG(x) I64_PRINTF_ARG(x)
-#else
-#error Unknown: SIZEOF_INTPTR_T
-#endif /* (SIZEOF_INTPTR_T == SIZEOF_INT) || ... */
-
-/** Represents an mmaped file. Allocated via tor_mmap_file; freed with
- * tor_munmap_file. */
-typedef struct tor_mmap_t {
- const char *data; /**< Mapping of the file's contents. */
- size_t size; /**< Size of the file. */
-
- /* None of the fields below should be accessed from outside compat.c */
-#ifdef HAVE_MMAP
- size_t mapping_size; /**< Size of the actual mapping. (This is this file
- * size, rounded up to the nearest page.) */
-#elif defined _WIN32
- HANDLE mmap_handle;
-#endif /* defined(HAVE_MMAP) || ... */
-
-} tor_mmap_t;
-
-tor_mmap_t *tor_mmap_file(const char *filename) ATTR_NONNULL((1));
-int tor_munmap_file(tor_mmap_t *handle) ATTR_NONNULL((1));
-
-int tor_snprintf(char *str, size_t size, const char *format, ...)
- CHECK_PRINTF(3,4) ATTR_NONNULL((1,3));
-int tor_vsnprintf(char *str, size_t size, const char *format, va_list args)
- CHECK_PRINTF(3,0) ATTR_NONNULL((1,3));
-
-int tor_asprintf(char **strp, const char *fmt, ...)
- CHECK_PRINTF(2,3);
-int tor_vasprintf(char **strp, const char *fmt, va_list args)
- CHECK_PRINTF(2,0);
-
-const void *tor_memmem(const void *haystack, size_t hlen, const void *needle,
- size_t nlen) ATTR_NONNULL((1,3));
-static const void *tor_memstr(const void *haystack, size_t hlen,
- const char *needle) ATTR_NONNULL((1,3));
-static inline const void *
-tor_memstr(const void *haystack, size_t hlen, const char *needle)
-{
- return tor_memmem(haystack, hlen, needle, strlen(needle));
-}
-
-/* Much of the time when we're checking ctypes, we're doing spec compliance,
- * which all assumes we're doing ASCII. */
-#define DECLARE_CTYPE_FN(name) \
- static int TOR_##name(char c); \
- extern const uint32_t TOR_##name##_TABLE[]; \
- static inline int TOR_##name(char c) { \
- uint8_t u = c; \
- return !!(TOR_##name##_TABLE[(u >> 5) & 7] & (1u << (u & 31))); \
- }
-DECLARE_CTYPE_FN(ISALPHA)
-DECLARE_CTYPE_FN(ISALNUM)
-DECLARE_CTYPE_FN(ISSPACE)
-DECLARE_CTYPE_FN(ISDIGIT)
-DECLARE_CTYPE_FN(ISXDIGIT)
-DECLARE_CTYPE_FN(ISPRINT)
-DECLARE_CTYPE_FN(ISLOWER)
-DECLARE_CTYPE_FN(ISUPPER)
-extern const uint8_t TOR_TOUPPER_TABLE[];
-extern const uint8_t TOR_TOLOWER_TABLE[];
-#define TOR_TOLOWER(c) (TOR_TOLOWER_TABLE[(uint8_t)c])
-#define TOR_TOUPPER(c) (TOR_TOUPPER_TABLE[(uint8_t)c])
-
-char *tor_strtok_r_impl(char *str, const char *sep, char **lasts);
-#ifdef HAVE_STRTOK_R
-#define tor_strtok_r(str, sep, lasts) strtok_r(str, sep, lasts)
-#else
-#define tor_strtok_r(str, sep, lasts) tor_strtok_r_impl(str, sep, lasts)
-#endif
-
-#ifdef _WIN32
-#define SHORT_FILE__ (tor_fix_source_file(__FILE__))
-const char *tor_fix_source_file(const char *fname);
-#else
-#define SHORT_FILE__ (__FILE__)
-#define tor_fix_source_file(s) (s)
-#endif /* defined(_WIN32) */
-
-/* ===== Time compatibility */
-
-struct tm *tor_localtime_r(const time_t *timep, struct tm *result);
-struct tm *tor_gmtime_r(const time_t *timep, struct tm *result);
-
-#ifndef timeradd
-/** Replacement for timeradd on platforms that do not have it: sets tvout to
- * the sum of tv1 and tv2. */
-#define timeradd(tv1,tv2,tvout) \
- do { \
- (tvout)->tv_sec = (tv1)->tv_sec + (tv2)->tv_sec; \
- (tvout)->tv_usec = (tv1)->tv_usec + (tv2)->tv_usec; \
- if ((tvout)->tv_usec >= 1000000) { \
- (tvout)->tv_usec -= 1000000; \
- (tvout)->tv_sec++; \
- } \
- } while (0)
-#endif /* !defined(timeradd) */
-
-#ifndef timersub
-/** Replacement for timersub on platforms that do not have it: sets tvout to
- * tv1 minus tv2. */
-#define timersub(tv1,tv2,tvout) \
- do { \
- (tvout)->tv_sec = (tv1)->tv_sec - (tv2)->tv_sec; \
- (tvout)->tv_usec = (tv1)->tv_usec - (tv2)->tv_usec; \
- if ((tvout)->tv_usec < 0) { \
- (tvout)->tv_usec += 1000000; \
- (tvout)->tv_sec--; \
- } \
- } while (0)
-#endif /* !defined(timersub) */
-
-#ifndef timercmp
-/** Replacement for timercmp on platforms that do not have it: returns true
- * iff the relational operator "op" makes the expression tv1 op tv2 true.
- *
- * Note that while this definition should work for all boolean operators, some
- * platforms' native timercmp definitions do not support >=, <=, or ==. So
- * don't use those.
- */
-#define timercmp(tv1,tv2,op) \
- (((tv1)->tv_sec == (tv2)->tv_sec) ? \
- ((tv1)->tv_usec op (tv2)->tv_usec) : \
- ((tv1)->tv_sec op (tv2)->tv_sec))
-#endif /* !defined(timercmp) */
-
-/* ===== File compatibility */
-int tor_open_cloexec(const char *path, int flags, unsigned mode);
-FILE *tor_fopen_cloexec(const char *path, const char *mode);
-int tor_rename(const char *path_old, const char *path_new);
-
-int replace_file(const char *from, const char *to);
-int touch_file(const char *fname);
-
-typedef struct tor_lockfile_t tor_lockfile_t;
-tor_lockfile_t *tor_lockfile_lock(const char *filename, int blocking,
- int *locked_out);
-void tor_lockfile_unlock(tor_lockfile_t *lockfile);
-
-off_t tor_fd_getpos(int fd);
-int tor_fd_setpos(int fd, off_t pos);
-int tor_fd_seekend(int fd);
-int tor_ftruncate(int fd);
-
-int64_t tor_get_avail_disk_space(const char *path);
-
-#ifdef _WIN32
-#define PATH_SEPARATOR "\\"
-#else
-#define PATH_SEPARATOR "/"
-#endif
-
-/* ===== Net compatibility */
-
-#if (SIZEOF_SOCKLEN_T == 0)
-typedef int socklen_t;
-#endif
-
-#ifdef _WIN32
-/* XXX Actually, this should arguably be SOCKET; we use intptr_t here so that
- * any inadvertent checks for the socket being <= 0 or > 0 will probably
- * still work. */
-#define tor_socket_t intptr_t
-#define TOR_SOCKET_T_FORMAT INTPTR_T_FORMAT
-#define SOCKET_OK(s) ((SOCKET)(s) != INVALID_SOCKET)
-#define TOR_INVALID_SOCKET INVALID_SOCKET
-#else /* !(defined(_WIN32)) */
-/** Type used for a network socket. */
-#define tor_socket_t int
-#define TOR_SOCKET_T_FORMAT "%d"
-/** Macro: true iff 's' is a possible value for a valid initialized socket. */
-#define SOCKET_OK(s) ((s) >= 0)
-/** Error/uninitialized value for a tor_socket_t. */
-#define TOR_INVALID_SOCKET (-1)
-#endif /* defined(_WIN32) */
-
-int tor_close_socket_simple(tor_socket_t s);
-MOCK_DECL(int, tor_close_socket, (tor_socket_t s));
-void tor_take_socket_ownership(tor_socket_t s);
-tor_socket_t tor_open_socket_with_extensions(
- int domain, int type, int protocol,
- int cloexec, int nonblock);
-MOCK_DECL(tor_socket_t,
-tor_open_socket,(int domain, int type, int protocol));
-tor_socket_t tor_open_socket_nonblocking(int domain, int type, int protocol);
-tor_socket_t tor_accept_socket(tor_socket_t sockfd, struct sockaddr *addr,
- socklen_t *len);
-tor_socket_t tor_accept_socket_nonblocking(tor_socket_t sockfd,
- struct sockaddr *addr,
- socklen_t *len);
-tor_socket_t tor_accept_socket_with_extensions(tor_socket_t sockfd,
- struct sockaddr *addr,
- socklen_t *len,
- int cloexec, int nonblock);
-MOCK_DECL(tor_socket_t,
-tor_connect_socket,(tor_socket_t socket,const struct sockaddr *address,
- socklen_t address_len));
-int get_n_open_sockets(void);
-
-MOCK_DECL(int,
-tor_getsockname,(tor_socket_t socket, struct sockaddr *address,
- socklen_t *address_len));
-struct tor_addr_t;
-int tor_addr_from_getsockname(struct tor_addr_t *addr_out, tor_socket_t sock);
-
-#define tor_socket_send(s, buf, len, flags) send(s, buf, len, flags)
-#define tor_socket_recv(s, buf, len, flags) recv(s, buf, len, flags)
-
-/** Implementation of struct in6_addr for platforms that do not have it.
- * Generally, these platforms are ones without IPv6 support, but we want to
- * have a working in6_addr there anyway, so we can use it to parse IPv6
- * addresses. */
-#if !defined(HAVE_STRUCT_IN6_ADDR)
-struct in6_addr
-{
- union {
- uint8_t u6_addr8[16];
- uint16_t u6_addr16[8];
- uint32_t u6_addr32[4];
- } in6_u;
-#define s6_addr in6_u.u6_addr8
-#define s6_addr16 in6_u.u6_addr16
-#define s6_addr32 in6_u.u6_addr32
-};
-#endif /* !defined(HAVE_STRUCT_IN6_ADDR) */
-
-/** @{ */
-/** Many BSD variants seem not to define these. */
-#if defined(__APPLE__) || defined(__darwin__) || \
- defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__)
-#ifndef s6_addr16
-#define s6_addr16 __u6_addr.__u6_addr16
-#endif
-#ifndef s6_addr32
-#define s6_addr32 __u6_addr.__u6_addr32
-#endif
-#endif /* defined(__APPLE__) || defined(__darwin__) || ... */
-/** @} */
-
-#ifndef HAVE_SA_FAMILY_T
-typedef uint16_t sa_family_t;
-#endif
-
-/** @{ */
-/** Apparently, MS and Solaris don't define s6_addr16 or s6_addr32; these
- * macros get you a pointer to s6_addr32 or local equivalent. */
-#ifdef HAVE_STRUCT_IN6_ADDR_S6_ADDR32
-#define S6_ADDR32(x) ((uint32_t*)(x).s6_addr32)
-#else
-#define S6_ADDR32(x) ((uint32_t*)((char*)&(x).s6_addr))
-#endif
-#ifdef HAVE_STRUCT_IN6_ADDR_S6_ADDR16
-#define S6_ADDR16(x) ((uint16_t*)(x).s6_addr16)
-#else
-#define S6_ADDR16(x) ((uint16_t*)((char*)&(x).s6_addr))
-#endif
-/** @} */
-
-/** Implementation of struct sockaddr_in6 on platforms that do not have
- * it. See notes on struct in6_addr. */
-#if !defined(HAVE_STRUCT_SOCKADDR_IN6)
-struct sockaddr_in6 {
- sa_family_t sin6_family;
- uint16_t sin6_port;
- // uint32_t sin6_flowinfo;
- struct in6_addr sin6_addr;
- // uint32_t sin6_scope_id;
-};
-#endif /* !defined(HAVE_STRUCT_SOCKADDR_IN6) */
-
-MOCK_DECL(int,tor_gethostname,(char *name, size_t namelen));
-int tor_inet_aton(const char *cp, struct in_addr *addr) ATTR_NONNULL((1,2));
-const char *tor_inet_ntop(int af, const void *src, char *dst, size_t len);
-int tor_inet_pton(int af, const char *src, void *dst);
-MOCK_DECL(int,tor_lookup_hostname,(const char *name, uint32_t *addr));
-int set_socket_nonblocking(tor_socket_t socket);
-int tor_socketpair(int family, int type, int protocol, tor_socket_t fd[2]);
-int network_init(void);
-
-/* For stupid historical reasons, windows sockets have an independent
- * set of errnos, and an independent way to get them. Also, you can't
- * always believe WSAEWOULDBLOCK. Use the macros below to compare
- * errnos against expected values, and use tor_socket_errno to find
- * the actual errno after a socket operation fails.
- */
-#if defined(_WIN32)
-/** Expands to WSA<b>e</b> on Windows, and to <b>e</b> elsewhere. */
-#define SOCK_ERRNO(e) WSA##e
-/** Return true if e is EAGAIN or the local equivalent. */
-#define ERRNO_IS_EAGAIN(e) ((e) == EAGAIN || (e) == WSAEWOULDBLOCK)
-/** Return true if e is EINPROGRESS or the local equivalent. */
-#define ERRNO_IS_EINPROGRESS(e) ((e) == WSAEINPROGRESS)
-/** Return true if e is EINPROGRESS or the local equivalent as returned by
- * a call to connect(). */
-#define ERRNO_IS_CONN_EINPROGRESS(e) \
- ((e) == WSAEINPROGRESS || (e)== WSAEINVAL || (e) == WSAEWOULDBLOCK)
-/** Return true if e is EAGAIN or another error indicating that a call to
- * accept() has no pending connections to return. */
-#define ERRNO_IS_ACCEPT_EAGAIN(e) ERRNO_IS_EAGAIN(e)
-/** Return true if e is EMFILE or another error indicating that a call to
- * accept() has failed because we're out of fds or something. */
-#define ERRNO_IS_RESOURCE_LIMIT(e) \
- ((e) == WSAEMFILE || (e) == WSAENOBUFS)
-/** Return true if e is EADDRINUSE or the local equivalent. */
-#define ERRNO_IS_EADDRINUSE(e) ((e) == WSAEADDRINUSE)
-/** Return true if e is EINTR or the local equivalent */
-#define ERRNO_IS_EINTR(e) ((e) == WSAEINTR || 0)
-int tor_socket_errno(tor_socket_t sock);
-const char *tor_socket_strerror(int e);
-#else /* !(defined(_WIN32)) */
-#define SOCK_ERRNO(e) e
-#if EAGAIN == EWOULDBLOCK
-/* || 0 is for -Wparentheses-equality (-Wall?) appeasement under clang */
-#define ERRNO_IS_EAGAIN(e) ((e) == EAGAIN || 0)
-#else
-#define ERRNO_IS_EAGAIN(e) ((e) == EAGAIN || (e) == EWOULDBLOCK)
-#endif /* EAGAIN == EWOULDBLOCK */
-#define ERRNO_IS_EINTR(e) ((e) == EINTR || 0)
-#define ERRNO_IS_EINPROGRESS(e) ((e) == EINPROGRESS || 0)
-#define ERRNO_IS_CONN_EINPROGRESS(e) ((e) == EINPROGRESS || 0)
-#define ERRNO_IS_ACCEPT_EAGAIN(e) \
- (ERRNO_IS_EAGAIN(e) || (e) == ECONNABORTED)
-#define ERRNO_IS_RESOURCE_LIMIT(e) \
- ((e) == EMFILE || (e) == ENFILE || (e) == ENOBUFS || (e) == ENOMEM)
-#define ERRNO_IS_EADDRINUSE(e) (((e) == EADDRINUSE) || 0)
-#define tor_socket_errno(sock) (errno)
-#define tor_socket_strerror(e) strerror(e)
-#endif /* defined(_WIN32) */
-
-/** Specified SOCKS5 status codes. */
-typedef enum {
- SOCKS5_SUCCEEDED = 0x00,
- SOCKS5_GENERAL_ERROR = 0x01,
- SOCKS5_NOT_ALLOWED = 0x02,
- SOCKS5_NET_UNREACHABLE = 0x03,
- SOCKS5_HOST_UNREACHABLE = 0x04,
- SOCKS5_CONNECTION_REFUSED = 0x05,
- SOCKS5_TTL_EXPIRED = 0x06,
- SOCKS5_COMMAND_NOT_SUPPORTED = 0x07,
- SOCKS5_ADDRESS_TYPE_NOT_SUPPORTED = 0x08,
-} socks5_reply_status_t;
-
-/* ===== OS compatibility */
-MOCK_DECL(const char *, get_uname, (void));
-
-uint16_t get_uint16(const void *cp) ATTR_NONNULL((1));
-uint32_t get_uint32(const void *cp) ATTR_NONNULL((1));
-uint64_t get_uint64(const void *cp) ATTR_NONNULL((1));
-void set_uint16(void *cp, uint16_t v) ATTR_NONNULL((1));
-void set_uint32(void *cp, uint32_t v) ATTR_NONNULL((1));
-void set_uint64(void *cp, uint64_t v) ATTR_NONNULL((1));
-
-/* These uint8 variants are defined to make the code more uniform. */
-#define get_uint8(cp) (*(const uint8_t*)(cp))
-static void set_uint8(void *cp, uint8_t v);
-static inline void
-set_uint8(void *cp, uint8_t v)
-{
- *(uint8_t*)cp = v;
-}
-
-#if !defined(HAVE_RLIM_T)
-typedef unsigned long rlim_t;
-#endif
-int get_max_sockets(void);
-int set_max_file_descriptors(rlim_t limit, int *max);
-int tor_disable_debugger_attach(void);
-
-#if defined(HAVE_SYS_CAPABILITY_H) && defined(HAVE_CAP_SET_PROC)
-#define HAVE_LINUX_CAPABILITIES
-#endif
-
-int have_capability_support(void);
-
-/** Flag for switch_id; see switch_id() for documentation */
-#define SWITCH_ID_KEEP_BINDLOW (1<<0)
-/** Flag for switch_id; see switch_id() for documentation */
-#define SWITCH_ID_WARN_IF_NO_CAPS (1<<1)
-int switch_id(const char *user, unsigned flags);
-#ifdef HAVE_PWD_H
-char *get_user_homedir(const char *username);
-#endif
-
-#ifndef _WIN32
-const struct passwd *tor_getpwnam(const char *username);
-const struct passwd *tor_getpwuid(uid_t uid);
-#endif
-
-int get_parent_directory(char *fname);
-char *make_path_absolute(char *fname);
-
-char **get_environment(void);
-
-MOCK_DECL(int, get_total_system_memory, (size_t *mem_out));
-
-int compute_num_cpus(void);
-
-int tor_mlockall(void);
-
-/** Macros for MIN/MAX. Never use these when the arguments could have
- * side-effects.
- * {With GCC extensions we could probably define a safer MIN/MAX. But
- * depending on that safety would be dangerous, since not every platform
- * has it.}
- **/
-#ifndef MAX
-#define MAX(a,b) ( ((a)<(b)) ? (b) : (a) )
-#endif
-#ifndef MIN
-#define MIN(a,b) ( ((a)>(b)) ? (b) : (a) )
-#endif
-
-/* Platform-specific helpers. */
-#ifdef _WIN32
-char *format_win32_error(DWORD err);
-#endif
-
-/*for some reason my compiler doesn't have these version flags defined
- a nice homework assignment for someone one day is to define the rest*/
-//these are the values as given on MSDN
-#ifdef _WIN32
-
-#ifndef VER_SUITE_EMBEDDEDNT
-#define VER_SUITE_EMBEDDEDNT 0x00000040
-#endif
-
-#ifndef VER_SUITE_SINGLEUSERTS
-#define VER_SUITE_SINGLEUSERTS 0x00000100
-#endif
-
-#endif /* defined(_WIN32) */
-
-#ifdef COMPAT_PRIVATE
-#if !defined(HAVE_SOCKETPAIR) || defined(_WIN32) || defined(TOR_UNIT_TESTS)
-#define NEED_ERSATZ_SOCKETPAIR
-STATIC int tor_ersatz_socketpair(int family, int type, int protocol,
- tor_socket_t fd[2]);
-#endif
-#endif /* defined(COMPAT_PRIVATE) */
-
-ssize_t tor_getpass(const char *prompt, char *output, size_t buflen);
-
-/* This needs some of the declarations above so we include it here. */
-#include "compat_threads.h"
-
-#endif /* !defined(TOR_COMPAT_H) */
-
diff --git a/src/common/compat_libevent.c b/src/common/compat_libevent.c
deleted file mode 100644
index e60eb148d8..0000000000
--- a/src/common/compat_libevent.c
+++ /dev/null
@@ -1,536 +0,0 @@
-/* Copyright (c) 2009-2017, The Tor Project, Inc. */
-/* See LICENSE for licensing information */
-
-/**
- * \file compat_libevent.c
- * \brief Wrappers and utility functions for Libevent.
- */
-
-#include "orconfig.h"
-#include "compat.h"
-#define COMPAT_LIBEVENT_PRIVATE
-#include "compat_libevent.h"
-
-#include "crypto_rand.h"
-
-#include "util.h"
-#include "torlog.h"
-
-#include <event2/event.h>
-#include <event2/thread.h>
-
-/** A string which, if it appears in a libevent log, should be ignored. */
-static const char *suppress_msg = NULL;
-/** Callback function passed to event_set_log() so we can intercept
- * log messages from libevent. */
-STATIC void
-libevent_logging_callback(int severity, const char *msg)
-{
- char buf[1024];
- size_t n;
- if (suppress_msg && strstr(msg, suppress_msg))
- return;
- n = strlcpy(buf, msg, sizeof(buf));
- if (n && n < sizeof(buf) && buf[n-1] == '\n') {
- buf[n-1] = '\0';
- }
- switch (severity) {
- case _EVENT_LOG_DEBUG:
- log_debug(LD_NOCB|LD_NET, "Message from libevent: %s", buf);
- break;
- case _EVENT_LOG_MSG:
- log_info(LD_NOCB|LD_NET, "Message from libevent: %s", buf);
- break;
- case _EVENT_LOG_WARN:
- log_warn(LD_NOCB|LD_GENERAL, "Warning from libevent: %s", buf);
- break;
- case _EVENT_LOG_ERR:
- log_err(LD_NOCB|LD_GENERAL, "Error from libevent: %s", buf);
- break;
- default:
- log_warn(LD_NOCB|LD_GENERAL, "Message [%d] from libevent: %s",
- severity, buf);
- break;
- }
-}
-/** Set hook to intercept log messages from libevent. */
-void
-configure_libevent_logging(void)
-{
- event_set_log_callback(libevent_logging_callback);
-}
-
-/** Ignore any libevent log message that contains <b>msg</b>. */
-void
-suppress_libevent_log_msg(const char *msg)
-{
- suppress_msg = msg;
-}
-
-/* Wrapper for event_free() that tolerates tor_event_free(NULL) */
-void
-tor_event_free_(struct event *ev)
-{
- if (ev == NULL)
- return;
- event_free(ev);
-}
-
-/** Global event base for use by the main thread. */
-static struct event_base *the_event_base = NULL;
-
-/**
- * @defgroup postloop post-loop event helpers
- *
- * If we're not careful, Libevent can susceptible to infinite event chains:
- * one event can activate another, whose callback activates another, whose
- * callback activates another, ad infinitum. While this is happening,
- * Libevent won't be checking timeouts, socket-based events, signals, and so
- * on.
- *
- * We solve this problem by marking some events as "post-loop". A post-loop
- * event behaves like any ordinary event, but any events that _it_ activates
- * cannot run until Libevent has checked for other events at least once.
- *
- * @{ */
-
-/**
- * An event that stops Libevent from running any more events on the current
- * iteration of its loop, until it has re-checked for socket events, signal
- * events, timeouts, etc.
- */
-static struct event *rescan_mainloop_ev = NULL;
-
-/**
- * Callback to implement rescan_mainloop_ev: it simply exits the mainloop,
- * and relies on Tor to re-enter the mainloop since no error has occurred.
- */
-static void
-rescan_mainloop_cb(evutil_socket_t fd, short events, void *arg)
-{
- (void)fd;
- (void)events;
- struct event_base *the_base = arg;
- event_base_loopbreak(the_base);
-}
-
-/** @} */
-
-/* This is what passes for version detection on OSX. We set
- * MACOSX_KQUEUE_IS_BROKEN to true iff we're on a version of OSX before
- * 10.4.0 (aka 1040). */
-#ifdef __APPLE__
-#ifdef __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__
-#define MACOSX_KQUEUE_IS_BROKEN \
- (__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ < 1040)
-#else
-#define MACOSX_KQUEUE_IS_BROKEN 0
-#endif /* defined(__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__) */
-#endif /* defined(__APPLE__) */
-
-/** Initialize the Libevent library and set up the event base. */
-void
-tor_libevent_initialize(tor_libevent_cfg *torcfg)
-{
- tor_assert(the_event_base == NULL);
- /* some paths below don't use torcfg, so avoid unused variable warnings */
- (void)torcfg;
-
- {
- int attempts = 0;
- struct event_config *cfg;
-
- ++attempts;
- cfg = event_config_new();
- tor_assert(cfg);
-
- /* Telling Libevent not to try to turn locking on can avoid a needless
- * socketpair() attempt. */
- event_config_set_flag(cfg, EVENT_BASE_FLAG_NOLOCK);
-
- if (torcfg->num_cpus > 0)
- event_config_set_num_cpus_hint(cfg, torcfg->num_cpus);
-
- /* We can enable changelist support with epoll, since we don't give
- * Libevent any dup'd fds. This lets us avoid some syscalls. */
- event_config_set_flag(cfg, EVENT_BASE_FLAG_EPOLL_USE_CHANGELIST);
-
- the_event_base = event_base_new_with_config(cfg);
-
- event_config_free(cfg);
- }
-
- if (!the_event_base) {
- /* LCOV_EXCL_START */
- log_err(LD_GENERAL, "Unable to initialize Libevent: cannot continue.");
- exit(1); // exit ok: libevent is broken.
- /* LCOV_EXCL_STOP */
- }
-
- rescan_mainloop_ev = event_new(the_event_base, -1, 0,
- rescan_mainloop_cb, the_event_base);
- if (!rescan_mainloop_ev) {
- /* LCOV_EXCL_START */
- log_err(LD_GENERAL, "Unable to create rescan event: cannot continue.");
- exit(1); // exit ok: libevent is broken.
- /* LCOV_EXCL_STOP */
- }
-
- log_info(LD_GENERAL,
- "Initialized libevent version %s using method %s. Good.",
- event_get_version(), tor_libevent_get_method());
-}
-
-/** Return the current Libevent event base that we're set up to use. */
-MOCK_IMPL(struct event_base *,
-tor_libevent_get_base, (void))
-{
- tor_assert(the_event_base != NULL);
- return the_event_base;
-}
-
-/** Return the name of the Libevent backend we're using. */
-const char *
-tor_libevent_get_method(void)
-{
- return event_base_get_method(the_event_base);
-}
-
-/** Return a string representation of the version of the currently running
- * version of Libevent. */
-const char *
-tor_libevent_get_version_str(void)
-{
- return event_get_version();
-}
-
-/** Return a string representation of the version of Libevent that was used
-* at compilation time. */
-const char *
-tor_libevent_get_header_version_str(void)
-{
- return LIBEVENT_VERSION;
-}
-
-/** Represents a timer that's run every N microseconds by Libevent. */
-struct periodic_timer_t {
- /** Underlying event used to implement this periodic event. */
- struct event *ev;
- /** The callback we'll be invoking whenever the event triggers */
- void (*cb)(struct periodic_timer_t *, void *);
- /** User-supplied data for the callback */
- void *data;
-};
-
-/** Libevent callback to implement a periodic event. */
-static void
-periodic_timer_cb(evutil_socket_t fd, short what, void *arg)
-{
- periodic_timer_t *timer = arg;
- (void) what;
- (void) fd;
- timer->cb(timer, timer->data);
-}
-
-/** Create and schedule a new timer that will run every <b>tv</b> in
- * the event loop of <b>base</b>. When the timer fires, it will
- * run the timer in <b>cb</b> with the user-supplied data in <b>data</b>. */
-periodic_timer_t *
-periodic_timer_new(struct event_base *base,
- const struct timeval *tv,
- void (*cb)(periodic_timer_t *timer, void *data),
- void *data)
-{
- periodic_timer_t *timer;
- tor_assert(base);
- tor_assert(tv);
- tor_assert(cb);
- timer = tor_malloc_zero(sizeof(periodic_timer_t));
- if (!(timer->ev = tor_event_new(base, -1, EV_PERSIST,
- periodic_timer_cb, timer))) {
- tor_free(timer);
- return NULL;
- }
- timer->cb = cb;
- timer->data = data;
- periodic_timer_launch(timer, tv);
- return timer;
-}
-
-/**
- * Launch the timer <b>timer</b> to run at <b>tv</b> from now, and every
- * <b>tv</b> thereafter.
- *
- * If the timer is already enabled, this function does nothing.
- */
-void
-periodic_timer_launch(periodic_timer_t *timer, const struct timeval *tv)
-{
- tor_assert(timer);
- if (event_pending(timer->ev, EV_TIMEOUT, NULL))
- return;
- event_add(timer->ev, tv);
-}
-
-/**
- * Disable the provided <b>timer</b>, but do not free it.
- *
- * You can reenable the same timer later with periodic_timer_launch.
- *
- * If the timer is already disabled, this function does nothing.
- */
-void
-periodic_timer_disable(periodic_timer_t *timer)
-{
- tor_assert(timer);
- (void) event_del(timer->ev);
-}
-
-/** Stop and free a periodic timer */
-void
-periodic_timer_free_(periodic_timer_t *timer)
-{
- if (!timer)
- return;
- tor_event_free(timer->ev);
- tor_free(timer);
-}
-
-/**
- * Type used to represent events that run directly from the main loop,
- * either because they are activated from elsewhere in the code, or
- * because they have a simple timeout.
- *
- * We use this type to avoid exposing Libevent's API throughout the rest
- * of the codebase.
- *
- * This type can't be used for all events: it doesn't handle events that
- * are triggered by signals or by sockets.
- */
-struct mainloop_event_t {
- struct event *ev;
- void (*cb)(mainloop_event_t *, void *);
- void *userdata;
-};
-
-/**
- * Internal: Implements mainloop event using a libevent event.
- */
-static void
-mainloop_event_cb(evutil_socket_t fd, short what, void *arg)
-{
- (void)fd;
- (void)what;
- mainloop_event_t *mev = arg;
- mev->cb(mev, mev->userdata);
-}
-
-/**
- * As mainloop_event_cb, but implements a post-loop event.
- */
-static void
-mainloop_event_postloop_cb(evutil_socket_t fd, short what, void *arg)
-{
- (void)fd;
- (void)what;
-
- /* Note that if rescan_mainloop_ev is already activated,
- * event_active() will do nothing: only the first post-loop event that
- * happens each time through the event loop will cause it to be
- * activated.
- *
- * Because event_active() puts events on a FIFO queue, every event
- * that is made active _after_ rescan_mainloop_ev will get its
- * callback run after rescan_mainloop_cb is called -- that is, on the
- * next iteration of the loop.
- */
- event_active(rescan_mainloop_ev, EV_READ, 1);
-
- mainloop_event_t *mev = arg;
- mev->cb(mev, mev->userdata);
-}
-
-/**
- * Helper for mainloop_event_new() and mainloop_event_postloop_new().
- */
-static mainloop_event_t *
-mainloop_event_new_impl(int postloop,
- void (*cb)(mainloop_event_t *, void *),
- void *userdata)
-{
- tor_assert(cb);
-
- struct event_base *base = tor_libevent_get_base();
- mainloop_event_t *mev = tor_malloc_zero(sizeof(mainloop_event_t));
- mev->ev = tor_event_new(base, -1, 0,
- postloop ? mainloop_event_postloop_cb : mainloop_event_cb,
- mev);
- tor_assert(mev->ev);
- mev->cb = cb;
- mev->userdata = userdata;
- return mev;
-}
-
-/**
- * Create and return a new mainloop_event_t to run the function <b>cb</b>.
- *
- * When run, the callback function will be passed the mainloop_event_t
- * and <b>userdata</b> as its arguments. The <b>userdata</b> pointer
- * must remain valid for as long as the mainloop_event_t event exists:
- * it is your responsibility to free it.
- *
- * The event is not scheduled by default: Use mainloop_event_activate()
- * or mainloop_event_schedule() to make it run.
- */
-mainloop_event_t *
-mainloop_event_new(void (*cb)(mainloop_event_t *, void *),
- void *userdata)
-{
- return mainloop_event_new_impl(0, cb, userdata);
-}
-
-/**
- * As mainloop_event_new(), but create a post-loop event.
- *
- * A post-loop event behaves like any ordinary event, but any events
- * that _it_ activates cannot run until Libevent has checked for other
- * events at least once.
- */
-mainloop_event_t *
-mainloop_event_postloop_new(void (*cb)(mainloop_event_t *, void *),
- void *userdata)
-{
- return mainloop_event_new_impl(1, cb, userdata);
-}
-
-/**
- * Schedule <b>event</b> to run in the main loop, immediately. If it is
- * not scheduled, it will run anyway. If it is already scheduled to run
- * later, it will run now instead. This function will have no effect if
- * the event is already scheduled to run.
- *
- * This function may only be called from the main thread.
- */
-void
-mainloop_event_activate(mainloop_event_t *event)
-{
- tor_assert(event);
- event_active(event->ev, EV_READ, 1);
-}
-
-/** Schedule <b>event</b> to run in the main loop, after a delay of <b>tv</b>.
- *
- * If the event is scheduled for a different time, cancel it and run
- * after this delay instead. If the event is currently pending to run
- * <em>now</b>, has no effect.
- *
- * Do not call this function with <b>tv</b> == NULL -- use
- * mainloop_event_activate() instead.
- *
- * This function may only be called from the main thread.
- */
-int
-mainloop_event_schedule(mainloop_event_t *event, const struct timeval *tv)
-{
- tor_assert(event);
- if (BUG(tv == NULL)) {
- // LCOV_EXCL_START
- mainloop_event_activate(event);
- return 0;
- // LCOV_EXCL_STOP
- }
- return event_add(event->ev, tv);
-}
-
-/** Cancel <b>event</b> if it is currently active or pending. (Do nothing if
- * the event is not currently active or pending.) */
-void
-mainloop_event_cancel(mainloop_event_t *event)
-{
- if (!event)
- return;
- (void) event_del(event->ev);
-}
-
-/** Cancel <b>event</b> and release all storage associated with it. */
-void
-mainloop_event_free_(mainloop_event_t *event)
-{
- if (!event)
- return;
- tor_event_free(event->ev);
- memset(event, 0xb8, sizeof(*event));
- tor_free(event);
-}
-
-int
-tor_init_libevent_rng(void)
-{
- int rv = 0;
- char buf[256];
- if (evutil_secure_rng_init() < 0) {
- rv = -1;
- }
- crypto_rand(buf, 32);
-#ifdef HAVE_EVUTIL_SECURE_RNG_ADD_BYTES
- evutil_secure_rng_add_bytes(buf, 32);
-#endif
- evutil_secure_rng_get_bytes(buf, sizeof(buf));
- return rv;
-}
-
-/**
- * Un-initialize libevent in preparation for an exit
- */
-void
-tor_libevent_free_all(void)
-{
- tor_event_free(rescan_mainloop_ev);
- if (the_event_base)
- event_base_free(the_event_base);
- the_event_base = NULL;
-}
-
-/**
- * Run the event loop for the provided event_base, handling events until
- * something stops it. If <b>once</b> is set, then just poll-and-run
- * once, then exit. Return 0 on success, -1 if an error occurred, or 1
- * if we exited because no events were pending or active.
- *
- * This isn't reentrant or multithreaded.
- */
-int
-tor_libevent_run_event_loop(struct event_base *base, int once)
-{
- const int flags = once ? EVLOOP_ONCE : 0;
- return event_base_loop(base, flags);
-}
-
-/** Tell the event loop to exit after <b>delay</b>. If <b>delay</b> is NULL,
- * instead exit after we're done running the currently active events. */
-void
-tor_libevent_exit_loop_after_delay(struct event_base *base,
- const struct timeval *delay)
-{
- event_base_loopexit(base, delay);
-}
-
-/** Tell the event loop to exit after running whichever callback is currently
- * active. */
-void
-tor_libevent_exit_loop_after_callback(struct event_base *base)
-{
- event_base_loopbreak(base);
-}
-
-#if defined(TOR_UNIT_TESTS)
-/** For testing: called post-fork to make libevent reinitialize
- * kernel structures. */
-void
-tor_libevent_postfork(void)
-{
- int r = event_reinit(tor_libevent_get_base());
- tor_assert(r == 0);
-}
-#endif /* defined(TOR_UNIT_TESTS) */
-
diff --git a/src/common/compat_libevent.h b/src/common/compat_libevent.h
deleted file mode 100644
index 286a268122..0000000000
--- a/src/common/compat_libevent.h
+++ /dev/null
@@ -1,98 +0,0 @@
-/* Copyright (c) 2009-2017, The Tor Project, Inc. */
-/* See LICENSE for licensing information */
-
-#ifndef TOR_COMPAT_LIBEVENT_H
-#define TOR_COMPAT_LIBEVENT_H
-
-#include "orconfig.h"
-#include "testsupport.h"
-
-void configure_libevent_logging(void);
-void suppress_libevent_log_msg(const char *msg);
-
-#define tor_event_new event_new
-#define tor_evtimer_new evtimer_new
-#define tor_evsignal_new evsignal_new
-#define tor_evdns_add_server_port(sock, tcp, cb, data) \
- evdns_add_server_port_with_base(tor_libevent_get_base(), \
- (sock),(tcp),(cb),(data));
-
-struct event;
-struct event_base;
-
-void tor_event_free_(struct event *ev);
-#define tor_event_free(ev) \
- FREE_AND_NULL(struct event, tor_event_free_, (ev))
-
-typedef struct periodic_timer_t periodic_timer_t;
-
-periodic_timer_t *periodic_timer_new(struct event_base *base,
- const struct timeval *tv,
- void (*cb)(periodic_timer_t *timer, void *data),
- void *data);
-void periodic_timer_free_(periodic_timer_t *);
-void periodic_timer_launch(periodic_timer_t *, const struct timeval *tv);
-void periodic_timer_disable(periodic_timer_t *);
-#define periodic_timer_free(t) \
- FREE_AND_NULL(periodic_timer_t, periodic_timer_free_, (t))
-
-typedef struct mainloop_event_t mainloop_event_t;
-mainloop_event_t *mainloop_event_new(void (*cb)(mainloop_event_t *, void *),
- void *userdata);
-mainloop_event_t * mainloop_event_postloop_new(
- void (*cb)(mainloop_event_t *, void *),
- void *userdata);
-void mainloop_event_activate(mainloop_event_t *event);
-int mainloop_event_schedule(mainloop_event_t *event,
- const struct timeval *delay);
-void mainloop_event_cancel(mainloop_event_t *event);
-void mainloop_event_free_(mainloop_event_t *event);
-#define mainloop_event_free(event) \
- FREE_AND_NULL(mainloop_event_t, mainloop_event_free_, (event))
-
-/** Defines a configuration for using libevent with Tor: passed as an argument
- * to tor_libevent_initialize() to describe how we want to set up. */
-typedef struct tor_libevent_cfg {
- /** How many CPUs should we use (not currently useful). */
- int num_cpus;
- /** How many milliseconds should we allow between updating bandwidth limits?
- * (Not currently useful). */
- int msec_per_tick;
-} tor_libevent_cfg;
-
-void tor_libevent_initialize(tor_libevent_cfg *cfg);
-MOCK_DECL(struct event_base *, tor_libevent_get_base, (void));
-const char *tor_libevent_get_method(void);
-void tor_check_libevent_header_compatibility(void);
-const char *tor_libevent_get_version_str(void);
-const char *tor_libevent_get_header_version_str(void);
-void tor_libevent_free_all(void);
-
-int tor_init_libevent_rng(void);
-
-#ifdef TOR_UNIT_TESTS
-void tor_libevent_postfork(void);
-#endif
-
-int tor_libevent_run_event_loop(struct event_base *base, int once);
-void tor_libevent_exit_loop_after_delay(struct event_base *base,
- const struct timeval *delay);
-void tor_libevent_exit_loop_after_callback(struct event_base *base);
-
-#ifdef COMPAT_LIBEVENT_PRIVATE
-
-/** Macro: returns the number of a Libevent version as a 4-byte number,
- with the first three bytes representing the major, minor, and patchlevel
- respectively of the library. The fourth byte is unused.
-
- This is equivalent to the format of LIBEVENT_VERSION_NUMBER on Libevent
- 2.0.1 or later. */
-#define V(major, minor, patch) \
- (((major) << 24) | ((minor) << 16) | ((patch) << 8))
-
-STATIC void
-libevent_logging_callback(int severity, const char *msg);
-#endif /* defined(COMPAT_LIBEVENT_PRIVATE) */
-
-#endif /* !defined(TOR_COMPAT_LIBEVENT_H) */
-
diff --git a/src/common/compat_openssl.h b/src/common/compat_openssl.h
deleted file mode 100644
index d1481fb46c..0000000000
--- a/src/common/compat_openssl.h
+++ /dev/null
@@ -1,51 +0,0 @@
-/* Copyright (c) 2001, Matej Pfajfar.
- * Copyright (c) 2001-2004, Roger Dingledine.
- * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2017, The Tor Project, Inc. */
-/* See LICENSE for licensing information */
-
-#ifndef TOR_COMPAT_OPENSSL_H
-#define TOR_COMPAT_OPENSSL_H
-
-#include <openssl/opensslv.h>
-#include "crypto_openssl_mgt.h"
-
-/**
- * \file compat_openssl.h
- *
- * \brief compatibility definitions for working with different openssl forks
- **/
-
-#if !defined(LIBRESSL_VERSION_NUMBER) && \
- OPENSSL_VERSION_NUMBER < OPENSSL_V_SERIES(1,0,1)
-#error "We require OpenSSL >= 1.0.1"
-#endif
-
-#if OPENSSL_VERSION_NUMBER >= OPENSSL_V_SERIES(1,1,0) && \
- ! defined(LIBRESSL_VERSION_NUMBER)
-/* We define this macro if we're trying to build with the majorly refactored
- * API in OpenSSL 1.1 */
-#define OPENSSL_1_1_API
-#endif /* OPENSSL_VERSION_NUMBER >= OPENSSL_V_SERIES(1,1,0) && ... */
-
-#ifndef OPENSSL_VERSION
-#define OPENSSL_VERSION SSLEAY_VERSION
-#endif
-
-#ifndef OPENSSL_1_1_API
-#define OpenSSL_version(v) SSLeay_version(v)
-#define OpenSSL_version_num() SSLeay()
-#define RAND_OpenSSL() RAND_SSLeay()
-#define STATE_IS_SW_SERVER_HELLO(st) \
- (((st) == SSL3_ST_SW_SRVR_HELLO_A) || \
- ((st) == SSL3_ST_SW_SRVR_HELLO_B))
-#define OSSL_HANDSHAKE_STATE int
-#define CONST_IF_OPENSSL_1_1_API
-#else /* !(!defined(OPENSSL_1_1_API)) */
-#define STATE_IS_SW_SERVER_HELLO(st) \
- ((st) == TLS_ST_SW_SRVR_HELLO)
-#define CONST_IF_OPENSSL_1_1_API const
-#endif /* !defined(OPENSSL_1_1_API) */
-
-#endif /* !defined(TOR_COMPAT_OPENSSL_H) */
-
diff --git a/src/common/compat_pthreads.c b/src/common/compat_pthreads.c
deleted file mode 100644
index 002274c469..0000000000
--- a/src/common/compat_pthreads.c
+++ /dev/null
@@ -1,350 +0,0 @@
-/* Copyright (c) 2003-2004, Roger Dingledine
- * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2017, The Tor Project, Inc. */
-/* See LICENSE for licensing information */
-
-/**
- * \file compat_pthreads.c
- *
- * \brief Implementation for the pthreads-based multithreading backend
- * functions.
- */
-
-#include "orconfig.h"
-#include <pthread.h>
-#include <signal.h>
-#include <time.h>
-
-#include "compat.h"
-#include "torlog.h"
-#include "util.h"
-
-/** Wraps a void (*)(void*) function and its argument so we can
- * invoke them in a way pthreads would expect.
- */
-typedef struct tor_pthread_data_t {
- void (*func)(void *);
- void *data;
-} tor_pthread_data_t;
-/** Given a tor_pthread_data_t <b>_data</b>, call _data-&gt;func(d-&gt;data)
- * and free _data. Used to make sure we can call functions the way pthread
- * expects. */
-static void *
-tor_pthread_helper_fn(void *_data)
-{
- tor_pthread_data_t *data = _data;
- void (*func)(void*);
- void *arg;
- /* mask signals to worker threads to avoid SIGPIPE, etc */
- sigset_t sigs;
- /* We're in a subthread; don't handle any signals here. */
- sigfillset(&sigs);
- pthread_sigmask(SIG_SETMASK, &sigs, NULL);
-
- func = data->func;
- arg = data->data;
- tor_free(_data);
- func(arg);
- return NULL;
-}
-/**
- * A pthread attribute to make threads start detached.
- */
-static pthread_attr_t attr_detached;
-/** True iff we've called tor_threads_init() */
-static int threads_initialized = 0;
-
-/** Minimalist interface to run a void function in the background. On
- * Unix calls pthread_create, on win32 calls beginthread. Returns -1 on
- * failure.
- * func should not return, but rather should call spawn_exit.
- *
- * NOTE: if <b>data</b> is used, it should not be allocated on the stack,
- * since in a multithreaded environment, there is no way to be sure that
- * the caller's stack will still be around when the called function is
- * running.
- */
-int
-spawn_func(void (*func)(void *), void *data)
-{
- pthread_t thread;
- tor_pthread_data_t *d;
- if (PREDICT_UNLIKELY(!threads_initialized)) {
- tor_threads_init();
- }
- d = tor_malloc(sizeof(tor_pthread_data_t));
- d->data = data;
- d->func = func;
- if (pthread_create(&thread, &attr_detached, tor_pthread_helper_fn, d)) {
- tor_free(d);
- return -1;
- }
-
- return 0;
-}
-
-/** End the current thread/process.
- */
-void
-spawn_exit(void)
-{
- pthread_exit(NULL);
-}
-
-/** A mutex attribute that we're going to use to tell pthreads that we want
- * "recursive" mutexes (i.e., once we can re-lock if we're already holding
- * them.) */
-static pthread_mutexattr_t attr_recursive;
-
-/** Initialize <b>mutex</b> so it can be locked. Every mutex must be set
- * up with tor_mutex_init() or tor_mutex_new(); not both. */
-void
-tor_mutex_init(tor_mutex_t *mutex)
-{
- if (PREDICT_UNLIKELY(!threads_initialized))
- tor_threads_init(); // LCOV_EXCL_LINE
- const int err = pthread_mutex_init(&mutex->mutex, &attr_recursive);
- if (PREDICT_UNLIKELY(err)) {
- // LCOV_EXCL_START
- log_err(LD_GENERAL, "Error %d creating a mutex.", err);
- tor_assert_unreached();
- // LCOV_EXCL_STOP
- }
-}
-
-/** As tor_mutex_init, but initialize a mutex suitable that may be
- * non-recursive, if the OS supports that. */
-void
-tor_mutex_init_nonrecursive(tor_mutex_t *mutex)
-{
- int err;
- if (!threads_initialized)
- tor_threads_init(); // LCOV_EXCL_LINE
- err = pthread_mutex_init(&mutex->mutex, NULL);
- if (PREDICT_UNLIKELY(err)) {
- // LCOV_EXCL_START
- log_err(LD_GENERAL, "Error %d creating a mutex.", err);
- tor_assert_unreached();
- // LCOV_EXCL_STOP
- }
-}
-
-/** Wait until <b>m</b> is free, then acquire it. */
-void
-tor_mutex_acquire(tor_mutex_t *m)
-{
- int err;
- tor_assert(m);
- err = pthread_mutex_lock(&m->mutex);
- if (PREDICT_UNLIKELY(err)) {
- // LCOV_EXCL_START
- log_err(LD_GENERAL, "Error %d locking a mutex.", err);
- tor_assert_unreached();
- // LCOV_EXCL_STOP
- }
-}
-/** Release the lock <b>m</b> so another thread can have it. */
-void
-tor_mutex_release(tor_mutex_t *m)
-{
- int err;
- tor_assert(m);
- err = pthread_mutex_unlock(&m->mutex);
- if (PREDICT_UNLIKELY(err)) {
- // LCOV_EXCL_START
- log_err(LD_GENERAL, "Error %d unlocking a mutex.", err);
- tor_assert_unreached();
- // LCOV_EXCL_STOP
- }
-}
-/** Clean up the mutex <b>m</b> so that it no longer uses any system
- * resources. Does not free <b>m</b>. This function must only be called on
- * mutexes from tor_mutex_init(). */
-void
-tor_mutex_uninit(tor_mutex_t *m)
-{
- int err;
- tor_assert(m);
- err = pthread_mutex_destroy(&m->mutex);
- if (PREDICT_UNLIKELY(err)) {
- // LCOV_EXCL_START
- log_err(LD_GENERAL, "Error %d destroying a mutex.", err);
- tor_assert_unreached();
- // LCOV_EXCL_STOP
- }
-}
-/** Return an integer representing this thread. */
-unsigned long
-tor_get_thread_id(void)
-{
- union {
- pthread_t thr;
- unsigned long id;
- } r;
- r.thr = pthread_self();
- return r.id;
-}
-
-/* Conditions. */
-
-/** Initialize an already-allocated condition variable. */
-int
-tor_cond_init(tor_cond_t *cond)
-{
- pthread_condattr_t condattr;
-
- memset(cond, 0, sizeof(tor_cond_t));
- /* Default condition attribute. Might be used if clock monotonic is
- * available else this won't affect anything. */
- if (pthread_condattr_init(&condattr)) {
- return -1;
- }
-
-#if defined(HAVE_CLOCK_GETTIME)
-#if defined(HAVE_PTHREAD_CONDATTR_SETCLOCK) && \
- defined(CLOCK_MONOTONIC)
- /* Use monotonic time so when we timedwait() on it, any clock adjustment
- * won't affect the timeout value. */
- if (pthread_condattr_setclock(&condattr, CLOCK_MONOTONIC)) {
- return -1;
- }
-#define USE_COND_CLOCK CLOCK_MONOTONIC
-#else /* !(defined(HAVE_PTHREAD_CONDATTR_SETCLOCK) && ...) */
- /* On OSX Sierra, there is no pthread_condattr_setclock, so we are stuck
- * with the realtime clock.
- */
-#define USE_COND_CLOCK CLOCK_REALTIME
-#endif /* defined(HAVE_PTHREAD_CONDATTR_SETCLOCK) && ... */
-#endif /* defined(HAVE_CLOCK_GETTIME) */
- if (pthread_cond_init(&cond->cond, &condattr)) {
- return -1;
- }
- return 0;
-}
-
-/** Release all resources held by <b>cond</b>, but do not free <b>cond</b>
- * itself. */
-void
-tor_cond_uninit(tor_cond_t *cond)
-{
- if (pthread_cond_destroy(&cond->cond)) {
- // LCOV_EXCL_START
- log_warn(LD_GENERAL,"Error freeing condition: %s", strerror(errno));
- return;
- // LCOV_EXCL_STOP
- }
-}
-/** Wait until one of the tor_cond_signal functions is called on <b>cond</b>.
- * (If <b>tv</b> is set, and that amount of time passes with no signal to
- * <b>cond</b>, return anyway. All waiters on the condition must wait holding
- * the same <b>mutex</b>. All signallers should hold that mutex. The mutex
- * needs to have been allocated with tor_mutex_init_for_cond().
- *
- * Returns 0 on success, -1 on failure, 1 on timeout. */
-int
-tor_cond_wait(tor_cond_t *cond, tor_mutex_t *mutex, const struct timeval *tv)
-{
- int r;
- if (tv == NULL) {
- while (1) {
- r = pthread_cond_wait(&cond->cond, &mutex->mutex);
- if (r == EINTR) {
- /* EINTR should be impossible according to POSIX, but POSIX, like the
- * Pirate's Code, is apparently treated "more like what you'd call
- * guidelines than actual rules." */
- continue; // LCOV_EXCL_LINE
- }
- return r ? -1 : 0;
- }
- } else {
- struct timeval tvnow, tvsum;
- struct timespec ts;
- while (1) {
-#if defined(HAVE_CLOCK_GETTIME) && defined(USE_COND_CLOCK)
- if (clock_gettime(USE_COND_CLOCK, &ts) < 0) {
- return -1;
- }
- tvnow.tv_sec = ts.tv_sec;
- tvnow.tv_usec = (int)(ts.tv_nsec / 1000);
- timeradd(tv, &tvnow, &tvsum);
-#else /* !(defined(HAVE_CLOCK_GETTIME) && defined(USE_COND_CLOCK)) */
- if (gettimeofday(&tvnow, NULL) < 0)
- return -1;
- timeradd(tv, &tvnow, &tvsum);
-#endif /* defined(HAVE_CLOCK_GETTIME) && defined(USE_COND_CLOCK) */
-
- ts.tv_sec = tvsum.tv_sec;
- ts.tv_nsec = tvsum.tv_usec * 1000;
-
- r = pthread_cond_timedwait(&cond->cond, &mutex->mutex, &ts);
- if (r == 0)
- return 0;
- else if (r == ETIMEDOUT)
- return 1;
- else if (r == EINTR)
- continue;
- else
- return -1;
- }
- }
-}
-/** Wake up one of the waiters on <b>cond</b>. */
-void
-tor_cond_signal_one(tor_cond_t *cond)
-{
- pthread_cond_signal(&cond->cond);
-}
-/** Wake up all of the waiters on <b>cond</b>. */
-void
-tor_cond_signal_all(tor_cond_t *cond)
-{
- pthread_cond_broadcast(&cond->cond);
-}
-
-int
-tor_threadlocal_init(tor_threadlocal_t *threadlocal)
-{
- int err = pthread_key_create(&threadlocal->key, NULL);
- return err ? -1 : 0;
-}
-
-void
-tor_threadlocal_destroy(tor_threadlocal_t *threadlocal)
-{
- pthread_key_delete(threadlocal->key);
- memset(threadlocal, 0, sizeof(tor_threadlocal_t));
-}
-
-void *
-tor_threadlocal_get(tor_threadlocal_t *threadlocal)
-{
- return pthread_getspecific(threadlocal->key);
-}
-
-void
-tor_threadlocal_set(tor_threadlocal_t *threadlocal, void *value)
-{
- int err = pthread_setspecific(threadlocal->key, value);
- tor_assert(err == 0);
-}
-
-/** Set up common structures for use by threading. */
-void
-tor_threads_init(void)
-{
- if (!threads_initialized) {
- pthread_mutexattr_init(&attr_recursive);
- pthread_mutexattr_settype(&attr_recursive, PTHREAD_MUTEX_RECURSIVE);
- const int ret1 = pthread_attr_init(&attr_detached);
- tor_assert(ret1 == 0);
-#ifndef PTHREAD_CREATE_DETACHED
-#define PTHREAD_CREATE_DETACHED 1
-#endif
- const int ret2 =
- pthread_attr_setdetachstate(&attr_detached, PTHREAD_CREATE_DETACHED);
- tor_assert(ret2 == 0);
- threads_initialized = 1;
- set_main_thread();
- }
-}
-
diff --git a/src/common/compat_threads.c b/src/common/compat_threads.c
deleted file mode 100644
index 9f64c06342..0000000000
--- a/src/common/compat_threads.c
+++ /dev/null
@@ -1,406 +0,0 @@
-/* Copyright (c) 2003-2004, Roger Dingledine
- * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2017, The Tor Project, Inc. */
-/* See LICENSE for licensing information */
-
-/**
- * \file compat_threads.c
- *
- * \brief Cross-platform threading and inter-thread communication logic.
- * (Platform-specific parts are written in the other compat_*threads
- * modules.)
- */
-
-#include "orconfig.h"
-#include <stdlib.h>
-#include "compat.h"
-#include "compat_threads.h"
-
-#include "util.h"
-#include "torlog.h"
-
-#ifdef HAVE_SYS_EVENTFD_H
-#include <sys/eventfd.h>
-#endif
-#ifdef HAVE_FCNTL_H
-#include <fcntl.h>
-#endif
-#ifdef HAVE_UNISTD_H
-#include <unistd.h>
-#endif
-
-/** Return a newly allocated, ready-for-use mutex. */
-tor_mutex_t *
-tor_mutex_new(void)
-{
- tor_mutex_t *m = tor_malloc_zero(sizeof(tor_mutex_t));
- tor_mutex_init(m);
- return m;
-}
-/** Return a newly allocated, ready-for-use mutex. This one might be
- * non-recursive, if that's faster. */
-tor_mutex_t *
-tor_mutex_new_nonrecursive(void)
-{
- tor_mutex_t *m = tor_malloc_zero(sizeof(tor_mutex_t));
- tor_mutex_init_nonrecursive(m);
- return m;
-}
-/** Release all storage and system resources held by <b>m</b>. */
-void
-tor_mutex_free_(tor_mutex_t *m)
-{
- if (!m)
- return;
- tor_mutex_uninit(m);
- tor_free(m);
-}
-
-/** Allocate and return a new condition variable. */
-tor_cond_t *
-tor_cond_new(void)
-{
- tor_cond_t *cond = tor_malloc(sizeof(tor_cond_t));
- if (BUG(tor_cond_init(cond)<0))
- tor_free(cond); // LCOV_EXCL_LINE
- return cond;
-}
-
-/** Free all storage held in <b>c</b>. */
-void
-tor_cond_free_(tor_cond_t *c)
-{
- if (!c)
- return;
- tor_cond_uninit(c);
- tor_free(c);
-}
-
-/** Identity of the "main" thread */
-static unsigned long main_thread_id = -1;
-
-/** Start considering the current thread to be the 'main thread'. This has
- * no effect on anything besides in_main_thread(). */
-void
-set_main_thread(void)
-{
- main_thread_id = tor_get_thread_id();
-}
-/** Return true iff called from the main thread. */
-int
-in_main_thread(void)
-{
- return main_thread_id == tor_get_thread_id();
-}
-
-#if defined(HAVE_EVENTFD) || defined(HAVE_PIPE)
-/* As write(), but retry on EINTR, and return the negative error code on
- * error. */
-static int
-write_ni(int fd, const void *buf, size_t n)
-{
- int r;
- again:
- r = (int) write(fd, buf, n);
- if (r < 0) {
- if (errno == EINTR)
- goto again;
- else
- return -errno;
- }
- return r;
-}
-/* As read(), but retry on EINTR, and return the negative error code on error.
- */
-static int
-read_ni(int fd, void *buf, size_t n)
-{
- int r;
- again:
- r = (int) read(fd, buf, n);
- if (r < 0) {
- if (errno == EINTR)
- goto again;
- else
- return -errno;
- }
- return r;
-}
-#endif /* defined(HAVE_EVENTFD) || defined(HAVE_PIPE) */
-
-/** As send(), but retry on EINTR, and return the negative error code on
- * error. */
-static int
-send_ni(int fd, const void *buf, size_t n, int flags)
-{
- int r;
- again:
- r = (int) send(fd, buf, n, flags);
- if (r < 0) {
- int error = tor_socket_errno(fd);
- if (ERRNO_IS_EINTR(error))
- goto again;
- else
- return -error;
- }
- return r;
-}
-
-/** As recv(), but retry on EINTR, and return the negative error code on
- * error. */
-static int
-recv_ni(int fd, void *buf, size_t n, int flags)
-{
- int r;
- again:
- r = (int) recv(fd, buf, n, flags);
- if (r < 0) {
- int error = tor_socket_errno(fd);
- if (ERRNO_IS_EINTR(error))
- goto again;
- else
- return -error;
- }
- return r;
-}
-
-#ifdef HAVE_EVENTFD
-/* Increment the event count on an eventfd <b>fd</b> */
-static int
-eventfd_alert(int fd)
-{
- uint64_t u = 1;
- int r = write_ni(fd, (void*)&u, sizeof(u));
- if (r < 0 && -r != EAGAIN)
- return -1;
- return 0;
-}
-
-/* Drain all events from an eventfd <b>fd</b>. */
-static int
-eventfd_drain(int fd)
-{
- uint64_t u = 0;
- int r = read_ni(fd, (void*)&u, sizeof(u));
- if (r < 0 && -r != EAGAIN)
- return r;
- return 0;
-}
-#endif /* defined(HAVE_EVENTFD) */
-
-#ifdef HAVE_PIPE
-/** Send a byte over a pipe. Return 0 on success or EAGAIN; -1 on error */
-static int
-pipe_alert(int fd)
-{
- ssize_t r = write_ni(fd, "x", 1);
- if (r < 0 && -r != EAGAIN)
- return (int)r;
- return 0;
-}
-
-/** Drain all input from a pipe <b>fd</b> and ignore it. Return 0 on
- * success, -1 on error. */
-static int
-pipe_drain(int fd)
-{
- char buf[32];
- ssize_t r;
- do {
- r = read_ni(fd, buf, sizeof(buf));
- } while (r > 0);
- if (r < 0 && errno != EAGAIN)
- return -errno;
- /* A value of r = 0 means EOF on the fd so successfully drained. */
- return 0;
-}
-#endif /* defined(HAVE_PIPE) */
-
-/** Send a byte on socket <b>fd</b>t. Return 0 on success or EAGAIN,
- * -1 on error. */
-static int
-sock_alert(tor_socket_t fd)
-{
- ssize_t r = send_ni(fd, "x", 1, 0);
- if (r < 0 && !ERRNO_IS_EAGAIN(-r))
- return (int)r;
- return 0;
-}
-
-/** Drain all the input from a socket <b>fd</b>, and ignore it. Return 0 on
- * success, -errno on error. */
-static int
-sock_drain(tor_socket_t fd)
-{
- char buf[32];
- ssize_t r;
- do {
- r = recv_ni(fd, buf, sizeof(buf), 0);
- } while (r > 0);
- if (r < 0 && !ERRNO_IS_EAGAIN(-r))
- return (int)r;
- /* A value of r = 0 means EOF on the fd so successfully drained. */
- return 0;
-}
-
-/** Allocate a new set of alert sockets, and set the appropriate function
- * pointers, in <b>socks_out</b>. */
-int
-alert_sockets_create(alert_sockets_t *socks_out, uint32_t flags)
-{
- tor_socket_t socks[2] = { TOR_INVALID_SOCKET, TOR_INVALID_SOCKET };
-
-#ifdef HAVE_EVENTFD
- /* First, we try the Linux eventfd() syscall. This gives a 64-bit counter
- * associated with a single file descriptor. */
-#if defined(EFD_CLOEXEC) && defined(EFD_NONBLOCK)
- if (!(flags & ASOCKS_NOEVENTFD2))
- socks[0] = eventfd(0, EFD_CLOEXEC|EFD_NONBLOCK);
-#endif
- if (socks[0] < 0 && !(flags & ASOCKS_NOEVENTFD)) {
- socks[0] = eventfd(0,0);
- if (socks[0] >= 0) {
- if (fcntl(socks[0], F_SETFD, FD_CLOEXEC) < 0 ||
- set_socket_nonblocking(socks[0]) < 0) {
- // LCOV_EXCL_START -- if eventfd succeeds, fcntl will.
- tor_assert_nonfatal_unreached();
- close(socks[0]);
- return -1;
- // LCOV_EXCL_STOP
- }
- }
- }
- if (socks[0] >= 0) {
- socks_out->read_fd = socks_out->write_fd = socks[0];
- socks_out->alert_fn = eventfd_alert;
- socks_out->drain_fn = eventfd_drain;
- return 0;
- }
-#endif /* defined(HAVE_EVENTFD) */
-
-#ifdef HAVE_PIPE2
- /* Now we're going to try pipes. First type the pipe2() syscall, if we
- * have it, so we can save some calls... */
- if (!(flags & ASOCKS_NOPIPE2) &&
- pipe2(socks, O_NONBLOCK|O_CLOEXEC) == 0) {
- socks_out->read_fd = socks[0];
- socks_out->write_fd = socks[1];
- socks_out->alert_fn = pipe_alert;
- socks_out->drain_fn = pipe_drain;
- return 0;
- }
-#endif /* defined(HAVE_PIPE2) */
-
-#ifdef HAVE_PIPE
- /* Now try the regular pipe() syscall. Pipes have a bit lower overhead than
- * socketpairs, fwict. */
- if (!(flags & ASOCKS_NOPIPE) &&
- pipe(socks) == 0) {
- if (fcntl(socks[0], F_SETFD, FD_CLOEXEC) < 0 ||
- fcntl(socks[1], F_SETFD, FD_CLOEXEC) < 0 ||
- set_socket_nonblocking(socks[0]) < 0 ||
- set_socket_nonblocking(socks[1]) < 0) {
- // LCOV_EXCL_START -- if pipe succeeds, you can fcntl the output
- tor_assert_nonfatal_unreached();
- close(socks[0]);
- close(socks[1]);
- return -1;
- // LCOV_EXCL_STOP
- }
- socks_out->read_fd = socks[0];
- socks_out->write_fd = socks[1];
- socks_out->alert_fn = pipe_alert;
- socks_out->drain_fn = pipe_drain;
- return 0;
- }
-#endif /* defined(HAVE_PIPE) */
-
- /* If nothing else worked, fall back on socketpair(). */
- if (!(flags & ASOCKS_NOSOCKETPAIR) &&
- tor_socketpair(AF_UNIX, SOCK_STREAM, 0, socks) == 0) {
- if (set_socket_nonblocking(socks[0]) < 0 ||
- set_socket_nonblocking(socks[1])) {
- // LCOV_EXCL_START -- if socketpair worked, you can make it nonblocking.
- tor_assert_nonfatal_unreached();
- tor_close_socket(socks[0]);
- tor_close_socket(socks[1]);
- return -1;
- // LCOV_EXCL_STOP
- }
- socks_out->read_fd = socks[0];
- socks_out->write_fd = socks[1];
- socks_out->alert_fn = sock_alert;
- socks_out->drain_fn = sock_drain;
- return 0;
- }
- return -1;
-}
-
-/** Close the sockets in <b>socks</b>. */
-void
-alert_sockets_close(alert_sockets_t *socks)
-{
- if (socks->alert_fn == sock_alert) {
- /* they are sockets. */
- tor_close_socket(socks->read_fd);
- tor_close_socket(socks->write_fd);
- } else {
- close(socks->read_fd);
- if (socks->write_fd != socks->read_fd)
- close(socks->write_fd);
- }
- socks->read_fd = socks->write_fd = -1;
-}
-
-#ifndef HAVE_WORKING_STDATOMIC
-/** Initialize a new atomic counter with the value 0 */
-void
-atomic_counter_init(atomic_counter_t *counter)
-{
- memset(counter, 0, sizeof(*counter));
- tor_mutex_init_nonrecursive(&counter->mutex);
-}
-/** Clean up all resources held by an atomic counter. */
-void
-atomic_counter_destroy(atomic_counter_t *counter)
-{
- tor_mutex_uninit(&counter->mutex);
- memset(counter, 0, sizeof(*counter));
-}
-/** Add a value to an atomic counter. */
-void
-atomic_counter_add(atomic_counter_t *counter, size_t add)
-{
- tor_mutex_acquire(&counter->mutex);
- counter->val += add;
- tor_mutex_release(&counter->mutex);
-}
-/** Subtract a value from an atomic counter. */
-void
-atomic_counter_sub(atomic_counter_t *counter, size_t sub)
-{
- // this relies on unsigned overflow, but that's fine.
- atomic_counter_add(counter, -sub);
-}
-/** Return the current value of an atomic counter */
-size_t
-atomic_counter_get(atomic_counter_t *counter)
-{
- size_t val;
- tor_mutex_acquire(&counter->mutex);
- val = counter->val;
- tor_mutex_release(&counter->mutex);
- return val;
-}
-/** Replace the value of an atomic counter; return the old one. */
-size_t
-atomic_counter_exchange(atomic_counter_t *counter, size_t newval)
-{
- size_t oldval;
- tor_mutex_acquire(&counter->mutex);
- oldval = counter->val;
- counter->val = newval;
- tor_mutex_release(&counter->mutex);
- return oldval;
-}
-#endif /* !defined(HAVE_WORKING_STDATOMIC) */
diff --git a/src/common/compat_threads.h b/src/common/compat_threads.h
deleted file mode 100644
index 8bf8225689..0000000000
--- a/src/common/compat_threads.h
+++ /dev/null
@@ -1,226 +0,0 @@
-/* Copyright (c) 2003-2004, Roger Dingledine
- * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2017, The Tor Project, Inc. */
-/* See LICENSE for licensing information */
-
-#ifndef TOR_COMPAT_THREADS_H
-#define TOR_COMPAT_THREADS_H
-
-#include "orconfig.h"
-#include "torint.h"
-#include "testsupport.h"
-
-#if defined(HAVE_PTHREAD_H) && !defined(_WIN32)
-#include <pthread.h>
-#endif
-
-#if defined(HAVE_STDATOMIC_H) && defined(STDATOMIC_WORKS)
-#define HAVE_WORKING_STDATOMIC
-#endif
-
-#ifdef HAVE_WORKING_STDATOMIC
-#include <stdatomic.h>
-#endif
-
-#if defined(_WIN32)
-#define USE_WIN32_THREADS
-#elif defined(HAVE_PTHREAD_H) && defined(HAVE_PTHREAD_CREATE)
-#define USE_PTHREADS
-#else
-#error "No threading system was found"
-#endif /* defined(_WIN32) || ... */
-
-int spawn_func(void (*func)(void *), void *data);
-void spawn_exit(void) ATTR_NORETURN;
-
-/* Because we use threads instead of processes on most platforms (Windows,
- * Linux, etc), we need locking for them. On platforms with poor thread
- * support or broken gethostbyname_r, these functions are no-ops. */
-
-/** A generic lock structure for multithreaded builds. */
-typedef struct tor_mutex_t {
-#if defined(USE_WIN32_THREADS)
- /** Windows-only: on windows, we implement locks with CRITICAL_SECTIONS. */
- CRITICAL_SECTION mutex;
-#elif defined(USE_PTHREADS)
- /** Pthreads-only: with pthreads, we implement locks with
- * pthread_mutex_t. */
- pthread_mutex_t mutex;
-#else
- /** No-threads only: Dummy variable so that tor_mutex_t takes up space. */
- int _unused;
-#endif /* defined(USE_WIN32_THREADS) || ... */
-} tor_mutex_t;
-
-tor_mutex_t *tor_mutex_new(void);
-tor_mutex_t *tor_mutex_new_nonrecursive(void);
-void tor_mutex_init(tor_mutex_t *m);
-void tor_mutex_init_nonrecursive(tor_mutex_t *m);
-void tor_mutex_acquire(tor_mutex_t *m);
-void tor_mutex_release(tor_mutex_t *m);
-void tor_mutex_free_(tor_mutex_t *m);
-#define tor_mutex_free(m) FREE_AND_NULL(tor_mutex_t, tor_mutex_free_, (m))
-void tor_mutex_uninit(tor_mutex_t *m);
-unsigned long tor_get_thread_id(void);
-void tor_threads_init(void);
-
-/** Conditions need nonrecursive mutexes with pthreads. */
-#define tor_mutex_init_for_cond(m) tor_mutex_init_nonrecursive(m)
-
-void set_main_thread(void);
-int in_main_thread(void);
-
-typedef struct tor_cond_t {
-#ifdef USE_PTHREADS
- pthread_cond_t cond;
-#elif defined(USE_WIN32_THREADS)
- HANDLE event;
-
- CRITICAL_SECTION lock;
- int n_waiting;
- int n_to_wake;
- int generation;
-#else
-#error no known condition implementation.
-#endif /* defined(USE_PTHREADS) || ... */
-} tor_cond_t;
-
-tor_cond_t *tor_cond_new(void);
-void tor_cond_free_(tor_cond_t *cond);
-#define tor_cond_free(c) FREE_AND_NULL(tor_cond_t, tor_cond_free_, (c))
-int tor_cond_init(tor_cond_t *cond);
-void tor_cond_uninit(tor_cond_t *cond);
-int tor_cond_wait(tor_cond_t *cond, tor_mutex_t *mutex,
- const struct timeval *tv);
-void tor_cond_signal_one(tor_cond_t *cond);
-void tor_cond_signal_all(tor_cond_t *cond);
-
-/** Helper type used to manage waking up the main thread while it's in
- * the libevent main loop. Used by the work queue code. */
-typedef struct alert_sockets_s {
- /* XXXX This structure needs a better name. */
- /** Socket that the main thread should listen for EV_READ events on.
- * Note that this socket may be a regular fd on a non-Windows platform.
- */
- tor_socket_t read_fd;
- /** Socket to use when alerting the main thread. */
- tor_socket_t write_fd;
- /** Function to alert the main thread */
- int (*alert_fn)(tor_socket_t write_fd);
- /** Function to make the main thread no longer alerted. */
- int (*drain_fn)(tor_socket_t read_fd);
-} alert_sockets_t;
-
-/* Flags to disable one or more alert_sockets backends. */
-#define ASOCKS_NOEVENTFD2 (1u<<0)
-#define ASOCKS_NOEVENTFD (1u<<1)
-#define ASOCKS_NOPIPE2 (1u<<2)
-#define ASOCKS_NOPIPE (1u<<3)
-#define ASOCKS_NOSOCKETPAIR (1u<<4)
-
-int alert_sockets_create(alert_sockets_t *socks_out, uint32_t flags);
-void alert_sockets_close(alert_sockets_t *socks);
-
-typedef struct tor_threadlocal_s {
-#ifdef _WIN32
- DWORD index;
-#else
- pthread_key_t key;
-#endif
-} tor_threadlocal_t;
-
-/** Initialize a thread-local variable.
- *
- * After you call this function on a tor_threadlocal_t, you can call
- * tor_threadlocal_set to change the current value of this variable for the
- * current thread, and tor_threadlocal_get to retrieve the current value for
- * the current thread. Each thread has its own value.
- **/
-int tor_threadlocal_init(tor_threadlocal_t *threadlocal);
-/**
- * Release all resource associated with a thread-local variable.
- */
-void tor_threadlocal_destroy(tor_threadlocal_t *threadlocal);
-/**
- * Return the current value of a thread-local variable for this thread.
- *
- * It's undefined behavior to use this function if the threadlocal hasn't
- * been initialized, or has been destroyed.
- */
-void *tor_threadlocal_get(tor_threadlocal_t *threadlocal);
-/**
- * Change the current value of a thread-local variable for this thread to
- * <b>value</b>.
- *
- * It's undefined behavior to use this function if the threadlocal hasn't
- * been initialized, or has been destroyed.
- */
-void tor_threadlocal_set(tor_threadlocal_t *threadlocal, void *value);
-
-/**
- * Atomic counter type; holds a size_t value.
- */
-#ifdef HAVE_WORKING_STDATOMIC
-typedef struct atomic_counter_t {
- atomic_size_t val;
-} atomic_counter_t;
-#define ATOMIC_LINKAGE static
-#else /* !(defined(HAVE_WORKING_STDATOMIC)) */
-typedef struct atomic_counter_t {
- tor_mutex_t mutex;
- size_t val;
-} atomic_counter_t;
-#define ATOMIC_LINKAGE
-#endif /* defined(HAVE_WORKING_STDATOMIC) */
-
-ATOMIC_LINKAGE void atomic_counter_init(atomic_counter_t *counter);
-ATOMIC_LINKAGE void atomic_counter_destroy(atomic_counter_t *counter);
-ATOMIC_LINKAGE void atomic_counter_add(atomic_counter_t *counter, size_t add);
-ATOMIC_LINKAGE void atomic_counter_sub(atomic_counter_t *counter, size_t sub);
-ATOMIC_LINKAGE size_t atomic_counter_get(atomic_counter_t *counter);
-ATOMIC_LINKAGE size_t atomic_counter_exchange(atomic_counter_t *counter,
- size_t newval);
-#undef ATOMIC_LINKAGE
-
-#ifdef HAVE_WORKING_STDATOMIC
-/** Initialize a new atomic counter with the value 0 */
-static inline void
-atomic_counter_init(atomic_counter_t *counter)
-{
- atomic_init(&counter->val, 0);
-}
-/** Clean up all resources held by an atomic counter. */
-static inline void
-atomic_counter_destroy(atomic_counter_t *counter)
-{
- (void)counter;
-}
-/** Add a value to an atomic counter. */
-static inline void
-atomic_counter_add(atomic_counter_t *counter, size_t add)
-{
- (void) atomic_fetch_add(&counter->val, add);
-}
-/** Subtract a value from an atomic counter. */
-static inline void
-atomic_counter_sub(atomic_counter_t *counter, size_t sub)
-{
- (void) atomic_fetch_sub(&counter->val, sub);
-}
-/** Return the current value of an atomic counter */
-static inline size_t
-atomic_counter_get(atomic_counter_t *counter)
-{
- return atomic_load(&counter->val);
-}
-/** Replace the value of an atomic counter; return the old one. */
-static inline size_t
-atomic_counter_exchange(atomic_counter_t *counter, size_t newval)
-{
- return atomic_exchange(&counter->val, newval);
-}
-
-#else /* !(defined(HAVE_WORKING_STDATOMIC)) */
-#endif /* defined(HAVE_WORKING_STDATOMIC) */
-
-#endif /* !defined(TOR_COMPAT_THREADS_H) */
diff --git a/src/common/compat_time.c b/src/common/compat_time.c
deleted file mode 100644
index 93b527def0..0000000000
--- a/src/common/compat_time.c
+++ /dev/null
@@ -1,913 +0,0 @@
-/* Copyright (c) 2003-2004, Roger Dingledine
- * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2017, The Tor Project, Inc. */
-/* See LICENSE for licensing information */
-
-/**
- * \file compat_time.c
- * \brief Portable wrappers for finding out the current time, running
- * timers, etc.
- **/
-
-#define COMPAT_TIME_PRIVATE
-#include "compat.h"
-
-#ifdef _WIN32
-#include <winsock2.h>
-#include <windows.h>
-#endif
-
-#ifdef HAVE_SYS_TYPES_H
-#include <sys/types.h>
-#endif
-#ifdef HAVE_UNISTD_H
-#include <unistd.h>
-#endif
-#ifdef TOR_UNIT_TESTS
-#if !defined(HAVE_USLEEP) && defined(HAVE_SYS_SELECT_H)
-/* as fallback implementation for tor_sleep_msec */
-#include <sys/select.h>
-#endif
-#endif /* defined(TOR_UNIT_TESTS) */
-
-#ifdef __APPLE__
-#include <mach/mach_time.h>
-#endif
-
-#include "torlog.h"
-#include "util.h"
-#include "container.h"
-
-#ifndef HAVE_GETTIMEOFDAY
-#ifdef HAVE_FTIME
-#include <sys/timeb.h>
-#endif
-#endif
-
-#ifdef _WIN32
-#undef HAVE_CLOCK_GETTIME
-#endif
-
-#ifdef TOR_UNIT_TESTS
-/** Delay for <b>msec</b> milliseconds. Only used in tests. */
-void
-tor_sleep_msec(int msec)
-{
-#ifdef _WIN32
- Sleep(msec);
-#elif defined(HAVE_USLEEP)
- sleep(msec / 1000);
- /* Some usleep()s hate sleeping more than 1 sec */
- usleep((msec % 1000) * 1000);
-#elif defined(HAVE_SYS_SELECT_H)
- struct timeval tv = { msec / 1000, (msec % 1000) * 1000};
- select(0, NULL, NULL, NULL, &tv);
-#else
- sleep(CEIL_DIV(msec, 1000));
-#endif /* defined(_WIN32) || ... */
-}
-#endif /* defined(TOR_UNIT_TESTS) */
-
-/** Set *timeval to the current time of day. On error, log and terminate.
- * (Same as gettimeofday(timeval,NULL), but never returns -1.)
- */
-MOCK_IMPL(void,
-tor_gettimeofday, (struct timeval *timeval))
-{
-#ifdef _WIN32
- /* Epoch bias copied from perl: number of units between windows epoch and
- * Unix epoch. */
-#define EPOCH_BIAS U64_LITERAL(116444736000000000)
-#define UNITS_PER_SEC U64_LITERAL(10000000)
-#define USEC_PER_SEC U64_LITERAL(1000000)
-#define UNITS_PER_USEC U64_LITERAL(10)
- union {
- uint64_t ft_64;
- FILETIME ft_ft;
- } ft;
- /* number of 100-nsec units since Jan 1, 1601 */
- GetSystemTimeAsFileTime(&ft.ft_ft);
- if (ft.ft_64 < EPOCH_BIAS) {
- /* LCOV_EXCL_START */
- log_err(LD_GENERAL,"System time is before 1970; failing.");
- exit(1); // exit ok: system clock is broken.
- /* LCOV_EXCL_STOP */
- }
- ft.ft_64 -= EPOCH_BIAS;
- timeval->tv_sec = (unsigned) (ft.ft_64 / UNITS_PER_SEC);
- timeval->tv_usec = (unsigned) ((ft.ft_64 / UNITS_PER_USEC) % USEC_PER_SEC);
-#elif defined(HAVE_GETTIMEOFDAY)
- if (gettimeofday(timeval, NULL)) {
- /* LCOV_EXCL_START */
- log_err(LD_GENERAL,"gettimeofday failed.");
- /* If gettimeofday dies, we have either given a bad timezone (we didn't),
- or segfaulted.*/
- exit(1); // exit ok: gettimeofday failed.
- /* LCOV_EXCL_STOP */
- }
-#elif defined(HAVE_FTIME)
- struct timeb tb;
- ftime(&tb);
- timeval->tv_sec = tb.time;
- timeval->tv_usec = tb.millitm * 1000;
-#else
-#error "No way to get time."
-#endif /* defined(_WIN32) || ... */
- return;
-}
-
-#define ONE_MILLION ((int64_t) (1000 * 1000))
-#define ONE_BILLION ((int64_t) (1000 * 1000 * 1000))
-
-/** True iff monotime_init has been called. */
-static int monotime_initialized = 0;
-
-static monotime_t initialized_at;
-#ifdef MONOTIME_COARSE_FN_IS_DIFFERENT
-static monotime_coarse_t initialized_at_coarse;
-#endif
-
-#ifdef TOR_UNIT_TESTS
-/** True if we are running unit tests and overriding the current monotonic
- * time. Note that mocked monotonic time might not be monotonic.
- */
-static int monotime_mocking_enabled = 0;
-static monotime_t initialized_at_saved;
-
-static int64_t mock_time_nsec = 0;
-#ifdef MONOTIME_COARSE_FN_IS_DIFFERENT
-static int64_t mock_time_nsec_coarse = 0;
-static monotime_coarse_t initialized_at_coarse_saved;
-#endif
-
-void
-monotime_enable_test_mocking(void)
-{
- if (BUG(monotime_initialized == 0)) {
- monotime_init();
- }
-
- tor_assert_nonfatal(monotime_mocking_enabled == 0);
- monotime_mocking_enabled = 1;
- memcpy(&initialized_at_saved,
- &initialized_at, sizeof(monotime_t));
- memset(&initialized_at, 0, sizeof(monotime_t));
-#ifdef MONOTIME_COARSE_FN_IS_DIFFERENT
- memcpy(&initialized_at_coarse_saved,
- &initialized_at_coarse, sizeof(monotime_coarse_t));
- memset(&initialized_at_coarse, 0, sizeof(monotime_coarse_t));
-#endif
-}
-
-void
-monotime_disable_test_mocking(void)
-{
- tor_assert_nonfatal(monotime_mocking_enabled == 1);
- monotime_mocking_enabled = 0;
-
- memcpy(&initialized_at,
- &initialized_at_saved, sizeof(monotime_t));
-#ifdef MONOTIME_COARSE_FN_IS_DIFFERENT
- memcpy(&initialized_at_coarse,
- &initialized_at_coarse_saved, sizeof(monotime_coarse_t));
-#endif
-}
-
-void
-monotime_set_mock_time_nsec(int64_t nsec)
-{
- tor_assert_nonfatal(monotime_mocking_enabled == 1);
- mock_time_nsec = nsec;
-}
-
-#ifdef MONOTIME_COARSE_FN_IS_DIFFERENT
-void
-monotime_coarse_set_mock_time_nsec(int64_t nsec)
-{
- tor_assert_nonfatal(monotime_mocking_enabled == 1);
- mock_time_nsec_coarse = nsec;
-}
-#endif /* defined(MONOTIME_COARSE_FN_IS_DIFFERENT) */
-#endif /* defined(TOR_UNIT_TESTS) */
-
-/* "ratchet" functions for monotonic time. */
-
-#if defined(_WIN32) || defined(TOR_UNIT_TESTS)
-
-/** Protected by lock: last value returned by monotime_get(). */
-static int64_t last_pctr = 0;
-/** Protected by lock: offset we must add to monotonic time values. */
-static int64_t pctr_offset = 0;
-/* If we are using GetTickCount(), how many times has it rolled over? */
-static uint32_t rollover_count = 0;
-/* If we are using GetTickCount(), what's the last value it returned? */
-static int64_t last_tick_count = 0;
-
-/** Helper for windows: Called with a sequence of times that are supposed
- * to be monotonic; increments them as appropriate so that they actually
- * _are_ monotonic.
- *
- * Caller must hold lock. */
-STATIC int64_t
-ratchet_performance_counter(int64_t count_raw)
-{
- /* must hold lock */
- const int64_t count_adjusted = count_raw + pctr_offset;
-
- if (PREDICT_UNLIKELY(count_adjusted < last_pctr)) {
- /* Monotonicity failed! Pretend no time elapsed. */
- pctr_offset = last_pctr - count_raw;
- return last_pctr;
- } else {
- last_pctr = count_adjusted;
- return count_adjusted;
- }
-}
-
-STATIC int64_t
-ratchet_coarse_performance_counter(const int64_t count_raw)
-{
- int64_t count = count_raw + (((int64_t)rollover_count) << 32);
- while (PREDICT_UNLIKELY(count < last_tick_count)) {
- ++rollover_count;
- count = count_raw + (((int64_t)rollover_count) << 32);
- }
- last_tick_count = count;
- return count;
-}
-#endif /* defined(_WIN32) || defined(TOR_UNIT_TESTS) */
-
-#if defined(MONOTIME_USING_GETTIMEOFDAY) || defined(TOR_UNIT_TESTS)
-static struct timeval last_timeofday = { 0, 0 };
-static struct timeval timeofday_offset = { 0, 0 };
-
-/** Helper for gettimeofday(): Called with a sequence of times that are
- * supposed to be monotonic; increments them as appropriate so that they
- * actually _are_ monotonic.
- *
- * Caller must hold lock. */
-STATIC void
-ratchet_timeval(const struct timeval *timeval_raw, struct timeval *out)
-{
- /* must hold lock */
- timeradd(timeval_raw, &timeofday_offset, out);
- if (PREDICT_UNLIKELY(timercmp(out, &last_timeofday, OP_LT))) {
- /* time ran backwards. Instead, declare that no time occurred. */
- timersub(&last_timeofday, timeval_raw, &timeofday_offset);
- memcpy(out, &last_timeofday, sizeof(struct timeval));
- } else {
- memcpy(&last_timeofday, out, sizeof(struct timeval));
- }
-}
-#endif /* defined(MONOTIME_USING_GETTIMEOFDAY) || defined(TOR_UNIT_TESTS) */
-
-#ifdef TOR_UNIT_TESTS
-/** For testing: reset all the ratchets */
-void
-monotime_reset_ratchets_for_testing(void)
-{
- last_pctr = pctr_offset = last_tick_count = 0;
- rollover_count = 0;
- memset(&last_timeofday, 0, sizeof(struct timeval));
- memset(&timeofday_offset, 0, sizeof(struct timeval));
-}
-#endif /* defined(TOR_UNIT_TESTS) */
-
-#ifdef __APPLE__
-
-/** Initialized on startup: tells is how to convert from ticks to
- * nanoseconds.
- */
-static struct mach_timebase_info mach_time_info;
-static struct mach_timebase_info mach_time_info_msec_cvt;
-static int32_t mach_time_msec_cvt_threshold;
-static int monotime_shift = 0;
-
-static void
-monotime_init_internal(void)
-{
- tor_assert(!monotime_initialized);
- int r = mach_timebase_info(&mach_time_info);
- tor_assert(r == 0);
- tor_assert(mach_time_info.denom != 0);
-
- {
- // approximate only.
- uint64_t ns_per_tick = mach_time_info.numer / mach_time_info.denom;
- uint64_t ms_per_tick = ns_per_tick * ONE_MILLION;
- // requires that tor_log2(0) == 0.
- monotime_shift = tor_log2(ms_per_tick);
- }
- {
- // For converting ticks to milliseconds in a 32-bit-friendly way, we
- // will first right-shift by 20, and then multiply by 2048/1953, since
- // (1<<20) * 1953/2048 is about 1e6. We precompute a new numerator and
- // denominator here to avoid multiple multiplies.
- mach_time_info_msec_cvt.numer = mach_time_info.numer * 2048;
- mach_time_info_msec_cvt.denom = mach_time_info.denom * 1953;
- // For any value above this amount, we should divide before multiplying,
- // to avoid overflow. For a value below this, we should multiply
- // before dividing, to improve accuracy.
- mach_time_msec_cvt_threshold = INT32_MAX / mach_time_info_msec_cvt.numer;
- }
-}
-
-/**
- * Set "out" to the most recent monotonic time value
- */
-void
-monotime_get(monotime_t *out)
-{
-#ifdef TOR_UNIT_TESTS
- if (monotime_mocking_enabled) {
- out->abstime_ = (mock_time_nsec * mach_time_info.denom)
- / mach_time_info.numer;
- return;
- }
-#endif /* defined(TOR_UNIT_TESTS) */
- out->abstime_ = mach_absolute_time();
-}
-
-#if defined(HAVE_MACH_APPROXIMATE_TIME)
-void
-monotime_coarse_get(monotime_coarse_t *out)
-{
-#ifdef TOR_UNIT_TESTS
- if (monotime_mocking_enabled) {
- out->abstime_ = (mock_time_nsec_coarse * mach_time_info.denom)
- / mach_time_info.numer;
- return;
- }
-#endif /* defined(TOR_UNIT_TESTS) */
- out->abstime_ = mach_approximate_time();
-}
-#endif
-
-/**
- * Return the number of nanoseconds between <b>start</b> and <b>end</b>.
- */
-int64_t
-monotime_diff_nsec(const monotime_t *start,
- const monotime_t *end)
-{
- if (BUG(mach_time_info.denom == 0)) {
- monotime_init();
- }
- const int64_t diff_ticks = end->abstime_ - start->abstime_;
- const int64_t diff_nsec =
- (diff_ticks * mach_time_info.numer) / mach_time_info.denom;
- return diff_nsec;
-}
-
-int32_t
-monotime_coarse_diff_msec32_(const monotime_coarse_t *start,
- const monotime_coarse_t *end)
-{
- if (BUG(mach_time_info.denom == 0)) {
- monotime_init();
- }
- const int64_t diff_ticks = end->abstime_ - start->abstime_;
-
- /* We already require in di_ops.c that right-shift performs a sign-extend. */
- const int32_t diff_microticks = (int32_t)(diff_ticks >> 20);
-
- if (diff_microticks >= mach_time_msec_cvt_threshold) {
- return (diff_microticks / mach_time_info_msec_cvt.denom) *
- mach_time_info_msec_cvt.numer;
- } else {
- return (diff_microticks * mach_time_info_msec_cvt.numer) /
- mach_time_info_msec_cvt.denom;
- }
-}
-
-uint32_t
-monotime_coarse_to_stamp(const monotime_coarse_t *t)
-{
- return (uint32_t)(t->abstime_ >> monotime_shift);
-}
-
-int
-monotime_is_zero(const monotime_t *val)
-{
- return val->abstime_ == 0;
-}
-
-void
-monotime_add_msec(monotime_t *out, const monotime_t *val, uint32_t msec)
-{
- const uint64_t nsec = msec * ONE_MILLION;
- const uint64_t ticks = (nsec * mach_time_info.denom) / mach_time_info.numer;
- out->abstime_ = val->abstime_ + ticks;
-}
-
-/* end of "__APPLE__" */
-#elif defined(HAVE_CLOCK_GETTIME)
-
-#ifdef CLOCK_MONOTONIC_COARSE
-/**
- * Which clock should we use for coarse-grained monotonic time? By default
- * this is CLOCK_MONOTONIC_COARSE, but it might not work -- for example,
- * if we're compiled with newer Linux headers and then we try to run on
- * an old Linux kernel. In that case, we will fall back to CLOCK_MONOTONIC.
- */
-static int clock_monotonic_coarse = CLOCK_MONOTONIC_COARSE;
-#endif /* defined(CLOCK_MONOTONIC_COARSE) */
-
-static void
-monotime_init_internal(void)
-{
-#ifdef CLOCK_MONOTONIC_COARSE
- struct timespec ts;
- if (clock_gettime(CLOCK_MONOTONIC_COARSE, &ts) < 0) {
- log_info(LD_GENERAL, "CLOCK_MONOTONIC_COARSE isn't working (%s); "
- "falling back to CLOCK_MONOTONIC.", strerror(errno));
- clock_monotonic_coarse = CLOCK_MONOTONIC;
- }
-#endif /* defined(CLOCK_MONOTONIC_COARSE) */
-}
-
-void
-monotime_get(monotime_t *out)
-{
-#ifdef TOR_UNIT_TESTS
- if (monotime_mocking_enabled) {
- out->ts_.tv_sec = (time_t) (mock_time_nsec / ONE_BILLION);
- out->ts_.tv_nsec = (int) (mock_time_nsec % ONE_BILLION);
- return;
- }
-#endif /* defined(TOR_UNIT_TESTS) */
- int r = clock_gettime(CLOCK_MONOTONIC, &out->ts_);
- tor_assert(r == 0);
-}
-
-#ifdef CLOCK_MONOTONIC_COARSE
-void
-monotime_coarse_get(monotime_coarse_t *out)
-{
-#ifdef TOR_UNIT_TESTS
- if (monotime_mocking_enabled) {
- out->ts_.tv_sec = (time_t) (mock_time_nsec_coarse / ONE_BILLION);
- out->ts_.tv_nsec = (int) (mock_time_nsec_coarse % ONE_BILLION);
- return;
- }
-#endif /* defined(TOR_UNIT_TESTS) */
- int r = clock_gettime(clock_monotonic_coarse, &out->ts_);
- if (PREDICT_UNLIKELY(r < 0) &&
- errno == EINVAL &&
- clock_monotonic_coarse == CLOCK_MONOTONIC_COARSE) {
- /* We should have caught this at startup in monotime_init_internal!
- */
- log_warn(LD_BUG, "Falling back to non-coarse monotonic time %s initial "
- "system start?", monotime_initialized?"after":"without");
- clock_monotonic_coarse = CLOCK_MONOTONIC;
- r = clock_gettime(clock_monotonic_coarse, &out->ts_);
- }
-
- tor_assert(r == 0);
-}
-#endif /* defined(CLOCK_MONOTONIC_COARSE) */
-
-int64_t
-monotime_diff_nsec(const monotime_t *start,
- const monotime_t *end)
-{
- const int64_t diff_sec = end->ts_.tv_sec - start->ts_.tv_sec;
- const int64_t diff_nsec = diff_sec * ONE_BILLION +
- (end->ts_.tv_nsec - start->ts_.tv_nsec);
-
- return diff_nsec;
-}
-
-int32_t
-monotime_coarse_diff_msec32_(const monotime_coarse_t *start,
- const monotime_coarse_t *end)
-{
- const int32_t diff_sec = (int32_t)(end->ts_.tv_sec - start->ts_.tv_sec);
- const int32_t diff_nsec = (int32_t)(end->ts_.tv_nsec - start->ts_.tv_nsec);
- return diff_sec * 1000 + diff_nsec / ONE_MILLION;
-}
-
-/* This value is ONE_BILLION >> 20. */
-static const uint32_t STAMP_TICKS_PER_SECOND = 953;
-
-uint32_t
-monotime_coarse_to_stamp(const monotime_coarse_t *t)
-{
- uint32_t nsec = (uint32_t)t->ts_.tv_nsec;
- uint32_t sec = (uint32_t)t->ts_.tv_sec;
-
- return (sec * STAMP_TICKS_PER_SECOND) + (nsec >> 20);
-}
-
-int
-monotime_is_zero(const monotime_t *val)
-{
- return val->ts_.tv_sec == 0 && val->ts_.tv_nsec == 0;
-}
-
-void
-monotime_add_msec(monotime_t *out, const monotime_t *val, uint32_t msec)
-{
- const uint32_t sec = msec / 1000;
- const uint32_t msec_remainder = msec % 1000;
- out->ts_.tv_sec = val->ts_.tv_sec + sec;
- out->ts_.tv_nsec = val->ts_.tv_nsec + (msec_remainder * ONE_MILLION);
- if (out->ts_.tv_nsec > ONE_BILLION) {
- out->ts_.tv_nsec -= ONE_BILLION;
- out->ts_.tv_sec += 1;
- }
-}
-
-/* end of "HAVE_CLOCK_GETTIME" */
-#elif defined (_WIN32)
-
-/** Result of QueryPerformanceFrequency, in terms needed to
- * convert ticks to nanoseconds. */
-static int64_t nsec_per_tick_numer = 1;
-static int64_t nsec_per_tick_denom = 1;
-
-/** Lock to protect last_pctr and pctr_offset */
-static CRITICAL_SECTION monotime_lock;
-/** Lock to protect rollover_count and last_tick_count */
-static CRITICAL_SECTION monotime_coarse_lock;
-
-typedef ULONGLONG (WINAPI *GetTickCount64_fn_t)(void);
-static GetTickCount64_fn_t GetTickCount64_fn = NULL;
-
-static void
-monotime_init_internal(void)
-{
- tor_assert(!monotime_initialized);
- BOOL ok = InitializeCriticalSectionAndSpinCount(&monotime_lock, 200);
- tor_assert(ok);
- ok = InitializeCriticalSectionAndSpinCount(&monotime_coarse_lock, 200);
- tor_assert(ok);
- LARGE_INTEGER li;
- ok = QueryPerformanceFrequency(&li);
- tor_assert(ok);
- tor_assert(li.QuadPart);
-
- uint64_t n = ONE_BILLION;
- uint64_t d = li.QuadPart;
- /* We need to simplify this or we'll probably overflow the int64. */
- simplify_fraction64(&n, &d);
- tor_assert(n <= INT64_MAX);
- tor_assert(d <= INT64_MAX);
-
- nsec_per_tick_numer = (int64_t) n;
- nsec_per_tick_denom = (int64_t) d;
-
- last_pctr = 0;
- pctr_offset = 0;
-
- HANDLE h = load_windows_system_library(TEXT("kernel32.dll"));
- if (h) {
- GetTickCount64_fn = (GetTickCount64_fn_t)
- GetProcAddress(h, "GetTickCount64");
- }
- // FreeLibrary(h) ?
-}
-
-void
-monotime_get(monotime_t *out)
-{
- if (BUG(monotime_initialized == 0)) {
- monotime_init();
- }
-
-#ifdef TOR_UNIT_TESTS
- if (monotime_mocking_enabled) {
- out->pcount_ = (mock_time_nsec * nsec_per_tick_denom)
- / nsec_per_tick_numer;
- return;
- }
-#endif /* defined(TOR_UNIT_TESTS) */
-
- /* Alas, QueryPerformanceCounter is not always monotonic: see bug list at
-
- https://www.python.org/dev/peps/pep-0418/#windows-queryperformancecounter
- */
-
- EnterCriticalSection(&monotime_lock);
- LARGE_INTEGER res;
- BOOL ok = QueryPerformanceCounter(&res);
- tor_assert(ok);
- const int64_t count_raw = res.QuadPart;
- out->pcount_ = ratchet_performance_counter(count_raw);
- LeaveCriticalSection(&monotime_lock);
-}
-
-void
-monotime_coarse_get(monotime_coarse_t *out)
-{
-#ifdef TOR_UNIT_TESTS
- if (monotime_mocking_enabled) {
- out->tick_count_ = mock_time_nsec_coarse / ONE_MILLION;
- return;
- }
-#endif /* defined(TOR_UNIT_TESTS) */
-
- if (GetTickCount64_fn) {
- out->tick_count_ = (int64_t)GetTickCount64_fn();
- } else {
- EnterCriticalSection(&monotime_coarse_lock);
- DWORD tick = GetTickCount();
- out->tick_count_ = ratchet_coarse_performance_counter(tick);
- LeaveCriticalSection(&monotime_coarse_lock);
- }
-}
-
-int64_t
-monotime_diff_nsec(const monotime_t *start,
- const monotime_t *end)
-{
- if (BUG(monotime_initialized == 0)) {
- monotime_init();
- }
- const int64_t diff_ticks = end->pcount_ - start->pcount_;
- return (diff_ticks * nsec_per_tick_numer) / nsec_per_tick_denom;
-}
-
-int64_t
-monotime_coarse_diff_msec(const monotime_coarse_t *start,
- const monotime_coarse_t *end)
-{
- const int64_t diff_ticks = end->tick_count_ - start->tick_count_;
- return diff_ticks;
-}
-
-int32_t
-monotime_coarse_diff_msec32_(const monotime_coarse_t *start,
- const monotime_coarse_t *end)
-{
- return (int32_t)monotime_coarse_diff_msec(start, end);
-}
-
-int64_t
-monotime_coarse_diff_usec(const monotime_coarse_t *start,
- const monotime_coarse_t *end)
-{
- return monotime_coarse_diff_msec(start, end) * 1000;
-}
-
-int64_t
-monotime_coarse_diff_nsec(const monotime_coarse_t *start,
- const monotime_coarse_t *end)
-{
- return monotime_coarse_diff_msec(start, end) * ONE_MILLION;
-}
-
-static const uint32_t STAMP_TICKS_PER_SECOND = 1000;
-
-uint32_t
-monotime_coarse_to_stamp(const monotime_coarse_t *t)
-{
- return (uint32_t) t->tick_count_;
-}
-
-int
-monotime_is_zero(const monotime_t *val)
-{
- return val->pcount_ == 0;
-}
-
-int
-monotime_coarse_is_zero(const monotime_coarse_t *val)
-{
- return val->tick_count_ == 0;
-}
-
-void
-monotime_add_msec(monotime_t *out, const monotime_t *val, uint32_t msec)
-{
- const uint64_t nsec = msec * ONE_MILLION;
- const uint64_t ticks = (nsec * nsec_per_tick_denom) / nsec_per_tick_numer;
- out->pcount_ = val->pcount_ + ticks;
-}
-
-void
-monotime_coarse_add_msec(monotime_coarse_t *out, const monotime_coarse_t *val,
- uint32_t msec)
-{
- out->tick_count_ = val->tick_count_ + msec;
-}
-
-/* end of "_WIN32" */
-#elif defined(MONOTIME_USING_GETTIMEOFDAY)
-
-static tor_mutex_t monotime_lock;
-
-/** Initialize the monotonic timer subsystem. */
-static void
-monotime_init_internal(void)
-{
- tor_assert(!monotime_initialized);
- tor_mutex_init(&monotime_lock);
-}
-
-void
-monotime_get(monotime_t *out)
-{
- if (BUG(monotime_initialized == 0)) {
- monotime_init();
- }
-
- tor_mutex_acquire(&monotime_lock);
- struct timeval timeval_raw;
- tor_gettimeofday(&timeval_raw);
- ratchet_timeval(&timeval_raw, &out->tv_);
- tor_mutex_release(&monotime_lock);
-}
-
-int64_t
-monotime_diff_nsec(const monotime_t *start,
- const monotime_t *end)
-{
- struct timeval diff;
- timersub(&end->tv_, &start->tv_, &diff);
- return (diff.tv_sec * ONE_BILLION + diff.tv_usec * 1000);
-}
-
-int32_t
-monotime_coarse_diff_msec32_(const monotime_coarse_t *start,
- const monotime_coarse_t *end)
-{
- struct timeval diff;
- timersub(&end->tv_, &start->tv_, &diff);
- return diff.tv_sec * 1000 + diff.tv_usec / 1000;
-}
-
-/* This value is ONE_MILLION >> 10. */
-static const uint32_t STAMP_TICKS_PER_SECOND = 976;
-
-uint32_t
-monotime_coarse_to_stamp(const monotime_coarse_t *t)
-{
- const uint32_t usec = (uint32_t)t->tv_.tv_usec;
- const uint32_t sec = (uint32_t)t->tv_.tv_sec;
- return (sec * STAMP_TICKS_PER_SECOND) | (nsec >> 10);
-}
-
-int
-monotime_is_zero(const monotime_t *val)
-{
- return val->tv_.tv_sec == 0 && val->tv_.tv_usec == 0;
-}
-
-void
-monotime_add_msec(monotime_t *out, const monotime_t *val, uint32_t msec)
-{
- const uint32_t sec = msec / 1000;
- const uint32_t msec_remainder = msec % 1000;
- out->tv_.tv_sec = val->tv_.tv_sec + sec;
- out->tv_.tv_usec = val->tv_.tv_nsec + (msec_remainder * 1000);
- if (out->tv_.tv_usec > ONE_MILLION) {
- out->tv_.tv_usec -= ONE_MILLION;
- out->tv_.tv_sec += 1;
- }
-}
-
-/* end of "MONOTIME_USING_GETTIMEOFDAY" */
-#else
-#error "No way to implement monotonic timers."
-#endif /* defined(__APPLE__) || ... */
-
-/**
- * Initialize the monotonic timer subsystem. Must be called before any
- * monotonic timer functions. This function is idempotent.
- */
-void
-monotime_init(void)
-{
- if (!monotime_initialized) {
- monotime_init_internal();
- monotime_initialized = 1;
- monotime_get(&initialized_at);
-#ifdef MONOTIME_COARSE_FN_IS_DIFFERENT
- monotime_coarse_get(&initialized_at_coarse);
-#endif
- }
-}
-
-void
-monotime_zero(monotime_t *out)
-{
- memset(out, 0, sizeof(*out));
-}
-#ifdef MONOTIME_COARSE_TYPE_IS_DIFFERENT
-void
-monotime_coarse_zero(monotime_coarse_t *out)
-{
- memset(out, 0, sizeof(*out));
-}
-#endif
-
-int64_t
-monotime_diff_usec(const monotime_t *start,
- const monotime_t *end)
-{
- const int64_t nsec = monotime_diff_nsec(start, end);
- return CEIL_DIV(nsec, 1000);
-}
-
-int64_t
-monotime_diff_msec(const monotime_t *start,
- const monotime_t *end)
-{
- const int64_t nsec = monotime_diff_nsec(start, end);
- return CEIL_DIV(nsec, ONE_MILLION);
-}
-
-uint64_t
-monotime_absolute_nsec(void)
-{
- monotime_t now;
- if (BUG(monotime_initialized == 0)) {
- monotime_init();
- }
-
- monotime_get(&now);
- return monotime_diff_nsec(&initialized_at, &now);
-}
-
-uint64_t
-monotime_absolute_usec(void)
-{
- return monotime_absolute_nsec() / 1000;
-}
-
-uint64_t
-monotime_absolute_msec(void)
-{
- return monotime_absolute_nsec() / ONE_MILLION;
-}
-
-#ifdef MONOTIME_COARSE_FN_IS_DIFFERENT
-uint64_t
-monotime_coarse_absolute_nsec(void)
-{
- if (BUG(monotime_initialized == 0)) {
- monotime_init();
- }
-
- monotime_coarse_t now;
- monotime_coarse_get(&now);
- return monotime_coarse_diff_nsec(&initialized_at_coarse, &now);
-}
-
-uint64_t
-monotime_coarse_absolute_usec(void)
-{
- return monotime_coarse_absolute_nsec() / 1000;
-}
-
-uint64_t
-monotime_coarse_absolute_msec(void)
-{
- return monotime_coarse_absolute_nsec() / ONE_MILLION;
-}
-#else
-#define initialized_at_coarse initialized_at
-#endif /* defined(MONOTIME_COARSE_FN_IS_DIFFERENT) */
-
-/**
- * Return the current time "stamp" as described by monotime_coarse_to_stamp.
- */
-uint32_t
-monotime_coarse_get_stamp(void)
-{
- monotime_coarse_t now;
- monotime_coarse_get(&now);
- return monotime_coarse_to_stamp(&now);
-}
-
-#ifdef __APPLE__
-uint64_t
-monotime_coarse_stamp_units_to_approx_msec(uint64_t units)
-{
- /* Recover as much precision as we can. */
- uint64_t abstime_diff = (units << monotime_shift);
- return (abstime_diff * mach_time_info.numer) /
- (mach_time_info.denom * ONE_MILLION);
-}
-uint64_t
-monotime_msec_to_approx_coarse_stamp_units(uint64_t msec)
-{
- uint64_t abstime_val =
- (((uint64_t)msec) * ONE_MILLION * mach_time_info.denom) /
- mach_time_info.numer;
- return abstime_val >> monotime_shift;
-}
-#else
-uint64_t
-monotime_coarse_stamp_units_to_approx_msec(uint64_t units)
-{
- return (units * 1000) / STAMP_TICKS_PER_SECOND;
-}
-uint64_t
-monotime_msec_to_approx_coarse_stamp_units(uint64_t msec)
-{
- return (msec * STAMP_TICKS_PER_SECOND) / 1000;
-}
-#endif
-
diff --git a/src/common/compat_time.h b/src/common/compat_time.h
deleted file mode 100644
index f241aa5eba..0000000000
--- a/src/common/compat_time.h
+++ /dev/null
@@ -1,234 +0,0 @@
-/* Copyright (c) 2003-2004, Roger Dingledine
- * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2017, The Tor Project, Inc. */
-/* See LICENSE for licensing information */
-
-/**
- * \file compat_time.h
- *
- * \brief Functions and types for monotonic times.
- *
- * monotime_* functions try to provide a high-resolution monotonic timer with
- * something the best resolution the system provides. monotime_coarse_*
- * functions run faster (if the operating system gives us a way to do that)
- * but produce a less accurate timer: accuracy will probably be on the order
- * of tens of milliseconds.
- */
-
-#ifndef TOR_COMPAT_TIME_H
-#define TOR_COMPAT_TIME_H
-
-#include "orconfig.h"
-#ifdef _WIN32
-#undef HAVE_CLOCK_GETTIME
-#endif
-
-#if defined(HAVE_CLOCK_GETTIME)
-/* to ensure definition of CLOCK_MONOTONIC_COARSE if it's there */
-#include <time.h>
-#endif
-
-#if !defined(HAVE_STRUCT_TIMEVAL_TV_SEC)
-/** Implementation of timeval for platforms that don't have it. */
-struct timeval {
- time_t tv_sec;
- unsigned int tv_usec;
-};
-#endif /* !defined(HAVE_STRUCT_TIMEVAL_TV_SEC) */
-
-/** Represents a monotonic timer in a platform-dependent way. */
-typedef struct monotime_t {
-#ifdef __APPLE__
- /* On apple, there is a 64-bit counter whose precision we must look up. */
- uint64_t abstime_;
-#elif defined(HAVE_CLOCK_GETTIME)
- /* It sure would be nice to use clock_gettime(). Posix is a nice thing. */
- struct timespec ts_;
-#elif defined (_WIN32)
- /* On Windows, there is a 64-bit counter whose precision we must look up. */
- int64_t pcount_;
-#else
-#define MONOTIME_USING_GETTIMEOFDAY
- /* Otherwise, we will be stuck using gettimeofday. */
- struct timeval tv_;
-#endif /* defined(__APPLE__) || ... */
-} monotime_t;
-
-#if defined(CLOCK_MONOTONIC_COARSE) && \
- defined(HAVE_CLOCK_GETTIME)
-#define MONOTIME_COARSE_FN_IS_DIFFERENT
-#define monotime_coarse_t monotime_t
-#elif defined(_WIN32)
-#define MONOTIME_COARSE_FN_IS_DIFFERENT
-#define MONOTIME_COARSE_TYPE_IS_DIFFERENT
-/** Represents a coarse monotonic time in a platform-independent way. */
-typedef struct monotime_coarse_t {
- uint64_t tick_count_;
-} monotime_coarse_t;
-#elif defined(__APPLE__) && defined(HAVE_MACH_APPROXIMATE_TIME)
-#define MONOTIME_COARSE_FN_IS_DIFFERENT
-#define monotime_coarse_t monotime_t
-#else
-#define monotime_coarse_t monotime_t
-#endif /* defined(CLOCK_MONOTONIC_COARSE) && ... || ... */
-
-/**
- * Initialize the timing subsystem. This function is idempotent.
- */
-void monotime_init(void);
-/**
- * Set <b>out</b> to the current time.
- */
-void monotime_get(monotime_t *out);
-/**
- * Return the number of nanoseconds between <b>start</b> and <b>end</b>.
- */
-int64_t monotime_diff_nsec(const monotime_t *start, const monotime_t *end);
-/**
- * Return the number of microseconds between <b>start</b> and <b>end</b>.
- */
-int64_t monotime_diff_usec(const monotime_t *start, const monotime_t *end);
-/**
- * Return the number of milliseconds between <b>start</b> and <b>end</b>.
- */
-int64_t monotime_diff_msec(const monotime_t *start, const monotime_t *end);
-/**
- * Return the number of nanoseconds since the timer system was initialized.
- */
-uint64_t monotime_absolute_nsec(void);
-/**
- * Return the number of microseconds since the timer system was initialized.
- */
-uint64_t monotime_absolute_usec(void);
-/**
- * Return the number of milliseconds since the timer system was initialized.
- */
-uint64_t monotime_absolute_msec(void);
-
-/**
- * Set <b>out</b> to zero.
- */
-void monotime_zero(monotime_t *out);
-/**
- * Return true iff <b>out</b> is zero
- */
-int monotime_is_zero(const monotime_t *out);
-
-/**
- * Set <b>out</b> to N milliseconds after <b>val</b>.
- */
-/* XXXX We should add a more generic function here if we ever need to */
-void monotime_add_msec(monotime_t *out, const monotime_t *val, uint32_t msec);
-
-#if defined(MONOTIME_COARSE_FN_IS_DIFFERENT)
-/**
- * Set <b>out</b> to the current coarse time.
- */
-void monotime_coarse_get(monotime_coarse_t *out);
-uint64_t monotime_coarse_absolute_nsec(void);
-uint64_t monotime_coarse_absolute_usec(void);
-uint64_t monotime_coarse_absolute_msec(void);
-#else /* !(defined(MONOTIME_COARSE_FN_IS_DIFFERENT)) */
-#define monotime_coarse_get monotime_get
-#define monotime_coarse_absolute_nsec monotime_absolute_nsec
-#define monotime_coarse_absolute_usec monotime_absolute_usec
-#define monotime_coarse_absolute_msec monotime_absolute_msec
-#endif /* defined(MONOTIME_COARSE_FN_IS_DIFFERENT) */
-
-/**
- * Return a "timestamp" approximation for a coarse monotonic timer.
- * This timestamp is meant to be fast to calculate and easy to
- * compare, and have a unit of something roughly around 1 msec.
- *
- * It will wrap over from time to time.
- *
- * It has no defined zero point.
- */
-uint32_t monotime_coarse_to_stamp(const monotime_coarse_t *t);
-/**
- * Convert a difference, expressed in the units of monotime_coarse_to_stamp,
- * into an approximate number of milliseconds.
- */
-uint64_t monotime_coarse_stamp_units_to_approx_msec(uint64_t units);
-uint64_t monotime_msec_to_approx_coarse_stamp_units(uint64_t msec);
-uint32_t monotime_coarse_get_stamp(void);
-
-#if defined(MONOTIME_COARSE_TYPE_IS_DIFFERENT)
-int64_t monotime_coarse_diff_nsec(const monotime_coarse_t *start,
- const monotime_coarse_t *end);
-int64_t monotime_coarse_diff_usec(const monotime_coarse_t *start,
- const monotime_coarse_t *end);
-int64_t monotime_coarse_diff_msec(const monotime_coarse_t *start,
- const monotime_coarse_t *end);
-void monotime_coarse_zero(monotime_coarse_t *out);
-int monotime_coarse_is_zero(const monotime_coarse_t *val);
-void monotime_coarse_add_msec(monotime_coarse_t *out,
- const monotime_coarse_t *val, uint32_t msec);
-#else /* !(defined(MONOTIME_COARSE_TYPE_IS_DIFFERENT)) */
-#define monotime_coarse_diff_nsec monotime_diff_nsec
-#define monotime_coarse_diff_usec monotime_diff_usec
-#define monotime_coarse_diff_msec monotime_diff_msec
-#define monotime_coarse_zero monotime_zero
-#define monotime_coarse_is_zero monotime_is_zero
-#define monotime_coarse_add_msec monotime_add_msec
-#endif /* defined(MONOTIME_COARSE_TYPE_IS_DIFFERENT) */
-
-/**
- * As monotime_coarse_diff_msec, but avoid 64-bit division.
- *
- * Requires that the difference fit into an int32_t; not for use with
- * large time differences.
- */
-int32_t monotime_coarse_diff_msec32_(const monotime_coarse_t *start,
- const monotime_coarse_t *end);
-
-/**
- * As monotime_coarse_diff_msec, but avoid 64-bit division if it is expensive.
- *
- * Requires that the difference fit into an int32_t; not for use with
- * large time differences.
- */
-static inline int32_t
-monotime_coarse_diff_msec32(const monotime_coarse_t *start,
- const monotime_coarse_t *end)
-{
-#if SIZEOF_VOID_P == 8
- // on a 64-bit platform, let's assume 64/64 division is cheap.
- return (int32_t) monotime_coarse_diff_msec(start, end);
-#else
-#define USING_32BIT_MSEC_HACK
- return monotime_coarse_diff_msec32_(start, end);
-#endif
-}
-
-MOCK_DECL(void, tor_gettimeofday, (struct timeval *timeval));
-
-#ifdef TOR_UNIT_TESTS
-void tor_sleep_msec(int msec);
-
-void monotime_enable_test_mocking(void);
-void monotime_disable_test_mocking(void);
-void monotime_set_mock_time_nsec(int64_t);
-#if defined(MONOTIME_COARSE_FN_IS_DIFFERENT)
-void monotime_coarse_set_mock_time_nsec(int64_t);
-#else
-#define monotime_coarse_set_mock_time_nsec monotime_set_mock_time_nsec
-#endif
-#endif /* defined(TOR_UNIT_TESTS) */
-
-#ifdef COMPAT_TIME_PRIVATE
-#if defined(_WIN32) || defined(TOR_UNIT_TESTS)
-STATIC int64_t ratchet_performance_counter(int64_t count_raw);
-STATIC int64_t ratchet_coarse_performance_counter(int64_t count_raw);
-#endif
-#if defined(MONOTIME_USING_GETTIMEOFDAY) || defined(TOR_UNIT_TESTS)
-STATIC void ratchet_timeval(const struct timeval *timeval_raw,
- struct timeval *out);
-#endif
-#ifdef TOR_UNIT_TESTS
-void monotime_reset_ratchets_for_testing(void);
-#endif
-#endif /* defined(COMPAT_TIME_PRIVATE) */
-
-#endif /* !defined(TOR_COMPAT_TIME_H) */
-
diff --git a/src/common/compat_winthreads.c b/src/common/compat_winthreads.c
deleted file mode 100644
index 7021344f6e..0000000000
--- a/src/common/compat_winthreads.c
+++ /dev/null
@@ -1,251 +0,0 @@
-/* Copyright (c) 2003-2004, Roger Dingledine
- * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2017, The Tor Project, Inc. */
-/* See LICENSE for licensing information */
-
-/**
- * \file compat_winthreads.c
- *
- * \brief Implementation for the windows-based multithreading backend
- * functions.
- */
-
-#ifdef _WIN32
-
-#include "compat.h"
-#include <windows.h>
-#include <process.h>
-#include "util.h"
-#include "container.h"
-#include "torlog.h"
-
-/* This value is more or less total cargo-cult */
-#define SPIN_COUNT 2000
-
-/** Minimalist interface to run a void function in the background. On
- * Unix calls fork, on win32 calls beginthread. Returns -1 on failure.
- * func should not return, but rather should call spawn_exit.
- *
- * NOTE: if <b>data</b> is used, it should not be allocated on the stack,
- * since in a multithreaded environment, there is no way to be sure that
- * the caller's stack will still be around when the called function is
- * running.
- */
-int
-spawn_func(void (*func)(void *), void *data)
-{
- int rv;
- rv = (int)_beginthread(func, 0, data);
- if (rv == (int)-1)
- return -1;
- return 0;
-}
-
-/** End the current thread/process.
- */
-void
-spawn_exit(void)
-{
- _endthread();
- // LCOV_EXCL_START
- //we should never get here. my compiler thinks that _endthread returns, this
- //is an attempt to fool it.
- tor_assert(0);
- _exit(0); // exit ok: unreachable.
- // LCOV_EXCL_STOP
-}
-
-void
-tor_mutex_init(tor_mutex_t *m)
-{
- InitializeCriticalSection(&m->mutex);
-}
-void
-tor_mutex_init_nonrecursive(tor_mutex_t *m)
-{
- InitializeCriticalSection(&m->mutex);
-}
-
-void
-tor_mutex_uninit(tor_mutex_t *m)
-{
- DeleteCriticalSection(&m->mutex);
-}
-void
-tor_mutex_acquire(tor_mutex_t *m)
-{
- tor_assert(m);
- EnterCriticalSection(&m->mutex);
-}
-void
-tor_mutex_release(tor_mutex_t *m)
-{
- LeaveCriticalSection(&m->mutex);
-}
-unsigned long
-tor_get_thread_id(void)
-{
- return (unsigned long)GetCurrentThreadId();
-}
-
-int
-tor_cond_init(tor_cond_t *cond)
-{
- memset(cond, 0, sizeof(tor_cond_t));
- if (InitializeCriticalSectionAndSpinCount(&cond->lock, SPIN_COUNT)==0) {
- return -1;
- }
- if ((cond->event = CreateEvent(NULL,TRUE,FALSE,NULL)) == NULL) {
- DeleteCriticalSection(&cond->lock);
- return -1;
- }
- cond->n_waiting = cond->n_to_wake = cond->generation = 0;
- return 0;
-}
-void
-tor_cond_uninit(tor_cond_t *cond)
-{
- DeleteCriticalSection(&cond->lock);
- CloseHandle(cond->event);
-}
-
-static void
-tor_cond_signal_impl(tor_cond_t *cond, int broadcast)
-{
- EnterCriticalSection(&cond->lock);
- if (broadcast)
- cond->n_to_wake = cond->n_waiting;
- else
- ++cond->n_to_wake;
- cond->generation++;
- SetEvent(cond->event);
- LeaveCriticalSection(&cond->lock);
-}
-void
-tor_cond_signal_one(tor_cond_t *cond)
-{
- tor_cond_signal_impl(cond, 0);
-}
-void
-tor_cond_signal_all(tor_cond_t *cond)
-{
- tor_cond_signal_impl(cond, 1);
-}
-
-int
-tor_threadlocal_init(tor_threadlocal_t *threadlocal)
-{
- threadlocal->index = TlsAlloc();
- return (threadlocal->index == TLS_OUT_OF_INDEXES) ? -1 : 0;
-}
-
-void
-tor_threadlocal_destroy(tor_threadlocal_t *threadlocal)
-{
- TlsFree(threadlocal->index);
- memset(threadlocal, 0, sizeof(tor_threadlocal_t));
-}
-
-void *
-tor_threadlocal_get(tor_threadlocal_t *threadlocal)
-{
- void *value = TlsGetValue(threadlocal->index);
- if (value == NULL) {
- DWORD err = GetLastError();
- if (err != ERROR_SUCCESS) {
- char *msg = format_win32_error(err);
- log_err(LD_GENERAL, "Error retrieving thread-local value: %s", msg);
- tor_free(msg);
- tor_assert(err == ERROR_SUCCESS);
- }
- }
- return value;
-}
-
-void
-tor_threadlocal_set(tor_threadlocal_t *threadlocal, void *value)
-{
- BOOL ok = TlsSetValue(threadlocal->index, value);
- if (!ok) {
- DWORD err = GetLastError();
- char *msg = format_win32_error(err);
- log_err(LD_GENERAL, "Error adjusting thread-local value: %s", msg);
- tor_free(msg);
- tor_assert(ok);
- }
-}
-
-int
-tor_cond_wait(tor_cond_t *cond, tor_mutex_t *lock_, const struct timeval *tv)
-{
- CRITICAL_SECTION *lock = &lock_->mutex;
- int generation_at_start;
- int waiting = 1;
- int result = -1;
- DWORD ms = INFINITE, ms_orig = INFINITE, startTime, endTime;
- if (tv)
- ms_orig = ms = tv->tv_sec*1000 + (tv->tv_usec+999)/1000;
-
- EnterCriticalSection(&cond->lock);
- ++cond->n_waiting;
- generation_at_start = cond->generation;
- LeaveCriticalSection(&cond->lock);
-
- LeaveCriticalSection(lock);
-
- startTime = GetTickCount();
- do {
- DWORD res;
- res = WaitForSingleObject(cond->event, ms);
- EnterCriticalSection(&cond->lock);
- if (cond->n_to_wake &&
- cond->generation != generation_at_start) {
- --cond->n_to_wake;
- --cond->n_waiting;
- result = 0;
- waiting = 0;
- goto out;
- } else if (res != WAIT_OBJECT_0) {
- result = (res==WAIT_TIMEOUT) ? 1 : -1;
- --cond->n_waiting;
- waiting = 0;
- goto out;
- } else if (ms != INFINITE) {
- endTime = GetTickCount();
- if (startTime + ms_orig <= endTime) {
- result = 1; /* Timeout */
- --cond->n_waiting;
- waiting = 0;
- goto out;
- } else {
- ms = startTime + ms_orig - endTime;
- }
- }
- /* If we make it here, we are still waiting. */
- if (cond->n_to_wake == 0) {
- /* There is nobody else who should wake up; reset
- * the event. */
- ResetEvent(cond->event);
- }
- out:
- LeaveCriticalSection(&cond->lock);
- } while (waiting);
-
- EnterCriticalSection(lock);
-
- EnterCriticalSection(&cond->lock);
- if (!cond->n_waiting)
- ResetEvent(cond->event);
- LeaveCriticalSection(&cond->lock);
-
- return result;
-}
-
-void
-tor_threads_init(void)
-{
- set_main_thread();
-}
-
-#endif /* defined(_WIN32) */
-
diff --git a/src/common/compress.c b/src/common/compress.c
deleted file mode 100644
index cb1549f1aa..0000000000
--- a/src/common/compress.c
+++ /dev/null
@@ -1,675 +0,0 @@
-/* Copyright (c) 2004, Roger Dingledine.
- * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2017, The Tor Project, Inc. */
-/* See LICENSE for licensing information */
-
-/**
- * \file compress.c
- * \brief Common compression API.
- **/
-
-#include "orconfig.h"
-
-#include <stdlib.h>
-#include <stdio.h>
-#include <assert.h>
-#include <string.h>
-#include "torint.h"
-
-#ifdef HAVE_NETINET_IN_H
-#include <netinet/in.h>
-#endif
-
-#include "util.h"
-#include "torlog.h"
-#include "compress.h"
-#include "compress_lzma.h"
-#include "compress_none.h"
-#include "compress_zlib.h"
-#include "compress_zstd.h"
-
-/** Total number of bytes allocated for compression state overhead. */
-static atomic_counter_t total_compress_allocation;
-
-/** @{ */
-/* These macros define the maximum allowable compression factor. Anything of
- * size greater than CHECK_FOR_COMPRESSION_BOMB_AFTER is not allowed to
- * have an uncompression factor (uncompressed size:compressed size ratio) of
- * any greater than MAX_UNCOMPRESSION_FACTOR.
- *
- * Picking a value for MAX_UNCOMPRESSION_FACTOR is a trade-off: we want it to
- * be small to limit the attack multiplier, but we also want it to be large
- * enough so that no legitimate document --even ones we might invent in the
- * future -- ever compresses by a factor of greater than
- * MAX_UNCOMPRESSION_FACTOR. Within those parameters, there's a reasonably
- * large range of possible values. IMO, anything over 8 is probably safe; IMO
- * anything under 50 is probably sufficient.
- */
-#define MAX_UNCOMPRESSION_FACTOR 25
-#define CHECK_FOR_COMPRESSION_BOMB_AFTER (1024*64)
-/** @} */
-
-/** Return true if uncompressing an input of size <b>in_size</b> to an input of
- * size at least <b>size_out</b> looks like a compression bomb. */
-MOCK_IMPL(int,
-tor_compress_is_compression_bomb,(size_t size_in, size_t size_out))
-{
- if (size_in == 0 || size_out < CHECK_FOR_COMPRESSION_BOMB_AFTER)
- return 0;
-
- return (size_out / size_in > MAX_UNCOMPRESSION_FACTOR);
-}
-
-/** Guess the size that <b>in_len</b> will be after compression or
- * decompression. */
-static size_t
-guess_compress_size(int compress, compress_method_t method,
- compression_level_t compression_level,
- size_t in_len)
-{
- // ignore these for now.
- (void)compression_level;
- if (method == NO_METHOD) {
- /* Guess that we'll need an extra byte, to avoid a needless realloc
- * for nul-termination */
- return (in_len < SIZE_MAX) ? in_len + 1 : in_len;
- }
-
- /* Always guess a factor of 2. */
- if (compress) {
- in_len /= 2;
- } else {
- if (in_len < SIZE_T_CEILING/2)
- in_len *= 2;
- }
- return MAX(in_len, 1024);
-}
-
-/** Internal function to implement tor_compress/tor_uncompress, depending on
- * whether <b>compress</b> is set. All arguments are as for tor_compress or
- * tor_uncompress. */
-static int
-tor_compress_impl(int compress,
- char **out, size_t *out_len,
- const char *in, size_t in_len,
- compress_method_t method,
- compression_level_t compression_level,
- int complete_only,
- int protocol_warn_level)
-{
- tor_compress_state_t *stream;
- int rv;
-
- stream = tor_compress_new(compress, method, compression_level);
-
- if (stream == NULL) {
- log_warn(LD_GENERAL, "NULL stream while %scompressing",
- compress?"":"de");
- log_debug(LD_GENERAL, "method: %d level: %d at len: %lu",
- method, compression_level, (unsigned long)in_len);
- return -1;
- }
-
- size_t in_len_orig = in_len;
- size_t out_remaining, out_alloc;
- char *outptr;
-
- out_remaining = out_alloc =
- guess_compress_size(compress, method, compression_level, in_len);
- *out = outptr = tor_malloc(out_remaining);
-
- const int finish = complete_only || compress;
-
- while (1) {
- switch (tor_compress_process(stream,
- &outptr, &out_remaining,
- &in, &in_len, finish)) {
- case TOR_COMPRESS_DONE:
- if (in_len == 0 || compress) {
- goto done;
- } else {
- // More data is present, and we're decompressing. So we may need to
- // reinitialize the stream if we are handling multiple concatenated
- // inputs.
- tor_compress_free(stream);
- stream = tor_compress_new(compress, method, compression_level);
- if (stream == NULL) {
- log_warn(LD_GENERAL, "NULL stream while %scompressing",
- compress?"":"de");
- goto err;
- }
- }
- break;
- case TOR_COMPRESS_OK:
- if (compress || complete_only) {
- log_fn(protocol_warn_level, LD_PROTOCOL,
- "Unexpected %s while %scompressing",
- complete_only?"end of input":"result",
- compress?"":"de");
- log_debug(LD_GENERAL, "method: %d level: %d at len: %lu",
- method, compression_level, (unsigned long)in_len);
- goto err;
- } else {
- if (in_len == 0) {
- goto done;
- }
- }
- break;
- case TOR_COMPRESS_BUFFER_FULL: {
- if (!compress && outptr < *out+out_alloc) {
- // A buffer error in this case means that we have a problem
- // with our input.
- log_fn(protocol_warn_level, LD_PROTOCOL,
- "Possible truncated or corrupt compressed data");
- goto err;
- }
- if (out_alloc >= SIZE_T_CEILING / 2) {
- log_warn(LD_GENERAL, "While %scompressing data: ran out of space.",
- compress?"":"un");
- goto err;
- }
- if (!compress &&
- tor_compress_is_compression_bomb(in_len_orig, out_alloc)) {
- // This should already have been caught down in the backend logic.
- // LCOV_EXCL_START
- tor_assert_nonfatal_unreached();
- goto err;
- // LCOV_EXCL_STOP
- }
- const size_t offset = outptr - *out;
- out_alloc *= 2;
- *out = tor_realloc(*out, out_alloc);
- outptr = *out + offset;
- out_remaining = out_alloc - offset;
- break;
- }
- case TOR_COMPRESS_ERROR:
- log_fn(protocol_warn_level, LD_GENERAL,
- "Error while %scompressing data: bad input?",
- compress?"":"un");
- goto err; // bad data.
-
- // LCOV_EXCL_START
- default:
- tor_assert_nonfatal_unreached();
- goto err;
- // LCOV_EXCL_STOP
- }
- }
- done:
- *out_len = outptr - *out;
- if (compress && tor_compress_is_compression_bomb(*out_len, in_len_orig)) {
- log_warn(LD_BUG, "We compressed something and got an insanely high "
- "compression factor; other Tors would think this was a "
- "compression bomb.");
- goto err;
- }
- if (!compress) {
- // NUL-terminate our output.
- if (out_alloc == *out_len)
- *out = tor_realloc(*out, out_alloc + 1);
- (*out)[*out_len] = '\0';
- }
- rv = 0;
- goto out;
-
- err:
- tor_free(*out);
- *out_len = 0;
- rv = -1;
- goto out;
-
- out:
- tor_compress_free(stream);
- return rv;
-}
-
-/** Given <b>in_len</b> bytes at <b>in</b>, compress them into a newly
- * allocated buffer, using the method described in <b>method</b>. Store the
- * compressed string in *<b>out</b>, and its length in *<b>out_len</b>.
- * Return 0 on success, -1 on failure.
- */
-int
-tor_compress(char **out, size_t *out_len,
- const char *in, size_t in_len,
- compress_method_t method)
-{
- return tor_compress_impl(1, out, out_len, in, in_len, method,
- BEST_COMPRESSION,
- 1, LOG_WARN);
-}
-
-/** Given zero or more compressed strings of total length <b>in_len</b> bytes
- * at <b>in</b>, uncompress them into a newly allocated buffer, using the
- * method described in <b>method</b>. Store the uncompressed string in
- * *<b>out</b>, and its length in *<b>out_len</b>. Return 0 on success, -1 on
- * failure.
- *
- * If any bytes are written to <b>out</b>, an extra byte NUL is always
- * written at the end, but not counted in <b>out_len</b>. This is a
- * safety feature to ensure that the output can be treated as a
- * NUL-terminated string -- though of course, callers should check
- * out_len anyway.
- *
- * If <b>complete_only</b> is true, we consider a truncated input as a
- * failure; otherwise we decompress as much as we can. Warn about truncated
- * or corrupt inputs at <b>protocol_warn_level</b>.
- */
-int
-tor_uncompress(char **out, size_t *out_len,
- const char *in, size_t in_len,
- compress_method_t method,
- int complete_only,
- int protocol_warn_level)
-{
- return tor_compress_impl(0, out, out_len, in, in_len, method,
- BEST_COMPRESSION,
- complete_only, protocol_warn_level);
-}
-
-/** Try to tell whether the <b>in_len</b>-byte string in <b>in</b> is likely
- * to be compressed or not. If it is, return the likeliest compression method.
- * Otherwise, return UNKNOWN_METHOD.
- */
-compress_method_t
-detect_compression_method(const char *in, size_t in_len)
-{
- if (in_len > 2 && fast_memeq(in, "\x1f\x8b", 2)) {
- return GZIP_METHOD;
- } else if (in_len > 2 && (in[0] & 0x0f) == 8 &&
- (ntohs(get_uint16(in)) % 31) == 0) {
- return ZLIB_METHOD;
- } else if (in_len > 2 &&
- fast_memeq(in, "\x5d\x00\x00", 3)) {
- return LZMA_METHOD;
- } else if (in_len > 3 &&
- fast_memeq(in, "\x28\xb5\x2f\xfd", 4)) {
- return ZSTD_METHOD;
- } else {
- return UNKNOWN_METHOD;
- }
-}
-
-/** Return 1 if a given <b>method</b> is supported; otherwise 0. */
-int
-tor_compress_supports_method(compress_method_t method)
-{
- switch (method) {
- case GZIP_METHOD:
- case ZLIB_METHOD:
- return tor_zlib_method_supported();
- case LZMA_METHOD:
- return tor_lzma_method_supported();
- case ZSTD_METHOD:
- return tor_zstd_method_supported();
- case NO_METHOD:
- return 1;
- case UNKNOWN_METHOD:
- default:
- return 0;
- }
-}
-
-/**
- * Return a bitmask of the supported compression types, where 1&lt;&lt;m is
- * set in the bitmask if and only if compression with method <b>m</b> is
- * supported.
- */
-unsigned
-tor_compress_get_supported_method_bitmask(void)
-{
- static unsigned supported = 0;
- if (supported == 0) {
- compress_method_t m;
- for (m = NO_METHOD; m <= UNKNOWN_METHOD; ++m) {
- if (tor_compress_supports_method(m)) {
- supported |= (1u << m);
- }
- }
- }
- return supported;
-}
-
-/** Table of compression method names. These should have an "x-" prefix,
- * if they are not listed in the IANA content coding registry. */
-static const struct {
- const char *name;
- compress_method_t method;
-} compression_method_names[] = {
- { "gzip", GZIP_METHOD },
- { "deflate", ZLIB_METHOD },
- // We call this "x-tor-lzma" rather than "x-lzma", because we impose a
- // lower maximum memory usage on the decoding side.
- { "x-tor-lzma", LZMA_METHOD },
- { "x-zstd" , ZSTD_METHOD },
- { "identity", NO_METHOD },
-
- /* Later entries in this table are not canonical; these are recognized but
- * not emitted. */
- { "x-gzip", GZIP_METHOD },
-};
-
-/** Return the canonical string representation of the compression method
- * <b>method</b>, or NULL if the method isn't recognized. */
-const char *
-compression_method_get_name(compress_method_t method)
-{
- unsigned i;
- for (i = 0; i < ARRAY_LENGTH(compression_method_names); ++i) {
- if (method == compression_method_names[i].method)
- return compression_method_names[i].name;
- }
- return NULL;
-}
-
-/** Table of compression human readable method names. */
-static const struct {
- compress_method_t method;
- const char *name;
-} compression_method_human_names[] = {
- { NO_METHOD, "uncompressed" },
- { GZIP_METHOD, "gzipped" },
- { ZLIB_METHOD, "deflated" },
- { LZMA_METHOD, "LZMA compressed" },
- { ZSTD_METHOD, "Zstandard compressed" },
- { UNKNOWN_METHOD, "unknown encoding" },
-};
-
-/** Return a human readable string representation of the compression method
- * <b>method</b>, or NULL if the method isn't recognized. */
-const char *
-compression_method_get_human_name(compress_method_t method)
-{
- unsigned i;
- for (i = 0; i < ARRAY_LENGTH(compression_method_human_names); ++i) {
- if (method == compression_method_human_names[i].method)
- return compression_method_human_names[i].name;
- }
- return NULL;
-}
-
-/** Return the compression method represented by the string <b>name</b>, or
- * UNKNOWN_METHOD if the string isn't recognized. */
-compress_method_t
-compression_method_get_by_name(const char *name)
-{
- unsigned i;
- for (i = 0; i < ARRAY_LENGTH(compression_method_names); ++i) {
- if (!strcmp(compression_method_names[i].name, name))
- return compression_method_names[i].method;
- }
- return UNKNOWN_METHOD;
-}
-
-/** Return a string representation of the version of the library providing the
- * compression method given in <b>method</b>. Returns NULL if <b>method</b> is
- * unknown or unsupported. */
-const char *
-tor_compress_version_str(compress_method_t method)
-{
- switch (method) {
- case GZIP_METHOD:
- case ZLIB_METHOD:
- return tor_zlib_get_version_str();
- case LZMA_METHOD:
- return tor_lzma_get_version_str();
- case ZSTD_METHOD:
- return tor_zstd_get_version_str();
- case NO_METHOD:
- case UNKNOWN_METHOD:
- default:
- return NULL;
- }
-}
-
-/** Return a string representation of the version of the library, found at
- * compile time, providing the compression method given in <b>method</b>.
- * Returns NULL if <b>method</b> is unknown or unsupported. */
-const char *
-tor_compress_header_version_str(compress_method_t method)
-{
- switch (method) {
- case GZIP_METHOD:
- case ZLIB_METHOD:
- return tor_zlib_get_header_version_str();
- case LZMA_METHOD:
- return tor_lzma_get_header_version_str();
- case ZSTD_METHOD:
- return tor_zstd_get_header_version_str();
- case NO_METHOD:
- case UNKNOWN_METHOD:
- default:
- return NULL;
- }
-}
-
-/** Return the approximate number of bytes allocated for all
- * supported compression schemas. */
-size_t
-tor_compress_get_total_allocation(void)
-{
- return atomic_counter_get(&total_compress_allocation) +
- tor_zlib_get_total_allocation() +
- tor_lzma_get_total_allocation() +
- tor_zstd_get_total_allocation();
-}
-
-/** Internal state for an incremental compression/decompression. The body of
- * this struct is not exposed. */
-struct tor_compress_state_t {
- compress_method_t method; /**< The compression method. */
-
- union {
- tor_zlib_compress_state_t *zlib_state;
- tor_lzma_compress_state_t *lzma_state;
- tor_zstd_compress_state_t *zstd_state;
- } u; /**< Compression backend state. */
-};
-
-/** Construct and return a tor_compress_state_t object using <b>method</b>. If
- * <b>compress</b>, it's for compression; otherwise it's for decompression. */
-tor_compress_state_t *
-tor_compress_new(int compress, compress_method_t method,
- compression_level_t compression_level)
-{
- tor_compress_state_t *state;
-
- state = tor_malloc_zero(sizeof(tor_compress_state_t));
- state->method = method;
-
- switch (method) {
- case GZIP_METHOD:
- case ZLIB_METHOD: {
- tor_zlib_compress_state_t *zlib_state =
- tor_zlib_compress_new(compress, method, compression_level);
-
- if (zlib_state == NULL)
- goto err;
-
- state->u.zlib_state = zlib_state;
- break;
- }
- case LZMA_METHOD: {
- tor_lzma_compress_state_t *lzma_state =
- tor_lzma_compress_new(compress, method, compression_level);
-
- if (lzma_state == NULL)
- goto err;
-
- state->u.lzma_state = lzma_state;
- break;
- }
- case ZSTD_METHOD: {
- tor_zstd_compress_state_t *zstd_state =
- tor_zstd_compress_new(compress, method, compression_level);
-
- if (zstd_state == NULL)
- goto err;
-
- state->u.zstd_state = zstd_state;
- break;
- }
- case NO_METHOD: {
- break;
- }
- case UNKNOWN_METHOD:
- goto err;
- }
-
- atomic_counter_add(&total_compress_allocation,
- sizeof(tor_compress_state_t));
- return state;
-
- err:
- tor_free(state);
- return NULL;
-}
-
-/** Compress/decompress some bytes using <b>state</b>. Read up to
- * *<b>in_len</b> bytes from *<b>in</b>, and write up to *<b>out_len</b> bytes
- * to *<b>out</b>, adjusting the values as we go. If <b>finish</b> is true,
- * we've reached the end of the input.
- *
- * Return TOR_COMPRESS_DONE if we've finished the entire
- * compression/decompression.
- * Return TOR_COMPRESS_OK if we're processed everything from the input.
- * Return TOR_COMPRESS_BUFFER_FULL if we're out of space on <b>out</b>.
- * Return TOR_COMPRESS_ERROR if the stream is corrupt.
- */
-tor_compress_output_t
-tor_compress_process(tor_compress_state_t *state,
- char **out, size_t *out_len,
- const char **in, size_t *in_len,
- int finish)
-{
- tor_assert(state != NULL);
- const size_t in_len_orig = *in_len;
- const size_t out_len_orig = *out_len;
- tor_compress_output_t rv;
-
- if (*out_len == 0 && (*in_len > 0 || finish)) {
- // If we still have input data, but no space for output data, we might as
- // well return early and let the caller do the reallocation of the out
- // variable.
- return TOR_COMPRESS_BUFFER_FULL;
- }
-
- switch (state->method) {
- case GZIP_METHOD:
- case ZLIB_METHOD:
- rv = tor_zlib_compress_process(state->u.zlib_state,
- out, out_len, in, in_len,
- finish);
- break;
- case LZMA_METHOD:
- rv = tor_lzma_compress_process(state->u.lzma_state,
- out, out_len, in, in_len,
- finish);
- break;
- case ZSTD_METHOD:
- rv = tor_zstd_compress_process(state->u.zstd_state,
- out, out_len, in, in_len,
- finish);
- break;
- case NO_METHOD:
- rv = tor_cnone_compress_process(out, out_len, in, in_len,
- finish);
- break;
- default:
- case UNKNOWN_METHOD:
- goto err;
- }
- if (BUG((rv == TOR_COMPRESS_OK) &&
- *in_len == in_len_orig &&
- *out_len == out_len_orig)) {
- log_warn(LD_GENERAL,
- "More info on the bug: method == %s, finish == %d, "
- " *in_len == in_len_orig == %lu, "
- "*out_len == out_len_orig == %lu",
- compression_method_get_human_name(state->method), finish,
- (unsigned long)in_len_orig, (unsigned long)out_len_orig);
- return TOR_COMPRESS_ERROR;
- }
-
- return rv;
- err:
- return TOR_COMPRESS_ERROR;
-}
-
-/** Deallocate <b>state</b>. */
-void
-tor_compress_free_(tor_compress_state_t *state)
-{
- if (state == NULL)
- return;
-
- switch (state->method) {
- case GZIP_METHOD:
- case ZLIB_METHOD:
- tor_zlib_compress_free(state->u.zlib_state);
- break;
- case LZMA_METHOD:
- tor_lzma_compress_free(state->u.lzma_state);
- break;
- case ZSTD_METHOD:
- tor_zstd_compress_free(state->u.zstd_state);
- break;
- case NO_METHOD:
- break;
- case UNKNOWN_METHOD:
- break;
- }
-
- atomic_counter_sub(&total_compress_allocation,
- sizeof(tor_compress_state_t));
- tor_free(state);
-}
-
-/** Return the approximate number of bytes allocated for <b>state</b>. */
-size_t
-tor_compress_state_size(const tor_compress_state_t *state)
-{
- tor_assert(state != NULL);
-
- size_t size = sizeof(tor_compress_state_t);
-
- switch (state->method) {
- case GZIP_METHOD:
- case ZLIB_METHOD:
- size += tor_zlib_compress_state_size(state->u.zlib_state);
- break;
- case LZMA_METHOD:
- size += tor_lzma_compress_state_size(state->u.lzma_state);
- break;
- case ZSTD_METHOD:
- size += tor_zstd_compress_state_size(state->u.zstd_state);
- break;
- case NO_METHOD:
- case UNKNOWN_METHOD:
- break;
- }
-
- return size;
-}
-
-/** Initialize all compression modules. */
-void
-tor_compress_init(void)
-{
- atomic_counter_init(&total_compress_allocation);
-
- tor_zlib_init();
- tor_lzma_init();
- tor_zstd_init();
-}
-
-/** Warn if we had any problems while setting up our compression libraries.
- *
- * (This isn't part of tor_compress_init, since the logs aren't set up yet.)
- */
-void
-tor_compress_log_init_warnings(void)
-{
- tor_zstd_warn_if_version_mismatched();
-}
-
diff --git a/src/common/compress.h b/src/common/compress.h
deleted file mode 100644
index 65d63a4386..0000000000
--- a/src/common/compress.h
+++ /dev/null
@@ -1,93 +0,0 @@
-/* Copyright (c) 2003, Roger Dingledine
- * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2017, The Tor Project, Inc. */
-/* See LICENSE for licensing information */
-
-/**
- * \file compress.h
- * \brief Headers for compress.c
- **/
-
-#ifndef TOR_COMPRESS_H
-#define TOR_COMPRESS_H
-
-/** Enumeration of what kind of compression to use. Only ZLIB_METHOD and
- * GZIP_METHOD is guaranteed to be supported by the compress/uncompress
- * functions here. Call tor_compress_supports_method() to check if a given
- * compression schema is supported by Tor. */
-typedef enum {
- NO_METHOD=0, // This method must be first.
- GZIP_METHOD=1,
- ZLIB_METHOD=2,
- LZMA_METHOD=3,
- ZSTD_METHOD=4,
- UNKNOWN_METHOD=5, // This method must be last. Add new ones in the middle.
-} compress_method_t;
-
-/**
- * Enumeration to define tradeoffs between memory usage and compression level.
- * BEST_COMPRESSION saves the most bandwidth; LOW_COMPRESSION saves the most
- * memory.
- **/
-typedef enum {
- BEST_COMPRESSION, HIGH_COMPRESSION, MEDIUM_COMPRESSION, LOW_COMPRESSION
-} compression_level_t;
-
-int tor_compress(char **out, size_t *out_len,
- const char *in, size_t in_len,
- compress_method_t method);
-
-int tor_uncompress(char **out, size_t *out_len,
- const char *in, size_t in_len,
- compress_method_t method,
- int complete_only,
- int protocol_warn_level);
-
-compress_method_t detect_compression_method(const char *in, size_t in_len);
-
-MOCK_DECL(int,tor_compress_is_compression_bomb,(size_t size_in,
- size_t size_out));
-
-int tor_compress_supports_method(compress_method_t method);
-unsigned tor_compress_get_supported_method_bitmask(void);
-const char *compression_method_get_name(compress_method_t method);
-const char *compression_method_get_human_name(compress_method_t method);
-compress_method_t compression_method_get_by_name(const char *name);
-
-const char *tor_compress_version_str(compress_method_t method);
-
-const char *tor_compress_header_version_str(compress_method_t method);
-
-size_t tor_compress_get_total_allocation(void);
-
-/** Return values from tor_compress_process; see that function's documentation
- * for details. */
-typedef enum {
- TOR_COMPRESS_OK,
- TOR_COMPRESS_DONE,
- TOR_COMPRESS_BUFFER_FULL,
- TOR_COMPRESS_ERROR
-} tor_compress_output_t;
-
-/** Internal state for an incremental compression/decompression. */
-typedef struct tor_compress_state_t tor_compress_state_t;
-
-tor_compress_state_t *tor_compress_new(int compress,
- compress_method_t method,
- compression_level_t level);
-
-tor_compress_output_t tor_compress_process(tor_compress_state_t *state,
- char **out, size_t *out_len,
- const char **in, size_t *in_len,
- int finish);
-void tor_compress_free_(tor_compress_state_t *state);
-#define tor_compress_free(st) \
- FREE_AND_NULL(tor_compress_state_t, tor_compress_free_, (st))
-
-size_t tor_compress_state_size(const tor_compress_state_t *state);
-
-void tor_compress_init(void);
-void tor_compress_log_init_warnings(void);
-
-#endif /* !defined(TOR_COMPRESS_H) */
-
diff --git a/src/common/compress_lzma.c b/src/common/compress_lzma.c
deleted file mode 100644
index 051c59ba2d..0000000000
--- a/src/common/compress_lzma.c
+++ /dev/null
@@ -1,361 +0,0 @@
-/* Copyright (c) 2004, Roger Dingledine.
- * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2017, The Tor Project, Inc. */
-/* See LICENSE for licensing information */
-
-/**
- * \file compress_lzma.c
- * \brief Compression backend for LZMA.
- *
- * This module should never be invoked directly. Use the compress module
- * instead.
- **/
-
-#include "orconfig.h"
-
-#include "util.h"
-#include "torlog.h"
-#include "compress.h"
-#include "compress_lzma.h"
-
-#ifdef HAVE_LZMA
-#include <lzma.h>
-#endif
-
-/** The maximum amount of memory we allow the LZMA decoder to use, in bytes. */
-#define MEMORY_LIMIT (16 * 1024 * 1024)
-
-/** Total number of bytes allocated for LZMA state. */
-static atomic_counter_t total_lzma_allocation;
-
-#ifdef HAVE_LZMA
-/** Given <b>level</b> return the memory level. */
-static int
-memory_level(compression_level_t level)
-{
- switch (level) {
- default:
- case BEST_COMPRESSION:
- case HIGH_COMPRESSION: return 6;
- case MEDIUM_COMPRESSION: return 4;
- case LOW_COMPRESSION: return 2;
- }
-}
-
-/** Convert a given <b>error</b> to a human readable error string. */
-static const char *
-lzma_error_str(lzma_ret error)
-{
- switch (error) {
- case LZMA_OK:
- return "Operation completed successfully";
- case LZMA_STREAM_END:
- return "End of stream";
- case LZMA_NO_CHECK:
- return "Input stream lacks integrity check";
- case LZMA_UNSUPPORTED_CHECK:
- return "Unable to calculate integrity check";
- case LZMA_GET_CHECK:
- return "Integrity check available";
- case LZMA_MEM_ERROR:
- return "Unable to allocate memory";
- case LZMA_MEMLIMIT_ERROR:
- return "Memory limit reached";
- case LZMA_FORMAT_ERROR:
- return "Unknown file format";
- case LZMA_OPTIONS_ERROR:
- return "Unsupported options";
- case LZMA_DATA_ERROR:
- return "Corrupt input data";
- case LZMA_BUF_ERROR:
- return "Unable to progress";
- case LZMA_PROG_ERROR:
- return "Programming error";
- default:
- return "Unknown LZMA error";
- }
-}
-#endif /* defined(HAVE_LZMA) */
-
-/** Return 1 if LZMA compression is supported; otherwise 0. */
-int
-tor_lzma_method_supported(void)
-{
-#ifdef HAVE_LZMA
- return 1;
-#else
- return 0;
-#endif
-}
-
-/** Return a string representation of the version of the currently running
- * version of liblzma. Returns NULL if LZMA is unsupported. */
-const char *
-tor_lzma_get_version_str(void)
-{
-#ifdef HAVE_LZMA
- return lzma_version_string();
-#else
- return NULL;
-#endif
-}
-
-/** Return a string representation of the version of liblzma used at
- * compilation time. Returns NULL if LZMA is unsupported. */
-const char *
-tor_lzma_get_header_version_str(void)
-{
-#ifdef HAVE_LZMA
- return LZMA_VERSION_STRING;
-#else
- return NULL;
-#endif
-}
-
-/** Internal LZMA state for incremental compression/decompression.
- * The body of this struct is not exposed. */
-struct tor_lzma_compress_state_t {
-#ifdef HAVE_LZMA
- lzma_stream stream; /**< The LZMA stream. */
-#endif
-
- int compress; /**< True if we are compressing; false if we are inflating */
-
- /** Number of bytes read so far. Used to detect compression bombs. */
- size_t input_so_far;
- /** Number of bytes written so far. Used to detect compression bombs. */
- size_t output_so_far;
-
- /** Approximate number of bytes allocated for this object. */
- size_t allocation;
-};
-
-#ifdef HAVE_LZMA
-/** Return an approximate number of bytes stored in memory to hold the LZMA
- * encoder/decoder state. */
-static size_t
-tor_lzma_state_size_precalc(int compress, compression_level_t level)
-{
- uint64_t memory_usage;
-
- if (compress)
- memory_usage = lzma_easy_encoder_memusage(memory_level(level));
- else
- memory_usage = lzma_easy_decoder_memusage(memory_level(level));
-
- if (memory_usage == UINT64_MAX) {
- // LCOV_EXCL_START
- log_warn(LD_GENERAL, "Unsupported compression level passed to LZMA %s",
- compress ? "encoder" : "decoder");
- goto err;
- // LCOV_EXCL_STOP
- }
-
- if (memory_usage + sizeof(tor_lzma_compress_state_t) > SIZE_MAX)
- memory_usage = SIZE_MAX;
- else
- memory_usage += sizeof(tor_lzma_compress_state_t);
-
- return (size_t)memory_usage;
-
- // LCOV_EXCL_START
- err:
- return 0;
- // LCOV_EXCL_STOP
-}
-#endif /* defined(HAVE_LZMA) */
-
-/** Construct and return a tor_lzma_compress_state_t object using
- * <b>method</b>. If <b>compress</b>, it's for compression; otherwise it's for
- * decompression. */
-tor_lzma_compress_state_t *
-tor_lzma_compress_new(int compress,
- compress_method_t method,
- compression_level_t level)
-{
- tor_assert(method == LZMA_METHOD);
-
-#ifdef HAVE_LZMA
- tor_lzma_compress_state_t *result;
- lzma_ret retval;
- lzma_options_lzma stream_options;
-
- // Note that we do not explicitly initialize the lzma_stream object here,
- // since the LZMA_STREAM_INIT "just" initializes all members to 0, which is
- // also what `tor_malloc_zero()` does.
- result = tor_malloc_zero(sizeof(tor_lzma_compress_state_t));
- result->compress = compress;
- result->allocation = tor_lzma_state_size_precalc(compress, level);
-
- if (compress) {
- lzma_lzma_preset(&stream_options, memory_level(level));
-
- retval = lzma_alone_encoder(&result->stream, &stream_options);
-
- if (retval != LZMA_OK) {
- // LCOV_EXCL_START
- log_warn(LD_GENERAL, "Error from LZMA encoder: %s (%u).",
- lzma_error_str(retval), retval);
- goto err;
- // LCOV_EXCL_STOP
- }
- } else {
- retval = lzma_alone_decoder(&result->stream, MEMORY_LIMIT);
-
- if (retval != LZMA_OK) {
- // LCOV_EXCL_START
- log_warn(LD_GENERAL, "Error from LZMA decoder: %s (%u).",
- lzma_error_str(retval), retval);
- goto err;
- // LCOV_EXCL_STOP
- }
- }
-
- atomic_counter_add(&total_lzma_allocation, result->allocation);
- return result;
-
- /* LCOV_EXCL_START */
- err:
- tor_free(result);
- return NULL;
- /* LCOV_EXCL_STOP */
-#else /* !(defined(HAVE_LZMA)) */
- (void)compress;
- (void)method;
- (void)level;
-
- return NULL;
-#endif /* defined(HAVE_LZMA) */
-}
-
-/** Compress/decompress some bytes using <b>state</b>. Read up to
- * *<b>in_len</b> bytes from *<b>in</b>, and write up to *<b>out_len</b> bytes
- * to *<b>out</b>, adjusting the values as we go. If <b>finish</b> is true,
- * we've reached the end of the input.
- *
- * Return TOR_COMPRESS_DONE if we've finished the entire
- * compression/decompression.
- * Return TOR_COMPRESS_OK if we're processed everything from the input.
- * Return TOR_COMPRESS_BUFFER_FULL if we're out of space on <b>out</b>.
- * Return TOR_COMPRESS_ERROR if the stream is corrupt.
- */
-tor_compress_output_t
-tor_lzma_compress_process(tor_lzma_compress_state_t *state,
- char **out, size_t *out_len,
- const char **in, size_t *in_len,
- int finish)
-{
-#ifdef HAVE_LZMA
- lzma_ret retval;
- lzma_action action;
-
- tor_assert(state != NULL);
- tor_assert(*in_len <= UINT_MAX);
- tor_assert(*out_len <= UINT_MAX);
-
- state->stream.next_in = (unsigned char *)*in;
- state->stream.avail_in = *in_len;
- state->stream.next_out = (unsigned char *)*out;
- state->stream.avail_out = *out_len;
-
- action = finish ? LZMA_FINISH : LZMA_RUN;
-
- retval = lzma_code(&state->stream, action);
-
- state->input_so_far += state->stream.next_in - ((unsigned char *)*in);
- state->output_so_far += state->stream.next_out - ((unsigned char *)*out);
-
- *out = (char *)state->stream.next_out;
- *out_len = state->stream.avail_out;
- *in = (const char *)state->stream.next_in;
- *in_len = state->stream.avail_in;
-
- if (! state->compress &&
- tor_compress_is_compression_bomb(state->input_so_far,
- state->output_so_far)) {
- log_warn(LD_DIR, "Possible compression bomb; abandoning stream.");
- return TOR_COMPRESS_ERROR;
- }
-
- switch (retval) {
- case LZMA_OK:
- if (state->stream.avail_out == 0 || finish)
- return TOR_COMPRESS_BUFFER_FULL;
-
- return TOR_COMPRESS_OK;
-
- case LZMA_BUF_ERROR:
- if (state->stream.avail_in == 0 && !finish)
- return TOR_COMPRESS_OK;
-
- return TOR_COMPRESS_BUFFER_FULL;
-
- case LZMA_STREAM_END:
- return TOR_COMPRESS_DONE;
-
- // We list all the possible values of `lzma_ret` here to silence the
- // `switch-enum` warning and to detect if a new member was added.
- case LZMA_NO_CHECK:
- case LZMA_UNSUPPORTED_CHECK:
- case LZMA_GET_CHECK:
- case LZMA_MEM_ERROR:
- case LZMA_MEMLIMIT_ERROR:
- case LZMA_FORMAT_ERROR:
- case LZMA_OPTIONS_ERROR:
- case LZMA_DATA_ERROR:
- case LZMA_PROG_ERROR:
- default:
- log_warn(LD_GENERAL, "LZMA %s didn't finish: %s.",
- state->compress ? "compression" : "decompression",
- lzma_error_str(retval));
- return TOR_COMPRESS_ERROR;
- }
-#else /* !(defined(HAVE_LZMA)) */
- (void)state;
- (void)out;
- (void)out_len;
- (void)in;
- (void)in_len;
- (void)finish;
- return TOR_COMPRESS_ERROR;
-#endif /* defined(HAVE_LZMA) */
-}
-
-/** Deallocate <b>state</b>. */
-void
-tor_lzma_compress_free_(tor_lzma_compress_state_t *state)
-{
- if (state == NULL)
- return;
-
- atomic_counter_sub(&total_lzma_allocation, state->allocation);
-
-#ifdef HAVE_LZMA
- lzma_end(&state->stream);
-#endif
-
- tor_free(state);
-}
-
-/** Return the approximate number of bytes allocated for <b>state</b>. */
-size_t
-tor_lzma_compress_state_size(const tor_lzma_compress_state_t *state)
-{
- tor_assert(state != NULL);
- return state->allocation;
-}
-
-/** Return the approximate number of bytes allocated for all LZMA states. */
-size_t
-tor_lzma_get_total_allocation(void)
-{
- return atomic_counter_get(&total_lzma_allocation);
-}
-
-/** Initialize the lzma module */
-void
-tor_lzma_init(void)
-{
- atomic_counter_init(&total_lzma_allocation);
-}
-
diff --git a/src/common/compress_lzma.h b/src/common/compress_lzma.h
deleted file mode 100644
index 38a447c1f3..0000000000
--- a/src/common/compress_lzma.h
+++ /dev/null
@@ -1,46 +0,0 @@
-/* Copyright (c) 2003, Roger Dingledine
- * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2017, The Tor Project, Inc. */
-/* See LICENSE for licensing information */
-
-/**
- * \file compress_lzma.h
- * \brief Header for compress_lzma.c
- **/
-
-#ifndef TOR_COMPRESS_LZMA_H
-#define TOR_COMPRESS_LZMA_H
-
-int tor_lzma_method_supported(void);
-
-const char *tor_lzma_get_version_str(void);
-
-const char *tor_lzma_get_header_version_str(void);
-
-/** Internal state for an incremental LZMA compression/decompression. */
-typedef struct tor_lzma_compress_state_t tor_lzma_compress_state_t;
-
-tor_lzma_compress_state_t *
-tor_lzma_compress_new(int compress,
- compress_method_t method,
- compression_level_t compression_level);
-
-tor_compress_output_t
-tor_lzma_compress_process(tor_lzma_compress_state_t *state,
- char **out, size_t *out_len,
- const char **in, size_t *in_len,
- int finish);
-
-void tor_lzma_compress_free_(tor_lzma_compress_state_t *state);
-#define tor_lzma_compress_free(st) \
- FREE_AND_NULL(tor_lzma_compress_state_t, \
- tor_lzma_compress_free_, (st))
-
-size_t tor_lzma_compress_state_size(const tor_lzma_compress_state_t *state);
-
-size_t tor_lzma_get_total_allocation(void);
-
-void tor_lzma_init(void);
-
-#endif /* !defined(TOR_COMPRESS_LZMA_H) */
-
diff --git a/src/common/compress_none.c b/src/common/compress_none.c
deleted file mode 100644
index 34314e4af7..0000000000
--- a/src/common/compress_none.c
+++ /dev/null
@@ -1,53 +0,0 @@
-/* Copyright (c) 2004, Roger Dingledine.
- * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2017, The Tor Project, Inc. */
-/* See LICENSE for licensing information */
-
-/**
- * \file compress_none.c
- * \brief Compression backend for identity compression.
- *
- * We actually define this backend so that we can treat the identity transform
- * as another case of compression.
- *
- * This module should never be invoked directly. Use the compress module
- * instead.
- **/
-
-#include "orconfig.h"
-
-#include "util.h"
-#include "torlog.h"
-#include "compress.h"
-#include "compress_none.h"
-
-/** Transfer some bytes using the identity transformation. Read up to
- * *<b>in_len</b> bytes from *<b>in</b>, and write up to *<b>out_len</b> bytes
- * to *<b>out</b>, adjusting the values as we go. If <b>finish</b> is true,
- * we've reached the end of the input.
- *
- * Return TOR_COMPRESS_DONE if we've finished the entire
- * compression/decompression.
- * Return TOR_COMPRESS_OK if we're processed everything from the input.
- * Return TOR_COMPRESS_BUFFER_FULL if we're out of space on <b>out</b>.
- * Return TOR_COMPRESS_ERROR if the stream is corrupt.
- */
-tor_compress_output_t
-tor_cnone_compress_process(char **out, size_t *out_len,
- const char **in, size_t *in_len,
- int finish)
-{
- size_t n_to_copy = MIN(*in_len, *out_len);
-
- memcpy(*out, *in, n_to_copy);
- *out += n_to_copy;
- *in += n_to_copy;
- *out_len -= n_to_copy;
- *in_len -= n_to_copy;
- if (*in_len == 0) {
- return finish ? TOR_COMPRESS_DONE : TOR_COMPRESS_OK;
- } else {
- return TOR_COMPRESS_BUFFER_FULL;
- }
-}
-
diff --git a/src/common/compress_none.h b/src/common/compress_none.h
deleted file mode 100644
index 77c3cef47b..0000000000
--- a/src/common/compress_none.h
+++ /dev/null
@@ -1,20 +0,0 @@
-/* Copyright (c) 2003, Roger Dingledine
- * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2017, The Tor Project, Inc. */
-/* See LICENSE for licensing information */
-
-/**
- * \file compress_none.h
- * \brief Header for compress_none.c
- **/
-
-#ifndef TOR_COMPRESS_NONE_H
-#define TOR_COMPRESS_NONE_H
-
-tor_compress_output_t
-tor_cnone_compress_process(char **out, size_t *out_len,
- const char **in, size_t *in_len,
- int finish);
-
-#endif /* !defined(TOR_COMPRESS_NONE_H) */
-
diff --git a/src/common/compress_zlib.c b/src/common/compress_zlib.c
deleted file mode 100644
index 23d71d27be..0000000000
--- a/src/common/compress_zlib.c
+++ /dev/null
@@ -1,304 +0,0 @@
-/* Copyright (c) 2004, Roger Dingledine.
- * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2017, The Tor Project, Inc. */
-/* See LICENSE for licensing information */
-
-/**
- * \file compress_zlib.c
- * \brief Compression backend for gzip and zlib.
- *
- * This module should never be invoked directly. Use the compress module
- * instead.
- **/
-
-#include "orconfig.h"
-
-#include "util.h"
-#include "torlog.h"
-#include "compress.h"
-#include "compress_zlib.h"
-
-/* zlib 1.2.4 and 1.2.5 do some "clever" things with macros. Instead of
- saying "(defined(FOO) ? FOO : 0)" they like to say "FOO-0", on the theory
- that nobody will care if the compile outputs a no-such-identifier warning.
-
- Sorry, but we like -Werror over here, so I guess we need to define these.
- I hope that zlib 1.2.6 doesn't break these too.
-*/
-#ifndef _LARGEFILE64_SOURCE
-#define _LARGEFILE64_SOURCE 0
-#endif
-#ifndef _LFS64_LARGEFILE
-#define _LFS64_LARGEFILE 0
-#endif
-#ifndef _FILE_OFFSET_BITS
-#define _FILE_OFFSET_BITS 0
-#endif
-#ifndef off64_t
-#define off64_t int64_t
-#endif
-
-#include <zlib.h>
-
-#if defined ZLIB_VERNUM && ZLIB_VERNUM < 0x1200
-#error "We require zlib version 1.2 or later."
-#endif
-
-static size_t tor_zlib_state_size_precalc(int inflate,
- int windowbits, int memlevel);
-
-/** Total number of bytes allocated for zlib state */
-static atomic_counter_t total_zlib_allocation;
-
-/** Given <b>level</b> return the memory level. */
-static int
-memory_level(compression_level_t level)
-{
- switch (level) {
- default:
- case BEST_COMPRESSION: return 9;
- case HIGH_COMPRESSION: return 8;
- case MEDIUM_COMPRESSION: return 7;
- case LOW_COMPRESSION: return 6;
- }
-}
-
-/** Return the 'bits' value to tell zlib to use <b>method</b>.*/
-static inline int
-method_bits(compress_method_t method, compression_level_t level)
-{
- /* Bits+16 means "use gzip" in zlib >= 1.2 */
- const int flag = method == GZIP_METHOD ? 16 : 0;
- switch (level) {
- default:
- case BEST_COMPRESSION:
- case HIGH_COMPRESSION: return flag + 15;
- case MEDIUM_COMPRESSION: return flag + 13;
- case LOW_COMPRESSION: return flag + 11;
- }
-}
-
-/** Return 1 if zlib/gzip compression is supported; otherwise 0. */
-int
-tor_zlib_method_supported(void)
-{
- /* We currently always support zlib/gzip, but we keep this function around in
- * case we some day decide to deprecate zlib/gzip support.
- */
- return 1;
-}
-
-/** Return a string representation of the version of the currently running
- * version of zlib. */
-const char *
-tor_zlib_get_version_str(void)
-{
- return zlibVersion();
-}
-
-/** Return a string representation of the version of the version of zlib
-* used at compilation. */
-const char *
-tor_zlib_get_header_version_str(void)
-{
- return ZLIB_VERSION;
-}
-
-/** Internal zlib state for an incremental compression/decompression.
- * The body of this struct is not exposed. */
-struct tor_zlib_compress_state_t {
- struct z_stream_s stream; /**< The zlib stream */
- int compress; /**< True if we are compressing; false if we are inflating */
-
- /** Number of bytes read so far. Used to detect zlib bombs. */
- size_t input_so_far;
- /** Number of bytes written so far. Used to detect zlib bombs. */
- size_t output_so_far;
-
- /** Approximate number of bytes allocated for this object. */
- size_t allocation;
-};
-
-/** Return an approximate number of bytes used in RAM to hold a state with
- * window bits <b>windowBits</b> and compression level 'memlevel' */
-static size_t
-tor_zlib_state_size_precalc(int inflate_, int windowbits, int memlevel)
-{
- windowbits &= 15;
-
-#define A_FEW_KILOBYTES 2048
-
- if (inflate_) {
- /* From zconf.h:
-
- "The memory requirements for inflate are (in bytes) 1 << windowBits
- that is, 32K for windowBits=15 (default value) plus a few kilobytes
- for small objects."
- */
- return sizeof(tor_zlib_compress_state_t) + sizeof(struct z_stream_s) +
- (1 << 15) + A_FEW_KILOBYTES;
- } else {
- /* Also from zconf.h:
-
- "The memory requirements for deflate are (in bytes):
- (1 << (windowBits+2)) + (1 << (memLevel+9))
- ... plus a few kilobytes for small objects."
- */
- return sizeof(tor_zlib_compress_state_t) + sizeof(struct z_stream_s) +
- (1 << (windowbits + 2)) + (1 << (memlevel + 9)) + A_FEW_KILOBYTES;
- }
-#undef A_FEW_KILOBYTES
-}
-
-/** Construct and return a tor_zlib_compress_state_t object using
- * <b>method</b>. If <b>compress</b>, it's for compression; otherwise it's for
- * decompression. */
-tor_zlib_compress_state_t *
-tor_zlib_compress_new(int compress_,
- compress_method_t method,
- compression_level_t compression_level)
-{
- tor_zlib_compress_state_t *out;
- int bits, memlevel;
-
- if (! compress_) {
- /* use this setting for decompression, since we might have the
- * max number of window bits */
- compression_level = BEST_COMPRESSION;
- }
-
- out = tor_malloc_zero(sizeof(tor_zlib_compress_state_t));
- out->stream.zalloc = Z_NULL;
- out->stream.zfree = Z_NULL;
- out->stream.opaque = NULL;
- out->compress = compress_;
- bits = method_bits(method, compression_level);
- memlevel = memory_level(compression_level);
- if (compress_) {
- if (deflateInit2(&out->stream, Z_BEST_COMPRESSION, Z_DEFLATED,
- bits, memlevel,
- Z_DEFAULT_STRATEGY) != Z_OK)
- goto err; // LCOV_EXCL_LINE
- } else {
- if (inflateInit2(&out->stream, bits) != Z_OK)
- goto err; // LCOV_EXCL_LINE
- }
- out->allocation = tor_zlib_state_size_precalc(!compress_, bits, memlevel);
-
- atomic_counter_add(&total_zlib_allocation, out->allocation);
-
- return out;
-
- err:
- tor_free(out);
- return NULL;
-}
-
-/** Compress/decompress some bytes using <b>state</b>. Read up to
- * *<b>in_len</b> bytes from *<b>in</b>, and write up to *<b>out_len</b> bytes
- * to *<b>out</b>, adjusting the values as we go. If <b>finish</b> is true,
- * we've reached the end of the input.
- *
- * Return TOR_COMPRESS_DONE if we've finished the entire
- * compression/decompression.
- * Return TOR_COMPRESS_OK if we're processed everything from the input.
- * Return TOR_COMPRESS_BUFFER_FULL if we're out of space on <b>out</b>.
- * Return TOR_COMPRESS_ERROR if the stream is corrupt.
- */
-tor_compress_output_t
-tor_zlib_compress_process(tor_zlib_compress_state_t *state,
- char **out, size_t *out_len,
- const char **in, size_t *in_len,
- int finish)
-{
- int err;
- tor_assert(state != NULL);
- if (*in_len > UINT_MAX ||
- *out_len > UINT_MAX) {
- return TOR_COMPRESS_ERROR;
- }
-
- state->stream.next_in = (unsigned char*) *in;
- state->stream.avail_in = (unsigned int)*in_len;
- state->stream.next_out = (unsigned char*) *out;
- state->stream.avail_out = (unsigned int)*out_len;
-
- if (state->compress) {
- err = deflate(&state->stream, finish ? Z_FINISH : Z_NO_FLUSH);
- } else {
- err = inflate(&state->stream, finish ? Z_FINISH : Z_SYNC_FLUSH);
- }
-
- state->input_so_far += state->stream.next_in - ((unsigned char*)*in);
- state->output_so_far += state->stream.next_out - ((unsigned char*)*out);
-
- *out = (char*) state->stream.next_out;
- *out_len = state->stream.avail_out;
- *in = (const char *) state->stream.next_in;
- *in_len = state->stream.avail_in;
-
- if (! state->compress &&
- tor_compress_is_compression_bomb(state->input_so_far,
- state->output_so_far)) {
- log_warn(LD_DIR, "Possible zlib bomb; abandoning stream.");
- return TOR_COMPRESS_ERROR;
- }
-
- switch (err)
- {
- case Z_STREAM_END:
- return TOR_COMPRESS_DONE;
- case Z_BUF_ERROR:
- if (state->stream.avail_in == 0 && !finish)
- return TOR_COMPRESS_OK;
- return TOR_COMPRESS_BUFFER_FULL;
- case Z_OK:
- if (state->stream.avail_out == 0 || finish)
- return TOR_COMPRESS_BUFFER_FULL;
- return TOR_COMPRESS_OK;
- default:
- log_warn(LD_GENERAL, "Gzip returned an error: %s",
- state->stream.msg ? state->stream.msg : "<no message>");
- return TOR_COMPRESS_ERROR;
- }
-}
-
-/** Deallocate <b>state</b>. */
-void
-tor_zlib_compress_free_(tor_zlib_compress_state_t *state)
-{
- if (state == NULL)
- return;
-
- atomic_counter_sub(&total_zlib_allocation, state->allocation);
-
- if (state->compress)
- deflateEnd(&state->stream);
- else
- inflateEnd(&state->stream);
-
- tor_free(state);
-}
-
-/** Return the approximate number of bytes allocated for <b>state</b>. */
-size_t
-tor_zlib_compress_state_size(const tor_zlib_compress_state_t *state)
-{
- tor_assert(state != NULL);
- return state->allocation;
-}
-
-/** Return the approximate number of bytes allocated for all zlib states. */
-size_t
-tor_zlib_get_total_allocation(void)
-{
- return atomic_counter_get(&total_zlib_allocation);
-}
-
-/** Set up global state for the zlib module */
-void
-tor_zlib_init(void)
-{
- atomic_counter_init(&total_zlib_allocation);
-}
-
diff --git a/src/common/compress_zlib.h b/src/common/compress_zlib.h
deleted file mode 100644
index e3c1a2b339..0000000000
--- a/src/common/compress_zlib.h
+++ /dev/null
@@ -1,46 +0,0 @@
-/* Copyright (c) 2003, Roger Dingledine
- * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2017, The Tor Project, Inc. */
-/* See LICENSE for licensing information */
-
-/**
- * \file compress_zlib.h
- * \brief Header for compress_zlib.c
- **/
-
-#ifndef TOR_COMPRESS_ZLIB_H
-#define TOR_COMPRESS_ZLIB_H
-
-int tor_zlib_method_supported(void);
-
-const char *tor_zlib_get_version_str(void);
-
-const char *tor_zlib_get_header_version_str(void);
-
-/** Internal state for an incremental zlib/gzip compression/decompression. */
-typedef struct tor_zlib_compress_state_t tor_zlib_compress_state_t;
-
-tor_zlib_compress_state_t *
-tor_zlib_compress_new(int compress,
- compress_method_t method,
- compression_level_t compression_level);
-
-tor_compress_output_t
-tor_zlib_compress_process(tor_zlib_compress_state_t *state,
- char **out, size_t *out_len,
- const char **in, size_t *in_len,
- int finish);
-
-void tor_zlib_compress_free_(tor_zlib_compress_state_t *state);
-#define tor_zlib_compress_free(st) \
- FREE_AND_NULL(tor_zlib_compress_state_t, \
- tor_zlib_compress_free_, (st))
-
-size_t tor_zlib_compress_state_size(const tor_zlib_compress_state_t *state);
-
-size_t tor_zlib_get_total_allocation(void);
-
-void tor_zlib_init(void);
-
-#endif /* !defined(TOR_COMPRESS_ZLIB_H) */
-
diff --git a/src/common/compress_zstd.c b/src/common/compress_zstd.c
deleted file mode 100644
index dc8b4d621d..0000000000
--- a/src/common/compress_zstd.c
+++ /dev/null
@@ -1,540 +0,0 @@
-/* Copyright (c) 2004, Roger Dingledine.
- * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2017, The Tor Project, Inc. */
-/* See LICENSE for licensing information */
-
-/**
- * \file compress_zstd.c
- * \brief Compression backend for Zstandard.
- *
- * This module should never be invoked directly. Use the compress module
- * instead.
- **/
-
-#include "orconfig.h"
-
-#include "util.h"
-#include "torlog.h"
-#include "compress.h"
-#include "compress_zstd.h"
-
-#ifdef ENABLE_ZSTD_ADVANCED_APIS
-/* This is a lie, but we make sure it doesn't get us in trouble by wrapping
- * all invocations of zstd's static-only functions in a check to make sure
- * that the compile-time version matches the run-time version. */
-#define ZSTD_STATIC_LINKING_ONLY
-#endif
-
-#ifdef HAVE_ZSTD
-#ifdef HAVE_CFLAG_WUNUSED_CONST_VARIABLE
-DISABLE_GCC_WARNING(unused-const-variable)
-#endif
-#include <zstd.h>
-#ifdef HAVE_CFLAG_WUNUSED_CONST_VARIABLE
-ENABLE_GCC_WARNING(unused-const-variable)
-#endif
-#endif
-
-/** Total number of bytes allocated for Zstandard state. */
-static atomic_counter_t total_zstd_allocation;
-
-#ifdef HAVE_ZSTD
-/** Given <b>level</b> return the memory level. */
-static int
-memory_level(compression_level_t level)
-{
- switch (level) {
- default:
- case BEST_COMPRESSION:
- case HIGH_COMPRESSION: return 9;
- case MEDIUM_COMPRESSION: return 8;
- case LOW_COMPRESSION: return 7;
- }
-}
-#endif /* defined(HAVE_ZSTD) */
-
-/** Return 1 if Zstandard compression is supported; otherwise 0. */
-int
-tor_zstd_method_supported(void)
-{
-#ifdef HAVE_ZSTD
- return 1;
-#else
- return 0;
-#endif
-}
-
-#ifdef HAVE_ZSTD
-/** Format a zstd version number as a string in <b>buf</b>. */
-static void
-tor_zstd_format_version(char *buf, size_t buflen, unsigned version_number)
-{
- tor_snprintf(buf, buflen,
- "%u.%u.%u",
- version_number / 10000 % 100,
- version_number / 100 % 100,
- version_number % 100);
-}
-#endif
-
-#define VERSION_STR_MAX_LEN 16 /* more than enough space for 99.99.99 */
-
-/** Return a string representation of the version of the currently running
- * version of libzstd. Returns NULL if Zstandard is unsupported. */
-const char *
-tor_zstd_get_version_str(void)
-{
-#ifdef HAVE_ZSTD
- static char version_str[VERSION_STR_MAX_LEN];
-
- tor_zstd_format_version(version_str, sizeof(version_str),
- ZSTD_versionNumber());
-
- return version_str;
-#else /* !(defined(HAVE_ZSTD)) */
- return NULL;
-#endif /* defined(HAVE_ZSTD) */
-}
-
-/** Return a string representation of the version of the version of libzstd
- * used at compilation time. Returns NULL if Zstandard is unsupported. */
-const char *
-tor_zstd_get_header_version_str(void)
-{
-#ifdef HAVE_ZSTD
- return ZSTD_VERSION_STRING;
-#else
- return NULL;
-#endif
-}
-
-#ifdef TOR_UNIT_TESTS
-static int static_apis_disable_for_testing = 0;
-#endif
-
-/** Return true iff we can use the "static-only" APIs. */
-int
-tor_zstd_can_use_static_apis(void)
-{
-#if defined(ZSTD_STATIC_LINKING_ONLY) && defined(HAVE_ZSTD)
-#ifdef TOR_UNIT_TESTS
- if (static_apis_disable_for_testing) {
- return 0;
- }
-#endif
- return (ZSTD_VERSION_NUMBER == ZSTD_versionNumber());
-#else
- return 0;
-#endif
-}
-
-/** Internal Zstandard state for incremental compression/decompression.
- * The body of this struct is not exposed. */
-struct tor_zstd_compress_state_t {
-#ifdef HAVE_ZSTD
- union {
- /** Compression stream. Used when <b>compress</b> is true. */
- ZSTD_CStream *compress_stream;
- /** Decompression stream. Used when <b>compress</b> is false. */
- ZSTD_DStream *decompress_stream;
- } u; /**< Zstandard stream objects. */
-#endif /* defined(HAVE_ZSTD) */
-
- int compress; /**< True if we are compressing; false if we are inflating */
- int have_called_end; /**< True if we are compressing and we've called
- * ZSTD_endStream */
-
- /** Number of bytes read so far. Used to detect compression bombs. */
- size_t input_so_far;
- /** Number of bytes written so far. Used to detect compression bombs. */
- size_t output_so_far;
-
- /** Approximate number of bytes allocated for this object. */
- size_t allocation;
-};
-
-#ifdef HAVE_ZSTD
-/** Return an approximate number of bytes stored in memory to hold the
- * Zstandard compression/decompression state. This is a fake estimate
- * based on inspecting the zstd source: tor_zstd_state_size_precalc() is
- * more accurate when it's allowed to use "static-only" functions */
-static size_t
-tor_zstd_state_size_precalc_fake(int compress, int preset)
-{
- tor_assert(preset > 0);
-
- size_t memory_usage = sizeof(tor_zstd_compress_state_t);
-
- // The Zstandard library provides a number of functions that would be useful
- // here, but they are, unfortunately, still considered experimental and are
- // thus only available in libzstd if we link against the library statically.
- //
- // The code in this function tries to approximate the calculations without
- // being able to use the following:
- //
- // - We do not have access to neither the internal members of ZSTD_CStream
- // and ZSTD_DStream and their internal context objects.
- //
- // - We cannot use ZSTD_sizeof_CStream() and ZSTD_sizeof_DStream() since they
- // are unexposed.
- //
- // In the future it might be useful to check if libzstd have started
- // providing these functions in a stable manner and simplify this function.
- if (compress) {
- // We try to approximate the ZSTD_sizeof_CStream(ZSTD_CStream *stream)
- // function here. This function uses the following fields to make its
- // estimate:
-
- // - sizeof(ZSTD_CStream): Around 192 bytes on a 64-bit machine:
- memory_usage += 192;
-
- // - ZSTD_sizeof_CCtx(stream->cctx): This function requires access to
- // variables that are not exposed via the public API. We use a _very_
- // simplified function to calculate the estimated amount of bytes used in
- // this struct.
- // memory_usage += (preset - 0.5) * 1024 * 1024;
- memory_usage += (preset * 1024 * 1024) - (512 * 1024);
- // - ZSTD_sizeof_CDict(stream->cdictLocal): Unused in Tor: 0 bytes.
- // - stream->outBuffSize: 128 KB:
- memory_usage += 128 * 1024;
- // - stream->inBuffSize: 2048 KB:
- memory_usage += 2048 * 1024;
- } else {
- // We try to approximate the ZSTD_sizeof_DStream(ZSTD_DStream *stream)
- // function here. This function uses the following fields to make its
- // estimate:
-
- // - sizeof(ZSTD_DStream): Around 208 bytes on a 64-bit machine:
- memory_usage += 208;
- // - ZSTD_sizeof_DCtx(stream->dctx): Around 150 KB.
- memory_usage += 150 * 1024;
-
- // - ZSTD_sizeof_DDict(stream->ddictLocal): Unused in Tor: 0 bytes.
- // - stream->inBuffSize: 0 KB.
- // - stream->outBuffSize: 0 KB.
- }
-
- return memory_usage;
-}
-
-/** Return an approximate number of bytes stored in memory to hold the
- * Zstandard compression/decompression state. */
-static size_t
-tor_zstd_state_size_precalc(int compress, int preset)
-{
-#ifdef ZSTD_STATIC_LINKING_ONLY
- if (tor_zstd_can_use_static_apis()) {
- if (compress) {
-#ifdef HAVE_ZSTD_ESTIMATECSTREAMSIZE
- return ZSTD_estimateCStreamSize(preset);
-#endif
- } else {
-#ifdef HAVE_ZSTD_ESTIMATEDCTXSIZE
- /* Could use DStream, but that takes a windowSize. */
- return ZSTD_estimateDCtxSize();
-#endif
- }
- }
-#endif
- return tor_zstd_state_size_precalc_fake(compress, preset);
-}
-#endif /* defined(HAVE_ZSTD) */
-
-/** Construct and return a tor_zstd_compress_state_t object using
- * <b>method</b>. If <b>compress</b>, it's for compression; otherwise it's for
- * decompression. */
-tor_zstd_compress_state_t *
-tor_zstd_compress_new(int compress,
- compress_method_t method,
- compression_level_t level)
-{
- tor_assert(method == ZSTD_METHOD);
-
-#ifdef HAVE_ZSTD
- const int preset = memory_level(level);
- tor_zstd_compress_state_t *result;
- size_t retval;
-
- result = tor_malloc_zero(sizeof(tor_zstd_compress_state_t));
- result->compress = compress;
- result->allocation = tor_zstd_state_size_precalc(compress, preset);
-
- if (compress) {
- result->u.compress_stream = ZSTD_createCStream();
-
- if (result->u.compress_stream == NULL) {
- // LCOV_EXCL_START
- log_warn(LD_GENERAL, "Error while creating Zstandard compression "
- "stream");
- goto err;
- // LCOV_EXCL_STOP
- }
-
- retval = ZSTD_initCStream(result->u.compress_stream, preset);
-
- if (ZSTD_isError(retval)) {
- // LCOV_EXCL_START
- log_warn(LD_GENERAL, "Zstandard stream initialization error: %s",
- ZSTD_getErrorName(retval));
- goto err;
- // LCOV_EXCL_STOP
- }
- } else {
- result->u.decompress_stream = ZSTD_createDStream();
-
- if (result->u.decompress_stream == NULL) {
- // LCOV_EXCL_START
- log_warn(LD_GENERAL, "Error while creating Zstandard decompression "
- "stream");
- goto err;
- // LCOV_EXCL_STOP
- }
-
- retval = ZSTD_initDStream(result->u.decompress_stream);
-
- if (ZSTD_isError(retval)) {
- // LCOV_EXCL_START
- log_warn(LD_GENERAL, "Zstandard stream initialization error: %s",
- ZSTD_getErrorName(retval));
- goto err;
- // LCOV_EXCL_STOP
- }
- }
-
- atomic_counter_add(&total_zstd_allocation, result->allocation);
- return result;
-
- err:
- // LCOV_EXCL_START
- if (compress) {
- ZSTD_freeCStream(result->u.compress_stream);
- } else {
- ZSTD_freeDStream(result->u.decompress_stream);
- }
-
- tor_free(result);
- return NULL;
- // LCOV_EXCL_STOP
-#else /* !(defined(HAVE_ZSTD)) */
- (void)compress;
- (void)method;
- (void)level;
-
- return NULL;
-#endif /* defined(HAVE_ZSTD) */
-}
-
-/** Compress/decompress some bytes using <b>state</b>. Read up to
- * *<b>in_len</b> bytes from *<b>in</b>, and write up to *<b>out_len</b> bytes
- * to *<b>out</b>, adjusting the values as we go. If <b>finish</b> is true,
- * we've reached the end of the input.
- *
- * Return TOR_COMPRESS_DONE if we've finished the entire
- * compression/decompression.
- * Return TOR_COMPRESS_OK if we're processed everything from the input.
- * Return TOR_COMPRESS_BUFFER_FULL if we're out of space on <b>out</b>.
- * Return TOR_COMPRESS_ERROR if the stream is corrupt.
- */
-tor_compress_output_t
-tor_zstd_compress_process(tor_zstd_compress_state_t *state,
- char **out, size_t *out_len,
- const char **in, size_t *in_len,
- int finish)
-{
-#ifdef HAVE_ZSTD
- size_t retval;
-
- tor_assert(state != NULL);
- tor_assert(*in_len <= UINT_MAX);
- tor_assert(*out_len <= UINT_MAX);
-
- ZSTD_inBuffer input = { *in, *in_len, 0 };
- ZSTD_outBuffer output = { *out, *out_len, 0 };
-
- if (BUG(finish == 0 && state->have_called_end)) {
- finish = 1;
- }
-
- if (state->compress) {
- if (! state->have_called_end)
- retval = ZSTD_compressStream(state->u.compress_stream,
- &output, &input);
- else
- retval = 0;
- } else {
- retval = ZSTD_decompressStream(state->u.decompress_stream,
- &output, &input);
- }
-
- state->input_so_far += input.pos;
- state->output_so_far += output.pos;
-
- *out = (char *)output.dst + output.pos;
- *out_len = output.size - output.pos;
- *in = (char *)input.src + input.pos;
- *in_len = input.size - input.pos;
-
- if (! state->compress &&
- tor_compress_is_compression_bomb(state->input_so_far,
- state->output_so_far)) {
- log_warn(LD_DIR, "Possible compression bomb; abandoning stream.");
- return TOR_COMPRESS_ERROR;
- }
-
- if (ZSTD_isError(retval)) {
- log_warn(LD_GENERAL, "Zstandard %s didn't finish: %s.",
- state->compress ? "compression" : "decompression",
- ZSTD_getErrorName(retval));
- return TOR_COMPRESS_ERROR;
- }
-
- if (state->compress && !state->have_called_end) {
- retval = ZSTD_flushStream(state->u.compress_stream, &output);
-
- *out = (char *)output.dst + output.pos;
- *out_len = output.size - output.pos;
-
- if (ZSTD_isError(retval)) {
- log_warn(LD_GENERAL, "Zstandard compression unable to flush: %s.",
- ZSTD_getErrorName(retval));
- return TOR_COMPRESS_ERROR;
- }
-
- // ZSTD_flushStream returns 0 if the frame is done, or >0 if it
- // is incomplete.
- if (retval > 0) {
- return TOR_COMPRESS_BUFFER_FULL;
- }
- }
-
- if (!finish) {
- // The caller says we're not done with the input, so no need to write an
- // epilogue.
- return TOR_COMPRESS_OK;
- } else if (state->compress) {
- if (*in_len) {
- // We say that we're not done with the input, so we can't write an
- // epilogue.
- return TOR_COMPRESS_OK;
- }
-
- retval = ZSTD_endStream(state->u.compress_stream, &output);
- state->have_called_end = 1;
- *out = (char *)output.dst + output.pos;
- *out_len = output.size - output.pos;
-
- if (ZSTD_isError(retval)) {
- log_warn(LD_GENERAL, "Zstandard compression unable to write "
- "epilogue: %s.",
- ZSTD_getErrorName(retval));
- return TOR_COMPRESS_ERROR;
- }
-
- // endStream returns the number of bytes that is needed to write the
- // epilogue.
- if (retval > 0)
- return TOR_COMPRESS_BUFFER_FULL;
-
- return TOR_COMPRESS_DONE;
- } else /* if (!state->compress) */ {
- // ZSTD_decompressStream returns 0 if the frame is done, or >0 if it
- // is incomplete.
- // We check this above.
- tor_assert_nonfatal(!ZSTD_isError(retval));
- // Start a new frame if this frame is done
- if (retval == 0)
- return TOR_COMPRESS_DONE;
- // Don't check out_len, it might have some space left if the next output
- // chunk is larger than the remaining space
- else if (*in_len > 0)
- return TOR_COMPRESS_BUFFER_FULL;
- else
- return TOR_COMPRESS_OK;
- }
-
-#else /* !(defined(HAVE_ZSTD)) */
- (void)state;
- (void)out;
- (void)out_len;
- (void)in;
- (void)in_len;
- (void)finish;
-
- return TOR_COMPRESS_ERROR;
-#endif /* defined(HAVE_ZSTD) */
-}
-
-/** Deallocate <b>state</b>. */
-void
-tor_zstd_compress_free_(tor_zstd_compress_state_t *state)
-{
- if (state == NULL)
- return;
-
- atomic_counter_sub(&total_zstd_allocation, state->allocation);
-
-#ifdef HAVE_ZSTD
- if (state->compress) {
- ZSTD_freeCStream(state->u.compress_stream);
- } else {
- ZSTD_freeDStream(state->u.decompress_stream);
- }
-#endif /* defined(HAVE_ZSTD) */
-
- tor_free(state);
-}
-
-/** Return the approximate number of bytes allocated for <b>state</b>. */
-size_t
-tor_zstd_compress_state_size(const tor_zstd_compress_state_t *state)
-{
- tor_assert(state != NULL);
- return state->allocation;
-}
-
-/** Return the approximate number of bytes allocated for all Zstandard
- * states. */
-size_t
-tor_zstd_get_total_allocation(void)
-{
- return atomic_counter_get(&total_zstd_allocation);
-}
-
-/** Initialize the zstd module */
-void
-tor_zstd_init(void)
-{
- atomic_counter_init(&total_zstd_allocation);
-}
-
-/** Warn if the header and library versions don't match. */
-void
-tor_zstd_warn_if_version_mismatched(void)
-{
-#if defined(HAVE_ZSTD) && defined(ENABLE_ZSTD_ADVANCED_APIS)
- if (! tor_zstd_can_use_static_apis()) {
- char header_version[VERSION_STR_MAX_LEN];
- char runtime_version[VERSION_STR_MAX_LEN];
- tor_zstd_format_version(header_version, sizeof(header_version),
- ZSTD_VERSION_NUMBER);
- tor_zstd_format_version(runtime_version, sizeof(runtime_version),
- ZSTD_versionNumber());
-
- log_warn(LD_GENERAL,
- "Tor was compiled with zstd %s, but is running with zstd %s. "
- "For safety, we'll avoid using advanced zstd functionality.",
- header_version, runtime_version);
- }
-#endif
-}
-
-#ifdef TOR_UNIT_TESTS
-/** Testing only: disable usage of static-only APIs, so we can make sure that
- * we still work without them. */
-void
-tor_zstd_set_static_apis_disabled_for_testing(int disabled)
-{
- static_apis_disable_for_testing = disabled;
-}
-#endif
-
diff --git a/src/common/compress_zstd.h b/src/common/compress_zstd.h
deleted file mode 100644
index bd42cf65ce..0000000000
--- a/src/common/compress_zstd.h
+++ /dev/null
@@ -1,53 +0,0 @@
-/* Copyright (c) 2003, Roger Dingledine
- * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2017, The Tor Project, Inc. */
-/* See LICENSE for licensing information */
-
-/**
- * \file compress_zstd.h
- * \brief Header for compress_zstd.c
- **/
-
-#ifndef TOR_COMPRESS_ZSTD_H
-#define TOR_COMPRESS_ZSTD_H
-
-int tor_zstd_method_supported(void);
-
-const char *tor_zstd_get_version_str(void);
-
-const char *tor_zstd_get_header_version_str(void);
-
-int tor_zstd_can_use_static_apis(void);
-
-/** Internal state for an incremental Zstandard compression/decompression. */
-typedef struct tor_zstd_compress_state_t tor_zstd_compress_state_t;
-
-tor_zstd_compress_state_t *
-tor_zstd_compress_new(int compress,
- compress_method_t method,
- compression_level_t compression_level);
-
-tor_compress_output_t
-tor_zstd_compress_process(tor_zstd_compress_state_t *state,
- char **out, size_t *out_len,
- const char **in, size_t *in_len,
- int finish);
-
-void tor_zstd_compress_free_(tor_zstd_compress_state_t *state);
-#define tor_zstd_compress_free(st) \
- FREE_AND_NULL(tor_zstd_compress_state_t, \
- tor_zstd_compress_free_, (st))
-
-size_t tor_zstd_compress_state_size(const tor_zstd_compress_state_t *state);
-
-size_t tor_zstd_get_total_allocation(void);
-
-void tor_zstd_init(void);
-void tor_zstd_warn_if_version_mismatched(void);
-
-#ifdef TOR_UNIT_TESTS
-void tor_zstd_set_static_apis_disabled_for_testing(int disabled);
-#endif
-
-#endif /* !defined(TOR_COMPRESS_ZSTD_H) */
-
diff --git a/src/common/confline.c b/src/common/confline.c
deleted file mode 100644
index bf613ab742..0000000000
--- a/src/common/confline.c
+++ /dev/null
@@ -1,538 +0,0 @@
-/* Copyright (c) 2001 Matej Pfajfar.
- * Copyright (c) 2001-2004, Roger Dingledine.
- * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2017, The Tor Project, Inc. */
-/* See LICENSE for licensing information */
-
-#include "compat.h"
-#include "confline.h"
-#include "torlog.h"
-#include "util.h"
-#include "container.h"
-
-static int config_get_lines_aux(const char *string, config_line_t **result,
- int extended, int allow_include,
- int *has_include, smartlist_t *opened_lst,
- int recursion_level, config_line_t **last);
-static smartlist_t *config_get_file_list(const char *path,
- smartlist_t *opened_files);
-static int config_get_included_config(const char *path, int recursion_level,
- int extended, config_line_t **config,
- config_line_t **config_last,
- smartlist_t *opened_lst);
-static int config_process_include(const char *path, int recursion_level,
- int extended, config_line_t **list,
- config_line_t **list_last,
- smartlist_t *opened_lst);
-
-/** Helper: allocate a new configuration option mapping 'key' to 'val',
- * append it to *<b>lst</b>. */
-void
-config_line_append(config_line_t **lst,
- const char *key,
- const char *val)
-{
- tor_assert(lst);
-
- config_line_t *newline;
-
- newline = tor_malloc_zero(sizeof(config_line_t));
- newline->key = tor_strdup(key);
- newline->value = tor_strdup(val);
- newline->next = NULL;
- while (*lst)
- lst = &((*lst)->next);
-
- (*lst) = newline;
-}
-
-/** Helper: allocate a new configuration option mapping 'key' to 'val',
- * and prepend it to *<b>lst</b> */
-void
-config_line_prepend(config_line_t **lst,
- const char *key,
- const char *val)
-{
- tor_assert(lst);
-
- config_line_t *newline;
-
- newline = tor_malloc_zero(sizeof(config_line_t));
- newline->key = tor_strdup(key);
- newline->value = tor_strdup(val);
- newline->next = *lst;
- *lst = newline;
-}
-
-/** Return the first line in <b>lines</b> whose key is exactly <b>key</b>, or
- * NULL if no such key exists.
- *
- * (In options parsing, this is for handling commandline-only options only;
- * other options should be looked up in the appropriate data structure.) */
-const config_line_t *
-config_line_find(const config_line_t *lines,
- const char *key)
-{
- const config_line_t *cl;
- for (cl = lines; cl; cl = cl->next) {
- if (!strcmp(cl->key, key))
- return cl;
- }
- return NULL;
-}
-
-/** Auxiliary function that does all the work of config_get_lines.
- * <b>recursion_level</b> is the count of how many nested %includes we have.
- * <b>opened_lst</b> will have a list of opened files if provided.
- * Returns the a pointer to the last element of the <b>result</b> in
- * <b>last</b>. */
-static int
-config_get_lines_aux(const char *string, config_line_t **result, int extended,
- int allow_include, int *has_include,
- smartlist_t *opened_lst, int recursion_level,
- config_line_t **last)
-{
- config_line_t *list = NULL, **next, *list_last = NULL;
- char *k, *v;
- const char *parse_err;
- int include_used = 0;
-
- if (recursion_level > MAX_INCLUDE_RECURSION_LEVEL) {
- log_warn(LD_CONFIG, "Error while parsing configuration: more than %d "
- "nested %%includes.", MAX_INCLUDE_RECURSION_LEVEL);
- return -1;
- }
-
- next = &list;
- do {
- k = v = NULL;
- string = parse_config_line_from_str_verbose(string, &k, &v, &parse_err);
- if (!string) {
- log_warn(LD_CONFIG, "Error while parsing configuration: %s",
- parse_err?parse_err:"<unknown>");
- config_free_lines(list);
- tor_free(k);
- tor_free(v);
- return -1;
- }
- if (k && v) {
- unsigned command = CONFIG_LINE_NORMAL;
- if (extended) {
- if (k[0] == '+') {
- char *k_new = tor_strdup(k+1);
- tor_free(k);
- k = k_new;
- command = CONFIG_LINE_APPEND;
- } else if (k[0] == '/') {
- char *k_new = tor_strdup(k+1);
- tor_free(k);
- k = k_new;
- tor_free(v);
- v = tor_strdup("");
- command = CONFIG_LINE_CLEAR;
- }
- }
-
- if (allow_include && !strcmp(k, "%include")) {
- tor_free(k);
- include_used = 1;
-
- config_line_t *include_list;
- if (config_process_include(v, recursion_level, extended, &include_list,
- &list_last, opened_lst) < 0) {
- log_warn(LD_CONFIG, "Error reading included configuration "
- "file or directory: \"%s\".", v);
- config_free_lines(list);
- tor_free(v);
- return -1;
- }
- *next = include_list;
- if (list_last)
- next = &list_last->next;
- tor_free(v);
- } else {
- /* This list can get long, so we keep a pointer to the end of it
- * rather than using config_line_append over and over and getting
- * n^2 performance. */
- *next = tor_malloc_zero(sizeof(**next));
- (*next)->key = k;
- (*next)->value = v;
- (*next)->next = NULL;
- (*next)->command = command;
- list_last = *next;
- next = &((*next)->next);
- }
- } else {
- tor_free(k);
- tor_free(v);
- }
- } while (*string);
-
- if (last) {
- *last = list_last;
- }
- if (has_include) {
- *has_include = include_used;
- }
- *result = list;
- return 0;
-}
-
-/** Helper: parse the config string and strdup into key/value
- * strings. Set *result to the list, or NULL if parsing the string
- * failed. Set *has_include to 1 if <b>result</b> has values from
- * %included files. <b>opened_lst</b> will have a list of opened files if
- * provided. Return 0 on success, -1 on failure. Warn and ignore any
- * misformatted lines.
- *
- * If <b>extended</b> is set, then treat keys beginning with / and with + as
- * indicating "clear" and "append" respectively. */
-int
-config_get_lines_include(const char *string, config_line_t **result,
- int extended, int *has_include,
- smartlist_t *opened_lst)
-{
- return config_get_lines_aux(string, result, extended, 1, has_include,
- opened_lst, 1, NULL);
-}
-
-/** Same as config_get_lines_include but does not allow %include */
-int
-config_get_lines(const char *string, config_line_t **result, int extended)
-{
- return config_get_lines_aux(string, result, extended, 0, NULL, NULL, 1,
- NULL);
-}
-
-/** Adds a list of configuration files present on <b>path</b> to
- * <b>file_list</b>. <b>path</b> can be a file or a directory. If it is a file,
- * only that file will be added to <b>file_list</b>. If it is a directory,
- * all paths for files on that directory root (no recursion) except for files
- * whose name starts with a dot will be added to <b>file_list</b>.
- * <b>opened_files</b> will have a list of files opened by this function
- * if provided. Return 0 on success, -1 on failure. Ignores empty files.
- */
-static smartlist_t *
-config_get_file_list(const char *path, smartlist_t *opened_files)
-{
- smartlist_t *file_list = smartlist_new();
-
- if (opened_files) {
- smartlist_add_strdup(opened_files, path);
- }
-
- file_status_t file_type = file_status(path);
- if (file_type == FN_FILE) {
- smartlist_add_strdup(file_list, path);
- return file_list;
- } else if (file_type == FN_DIR) {
- smartlist_t *all_files = tor_listdir(path);
- if (!all_files) {
- smartlist_free(file_list);
- return NULL;
- }
- smartlist_sort_strings(all_files);
- SMARTLIST_FOREACH_BEGIN(all_files, char *, f) {
- if (f[0] == '.') {
- tor_free(f);
- continue;
- }
-
- char *fullname;
- tor_asprintf(&fullname, "%s"PATH_SEPARATOR"%s", path, f);
- tor_free(f);
-
- if (opened_files) {
- smartlist_add_strdup(opened_files, fullname);
- }
-
- if (file_status(fullname) != FN_FILE) {
- tor_free(fullname);
- continue;
- }
- smartlist_add(file_list, fullname);
- } SMARTLIST_FOREACH_END(f);
- smartlist_free(all_files);
- return file_list;
- } else if (file_type == FN_EMPTY) {
- return file_list;
- } else {
- smartlist_free(file_list);
- return NULL;
- }
-}
-
-/** Creates a list of config lines present on included <b>path</b>.
- * Set <b>config</b> to the list and <b>config_last</b> to the last element of
- * <b>config</b>. <b>opened_lst</b> will have a list of opened files if
- * provided. Return 0 on success, -1 on failure. */
-static int
-config_get_included_config(const char *path, int recursion_level, int extended,
- config_line_t **config, config_line_t **config_last,
- smartlist_t *opened_lst)
-{
- char *included_conf = read_file_to_str(path, 0, NULL);
- if (!included_conf) {
- return -1;
- }
-
- if (config_get_lines_aux(included_conf, config, extended, 1, NULL,
- opened_lst, recursion_level+1, config_last) < 0) {
- tor_free(included_conf);
- return -1;
- }
-
- tor_free(included_conf);
- return 0;
-}
-
-/** Process an %include <b>path</b> in a config file. Set <b>list</b> to the
- * list of configuration settings obtained and <b>list_last</b> to the last
- * element of the same list. <b>opened_lst</b> will have a list of opened
- * files if provided. Return 0 on success, -1 on failure. */
-static int
-config_process_include(const char *path, int recursion_level, int extended,
- config_line_t **list, config_line_t **list_last,
- smartlist_t *opened_lst)
-{
- config_line_t *ret_list = NULL;
- config_line_t **next = &ret_list;
-
- smartlist_t *config_files = config_get_file_list(path, opened_lst);
- if (!config_files) {
- return -1;
- }
-
- int rv = -1;
- SMARTLIST_FOREACH_BEGIN(config_files, const char *, config_file) {
- config_line_t *included_config = NULL;
- if (config_get_included_config(config_file, recursion_level, extended,
- &included_config, list_last,
- opened_lst) < 0) {
- goto done;
- }
-
- *next = included_config;
- if (*list_last)
- next = &(*list_last)->next;
-
- } SMARTLIST_FOREACH_END(config_file);
- *list = ret_list;
- rv = 0;
-
- done:
- SMARTLIST_FOREACH(config_files, char *, f, tor_free(f));
- smartlist_free(config_files);
- return rv;
-}
-
-/**
- * Free all the configuration lines on the linked list <b>front</b>.
- */
-void
-config_free_lines_(config_line_t *front)
-{
- config_line_t *tmp;
-
- while (front) {
- tmp = front;
- front = tmp->next;
-
- tor_free(tmp->key);
- tor_free(tmp->value);
- tor_free(tmp);
- }
-}
-
-/** Return a newly allocated deep copy of the lines in <b>inp</b>. */
-config_line_t *
-config_lines_dup(const config_line_t *inp)
-{
- return config_lines_dup_and_filter(inp, NULL);
-}
-
-/** Return a newly allocated deep copy of the lines in <b>inp</b>,
- * but only the ones whose keys begin with <b>key</b> (case-insensitive).
- * If <b>key</b> is NULL, do not filter. */
-config_line_t *
-config_lines_dup_and_filter(const config_line_t *inp,
- const char *key)
-{
- config_line_t *result = NULL;
- config_line_t **next_out = &result;
- while (inp) {
- if (key && strcasecmpstart(inp->key, key)) {
- inp = inp->next;
- continue;
- }
- *next_out = tor_malloc_zero(sizeof(config_line_t));
- (*next_out)->key = tor_strdup(inp->key);
- (*next_out)->value = tor_strdup(inp->value);
- inp = inp->next;
- next_out = &((*next_out)->next);
- }
- (*next_out) = NULL;
- return result;
-}
-
-/** Return true iff a and b contain identical keys and values in identical
- * order. */
-int
-config_lines_eq(config_line_t *a, config_line_t *b)
-{
- while (a && b) {
- if (strcasecmp(a->key, b->key) || strcmp(a->value, b->value))
- return 0;
- a = a->next;
- b = b->next;
- }
- if (a || b)
- return 0;
- return 1;
-}
-
-/** Return the number of lines in <b>a</b> whose key is <b>key</b>. */
-int
-config_count_key(const config_line_t *a, const char *key)
-{
- int n = 0;
- while (a) {
- if (!strcasecmp(a->key, key)) {
- ++n;
- }
- a = a->next;
- }
- return n;
-}
-
-/** Given a string containing part of a configuration file or similar format,
- * advance past comments and whitespace and try to parse a single line. If we
- * parse a line successfully, set *<b>key_out</b> to a new string holding the
- * key portion and *<b>value_out</b> to a new string holding the value portion
- * of the line, and return a pointer to the start of the next line. If we run
- * out of data, return a pointer to the end of the string. If we encounter an
- * error, return NULL and set *<b>err_out</b> (if provided) to an error
- * message.
- */
-const char *
-parse_config_line_from_str_verbose(const char *line, char **key_out,
- char **value_out,
- const char **err_out)
-{
- /*
- See torrc_format.txt for a description of the (silly) format this parses.
- */
- const char *key, *val, *cp;
- int continuation = 0;
-
- tor_assert(key_out);
- tor_assert(value_out);
-
- *key_out = *value_out = NULL;
- key = val = NULL;
- /* Skip until the first keyword. */
- while (1) {
- while (TOR_ISSPACE(*line))
- ++line;
- if (*line == '#') {
- while (*line && *line != '\n')
- ++line;
- } else {
- break;
- }
- }
-
- if (!*line) { /* End of string? */
- *key_out = *value_out = NULL;
- return line;
- }
-
- /* Skip until the next space or \ followed by newline. */
- key = line;
- while (*line && !TOR_ISSPACE(*line) && *line != '#' &&
- ! (line[0] == '\\' && line[1] == '\n'))
- ++line;
- *key_out = tor_strndup(key, line-key);
-
- /* Skip until the value. */
- while (*line == ' ' || *line == '\t')
- ++line;
-
- val = line;
-
- /* Find the end of the line. */
- if (*line == '\"') { // XXX No continuation handling is done here
- if (!(line = unescape_string(line, value_out, NULL))) {
- if (err_out)
- *err_out = "Invalid escape sequence in quoted string";
- return NULL;
- }
- while (*line == ' ' || *line == '\t')
- ++line;
- if (*line == '\r' && *(++line) == '\n')
- ++line;
- if (*line && *line != '#' && *line != '\n') {
- if (err_out)
- *err_out = "Excess data after quoted string";
- return NULL;
- }
- } else {
- /* Look for the end of the line. */
- while (*line && *line != '\n' && (*line != '#' || continuation)) {
- if (*line == '\\' && line[1] == '\n') {
- continuation = 1;
- line += 2;
- } else if (*line == '#') {
- do {
- ++line;
- } while (*line && *line != '\n');
- if (*line == '\n')
- ++line;
- } else {
- ++line;
- }
- }
-
- if (*line == '\n') {
- cp = line++;
- } else {
- cp = line;
- }
- /* Now back cp up to be the last nonspace character */
- while (cp>val && TOR_ISSPACE(*(cp-1)))
- --cp;
-
- tor_assert(cp >= val);
-
- /* Now copy out and decode the value. */
- *value_out = tor_strndup(val, cp-val);
- if (continuation) {
- char *v_out, *v_in;
- v_out = v_in = *value_out;
- while (*v_in) {
- if (*v_in == '#') {
- do {
- ++v_in;
- } while (*v_in && *v_in != '\n');
- if (*v_in == '\n')
- ++v_in;
- } else if (v_in[0] == '\\' && v_in[1] == '\n') {
- v_in += 2;
- } else {
- *v_out++ = *v_in++;
- }
- }
- *v_out = '\0';
- }
- }
-
- if (*line == '#') {
- do {
- ++line;
- } while (*line && *line != '\n');
- }
- while (TOR_ISSPACE(*line)) ++line;
-
- return line;
-}
-
diff --git a/src/common/confline.h b/src/common/confline.h
deleted file mode 100644
index 772a9bbbdc..0000000000
--- a/src/common/confline.h
+++ /dev/null
@@ -1,61 +0,0 @@
-/* Copyright (c) 2001 Matej Pfajfar.
- * Copyright (c) 2001-2004, Roger Dingledine.
- * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2017, The Tor Project, Inc. */
-/* See LICENSE for licensing information */
-
-#ifndef TOR_CONFLINE_H
-#define TOR_CONFLINE_H
-
-#include "container.h"
-
-/** Ordinary configuration line. */
-#define CONFIG_LINE_NORMAL 0
-/** Appends to previous configuration for the same option, even if we
- * would ordinary replace it. */
-#define CONFIG_LINE_APPEND 1
-/* Removes all previous configuration for an option. */
-#define CONFIG_LINE_CLEAR 2
-
-#define MAX_INCLUDE_RECURSION_LEVEL 31
-
-/** A linked list of lines in a config file, or elsewhere */
-typedef struct config_line_t {
- char *key;
- char *value;
- struct config_line_t *next;
-
- /** What special treatment (if any) does this line require? */
- unsigned int command:2;
- /** If true, subsequent assignments to this linelist should replace
- * it, not extend it. Set only on the first item in a linelist in an
- * or_options_t. */
- unsigned int fragile:1;
-} config_line_t;
-
-void config_line_append(config_line_t **lst,
- const char *key, const char *val);
-void config_line_prepend(config_line_t **lst,
- const char *key, const char *val);
-config_line_t *config_lines_dup(const config_line_t *inp);
-config_line_t *config_lines_dup_and_filter(const config_line_t *inp,
- const char *key);
-const config_line_t *config_line_find(const config_line_t *lines,
- const char *key);
-int config_lines_eq(config_line_t *a, config_line_t *b);
-int config_count_key(const config_line_t *a, const char *key);
-int config_get_lines(const char *string, config_line_t **result, int extended);
-int config_get_lines_include(const char *string, config_line_t **result,
- int extended, int *has_include,
- smartlist_t *opened_lst);
-void config_free_lines_(config_line_t *front);
-#define config_free_lines(front) \
- do { \
- config_free_lines_(front); \
- (front) = NULL; \
- } while (0)
-const char *parse_config_line_from_str_verbose(const char *line,
- char **key_out, char **value_out,
- const char **err_out);
-#endif /* !defined(TOR_CONFLINE_H) */
-
diff --git a/src/common/container.c b/src/common/container.c
deleted file mode 100644
index 5386e6458b..0000000000
--- a/src/common/container.c
+++ /dev/null
@@ -1,1542 +0,0 @@
-/* Copyright (c) 2003-2004, Roger Dingledine
- * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2017, The Tor Project, Inc. */
-/* See LICENSE for licensing information */
-
-/**
- * \file container.c
- * \brief Implements a smartlist (a resizable array) along
- * with helper functions to use smartlists. Also includes
- * hash table implementations of a string-to-void* map, and of
- * a digest-to-void* map.
- **/
-
-#include "compat.h"
-#include "util.h"
-#include "torlog.h"
-#include "container.h"
-#include "crypto_digest.h"
-
-#include <stdlib.h>
-#include <string.h>
-#include <assert.h>
-
-#include "ht.h"
-
-/** All newly allocated smartlists have this capacity. */
-#define SMARTLIST_DEFAULT_CAPACITY 16
-
-/** Allocate and return an empty smartlist.
- */
-MOCK_IMPL(smartlist_t *,
-smartlist_new,(void))
-{
- smartlist_t *sl = tor_malloc(sizeof(smartlist_t));
- sl->num_used = 0;
- sl->capacity = SMARTLIST_DEFAULT_CAPACITY;
- sl->list = tor_calloc(sizeof(void *), sl->capacity);
- return sl;
-}
-
-/** Deallocate a smartlist. Does not release storage associated with the
- * list's elements.
- */
-MOCK_IMPL(void,
-smartlist_free_,(smartlist_t *sl))
-{
- if (!sl)
- return;
- tor_free(sl->list);
- tor_free(sl);
-}
-
-/** Remove all elements from the list.
- */
-void
-smartlist_clear(smartlist_t *sl)
-{
- memset(sl->list, 0, sizeof(void *) * sl->num_used);
- sl->num_used = 0;
-}
-
-#if SIZE_MAX < INT_MAX
-#error "We don't support systems where size_t is smaller than int."
-#endif
-
-/** Make sure that <b>sl</b> can hold at least <b>size</b> entries. */
-static inline void
-smartlist_ensure_capacity(smartlist_t *sl, size_t size)
-{
- /* Set MAX_CAPACITY to MIN(INT_MAX, SIZE_MAX / sizeof(void*)) */
-#if (SIZE_MAX/SIZEOF_VOID_P) > INT_MAX
-#define MAX_CAPACITY (INT_MAX)
-#else
-#define MAX_CAPACITY (int)((SIZE_MAX / (sizeof(void*))))
-#endif
-
- tor_assert(size <= MAX_CAPACITY);
-
- if (size > (size_t) sl->capacity) {
- size_t higher = (size_t) sl->capacity;
- if (PREDICT_UNLIKELY(size > MAX_CAPACITY/2)) {
- higher = MAX_CAPACITY;
- } else {
- while (size > higher)
- higher *= 2;
- }
- sl->list = tor_reallocarray(sl->list, sizeof(void *),
- ((size_t)higher));
- memset(sl->list + sl->capacity, 0,
- sizeof(void *) * (higher - sl->capacity));
- sl->capacity = (int) higher;
- }
-#undef ASSERT_CAPACITY
-#undef MAX_CAPACITY
-}
-
-/** Append element to the end of the list. */
-void
-smartlist_add(smartlist_t *sl, void *element)
-{
- smartlist_ensure_capacity(sl, ((size_t) sl->num_used)+1);
- sl->list[sl->num_used++] = element;
-}
-
-/** Append each element from S2 to the end of S1. */
-void
-smartlist_add_all(smartlist_t *s1, const smartlist_t *s2)
-{
- size_t new_size = (size_t)s1->num_used + (size_t)s2->num_used;
- tor_assert(new_size >= (size_t) s1->num_used); /* check for overflow. */
- smartlist_ensure_capacity(s1, new_size);
- memcpy(s1->list + s1->num_used, s2->list, s2->num_used*sizeof(void*));
- tor_assert(new_size <= INT_MAX); /* redundant. */
- s1->num_used = (int) new_size;
-}
-
-/** Remove all elements E from sl such that E==element. Preserve
- * the order of any elements before E, but elements after E can be
- * rearranged.
- */
-void
-smartlist_remove(smartlist_t *sl, const void *element)
-{
- int i;
- if (element == NULL)
- return;
- for (i=0; i < sl->num_used; i++)
- if (sl->list[i] == element) {
- sl->list[i] = sl->list[--sl->num_used]; /* swap with the end */
- i--; /* so we process the new i'th element */
- sl->list[sl->num_used] = NULL;
- }
-}
-
-/** As <b>smartlist_remove</b>, but do not change the order of
- * any elements not removed */
-void
-smartlist_remove_keeporder(smartlist_t *sl, const void *element)
-{
- int i, j, num_used_orig = sl->num_used;
- if (element == NULL)
- return;
-
- for (i=j=0; j < num_used_orig; ++j) {
- if (sl->list[j] == element) {
- --sl->num_used;
- } else {
- sl->list[i++] = sl->list[j];
- }
- }
-}
-
-/** If <b>sl</b> is nonempty, remove and return the final element. Otherwise,
- * return NULL. */
-void *
-smartlist_pop_last(smartlist_t *sl)
-{
- tor_assert(sl);
- if (sl->num_used) {
- void *tmp = sl->list[--sl->num_used];
- sl->list[sl->num_used] = NULL;
- return tmp;
- } else
- return NULL;
-}
-
-/** Reverse the order of the items in <b>sl</b>. */
-void
-smartlist_reverse(smartlist_t *sl)
-{
- int i, j;
- void *tmp;
- tor_assert(sl);
- for (i = 0, j = sl->num_used-1; i < j; ++i, --j) {
- tmp = sl->list[i];
- sl->list[i] = sl->list[j];
- sl->list[j] = tmp;
- }
-}
-
-/** If there are any strings in sl equal to element, remove and free them.
- * Does not preserve order. */
-void
-smartlist_string_remove(smartlist_t *sl, const char *element)
-{
- int i;
- tor_assert(sl);
- tor_assert(element);
- for (i = 0; i < sl->num_used; ++i) {
- if (!strcmp(element, sl->list[i])) {
- tor_free(sl->list[i]);
- sl->list[i] = sl->list[--sl->num_used]; /* swap with the end */
- i--; /* so we process the new i'th element */
- sl->list[sl->num_used] = NULL;
- }
- }
-}
-
-/** Return true iff some element E of sl has E==element.
- */
-int
-smartlist_contains(const smartlist_t *sl, const void *element)
-{
- int i;
- for (i=0; i < sl->num_used; i++)
- if (sl->list[i] == element)
- return 1;
- return 0;
-}
-
-/** Return true iff <b>sl</b> has some element E such that
- * !strcmp(E,<b>element</b>)
- */
-int
-smartlist_contains_string(const smartlist_t *sl, const char *element)
-{
- int i;
- if (!sl) return 0;
- for (i=0; i < sl->num_used; i++)
- if (strcmp((const char*)sl->list[i],element)==0)
- return 1;
- return 0;
-}
-
-/** If <b>element</b> is equal to an element of <b>sl</b>, return that
- * element's index. Otherwise, return -1. */
-int
-smartlist_string_pos(const smartlist_t *sl, const char *element)
-{
- int i;
- if (!sl) return -1;
- for (i=0; i < sl->num_used; i++)
- if (strcmp((const char*)sl->list[i],element)==0)
- return i;
- return -1;
-}
-
-/** If <b>element</b> is the same pointer as an element of <b>sl</b>, return
- * that element's index. Otherwise, return -1. */
-int
-smartlist_pos(const smartlist_t *sl, const void *element)
-{
- int i;
- if (!sl) return -1;
- for (i=0; i < sl->num_used; i++)
- if (element == sl->list[i])
- return i;
- return -1;
-}
-
-/** Return true iff <b>sl</b> has some element E such that
- * !strcasecmp(E,<b>element</b>)
- */
-int
-smartlist_contains_string_case(const smartlist_t *sl, const char *element)
-{
- int i;
- if (!sl) return 0;
- for (i=0; i < sl->num_used; i++)
- if (strcasecmp((const char*)sl->list[i],element)==0)
- return 1;
- return 0;
-}
-
-/** Return true iff <b>sl</b> has some element E such that E is equal
- * to the decimal encoding of <b>num</b>.
- */
-int
-smartlist_contains_int_as_string(const smartlist_t *sl, int num)
-{
- char buf[32]; /* long enough for 64-bit int, and then some. */
- tor_snprintf(buf,sizeof(buf),"%d", num);
- return smartlist_contains_string(sl, buf);
-}
-
-/** Return true iff the two lists contain the same strings in the same
- * order, or if they are both NULL. */
-int
-smartlist_strings_eq(const smartlist_t *sl1, const smartlist_t *sl2)
-{
- if (sl1 == NULL)
- return sl2 == NULL;
- if (sl2 == NULL)
- return 0;
- if (smartlist_len(sl1) != smartlist_len(sl2))
- return 0;
- SMARTLIST_FOREACH(sl1, const char *, cp1, {
- const char *cp2 = smartlist_get(sl2, cp1_sl_idx);
- if (strcmp(cp1, cp2))
- return 0;
- });
- return 1;
-}
-
-/** Return true iff the two lists contain the same int pointer values in
- * the same order, or if they are both NULL. */
-int
-smartlist_ints_eq(const smartlist_t *sl1, const smartlist_t *sl2)
-{
- if (sl1 == NULL)
- return sl2 == NULL;
- if (sl2 == NULL)
- return 0;
- if (smartlist_len(sl1) != smartlist_len(sl2))
- return 0;
- SMARTLIST_FOREACH(sl1, int *, cp1, {
- int *cp2 = smartlist_get(sl2, cp1_sl_idx);
- if (*cp1 != *cp2)
- return 0;
- });
- return 1;
-}
-
-/** Return true iff <b>sl</b> has some element E such that
- * tor_memeq(E,<b>element</b>,DIGEST_LEN)
- */
-int
-smartlist_contains_digest(const smartlist_t *sl, const char *element)
-{
- int i;
- if (!sl) return 0;
- for (i=0; i < sl->num_used; i++)
- if (tor_memeq((const char*)sl->list[i],element,DIGEST_LEN))
- return 1;
- return 0;
-}
-
-/** Return true iff some element E of sl2 has smartlist_contains(sl1,E).
- */
-int
-smartlist_overlap(const smartlist_t *sl1, const smartlist_t *sl2)
-{
- int i;
- for (i=0; i < sl2->num_used; i++)
- if (smartlist_contains(sl1, sl2->list[i]))
- return 1;
- return 0;
-}
-
-/** Remove every element E of sl1 such that !smartlist_contains(sl2,E).
- * Does not preserve the order of sl1.
- */
-void
-smartlist_intersect(smartlist_t *sl1, const smartlist_t *sl2)
-{
- int i;
- for (i=0; i < sl1->num_used; i++)
- if (!smartlist_contains(sl2, sl1->list[i])) {
- sl1->list[i] = sl1->list[--sl1->num_used]; /* swap with the end */
- i--; /* so we process the new i'th element */
- sl1->list[sl1->num_used] = NULL;
- }
-}
-
-/** Remove every element E of sl1 such that smartlist_contains(sl2,E).
- * Does not preserve the order of sl1.
- */
-void
-smartlist_subtract(smartlist_t *sl1, const smartlist_t *sl2)
-{
- int i;
- for (i=0; i < sl2->num_used; i++)
- smartlist_remove(sl1, sl2->list[i]);
-}
-
-/** Remove the <b>idx</b>th element of sl; if idx is not the last
- * element, swap the last element of sl into the <b>idx</b>th space.
- */
-void
-smartlist_del(smartlist_t *sl, int idx)
-{
- tor_assert(sl);
- tor_assert(idx>=0);
- tor_assert(idx < sl->num_used);
- sl->list[idx] = sl->list[--sl->num_used];
- sl->list[sl->num_used] = NULL;
-}
-
-/** Remove the <b>idx</b>th element of sl; if idx is not the last element,
- * moving all subsequent elements back one space. Return the old value
- * of the <b>idx</b>th element.
- */
-void
-smartlist_del_keeporder(smartlist_t *sl, int idx)
-{
- tor_assert(sl);
- tor_assert(idx>=0);
- tor_assert(idx < sl->num_used);
- --sl->num_used;
- if (idx < sl->num_used)
- memmove(sl->list+idx, sl->list+idx+1, sizeof(void*)*(sl->num_used-idx));
- sl->list[sl->num_used] = NULL;
-}
-
-/** Insert the value <b>val</b> as the new <b>idx</b>th element of
- * <b>sl</b>, moving all items previously at <b>idx</b> or later
- * forward one space.
- */
-void
-smartlist_insert(smartlist_t *sl, int idx, void *val)
-{
- tor_assert(sl);
- tor_assert(idx>=0);
- tor_assert(idx <= sl->num_used);
- if (idx == sl->num_used) {
- smartlist_add(sl, val);
- } else {
- smartlist_ensure_capacity(sl, ((size_t) sl->num_used)+1);
- /* Move other elements away */
- if (idx < sl->num_used)
- memmove(sl->list + idx + 1, sl->list + idx,
- sizeof(void*)*(sl->num_used-idx));
- sl->num_used++;
- sl->list[idx] = val;
- }
-}
-
-/**
- * Split a string <b>str</b> along all occurrences of <b>sep</b>,
- * appending the (newly allocated) split strings, in order, to
- * <b>sl</b>. Return the number of strings added to <b>sl</b>.
- *
- * If <b>flags</b>&amp;SPLIT_SKIP_SPACE is true, remove initial and
- * trailing space from each entry.
- * If <b>flags</b>&amp;SPLIT_IGNORE_BLANK is true, remove any entries
- * of length 0.
- * If <b>flags</b>&amp;SPLIT_STRIP_SPACE is true, strip spaces from each
- * split string.
- *
- * If <b>max</b>\>0, divide the string into no more than <b>max</b> pieces. If
- * <b>sep</b> is NULL, split on any sequence of horizontal space.
- */
-int
-smartlist_split_string(smartlist_t *sl, const char *str, const char *sep,
- int flags, int max)
-{
- const char *cp, *end, *next;
- int n = 0;
-
- tor_assert(sl);
- tor_assert(str);
-
- cp = str;
- while (1) {
- if (flags&SPLIT_SKIP_SPACE) {
- while (TOR_ISSPACE(*cp)) ++cp;
- }
-
- if (max>0 && n == max-1) {
- end = strchr(cp,'\0');
- } else if (sep) {
- end = strstr(cp,sep);
- if (!end)
- end = strchr(cp,'\0');
- } else {
- for (end = cp; *end && *end != '\t' && *end != ' '; ++end)
- ;
- }
-
- tor_assert(end);
-
- if (!*end) {
- next = NULL;
- } else if (sep) {
- next = end+strlen(sep);
- } else {
- next = end+1;
- while (*next == '\t' || *next == ' ')
- ++next;
- }
-
- if (flags&SPLIT_SKIP_SPACE) {
- while (end > cp && TOR_ISSPACE(*(end-1)))
- --end;
- }
- if (end != cp || !(flags&SPLIT_IGNORE_BLANK)) {
- char *string = tor_strndup(cp, end-cp);
- if (flags&SPLIT_STRIP_SPACE)
- tor_strstrip(string, " ");
- smartlist_add(sl, string);
- ++n;
- }
- if (!next)
- break;
- cp = next;
- }
-
- return n;
-}
-
-/** Allocate and return a new string containing the concatenation of
- * the elements of <b>sl</b>, in order, separated by <b>join</b>. If
- * <b>terminate</b> is true, also terminate the string with <b>join</b>.
- * If <b>len_out</b> is not NULL, set <b>len_out</b> to the length of
- * the returned string. Requires that every element of <b>sl</b> is
- * NUL-terminated string.
- */
-char *
-smartlist_join_strings(smartlist_t *sl, const char *join,
- int terminate, size_t *len_out)
-{
- return smartlist_join_strings2(sl,join,strlen(join),terminate,len_out);
-}
-
-/** As smartlist_join_strings, but instead of separating/terminated with a
- * NUL-terminated string <b>join</b>, uses the <b>join_len</b>-byte sequence
- * at <b>join</b>. (Useful for generating a sequence of NUL-terminated
- * strings.)
- */
-char *
-smartlist_join_strings2(smartlist_t *sl, const char *join,
- size_t join_len, int terminate, size_t *len_out)
-{
- int i;
- size_t n = 0;
- char *r = NULL, *dst, *src;
-
- tor_assert(sl);
- tor_assert(join);
-
- if (terminate)
- n = join_len;
-
- for (i = 0; i < sl->num_used; ++i) {
- n += strlen(sl->list[i]);
- if (i+1 < sl->num_used) /* avoid double-counting the last one */
- n += join_len;
- }
- dst = r = tor_malloc(n+1);
- for (i = 0; i < sl->num_used; ) {
- for (src = sl->list[i]; *src; )
- *dst++ = *src++;
- if (++i < sl->num_used) {
- memcpy(dst, join, join_len);
- dst += join_len;
- }
- }
- if (terminate) {
- memcpy(dst, join, join_len);
- dst += join_len;
- }
- *dst = '\0';
-
- if (len_out)
- *len_out = dst-r;
- return r;
-}
-
-/** Sort the members of <b>sl</b> into an order defined by
- * the ordering function <b>compare</b>, which returns less then 0 if a
- * precedes b, greater than 0 if b precedes a, and 0 if a 'equals' b.
- */
-void
-smartlist_sort(smartlist_t *sl, int (*compare)(const void **a, const void **b))
-{
- if (!sl->num_used)
- return;
- qsort(sl->list, sl->num_used, sizeof(void*),
- (int (*)(const void *,const void*))compare);
-}
-
-/** Given a smartlist <b>sl</b> sorted with the function <b>compare</b>,
- * return the most frequent member in the list. Break ties in favor of
- * later elements. If the list is empty, return NULL. If count_out is
- * non-null, set it to the count of the most frequent member.
- */
-void *
-smartlist_get_most_frequent_(const smartlist_t *sl,
- int (*compare)(const void **a, const void **b),
- int *count_out)
-{
- const void *most_frequent = NULL;
- int most_frequent_count = 0;
-
- const void *cur = NULL;
- int i, count=0;
-
- if (!sl->num_used) {
- if (count_out)
- *count_out = 0;
- return NULL;
- }
- for (i = 0; i < sl->num_used; ++i) {
- const void *item = sl->list[i];
- if (cur && 0 == compare(&cur, &item)) {
- ++count;
- } else {
- if (cur && count >= most_frequent_count) {
- most_frequent = cur;
- most_frequent_count = count;
- }
- cur = item;
- count = 1;
- }
- }
- if (cur && count >= most_frequent_count) {
- most_frequent = cur;
- most_frequent_count = count;
- }
- if (count_out)
- *count_out = most_frequent_count;
- return (void*)most_frequent;
-}
-
-/** Given a sorted smartlist <b>sl</b> and the comparison function used to
- * sort it, remove all duplicate members. If free_fn is provided, calls
- * free_fn on each duplicate. Otherwise, just removes them. Preserves order.
- */
-void
-smartlist_uniq(smartlist_t *sl,
- int (*compare)(const void **a, const void **b),
- void (*free_fn)(void *a))
-{
- int i;
- for (i=1; i < sl->num_used; ++i) {
- if (compare((const void **)&(sl->list[i-1]),
- (const void **)&(sl->list[i])) == 0) {
- if (free_fn)
- free_fn(sl->list[i]);
- smartlist_del_keeporder(sl, i--);
- }
- }
-}
-
-/** Assuming the members of <b>sl</b> are in order, return a pointer to the
- * member that matches <b>key</b>. Ordering and matching are defined by a
- * <b>compare</b> function that returns 0 on a match; less than 0 if key is
- * less than member, and greater than 0 if key is greater then member.
- */
-void *
-smartlist_bsearch(smartlist_t *sl, const void *key,
- int (*compare)(const void *key, const void **member))
-{
- int found, idx;
- idx = smartlist_bsearch_idx(sl, key, compare, &found);
- return found ? smartlist_get(sl, idx) : NULL;
-}
-
-/** Assuming the members of <b>sl</b> are in order, return the index of the
- * member that matches <b>key</b>. If no member matches, return the index of
- * the first member greater than <b>key</b>, or smartlist_len(sl) if no member
- * is greater than <b>key</b>. Set <b>found_out</b> to true on a match, to
- * false otherwise. Ordering and matching are defined by a <b>compare</b>
- * function that returns 0 on a match; less than 0 if key is less than member,
- * and greater than 0 if key is greater then member.
- */
-int
-smartlist_bsearch_idx(const smartlist_t *sl, const void *key,
- int (*compare)(const void *key, const void **member),
- int *found_out)
-{
- 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;
- }
-
- /* 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) {
- 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) {
- /* sl[mid] == key; we found it */
- *found_out = 1;
- return mid;
- } 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);
-
- /*
- * 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)
-{
- return strcmp((const char*)*_a, (const char*)*_b);
-}
-
-/** Sort a smartlist <b>sl</b> containing strings into lexically ascending
- * order. */
-void
-smartlist_sort_strings(smartlist_t *sl)
-{
- smartlist_sort(sl, compare_string_ptrs_);
-}
-
-/** Return the most frequent string in the sorted list <b>sl</b> */
-const char *
-smartlist_get_most_frequent_string(smartlist_t *sl)
-{
- return smartlist_get_most_frequent(sl, compare_string_ptrs_);
-}
-
-/** Return the most frequent string in the sorted list <b>sl</b>.
- * If <b>count_out</b> is provided, set <b>count_out</b> to the
- * number of times that string appears.
- */
-const char *
-smartlist_get_most_frequent_string_(smartlist_t *sl, int *count_out)
-{
- return smartlist_get_most_frequent_(sl, compare_string_ptrs_, count_out);
-}
-
-/** Remove duplicate strings from a sorted list, and free them with tor_free().
- */
-void
-smartlist_uniq_strings(smartlist_t *sl)
-{
- smartlist_uniq(sl, compare_string_ptrs_, tor_free_);
-}
-
-/** Helper: compare two pointers. */
-static int
-compare_ptrs_(const void **_a, const void **_b)
-{
- const void *a = *_a, *b = *_b;
- if (a<b)
- return -1;
- else if (a==b)
- return 0;
- else
- return 1;
-}
-
-/** Sort <b>sl</b> in ascending order of the pointers it contains. */
-void
-smartlist_sort_pointers(smartlist_t *sl)
-{
- smartlist_sort(sl, compare_ptrs_);
-}
-
-/* Heap-based priority queue implementation for O(lg N) insert and remove.
- * Recall that the heap property is that, for every index I, h[I] <
- * H[LEFT_CHILD[I]] and h[I] < H[RIGHT_CHILD[I]].
- *
- * For us to remove items other than the topmost item, each item must store
- * its own index within the heap. When calling the pqueue functions, tell
- * them about the offset of the field that stores the index within the item.
- *
- * Example:
- *
- * typedef struct timer_t {
- * struct timeval tv;
- * int heap_index;
- * } timer_t;
- *
- * static int compare(const void *p1, const void *p2) {
- * const timer_t *t1 = p1, *t2 = p2;
- * if (t1->tv.tv_sec < t2->tv.tv_sec) {
- * return -1;
- * } else if (t1->tv.tv_sec > t2->tv.tv_sec) {
- * return 1;
- * } else {
- * return t1->tv.tv_usec - t2->tv_usec;
- * }
- * }
- *
- * void timer_heap_insert(smartlist_t *heap, timer_t *timer) {
- * smartlist_pqueue_add(heap, compare, offsetof(timer_t, heap_index),
- * timer);
- * }
- *
- * void timer_heap_pop(smartlist_t *heap) {
- * return smartlist_pqueue_pop(heap, compare,
- * offsetof(timer_t, heap_index));
- * }
- */
-
-/** @{ */
-/** Functions to manipulate heap indices to find a node's parent and children.
- *
- * For a 1-indexed array, we would use LEFT_CHILD[x] = 2*x and RIGHT_CHILD[x]
- * = 2*x + 1. But this is C, so we have to adjust a little. */
-
-/* MAX_PARENT_IDX is the largest IDX in the smartlist which might have
- * children whose indices fit inside an int.
- * LEFT_CHILD(MAX_PARENT_IDX) == INT_MAX-2;
- * RIGHT_CHILD(MAX_PARENT_IDX) == INT_MAX-1;
- * LEFT_CHILD(MAX_PARENT_IDX + 1) == INT_MAX // impossible, see max list size.
- */
-#define MAX_PARENT_IDX ((INT_MAX - 2) / 2)
-/* If this is true, then i is small enough to potentially have children
- * in the smartlist, and it is save to use LEFT_CHILD/RIGHT_CHILD on it. */
-#define IDX_MAY_HAVE_CHILDREN(i) ((i) <= MAX_PARENT_IDX)
-#define LEFT_CHILD(i) ( 2*(i) + 1 )
-#define RIGHT_CHILD(i) ( 2*(i) + 2 )
-#define PARENT(i) ( ((i)-1) / 2 )
-/** }@ */
-
-/** @{ */
-/** Helper macros for heaps: Given a local variable <b>idx_field_offset</b>
- * set to the offset of an integer index within the heap element structure,
- * IDX_OF_ITEM(p) gives you the index of p, and IDXP(p) gives you a pointer to
- * where p's index is stored. Given additionally a local smartlist <b>sl</b>,
- * UPDATE_IDX(i) sets the index of the element at <b>i</b> to the correct
- * value (that is, to <b>i</b>).
- */
-#define IDXP(p) ((int*)STRUCT_VAR_P(p, idx_field_offset))
-
-#define UPDATE_IDX(i) do { \
- void *updated = sl->list[i]; \
- *IDXP(updated) = i; \
- } while (0)
-
-#define IDX_OF_ITEM(p) (*IDXP(p))
-/** @} */
-
-/** Helper. <b>sl</b> may have at most one violation of the heap property:
- * the item at <b>idx</b> may be greater than one or both of its children.
- * Restore the heap property. */
-static inline void
-smartlist_heapify(smartlist_t *sl,
- int (*compare)(const void *a, const void *b),
- int idx_field_offset,
- int idx)
-{
- while (1) {
- if (! IDX_MAY_HAVE_CHILDREN(idx)) {
- /* idx is so large that it cannot have any children, since doing so
- * would mean the smartlist was over-capacity. Therefore it cannot
- * violate the heap property by being greater than a child (since it
- * doesn't have any). */
- return;
- }
-
- int left_idx = LEFT_CHILD(idx);
- int best_idx;
-
- if (left_idx >= sl->num_used)
- return;
- if (compare(sl->list[idx],sl->list[left_idx]) < 0)
- best_idx = idx;
- else
- best_idx = left_idx;
- if (left_idx+1 < sl->num_used &&
- compare(sl->list[left_idx+1],sl->list[best_idx]) < 0)
- best_idx = left_idx + 1;
-
- if (best_idx == idx) {
- return;
- } else {
- void *tmp = sl->list[idx];
- sl->list[idx] = sl->list[best_idx];
- sl->list[best_idx] = tmp;
- UPDATE_IDX(idx);
- UPDATE_IDX(best_idx);
-
- idx = best_idx;
- }
- }
-}
-
-/** Insert <b>item</b> into the heap stored in <b>sl</b>, where order is
- * determined by <b>compare</b> and the offset of the item in the heap is
- * stored in an int-typed field at position <b>idx_field_offset</b> within
- * item.
- */
-void
-smartlist_pqueue_add(smartlist_t *sl,
- int (*compare)(const void *a, const void *b),
- int idx_field_offset,
- void *item)
-{
- int idx;
- smartlist_add(sl,item);
- UPDATE_IDX(sl->num_used-1);
-
- for (idx = sl->num_used - 1; idx; ) {
- int parent = PARENT(idx);
- if (compare(sl->list[idx], sl->list[parent]) < 0) {
- void *tmp = sl->list[parent];
- sl->list[parent] = sl->list[idx];
- sl->list[idx] = tmp;
- UPDATE_IDX(parent);
- UPDATE_IDX(idx);
- idx = parent;
- } else {
- return;
- }
- }
-}
-
-/** Remove and return the top-priority item from the heap stored in <b>sl</b>,
- * where order is determined by <b>compare</b> and the item's position is
- * stored at position <b>idx_field_offset</b> within the item. <b>sl</b> must
- * not be empty. */
-void *
-smartlist_pqueue_pop(smartlist_t *sl,
- int (*compare)(const void *a, const void *b),
- int idx_field_offset)
-{
- void *top;
- tor_assert(sl->num_used);
-
- top = sl->list[0];
- *IDXP(top)=-1;
- if (--sl->num_used) {
- sl->list[0] = sl->list[sl->num_used];
- sl->list[sl->num_used] = NULL;
- UPDATE_IDX(0);
- smartlist_heapify(sl, compare, idx_field_offset, 0);
- }
- sl->list[sl->num_used] = NULL;
- return top;
-}
-
-/** Remove the item <b>item</b> from the heap stored in <b>sl</b>,
- * where order is determined by <b>compare</b> and the item's position is
- * stored at position <b>idx_field_offset</b> within the item. <b>sl</b> must
- * not be empty. */
-void
-smartlist_pqueue_remove(smartlist_t *sl,
- int (*compare)(const void *a, const void *b),
- int idx_field_offset,
- void *item)
-{
- int idx = IDX_OF_ITEM(item);
- tor_assert(idx >= 0);
- tor_assert(sl->list[idx] == item);
- --sl->num_used;
- *IDXP(item) = -1;
- if (idx == sl->num_used) {
- sl->list[sl->num_used] = NULL;
- return;
- } else {
- sl->list[idx] = sl->list[sl->num_used];
- sl->list[sl->num_used] = NULL;
- UPDATE_IDX(idx);
- smartlist_heapify(sl, compare, idx_field_offset, idx);
- }
-}
-
-/** Assert that the heap property is correctly maintained by the heap stored
- * in <b>sl</b>, where order is determined by <b>compare</b>. */
-void
-smartlist_pqueue_assert_ok(smartlist_t *sl,
- int (*compare)(const void *a, const void *b),
- int idx_field_offset)
-{
- int i;
- for (i = sl->num_used - 1; i >= 0; --i) {
- if (i>0)
- tor_assert(compare(sl->list[PARENT(i)], sl->list[i]) <= 0);
- tor_assert(IDX_OF_ITEM(sl->list[i]) == i);
- }
-}
-
-/** Helper: compare two DIGEST_LEN digests. */
-static int
-compare_digests_(const void **_a, const void **_b)
-{
- return tor_memcmp((const char*)*_a, (const char*)*_b, DIGEST_LEN);
-}
-
-/** Sort the list of DIGEST_LEN-byte digests into ascending order. */
-void
-smartlist_sort_digests(smartlist_t *sl)
-{
- smartlist_sort(sl, compare_digests_);
-}
-
-/** Remove duplicate digests from a sorted list, and free them with tor_free().
- */
-void
-smartlist_uniq_digests(smartlist_t *sl)
-{
- smartlist_uniq(sl, compare_digests_, tor_free_);
-}
-
-/** Helper: compare two DIGEST256_LEN digests. */
-static int
-compare_digests256_(const void **_a, const void **_b)
-{
- return tor_memcmp((const char*)*_a, (const char*)*_b, DIGEST256_LEN);
-}
-
-/** Sort the list of DIGEST256_LEN-byte digests into ascending order. */
-void
-smartlist_sort_digests256(smartlist_t *sl)
-{
- smartlist_sort(sl, compare_digests256_);
-}
-
-/** Return the most frequent member of the sorted list of DIGEST256_LEN
- * digests in <b>sl</b> */
-const uint8_t *
-smartlist_get_most_frequent_digest256(smartlist_t *sl)
-{
- return smartlist_get_most_frequent(sl, compare_digests256_);
-}
-
-/** Remove duplicate 256-bit digests from a sorted list, and free them with
- * tor_free().
- */
-void
-smartlist_uniq_digests256(smartlist_t *sl)
-{
- smartlist_uniq(sl, compare_digests256_, tor_free_);
-}
-
-/** Helper: Declare an entry type and a map type to implement a mapping using
- * ht.h. The map type will be called <b>maptype</b>. The key part of each
- * entry is declared using the C declaration <b>keydecl</b>. All functions
- * and types associated with the map get prefixed with <b>prefix</b> */
-#define DEFINE_MAP_STRUCTS(maptype, keydecl, prefix) \
- typedef struct prefix ## entry_t { \
- HT_ENTRY(prefix ## entry_t) node; \
- void *val; \
- keydecl; \
- } prefix ## entry_t; \
- struct maptype { \
- HT_HEAD(prefix ## impl, prefix ## entry_t) head; \
- }
-
-DEFINE_MAP_STRUCTS(strmap_t, char *key, strmap_);
-DEFINE_MAP_STRUCTS(digestmap_t, char key[DIGEST_LEN], digestmap_);
-DEFINE_MAP_STRUCTS(digest256map_t, uint8_t key[DIGEST256_LEN], digest256map_);
-
-/** Helper: compare strmap_entry_t objects by key value. */
-static inline int
-strmap_entries_eq(const strmap_entry_t *a, const strmap_entry_t *b)
-{
- return !strcmp(a->key, b->key);
-}
-
-/** Helper: return a hash value for a strmap_entry_t. */
-static inline unsigned int
-strmap_entry_hash(const strmap_entry_t *a)
-{
- return (unsigned) siphash24g(a->key, strlen(a->key));
-}
-
-/** Helper: compare digestmap_entry_t objects by key value. */
-static inline int
-digestmap_entries_eq(const digestmap_entry_t *a, const digestmap_entry_t *b)
-{
- return tor_memeq(a->key, b->key, DIGEST_LEN);
-}
-
-/** Helper: return a hash value for a digest_map_t. */
-static inline unsigned int
-digestmap_entry_hash(const digestmap_entry_t *a)
-{
- return (unsigned) siphash24g(a->key, DIGEST_LEN);
-}
-
-/** Helper: compare digestmap_entry_t objects by key value. */
-static inline int
-digest256map_entries_eq(const digest256map_entry_t *a,
- const digest256map_entry_t *b)
-{
- return tor_memeq(a->key, b->key, DIGEST256_LEN);
-}
-
-/** Helper: return a hash value for a digest_map_t. */
-static inline unsigned int
-digest256map_entry_hash(const digest256map_entry_t *a)
-{
- return (unsigned) siphash24g(a->key, DIGEST256_LEN);
-}
-
-HT_PROTOTYPE(strmap_impl, strmap_entry_t, node, strmap_entry_hash,
- strmap_entries_eq)
-HT_GENERATE2(strmap_impl, strmap_entry_t, node, strmap_entry_hash,
- strmap_entries_eq, 0.6, tor_reallocarray_, tor_free_)
-
-HT_PROTOTYPE(digestmap_impl, digestmap_entry_t, node, digestmap_entry_hash,
- digestmap_entries_eq)
-HT_GENERATE2(digestmap_impl, digestmap_entry_t, node, digestmap_entry_hash,
- digestmap_entries_eq, 0.6, tor_reallocarray_, tor_free_)
-
-HT_PROTOTYPE(digest256map_impl, digest256map_entry_t, node,
- digest256map_entry_hash,
- digest256map_entries_eq)
-HT_GENERATE2(digest256map_impl, digest256map_entry_t, node,
- digest256map_entry_hash,
- digest256map_entries_eq, 0.6, tor_reallocarray_, tor_free_)
-
-#define strmap_entry_free(ent) \
- FREE_AND_NULL(strmap_entry_t, strmap_entry_free_, (ent))
-#define digestmap_entry_free(ent) \
- FREE_AND_NULL(digestmap_entry_t, digestmap_entry_free_, (ent))
-#define digest256map_entry_free(ent) \
- FREE_AND_NULL(digest256map_entry_t, digest256map_entry_free_, (ent))
-
-static inline void
-strmap_entry_free_(strmap_entry_t *ent)
-{
- tor_free(ent->key);
- tor_free(ent);
-}
-static inline void
-digestmap_entry_free_(digestmap_entry_t *ent)
-{
- tor_free(ent);
-}
-static inline void
-digest256map_entry_free_(digest256map_entry_t *ent)
-{
- tor_free(ent);
-}
-
-static inline void
-strmap_assign_tmp_key(strmap_entry_t *ent, const char *key)
-{
- ent->key = (char*)key;
-}
-static inline void
-digestmap_assign_tmp_key(digestmap_entry_t *ent, const char *key)
-{
- memcpy(ent->key, key, DIGEST_LEN);
-}
-static inline void
-digest256map_assign_tmp_key(digest256map_entry_t *ent, const uint8_t *key)
-{
- memcpy(ent->key, key, DIGEST256_LEN);
-}
-static inline void
-strmap_assign_key(strmap_entry_t *ent, const char *key)
-{
- ent->key = tor_strdup(key);
-}
-static inline void
-digestmap_assign_key(digestmap_entry_t *ent, const char *key)
-{
- memcpy(ent->key, key, DIGEST_LEN);
-}
-static inline void
-digest256map_assign_key(digest256map_entry_t *ent, const uint8_t *key)
-{
- memcpy(ent->key, key, DIGEST256_LEN);
-}
-
-/**
- * Macro: implement all the functions for a map that are declared in
- * container.h by the DECLARE_MAP_FNS() macro. You must additionally define a
- * prefix_entry_free_() function to free entries (and their keys), a
- * prefix_assign_tmp_key() function to temporarily set a stack-allocated
- * entry to hold a key, and a prefix_assign_key() function to set a
- * heap-allocated entry to hold a key.
- */
-#define IMPLEMENT_MAP_FNS(maptype, keytype, prefix) \
- /** Create and return a new empty map. */ \
- MOCK_IMPL(maptype *, \
- prefix##_new,(void)) \
- { \
- maptype *result; \
- result = tor_malloc(sizeof(maptype)); \
- HT_INIT(prefix##_impl, &result->head); \
- return result; \
- } \
- \
- /** Return the item from <b>map</b> whose key matches <b>key</b>, or \
- * NULL if no such value exists. */ \
- void * \
- prefix##_get(const maptype *map, const keytype key) \
- { \
- prefix ##_entry_t *resolve; \
- prefix ##_entry_t search; \
- tor_assert(map); \
- tor_assert(key); \
- prefix ##_assign_tmp_key(&search, key); \
- resolve = HT_FIND(prefix ##_impl, &map->head, &search); \
- if (resolve) { \
- return resolve->val; \
- } else { \
- return NULL; \
- } \
- } \
- \
- /** Add an entry to <b>map</b> mapping <b>key</b> to <b>val</b>; \
- * return the previous value, or NULL if no such value existed. */ \
- void * \
- prefix##_set(maptype *map, const keytype key, void *val) \
- { \
- prefix##_entry_t search; \
- void *oldval; \
- tor_assert(map); \
- tor_assert(key); \
- tor_assert(val); \
- prefix##_assign_tmp_key(&search, key); \
- /* We a lot of our time in this function, so the code below is */ \
- /* meant to optimize the check/alloc/set cycle by avoiding the two */\
- /* trips to the hash table that we would do in the unoptimized */ \
- /* version of this code. (Each of HT_INSERT and HT_FIND calls */ \
- /* HT_SET_HASH and HT_FIND_P.) */ \
- HT_FIND_OR_INSERT_(prefix##_impl, node, prefix##_entry_hash, \
- &(map->head), \
- prefix##_entry_t, &search, ptr, \
- { \
- /* we found an entry. */ \
- oldval = (*ptr)->val; \
- (*ptr)->val = val; \
- return oldval; \
- }, \
- { \
- /* We didn't find the entry. */ \
- prefix##_entry_t *newent = \
- tor_malloc_zero(sizeof(prefix##_entry_t)); \
- prefix##_assign_key(newent, key); \
- newent->val = val; \
- HT_FOI_INSERT_(node, &(map->head), \
- &search, newent, ptr); \
- return NULL; \
- }); \
- } \
- \
- /** Remove the value currently associated with <b>key</b> from the map. \
- * Return the value if one was set, or NULL if there was no entry for \
- * <b>key</b>. \
- * \
- * Note: you must free any storage associated with the returned value. \
- */ \
- void * \
- prefix##_remove(maptype *map, const keytype key) \
- { \
- prefix##_entry_t *resolve; \
- prefix##_entry_t search; \
- void *oldval; \
- tor_assert(map); \
- tor_assert(key); \
- prefix##_assign_tmp_key(&search, key); \
- resolve = HT_REMOVE(prefix##_impl, &map->head, &search); \
- if (resolve) { \
- oldval = resolve->val; \
- prefix##_entry_free(resolve); \
- return oldval; \
- } else { \
- return NULL; \
- } \
- } \
- \
- /** Return the number of elements in <b>map</b>. */ \
- int \
- prefix##_size(const maptype *map) \
- { \
- return HT_SIZE(&map->head); \
- } \
- \
- /** Return true iff <b>map</b> has no entries. */ \
- int \
- prefix##_isempty(const maptype *map) \
- { \
- return HT_EMPTY(&map->head); \
- } \
- \
- /** Assert that <b>map</b> is not corrupt. */ \
- void \
- prefix##_assert_ok(const maptype *map) \
- { \
- tor_assert(!prefix##_impl_HT_REP_IS_BAD_(&map->head)); \
- } \
- \
- /** Remove all entries from <b>map</b>, and deallocate storage for \
- * those entries. If free_val is provided, invoked it every value in \
- * <b>map</b>. */ \
- MOCK_IMPL(void, \
- prefix##_free_, (maptype *map, void (*free_val)(void*))) \
- { \
- prefix##_entry_t **ent, **next, *this; \
- if (!map) \
- return; \
- for (ent = HT_START(prefix##_impl, &map->head); ent != NULL; \
- ent = next) { \
- this = *ent; \
- next = HT_NEXT_RMV(prefix##_impl, &map->head, ent); \
- if (free_val) \
- free_val(this->val); \
- prefix##_entry_free(this); \
- } \
- tor_assert(HT_EMPTY(&map->head)); \
- HT_CLEAR(prefix##_impl, &map->head); \
- tor_free(map); \
- } \
- \
- /** return an <b>iterator</b> pointer to the front of a map. \
- * \
- * Iterator example: \
- * \
- * \code \
- * // uppercase values in "map", removing empty values. \
- * \
- * strmap_iter_t *iter; \
- * const char *key; \
- * void *val; \
- * char *cp; \
- * \
- * for (iter = strmap_iter_init(map); !strmap_iter_done(iter); ) { \
- * strmap_iter_get(iter, &key, &val); \
- * cp = (char*)val; \
- * if (!*cp) { \
- * iter = strmap_iter_next_rmv(map,iter); \
- * free(val); \
- * } else { \
- * for (;*cp;cp++) *cp = TOR_TOUPPER(*cp); \
- */ \
- prefix##_iter_t * \
- prefix##_iter_init(maptype *map) \
- { \
- tor_assert(map); \
- return HT_START(prefix##_impl, &map->head); \
- } \
- \
- /** Advance <b>iter</b> a single step to the next entry, and return \
- * its new value. */ \
- prefix##_iter_t * \
- prefix##_iter_next(maptype *map, prefix##_iter_t *iter) \
- { \
- tor_assert(map); \
- tor_assert(iter); \
- return HT_NEXT(prefix##_impl, &map->head, iter); \
- } \
- /** Advance <b>iter</b> a single step to the next entry, removing the \
- * current entry, and return its new value. */ \
- prefix##_iter_t * \
- prefix##_iter_next_rmv(maptype *map, prefix##_iter_t *iter) \
- { \
- prefix##_entry_t *rmv; \
- tor_assert(map); \
- tor_assert(iter); \
- tor_assert(*iter); \
- rmv = *iter; \
- iter = HT_NEXT_RMV(prefix##_impl, &map->head, iter); \
- prefix##_entry_free(rmv); \
- return iter; \
- } \
- /** Set *<b>keyp</b> and *<b>valp</b> to the current entry pointed \
- * to by iter. */ \
- void \
- prefix##_iter_get(prefix##_iter_t *iter, const keytype *keyp, \
- void **valp) \
- { \
- tor_assert(iter); \
- tor_assert(*iter); \
- tor_assert(keyp); \
- tor_assert(valp); \
- *keyp = (*iter)->key; \
- *valp = (*iter)->val; \
- } \
- /** Return true iff <b>iter</b> has advanced past the last entry of \
- * <b>map</b>. */ \
- int \
- prefix##_iter_done(prefix##_iter_t *iter) \
- { \
- return iter == NULL; \
- }
-
-IMPLEMENT_MAP_FNS(strmap_t, char *, strmap)
-IMPLEMENT_MAP_FNS(digestmap_t, char *, digestmap)
-IMPLEMENT_MAP_FNS(digest256map_t, uint8_t *, digest256map)
-
-/** Same as strmap_set, but first converts <b>key</b> to lowercase. */
-void *
-strmap_set_lc(strmap_t *map, const char *key, void *val)
-{
- /* We could be a little faster by using strcasecmp instead, and a separate
- * type, but I don't think it matters. */
- void *v;
- char *lc_key = tor_strdup(key);
- tor_strlower(lc_key);
- v = strmap_set(map,lc_key,val);
- tor_free(lc_key);
- return v;
-}
-
-/** Same as strmap_get, but first converts <b>key</b> to lowercase. */
-void *
-strmap_get_lc(const strmap_t *map, const char *key)
-{
- void *v;
- char *lc_key = tor_strdup(key);
- tor_strlower(lc_key);
- v = strmap_get(map,lc_key);
- tor_free(lc_key);
- return v;
-}
-
-/** Same as strmap_remove, but first converts <b>key</b> to lowercase */
-void *
-strmap_remove_lc(strmap_t *map, const char *key)
-{
- void *v;
- char *lc_key = tor_strdup(key);
- tor_strlower(lc_key);
- v = strmap_remove(map,lc_key);
- tor_free(lc_key);
- return v;
-}
-
-/** Declare a function called <b>funcname</b> that acts as a find_nth_FOO
- * function for an array of type <b>elt_t</b>*.
- *
- * NOTE: The implementation kind of sucks: It's O(n log n), whereas finding
- * the kth element of an n-element list can be done in O(n). Then again, this
- * implementation is not in critical path, and it is obviously correct. */
-#define IMPLEMENT_ORDER_FUNC(funcname, elt_t) \
- static int \
- _cmp_ ## elt_t(const void *_a, const void *_b) \
- { \
- const elt_t *a = _a, *b = _b; \
- if (*a<*b) \
- return -1; \
- else if (*a>*b) \
- return 1; \
- else \
- return 0; \
- } \
- elt_t \
- funcname(elt_t *array, int n_elements, int nth) \
- { \
- tor_assert(nth >= 0); \
- tor_assert(nth < n_elements); \
- qsort(array, n_elements, sizeof(elt_t), _cmp_ ##elt_t); \
- return array[nth]; \
- }
-
-IMPLEMENT_ORDER_FUNC(find_nth_int, int)
-IMPLEMENT_ORDER_FUNC(find_nth_time, time_t)
-IMPLEMENT_ORDER_FUNC(find_nth_double, double)
-IMPLEMENT_ORDER_FUNC(find_nth_uint32, uint32_t)
-IMPLEMENT_ORDER_FUNC(find_nth_int32, int32_t)
-IMPLEMENT_ORDER_FUNC(find_nth_long, long)
-
-/** Return a newly allocated digestset_t, optimized to hold a total of
- * <b>max_elements</b> digests with a reasonably low false positive weight. */
-digestset_t *
-digestset_new(int max_elements)
-{
- /* The probability of false positives is about P=(1 - exp(-kn/m))^k, where k
- * is the number of hash functions per entry, m is the bits in the array,
- * and n is the number of elements inserted. For us, k==4, n<=max_elements,
- * and m==n_bits= approximately max_elements*32. This gives
- * P<(1-exp(-4*n/(32*n)))^4 == (1-exp(1/-8))^4 == .00019
- *
- * It would be more optimal in space vs false positives to get this false
- * positive rate by going for k==13, and m==18.5n, but we also want to
- * conserve CPU, and k==13 is pretty big.
- */
- int n_bits = 1u << (tor_log2(max_elements)+5);
- digestset_t *r = tor_malloc(sizeof(digestset_t));
- r->mask = n_bits - 1;
- r->ba = bitarray_init_zero(n_bits);
- return r;
-}
-
-/** Free all storage held in <b>set</b>. */
-void
-digestset_free_(digestset_t *set)
-{
- if (!set)
- return;
- bitarray_free(set->ba);
- tor_free(set);
-}
-
diff --git a/src/common/container.h b/src/common/container.h
deleted file mode 100644
index 5d2dce5416..0000000000
--- a/src/common/container.h
+++ /dev/null
@@ -1,742 +0,0 @@
-/* Copyright (c) 2003-2004, Roger Dingledine
- * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2017, The Tor Project, Inc. */
-/* See LICENSE for licensing information */
-
-#ifndef TOR_CONTAINER_H
-#define TOR_CONTAINER_H
-
-#include "util.h"
-#include "siphash.h"
-
-/** A resizeable list of pointers, with associated helpful functionality.
- *
- * The members of this struct are exposed only so that macros and inlines can
- * use them; all access to smartlist internals should go through the functions
- * and macros defined here.
- **/
-typedef struct smartlist_t {
- /** @{ */
- /** <b>list</b> has enough capacity to store exactly <b>capacity</b> elements
- * before it needs to be resized. Only the first <b>num_used</b> (\<=
- * capacity) elements point to valid data.
- */
- void **list;
- int num_used;
- int capacity;
- /** @} */
-} smartlist_t;
-
-MOCK_DECL(smartlist_t *, smartlist_new, (void));
-MOCK_DECL(void, smartlist_free_, (smartlist_t *sl));
-#define smartlist_free(sl) FREE_AND_NULL(smartlist_t, smartlist_free_, (sl))
-
-void smartlist_clear(smartlist_t *sl);
-void smartlist_add(smartlist_t *sl, void *element);
-void smartlist_add_all(smartlist_t *sl, const smartlist_t *s2);
-void smartlist_remove(smartlist_t *sl, const void *element);
-void smartlist_remove_keeporder(smartlist_t *sl, const void *element);
-void *smartlist_pop_last(smartlist_t *sl);
-void smartlist_reverse(smartlist_t *sl);
-void smartlist_string_remove(smartlist_t *sl, const char *element);
-int smartlist_contains(const smartlist_t *sl, const void *element);
-int smartlist_contains_string(const smartlist_t *sl, const char *element);
-int smartlist_pos(const smartlist_t *sl, const void *element);
-int smartlist_string_pos(const smartlist_t *, const char *elt);
-int smartlist_contains_string_case(const smartlist_t *sl, const char *element);
-int smartlist_contains_int_as_string(const smartlist_t *sl, int num);
-int smartlist_strings_eq(const smartlist_t *sl1, const smartlist_t *sl2);
-int smartlist_contains_digest(const smartlist_t *sl, const char *element);
-int smartlist_ints_eq(const smartlist_t *sl1, const smartlist_t *sl2);
-int smartlist_overlap(const smartlist_t *sl1, const smartlist_t *sl2);
-void smartlist_intersect(smartlist_t *sl1, const smartlist_t *sl2);
-void smartlist_subtract(smartlist_t *sl1, const smartlist_t *sl2);
-
-/* smartlist_choose() is defined in crypto.[ch] */
-#ifdef DEBUG_SMARTLIST
-/** Return the number of items in sl.
- */
-static inline int smartlist_len(const smartlist_t *sl);
-static inline int smartlist_len(const smartlist_t *sl) {
- tor_assert(sl);
- return (sl)->num_used;
-}
-/** Return the <b>idx</b>th element of sl.
- */
-static inline void *smartlist_get(const smartlist_t *sl, int idx);
-static inline void *smartlist_get(const smartlist_t *sl, int idx) {
- tor_assert(sl);
- tor_assert(idx>=0);
- tor_assert(sl->num_used > idx);
- return sl->list[idx];
-}
-static inline void smartlist_set(smartlist_t *sl, int idx, void *val) {
- tor_assert(sl);
- tor_assert(idx>=0);
- tor_assert(sl->num_used > idx);
- sl->list[idx] = val;
-}
-#else /* !(defined(DEBUG_SMARTLIST)) */
-#define smartlist_len(sl) ((sl)->num_used)
-#define smartlist_get(sl, idx) ((sl)->list[idx])
-#define smartlist_set(sl, idx, val) ((sl)->list[idx] = (val))
-#endif /* defined(DEBUG_SMARTLIST) */
-
-/** Exchange the elements at indices <b>idx1</b> and <b>idx2</b> of the
- * smartlist <b>sl</b>. */
-static inline void smartlist_swap(smartlist_t *sl, int idx1, int idx2)
-{
- if (idx1 != idx2) {
- void *elt = smartlist_get(sl, idx1);
- smartlist_set(sl, idx1, smartlist_get(sl, idx2));
- smartlist_set(sl, idx2, elt);
- }
-}
-
-void smartlist_del(smartlist_t *sl, int idx);
-void smartlist_del_keeporder(smartlist_t *sl, int idx);
-void smartlist_insert(smartlist_t *sl, int idx, void *val);
-void smartlist_sort(smartlist_t *sl,
- int (*compare)(const void **a, const void **b));
-void *smartlist_get_most_frequent_(const smartlist_t *sl,
- int (*compare)(const void **a, const void **b),
- int *count_out);
-#define smartlist_get_most_frequent(sl, compare) \
- smartlist_get_most_frequent_((sl), (compare), NULL)
-void smartlist_uniq(smartlist_t *sl,
- int (*compare)(const void **a, const void **b),
- void (*free_fn)(void *elt));
-
-void smartlist_sort_strings(smartlist_t *sl);
-void smartlist_sort_digests(smartlist_t *sl);
-void smartlist_sort_digests256(smartlist_t *sl);
-void smartlist_sort_pointers(smartlist_t *sl);
-
-const char *smartlist_get_most_frequent_string(smartlist_t *sl);
-const char *smartlist_get_most_frequent_string_(smartlist_t *sl,
- int *count_out);
-const uint8_t *smartlist_get_most_frequent_digest256(smartlist_t *sl);
-
-void smartlist_uniq_strings(smartlist_t *sl);
-void smartlist_uniq_digests(smartlist_t *sl);
-void smartlist_uniq_digests256(smartlist_t *sl);
-void *smartlist_bsearch(smartlist_t *sl, const void *key,
- int (*compare)(const void *key, const void **member));
-int smartlist_bsearch_idx(const smartlist_t *sl, const void *key,
- int (*compare)(const void *key, const void **member),
- int *found_out);
-
-void smartlist_pqueue_add(smartlist_t *sl,
- int (*compare)(const void *a, const void *b),
- int idx_field_offset,
- void *item);
-void *smartlist_pqueue_pop(smartlist_t *sl,
- int (*compare)(const void *a, const void *b),
- int idx_field_offset);
-void smartlist_pqueue_remove(smartlist_t *sl,
- int (*compare)(const void *a, const void *b),
- int idx_field_offset,
- void *item);
-void smartlist_pqueue_assert_ok(smartlist_t *sl,
- int (*compare)(const void *a, const void *b),
- int idx_field_offset);
-
-#define SPLIT_SKIP_SPACE 0x01
-#define SPLIT_IGNORE_BLANK 0x02
-#define SPLIT_STRIP_SPACE 0x04
-int smartlist_split_string(smartlist_t *sl, const char *str, const char *sep,
- int flags, int max);
-char *smartlist_join_strings(smartlist_t *sl, const char *join, int terminate,
- size_t *len_out) ATTR_MALLOC;
-char *smartlist_join_strings2(smartlist_t *sl, const char *join,
- size_t join_len, int terminate, size_t *len_out)
- ATTR_MALLOC;
-
-/** Iterate over the items in a smartlist <b>sl</b>, in order. For each item,
- * assign it to a new local variable of type <b>type</b> named <b>var</b>, and
- * execute the statements inside the loop body. Inside the loop, the loop
- * index can be accessed as <b>var</b>_sl_idx and the length of the list can
- * be accessed as <b>var</b>_sl_len.
- *
- * NOTE: Do not change the length of the list while the loop is in progress,
- * unless you adjust the _sl_len variable correspondingly. See second example
- * below.
- *
- * Example use:
- * <pre>
- * smartlist_t *list = smartlist_split("A:B:C", ":", 0, 0);
- * SMARTLIST_FOREACH_BEGIN(list, char *, cp) {
- * printf("%d: %s\n", cp_sl_idx, cp);
- * tor_free(cp);
- * } SMARTLIST_FOREACH_END(cp);
- * smartlist_free(list);
- * </pre>
- *
- * Example use (advanced):
- * <pre>
- * SMARTLIST_FOREACH_BEGIN(list, char *, cp) {
- * if (!strcmp(cp, "junk")) {
- * tor_free(cp);
- * SMARTLIST_DEL_CURRENT(list, cp);
- * }
- * } SMARTLIST_FOREACH_END(cp);
- * </pre>
- */
-/* Note: these macros use token pasting, and reach into smartlist internals.
- * This can make them a little daunting. Here's the approximate unpacking of
- * the above examples, for entertainment value:
- *
- * <pre>
- * smartlist_t *list = smartlist_split("A:B:C", ":", 0, 0);
- * {
- * int cp_sl_idx, cp_sl_len = smartlist_len(list);
- * char *cp;
- * for (cp_sl_idx = 0; cp_sl_idx < cp_sl_len; ++cp_sl_idx) {
- * cp = smartlist_get(list, cp_sl_idx);
- * printf("%d: %s\n", cp_sl_idx, cp);
- * tor_free(cp);
- * }
- * }
- * smartlist_free(list);
- * </pre>
- *
- * <pre>
- * {
- * int cp_sl_idx, cp_sl_len = smartlist_len(list);
- * char *cp;
- * for (cp_sl_idx = 0; cp_sl_idx < cp_sl_len; ++cp_sl_idx) {
- * cp = smartlist_get(list, cp_sl_idx);
- * if (!strcmp(cp, "junk")) {
- * tor_free(cp);
- * smartlist_del(list, cp_sl_idx);
- * --cp_sl_idx;
- * --cp_sl_len;
- * }
- * }
- * }
- * </pre>
- */
-#define SMARTLIST_FOREACH_BEGIN(sl, type, var) \
- STMT_BEGIN \
- int var ## _sl_idx, var ## _sl_len=(sl)->num_used; \
- type var; \
- for (var ## _sl_idx = 0; var ## _sl_idx < var ## _sl_len; \
- ++var ## _sl_idx) { \
- var = (sl)->list[var ## _sl_idx];
-
-#define SMARTLIST_FOREACH_END(var) \
- var = NULL; \
- (void) var ## _sl_idx; \
- } STMT_END
-
-/**
- * An alias for SMARTLIST_FOREACH_BEGIN and SMARTLIST_FOREACH_END, using
- * <b>cmd</b> as the loop body. This wrapper is here for convenience with
- * very short loops.
- *
- * By convention, we do not use this for loops which nest, or for loops over
- * 10 lines or so. Use SMARTLIST_FOREACH_{BEGIN,END} for those.
- */
-#define SMARTLIST_FOREACH(sl, type, var, cmd) \
- SMARTLIST_FOREACH_BEGIN(sl,type,var) { \
- cmd; \
- } SMARTLIST_FOREACH_END(var)
-
-/** Helper: While in a SMARTLIST_FOREACH loop over the list <b>sl</b> indexed
- * with the variable <b>var</b>, remove the current element in a way that
- * won't confuse the loop. */
-#define SMARTLIST_DEL_CURRENT(sl, var) \
- STMT_BEGIN \
- smartlist_del(sl, var ## _sl_idx); \
- --var ## _sl_idx; \
- --var ## _sl_len; \
- STMT_END
-
-/** Helper: While in a SMARTLIST_FOREACH loop over the list <b>sl</b> indexed
- * with the variable <b>var</b>, remove the current element in a way that
- * won't confuse the loop. */
-#define SMARTLIST_DEL_CURRENT_KEEPORDER(sl, var) \
- STMT_BEGIN \
- smartlist_del_keeporder(sl, var ## _sl_idx); \
- --var ## _sl_idx; \
- --var ## _sl_len; \
- STMT_END
-
-/** Helper: While in a SMARTLIST_FOREACH loop over the list <b>sl</b> indexed
- * with the variable <b>var</b>, replace the current element with <b>val</b>.
- * Does not deallocate the current value of <b>var</b>.
- */
-#define SMARTLIST_REPLACE_CURRENT(sl, var, val) \
- STMT_BEGIN \
- smartlist_set(sl, var ## _sl_idx, val); \
- STMT_END
-
-/* Helper: Given two lists of items, possibly of different types, such that
- * both lists are sorted on some common field (as determined by a comparison
- * expression <b>cmpexpr</b>), and such that one list (<b>sl1</b>) has no
- * duplicates on the common field, loop through the lists in lockstep, and
- * execute <b>unmatched_var2</b> on items in var2 that do not appear in
- * var1.
- *
- * WARNING: It isn't safe to add remove elements from either list while the
- * loop is in progress.
- *
- * Example use:
- * SMARTLIST_FOREACH_JOIN(routerstatus_list, routerstatus_t *, rs,
- * routerinfo_list, routerinfo_t *, ri,
- * tor_memcmp(rs->identity_digest, ri->identity_digest, 20),
- * log_info(LD_GENERAL,"No match for %s", ri->nickname)) {
- * log_info(LD_GENERAL, "%s matches routerstatus %p", ri->nickname, rs);
- * } SMARTLIST_FOREACH_JOIN_END(rs, ri);
- **/
-/* The example above unpacks (approximately) to:
- * int rs_sl_idx = 0, rs_sl_len = smartlist_len(routerstatus_list);
- * int ri_sl_idx, ri_sl_len = smartlist_len(routerinfo_list);
- * int rs_ri_cmp;
- * routerstatus_t *rs;
- * routerinfo_t *ri;
- * for (; ri_sl_idx < ri_sl_len; ++ri_sl_idx) {
- * ri = smartlist_get(routerinfo_list, ri_sl_idx);
- * while (rs_sl_idx < rs_sl_len) {
- * rs = smartlist_get(routerstatus_list, rs_sl_idx);
- * rs_ri_cmp = tor_memcmp(rs->identity_digest, ri->identity_digest, 20);
- * if (rs_ri_cmp > 0) {
- * break;
- * } else if (rs_ri_cmp == 0) {
- * goto matched_ri;
- * } else {
- * ++rs_sl_idx;
- * }
- * }
- * log_info(LD_GENERAL,"No match for %s", ri->nickname);
- * continue;
- * matched_ri: {
- * log_info(LD_GENERAL,"%s matches with routerstatus %p",ri->nickname,rs);
- * }
- * }
- */
-#define SMARTLIST_FOREACH_JOIN(sl1, type1, var1, sl2, type2, var2, \
- cmpexpr, unmatched_var2) \
- STMT_BEGIN \
- int var1 ## _sl_idx = 0, var1 ## _sl_len=(sl1)->num_used; \
- int var2 ## _sl_idx = 0, var2 ## _sl_len=(sl2)->num_used; \
- int var1 ## _ ## var2 ## _cmp; \
- type1 var1; \
- type2 var2; \
- for (; var2##_sl_idx < var2##_sl_len; ++var2##_sl_idx) { \
- var2 = (sl2)->list[var2##_sl_idx]; \
- while (var1##_sl_idx < var1##_sl_len) { \
- var1 = (sl1)->list[var1##_sl_idx]; \
- var1##_##var2##_cmp = (cmpexpr); \
- if (var1##_##var2##_cmp > 0) { \
- break; \
- } else if (var1##_##var2##_cmp == 0) { \
- goto matched_##var2; \
- } else { \
- ++var1##_sl_idx; \
- } \
- } \
- /* Ran out of v1, or no match for var2. */ \
- unmatched_var2; \
- continue; \
- matched_##var2: ; \
-
-#define SMARTLIST_FOREACH_JOIN_END(var1, var2) \
- } \
- STMT_END
-
-#define DECLARE_MAP_FNS(maptype, keytype, prefix) \
- typedef struct maptype maptype; \
- typedef struct prefix##entry_t *prefix##iter_t; \
- MOCK_DECL(maptype*, prefix##new, (void)); \
- void* prefix##set(maptype *map, keytype key, void *val); \
- void* prefix##get(const maptype *map, keytype key); \
- void* prefix##remove(maptype *map, keytype key); \
- MOCK_DECL(void, prefix##free_, (maptype *map, void (*free_val)(void*))); \
- int prefix##isempty(const maptype *map); \
- int prefix##size(const maptype *map); \
- prefix##iter_t *prefix##iter_init(maptype *map); \
- prefix##iter_t *prefix##iter_next(maptype *map, prefix##iter_t *iter); \
- prefix##iter_t *prefix##iter_next_rmv(maptype *map, prefix##iter_t *iter); \
- void prefix##iter_get(prefix##iter_t *iter, keytype *keyp, void **valp); \
- int prefix##iter_done(prefix##iter_t *iter); \
- void prefix##assert_ok(const maptype *map)
-
-/* Map from const char * to void *. Implemented with a hash table. */
-DECLARE_MAP_FNS(strmap_t, const char *, strmap_);
-/* Map from const char[DIGEST_LEN] to void *. Implemented with a hash table. */
-DECLARE_MAP_FNS(digestmap_t, const char *, digestmap_);
-/* Map from const uint8_t[DIGEST256_LEN] to void *. Implemented with a hash
- * table. */
-DECLARE_MAP_FNS(digest256map_t, const uint8_t *, digest256map_);
-
-#define MAP_FREE_AND_NULL(maptype, map, fn) \
- do { \
- maptype ## _free_((map), (fn)); \
- (map) = NULL; \
- } while (0)
-
-#define strmap_free(map, fn) MAP_FREE_AND_NULL(strmap, (map), (fn))
-#define digestmap_free(map, fn) MAP_FREE_AND_NULL(digestmap, (map), (fn))
-#define digest256map_free(map, fn) MAP_FREE_AND_NULL(digest256map, (map), (fn))
-
-#undef DECLARE_MAP_FNS
-
-/** Iterates over the key-value pairs in a map <b>map</b> in order.
- * <b>prefix</b> is as for DECLARE_MAP_FNS (i.e., strmap_ or digestmap_).
- * The map's keys and values are of type keytype and valtype respectively;
- * each iteration assigns them to keyvar and valvar.
- *
- * Example use:
- * MAP_FOREACH(digestmap_, m, const char *, k, routerinfo_t *, r) {
- * // use k and r
- * } MAP_FOREACH_END.
- */
-/* Unpacks to, approximately:
- * {
- * digestmap_iter_t *k_iter;
- * for (k_iter = digestmap_iter_init(m); !digestmap_iter_done(k_iter);
- * k_iter = digestmap_iter_next(m, k_iter)) {
- * const char *k;
- * void *r_voidp;
- * routerinfo_t *r;
- * digestmap_iter_get(k_iter, &k, &r_voidp);
- * r = r_voidp;
- * // use k and r
- * }
- * }
- */
-#define MAP_FOREACH(prefix, map, keytype, keyvar, valtype, valvar) \
- STMT_BEGIN \
- prefix##iter_t *keyvar##_iter; \
- for (keyvar##_iter = prefix##iter_init(map); \
- !prefix##iter_done(keyvar##_iter); \
- keyvar##_iter = prefix##iter_next(map, keyvar##_iter)) { \
- keytype keyvar; \
- void *valvar##_voidp; \
- valtype valvar; \
- prefix##iter_get(keyvar##_iter, &keyvar, &valvar##_voidp); \
- valvar = valvar##_voidp;
-
-/** As MAP_FOREACH, except allows members to be removed from the map
- * during the iteration via MAP_DEL_CURRENT. Example use:
- *
- * Example use:
- * MAP_FOREACH(digestmap_, m, const char *, k, routerinfo_t *, r) {
- * if (is_very_old(r))
- * MAP_DEL_CURRENT(k);
- * } MAP_FOREACH_END.
- **/
-/* Unpacks to, approximately:
- * {
- * digestmap_iter_t *k_iter;
- * int k_del=0;
- * for (k_iter = digestmap_iter_init(m); !digestmap_iter_done(k_iter);
- * k_iter = k_del ? digestmap_iter_next(m, k_iter)
- * : digestmap_iter_next_rmv(m, k_iter)) {
- * const char *k;
- * void *r_voidp;
- * routerinfo_t *r;
- * k_del=0;
- * digestmap_iter_get(k_iter, &k, &r_voidp);
- * r = r_voidp;
- * if (is_very_old(r)) {
- * k_del = 1;
- * }
- * }
- * }
- */
-#define MAP_FOREACH_MODIFY(prefix, map, keytype, keyvar, valtype, valvar) \
- STMT_BEGIN \
- prefix##iter_t *keyvar##_iter; \
- int keyvar##_del=0; \
- for (keyvar##_iter = prefix##iter_init(map); \
- !prefix##iter_done(keyvar##_iter); \
- keyvar##_iter = keyvar##_del ? \
- prefix##iter_next_rmv(map, keyvar##_iter) : \
- prefix##iter_next(map, keyvar##_iter)) { \
- keytype keyvar; \
- void *valvar##_voidp; \
- valtype valvar; \
- keyvar##_del=0; \
- prefix##iter_get(keyvar##_iter, &keyvar, &valvar##_voidp); \
- valvar = valvar##_voidp;
-
-/** Used with MAP_FOREACH_MODIFY to remove the currently-iterated-upon
- * member of the map. */
-#define MAP_DEL_CURRENT(keyvar) \
- STMT_BEGIN \
- keyvar##_del = 1; \
- STMT_END
-
-/** Used to end a MAP_FOREACH() block. */
-#define MAP_FOREACH_END } STMT_END ;
-
-/** As MAP_FOREACH, but does not require declaration of prefix or keytype.
- * Example use:
- * DIGESTMAP_FOREACH(m, k, routerinfo_t *, r) {
- * // use k and r
- * } DIGESTMAP_FOREACH_END.
- */
-#define DIGESTMAP_FOREACH(map, keyvar, valtype, valvar) \
- MAP_FOREACH(digestmap_, map, const char *, keyvar, valtype, valvar)
-
-/** As MAP_FOREACH_MODIFY, but does not require declaration of prefix or
- * keytype.
- * Example use:
- * DIGESTMAP_FOREACH_MODIFY(m, k, routerinfo_t *, r) {
- * if (is_very_old(r))
- * MAP_DEL_CURRENT(k);
- * } DIGESTMAP_FOREACH_END.
- */
-#define DIGESTMAP_FOREACH_MODIFY(map, keyvar, valtype, valvar) \
- MAP_FOREACH_MODIFY(digestmap_, map, const char *, keyvar, valtype, valvar)
-/** Used to end a DIGESTMAP_FOREACH() block. */
-#define DIGESTMAP_FOREACH_END MAP_FOREACH_END
-
-#define DIGEST256MAP_FOREACH(map, keyvar, valtype, valvar) \
- MAP_FOREACH(digest256map_, map, const uint8_t *, keyvar, valtype, valvar)
-#define DIGEST256MAP_FOREACH_MODIFY(map, keyvar, valtype, valvar) \
- MAP_FOREACH_MODIFY(digest256map_, map, const uint8_t *, \
- keyvar, valtype, valvar)
-#define DIGEST256MAP_FOREACH_END MAP_FOREACH_END
-
-#define STRMAP_FOREACH(map, keyvar, valtype, valvar) \
- MAP_FOREACH(strmap_, map, const char *, keyvar, valtype, valvar)
-#define STRMAP_FOREACH_MODIFY(map, keyvar, valtype, valvar) \
- MAP_FOREACH_MODIFY(strmap_, map, const char *, keyvar, valtype, valvar)
-#define STRMAP_FOREACH_END MAP_FOREACH_END
-
-void* strmap_set_lc(strmap_t *map, const char *key, void *val);
-void* strmap_get_lc(const strmap_t *map, const char *key);
-void* strmap_remove_lc(strmap_t *map, const char *key);
-
-#define DECLARE_TYPED_DIGESTMAP_FNS(prefix, maptype, valtype) \
- typedef struct maptype maptype; \
- typedef struct prefix##iter_t *prefix##iter_t; \
- ATTR_UNUSED static inline maptype* \
- prefix##new(void) \
- { \
- return (maptype*)digestmap_new(); \
- } \
- ATTR_UNUSED static inline digestmap_t* \
- prefix##to_digestmap(maptype *map) \
- { \
- return (digestmap_t*)map; \
- } \
- ATTR_UNUSED static inline valtype* \
- prefix##get(maptype *map, const char *key) \
- { \
- return (valtype*)digestmap_get((digestmap_t*)map, key); \
- } \
- ATTR_UNUSED static inline valtype* \
- prefix##set(maptype *map, const char *key, valtype *val) \
- { \
- return (valtype*)digestmap_set((digestmap_t*)map, key, val); \
- } \
- ATTR_UNUSED static inline valtype* \
- prefix##remove(maptype *map, const char *key) \
- { \
- return (valtype*)digestmap_remove((digestmap_t*)map, key); \
- } \
- ATTR_UNUSED static inline void \
- prefix##f##ree_(maptype *map, void (*free_val)(void*)) \
- { \
- digestmap_free_((digestmap_t*)map, free_val); \
- } \
- ATTR_UNUSED static inline int \
- prefix##isempty(maptype *map) \
- { \
- return digestmap_isempty((digestmap_t*)map); \
- } \
- ATTR_UNUSED static inline int \
- prefix##size(maptype *map) \
- { \
- return digestmap_size((digestmap_t*)map); \
- } \
- ATTR_UNUSED static inline \
- prefix##iter_t *prefix##iter_init(maptype *map) \
- { \
- return (prefix##iter_t*) digestmap_iter_init((digestmap_t*)map); \
- } \
- ATTR_UNUSED static inline \
- prefix##iter_t *prefix##iter_next(maptype *map, prefix##iter_t *iter) \
- { \
- return (prefix##iter_t*) digestmap_iter_next( \
- (digestmap_t*)map, (digestmap_iter_t*)iter); \
- } \
- ATTR_UNUSED static inline prefix##iter_t* \
- prefix##iter_next_rmv(maptype *map, prefix##iter_t *iter) \
- { \
- return (prefix##iter_t*) digestmap_iter_next_rmv( \
- (digestmap_t*)map, (digestmap_iter_t*)iter); \
- } \
- ATTR_UNUSED static inline void \
- prefix##iter_get(prefix##iter_t *iter, \
- const char **keyp, \
- valtype **valp) \
- { \
- void *v; \
- digestmap_iter_get((digestmap_iter_t*) iter, keyp, &v); \
- *valp = v; \
- } \
- ATTR_UNUSED static inline int \
- prefix##iter_done(prefix##iter_t *iter) \
- { \
- return digestmap_iter_done((digestmap_iter_t*)iter); \
- }
-
-#if SIZEOF_INT == 4
-#define BITARRAY_SHIFT 5
-#elif SIZEOF_INT == 8
-#define BITARRAY_SHIFT 6
-#else
-#error "int is neither 4 nor 8 bytes. I can't deal with that."
-#endif /* SIZEOF_INT == 4 || ... */
-#define BITARRAY_MASK ((1u<<BITARRAY_SHIFT)-1)
-
-/** A random-access array of one-bit-wide elements. */
-typedef unsigned int bitarray_t;
-/** Create a new bit array that can hold <b>n_bits</b> bits. */
-static inline bitarray_t *
-bitarray_init_zero(unsigned int n_bits)
-{
- /* round up to the next int. */
- size_t sz = (n_bits+BITARRAY_MASK) >> BITARRAY_SHIFT;
- return tor_calloc(sz, sizeof(unsigned int));
-}
-/** Expand <b>ba</b> from holding <b>n_bits_old</b> to <b>n_bits_new</b>,
- * clearing all new bits. Returns a possibly changed pointer to the
- * bitarray. */
-static inline bitarray_t *
-bitarray_expand(bitarray_t *ba,
- unsigned int n_bits_old, unsigned int n_bits_new)
-{
- size_t sz_old = (n_bits_old+BITARRAY_MASK) >> BITARRAY_SHIFT;
- size_t sz_new = (n_bits_new+BITARRAY_MASK) >> BITARRAY_SHIFT;
- char *ptr;
- if (sz_new <= sz_old)
- return ba;
- ptr = tor_reallocarray(ba, sz_new, sizeof(unsigned int));
- /* This memset does nothing to the older excess bytes. But they were
- * already set to 0 by bitarry_init_zero. */
- memset(ptr+sz_old*sizeof(unsigned int), 0,
- (sz_new-sz_old)*sizeof(unsigned int));
- return (bitarray_t*) ptr;
-}
-/** Free the bit array <b>ba</b>. */
-static inline void
-bitarray_free_(bitarray_t *ba)
-{
- tor_free(ba);
-}
-#define bitarray_free(ba) FREE_AND_NULL(bitarray_t, bitarray_free_, (ba))
-
-/** Set the <b>bit</b>th bit in <b>b</b> to 1. */
-static inline void
-bitarray_set(bitarray_t *b, int bit)
-{
- b[bit >> BITARRAY_SHIFT] |= (1u << (bit & BITARRAY_MASK));
-}
-/** Set the <b>bit</b>th bit in <b>b</b> to 0. */
-static inline void
-bitarray_clear(bitarray_t *b, int bit)
-{
- b[bit >> BITARRAY_SHIFT] &= ~ (1u << (bit & BITARRAY_MASK));
-}
-/** Return true iff <b>bit</b>th bit in <b>b</b> is nonzero. NOTE: does
- * not necessarily return 1 on true. */
-static inline unsigned int
-bitarray_is_set(bitarray_t *b, int bit)
-{
- return b[bit >> BITARRAY_SHIFT] & (1u << (bit & BITARRAY_MASK));
-}
-
-/** A set of digests, implemented as a Bloom filter. */
-typedef struct {
- int mask; /**< One less than the number of bits in <b>ba</b>; always one less
- * than a power of two. */
- bitarray_t *ba; /**< A bit array to implement the Bloom filter. */
-} digestset_t;
-
-#define BIT(n) ((n) & set->mask)
-/** Add the digest <b>digest</b> to <b>set</b>. */
-static inline void
-digestset_add(digestset_t *set, const char *digest)
-{
- const uint64_t x = siphash24g(digest, 20);
- const uint32_t d1 = (uint32_t) x;
- const uint32_t d2 = (uint32_t)( (x>>16) + x);
- const uint32_t d3 = (uint32_t)( (x>>32) + x);
- const uint32_t d4 = (uint32_t)( (x>>48) + x);
- bitarray_set(set->ba, BIT(d1));
- bitarray_set(set->ba, BIT(d2));
- bitarray_set(set->ba, BIT(d3));
- bitarray_set(set->ba, BIT(d4));
-}
-
-/** If <b>digest</b> is in <b>set</b>, return nonzero. Otherwise,
- * <em>probably</em> return zero. */
-static inline int
-digestset_contains(const digestset_t *set, const char *digest)
-{
- const uint64_t x = siphash24g(digest, 20);
- const uint32_t d1 = (uint32_t) x;
- const uint32_t d2 = (uint32_t)( (x>>16) + x);
- const uint32_t d3 = (uint32_t)( (x>>32) + x);
- const uint32_t d4 = (uint32_t)( (x>>48) + x);
- return bitarray_is_set(set->ba, BIT(d1)) &&
- bitarray_is_set(set->ba, BIT(d2)) &&
- bitarray_is_set(set->ba, BIT(d3)) &&
- bitarray_is_set(set->ba, BIT(d4));
-}
-#undef BIT
-
-digestset_t *digestset_new(int max_elements);
-void digestset_free_(digestset_t* set);
-#define digestset_free(set) FREE_AND_NULL(digestset_t, digestset_free_, (set))
-
-/* These functions, given an <b>array</b> of <b>n_elements</b>, return the
- * <b>nth</b> lowest element. <b>nth</b>=0 gives the lowest element;
- * <b>n_elements</b>-1 gives the highest; and (<b>n_elements</b>-1) / 2 gives
- * the median. As a side effect, the elements of <b>array</b> are sorted. */
-int find_nth_int(int *array, int n_elements, int nth);
-time_t find_nth_time(time_t *array, int n_elements, int nth);
-double find_nth_double(double *array, int n_elements, int nth);
-int32_t find_nth_int32(int32_t *array, int n_elements, int nth);
-uint32_t find_nth_uint32(uint32_t *array, int n_elements, int nth);
-long find_nth_long(long *array, int n_elements, int nth);
-static inline int
-median_int(int *array, int n_elements)
-{
- return find_nth_int(array, n_elements, (n_elements-1)/2);
-}
-static inline time_t
-median_time(time_t *array, int n_elements)
-{
- return find_nth_time(array, n_elements, (n_elements-1)/2);
-}
-static inline double
-median_double(double *array, int n_elements)
-{
- return find_nth_double(array, n_elements, (n_elements-1)/2);
-}
-static inline uint32_t
-median_uint32(uint32_t *array, int n_elements)
-{
- return find_nth_uint32(array, n_elements, (n_elements-1)/2);
-}
-static inline int32_t
-median_int32(int32_t *array, int n_elements)
-{
- return find_nth_int32(array, n_elements, (n_elements-1)/2);
-}
-
-static inline uint32_t
-third_quartile_uint32(uint32_t *array, int n_elements)
-{
- return find_nth_uint32(array, n_elements, (n_elements*3)/4);
-}
-
-#endif /* !defined(TOR_CONTAINER_H) */
-
diff --git a/src/common/crypto.c b/src/common/crypto.c
deleted file mode 100644
index d5b7c96916..0000000000
--- a/src/common/crypto.c
+++ /dev/null
@@ -1,1118 +0,0 @@
-/* Copyright (c) 2001, Matej Pfajfar.
- * Copyright (c) 2001-2004, Roger Dingledine.
- * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2017, The Tor Project, Inc. */
-/* See LICENSE for licensing information */
-
-/**
- * \file crypto.c
- * \brief Wrapper functions to present a consistent interface to
- * public-key and symmetric cryptography operations from OpenSSL and
- * other places.
- **/
-
-#include "orconfig.h"
-
-#ifdef _WIN32
-#include <winsock2.h>
-#include <windows.h>
-#include <wincrypt.h>
-/* Windows defines this; so does OpenSSL 0.9.8h and later. We don't actually
- * use either definition. */
-#undef OCSP_RESPONSE
-#endif /* defined(_WIN32) */
-
-#define CRYPTO_PRIVATE
-#include "compat_openssl.h"
-#include "crypto.h"
-#include "crypto_curve25519.h"
-#include "crypto_digest.h"
-#include "crypto_ed25519.h"
-#include "crypto_format.h"
-#include "crypto_rand.h"
-#include "crypto_rsa.h"
-#include "crypto_util.h"
-
-DISABLE_GCC_WARNING(redundant-decls)
-
-#include <openssl/err.h>
-#include <openssl/evp.h>
-#include <openssl/engine.h>
-#include <openssl/bn.h>
-#include <openssl/dh.h>
-#include <openssl/conf.h>
-#include <openssl/hmac.h>
-#include <openssl/ssl.h>
-
-ENABLE_GCC_WARNING(redundant-decls)
-
-#if __GNUC__ && GCC_VERSION >= 402
-#if GCC_VERSION >= 406
-#pragma GCC diagnostic pop
-#else
-#pragma GCC diagnostic warning "-Wredundant-decls"
-#endif
-#endif /* __GNUC__ && GCC_VERSION >= 402 */
-
-#ifdef HAVE_CTYPE_H
-#include <ctype.h>
-#endif
-#ifdef HAVE_UNISTD_H
-#include <unistd.h>
-#endif
-
-#include "torlog.h"
-#include "torint.h"
-#include "aes.h"
-#include "util.h"
-#include "container.h"
-#include "compat.h"
-#include "sandbox.h"
-#include "util_format.h"
-
-#include "keccak-tiny/keccak-tiny.h"
-
-/** A structure to hold the first half (x, g^x) of a Diffie-Hellman handshake
- * while we're waiting for the second.*/
-struct crypto_dh_t {
- DH *dh; /**< The openssl DH object */
-};
-
-static int tor_check_dh_key(int severity, const BIGNUM *bn);
-
-/** Boolean: has OpenSSL's crypto been initialized? */
-static int crypto_early_initialized_ = 0;
-
-/** Boolean: has OpenSSL's crypto been initialized? */
-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.
- */
-static void
-crypto_log_errors(int severity, const char *doing)
-{
- unsigned long err;
- const char *msg, *lib, *func;
- while ((err = ERR_get_error()) != 0) {
- msg = (const char*)ERR_reason_error_string(err);
- lib = (const char*)ERR_lib_error_string(err);
- func = (const char*)ERR_func_error_string(err);
- if (!msg) msg = "(null)";
- if (!lib) lib = "(null)";
- if (!func) func = "(null)";
- if (BUG(!doing)) doing = "(null)";
- tor_log(severity, LD_CRYPTO, "crypto error while %s: %s (in %s:%s)",
- doing, msg, lib, func);
- }
-}
-
-#ifndef DISABLE_ENGINES
-/** Log any OpenSSL engines we're using at NOTICE. */
-static void
-log_engine(const char *fn, ENGINE *e)
-{
- if (e) {
- const char *name, *id;
- name = ENGINE_get_name(e);
- id = ENGINE_get_id(e);
- log_notice(LD_CRYPTO, "Default OpenSSL engine for %s is %s [%s]",
- fn, name?name:"?", id?id:"?");
- } else {
- log_info(LD_CRYPTO, "Using default implementation for %s", fn);
- }
-}
-#endif /* !defined(DISABLE_ENGINES) */
-
-#ifndef DISABLE_ENGINES
-/** Try to load an engine in a shared library via fully qualified path.
- */
-static ENGINE *
-try_load_engine(const char *path, const char *engine)
-{
- ENGINE *e = ENGINE_by_id("dynamic");
- if (e) {
- if (!ENGINE_ctrl_cmd_string(e, "ID", engine, 0) ||
- !ENGINE_ctrl_cmd_string(e, "DIR_LOAD", "2", 0) ||
- !ENGINE_ctrl_cmd_string(e, "DIR_ADD", path, 0) ||
- !ENGINE_ctrl_cmd_string(e, "LOAD", NULL, 0)) {
- ENGINE_free(e);
- e = NULL;
- }
- }
- return e;
-}
-#endif /* !defined(DISABLE_ENGINES) */
-
-static int have_seeded_siphash = 0;
-
-/** Set up the siphash key if we haven't already done so. */
-int
-crypto_init_siphash_key(void)
-{
- struct sipkey key;
- if (have_seeded_siphash)
- return 0;
-
- crypto_rand((char*) &key, sizeof(key));
- siphash_set_global_key(&key);
- have_seeded_siphash = 1;
- return 0;
-}
-
-/** Initialize the crypto library. Return 0 on success, -1 on failure.
- */
-int
-crypto_early_init(void)
-{
- if (!crypto_early_initialized_) {
-
- crypto_early_initialized_ = 1;
-
-#ifdef OPENSSL_1_1_API
- OPENSSL_init_ssl(OPENSSL_INIT_LOAD_SSL_STRINGS |
- OPENSSL_INIT_LOAD_CRYPTO_STRINGS |
- OPENSSL_INIT_ADD_ALL_CIPHERS |
- OPENSSL_INIT_ADD_ALL_DIGESTS, NULL);
-#else
- ERR_load_crypto_strings();
- OpenSSL_add_all_algorithms();
-#endif
-
- setup_openssl_threading();
-
- unsigned long version_num = OpenSSL_version_num();
- const char *version_str = OpenSSL_version(OPENSSL_VERSION);
- if (version_num == OPENSSL_VERSION_NUMBER &&
- !strcmp(version_str, OPENSSL_VERSION_TEXT)) {
- log_info(LD_CRYPTO, "OpenSSL version matches version from headers "
- "(%lx: %s).", version_num, version_str);
- } 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,
- version_num, version_str);
- }
-
- crypto_force_rand_ssleay();
-
- if (crypto_seed_rng() < 0)
- return -1;
- if (crypto_init_siphash_key() < 0)
- return -1;
-
- curve25519_init();
- ed25519_init();
- }
- return 0;
-}
-
-/** 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_early_init() < 0)
- return -1;
-
- crypto_global_initialized_ = 1;
-
- if (useAccel > 0) {
-#ifdef DISABLE_ENGINES
- (void)accelName;
- (void)accelDir;
- log_warn(LD_CRYPTO, "No OpenSSL hardware acceleration support enabled.");
-#else
- ENGINE *e = NULL;
-
- log_info(LD_CRYPTO, "Initializing OpenSSL engine support.");
- ENGINE_load_builtin_engines();
- ENGINE_register_all_complete();
-
- if (accelName) {
- if (accelDir) {
- log_info(LD_CRYPTO, "Trying to load dynamic OpenSSL engine \"%s\""
- " via path \"%s\".", accelName, accelDir);
- e = try_load_engine(accelName, accelDir);
- } else {
- log_info(LD_CRYPTO, "Initializing dynamic OpenSSL engine \"%s\""
- " acceleration support.", accelName);
- e = ENGINE_by_id(accelName);
- }
- if (!e) {
- log_warn(LD_CRYPTO, "Unable to load dynamic OpenSSL engine \"%s\".",
- accelName);
- } else {
- log_info(LD_CRYPTO, "Loaded dynamic OpenSSL engine \"%s\".",
- accelName);
- }
- }
- if (e) {
- log_info(LD_CRYPTO, "Loaded OpenSSL hardware acceleration engine,"
- " setting default ciphers.");
- ENGINE_set_default(e, ENGINE_METHOD_ALL);
- }
- /* Log, if available, the intersection of the set of algorithms
- used by Tor and the set of algorithms available in the engine */
- log_engine("RSA", ENGINE_get_default_RSA());
- log_engine("DH", ENGINE_get_default_DH());
-#ifdef OPENSSL_1_1_API
- log_engine("EC", ENGINE_get_default_EC());
-#else
- log_engine("ECDH", ENGINE_get_default_ECDH());
- log_engine("ECDSA", ENGINE_get_default_ECDSA());
-#endif /* defined(OPENSSL_1_1_API) */
- log_engine("RAND", ENGINE_get_default_RAND());
- log_engine("RAND (which we will not use)", ENGINE_get_default_RAND());
- log_engine("SHA1", ENGINE_get_digest_engine(NID_sha1));
- log_engine("3DES-CBC", ENGINE_get_cipher_engine(NID_des_ede3_cbc));
- log_engine("AES-128-ECB", ENGINE_get_cipher_engine(NID_aes_128_ecb));
- log_engine("AES-128-CBC", ENGINE_get_cipher_engine(NID_aes_128_cbc));
-#ifdef NID_aes_128_ctr
- log_engine("AES-128-CTR", ENGINE_get_cipher_engine(NID_aes_128_ctr));
-#endif
-#ifdef NID_aes_128_gcm
- log_engine("AES-128-GCM", ENGINE_get_cipher_engine(NID_aes_128_gcm));
-#endif
- log_engine("AES-256-CBC", ENGINE_get_cipher_engine(NID_aes_256_cbc));
-#ifdef NID_aes_256_gcm
- log_engine("AES-256-GCM", ENGINE_get_cipher_engine(NID_aes_256_gcm));
-#endif
-
-#endif /* defined(DISABLE_ENGINES) */
- } else {
- log_info(LD_CRYPTO, "NOT using OpenSSL engine support.");
- }
-
- if (crypto_force_rand_ssleay()) {
- if (crypto_seed_rng() < 0)
- return -1;
- }
-
- evaluate_evp_for_aes(-1);
- evaluate_ctr_for_aes();
- }
- return 0;
-}
-
-/** Free crypto resources held by this thread. */
-void
-crypto_thread_cleanup(void)
-{
-#ifndef NEW_THREAD_API
- ERR_remove_thread_state(NULL);
-#endif
-}
-
-/** Used by tortls.c: Get the DH* from a crypto_dh_t.
- */
-DH *
-crypto_dh_get_dh_(crypto_dh_t *dh)
-{
- return dh->dh;
-}
-
-/** Allocate and return a new symmetric cipher using the provided key and iv.
- * The key is <b>bits</b> bits long; the IV is CIPHER_IV_LEN bytes. Both
- * must be provided. Key length must be 128, 192, or 256 */
-crypto_cipher_t *
-crypto_cipher_new_with_iv_and_bits(const uint8_t *key,
- const uint8_t *iv,
- int bits)
-{
- tor_assert(key);
- tor_assert(iv);
-
- return aes_new_cipher((const uint8_t*)key, (const uint8_t*)iv, bits);
-}
-
-/** Allocate and return a new symmetric cipher using the provided key and iv.
- * The key is CIPHER_KEY_LEN bytes; the IV is CIPHER_IV_LEN bytes. Both
- * must be provided.
- */
-crypto_cipher_t *
-crypto_cipher_new_with_iv(const char *key, const char *iv)
-{
- return crypto_cipher_new_with_iv_and_bits((uint8_t*)key, (uint8_t*)iv,
- 128);
-}
-
-/** Return a new crypto_cipher_t with the provided <b>key</b> and an IV of all
- * zero bytes and key length <b>bits</b>. Key length must be 128, 192, or
- * 256. */
-crypto_cipher_t *
-crypto_cipher_new_with_bits(const char *key, int bits)
-{
- char zeroiv[CIPHER_IV_LEN];
- memset(zeroiv, 0, sizeof(zeroiv));
- return crypto_cipher_new_with_iv_and_bits((uint8_t*)key, (uint8_t*)zeroiv,
- bits);
-}
-
-/** Return a new crypto_cipher_t with the provided <b>key</b> (of
- * CIPHER_KEY_LEN bytes) and an IV of all zero bytes. */
-crypto_cipher_t *
-crypto_cipher_new(const char *key)
-{
- return crypto_cipher_new_with_bits(key, 128);
-}
-
-/** Free a symmetric cipher.
- */
-void
-crypto_cipher_free_(crypto_cipher_t *env)
-{
- if (!env)
- return;
-
- aes_cipher_free(env);
-}
-
-/** Copy <b>in</b> to the <b>outlen</b>-byte buffer <b>out</b>, adding spaces
- * every four characters. */
-void
-crypto_add_spaces_to_fp(char *out, size_t outlen, const char *in)
-{
- int n = 0;
- char *end = out+outlen;
- tor_assert(outlen < SIZE_T_CEILING);
-
- while (*in && out<end) {
- *out++ = *in++;
- if (++n == 4 && *in && out<end) {
- n = 0;
- *out++ = ' ';
- }
- }
- tor_assert(out<end);
- *out = '\0';
-}
-
-/* symmetric crypto */
-
-/** Encrypt <b>fromlen</b> bytes from <b>from</b> using the cipher
- * <b>env</b>; on success, store the result to <b>to</b> and return 0.
- * Does not check for failure.
- */
-int
-crypto_cipher_encrypt(crypto_cipher_t *env, char *to,
- const char *from, size_t fromlen)
-{
- tor_assert(env);
- tor_assert(env);
- tor_assert(from);
- tor_assert(fromlen);
- tor_assert(to);
- tor_assert(fromlen < SIZE_T_CEILING);
-
- memcpy(to, from, fromlen);
- aes_crypt_inplace(env, to, fromlen);
- return 0;
-}
-
-/** Decrypt <b>fromlen</b> bytes from <b>from</b> using the cipher
- * <b>env</b>; on success, store the result to <b>to</b> and return 0.
- * Does not check for failure.
- */
-int
-crypto_cipher_decrypt(crypto_cipher_t *env, char *to,
- const char *from, size_t fromlen)
-{
- tor_assert(env);
- tor_assert(from);
- tor_assert(to);
- tor_assert(fromlen < SIZE_T_CEILING);
-
- memcpy(to, from, fromlen);
- aes_crypt_inplace(env, to, fromlen);
- return 0;
-}
-
-/** Encrypt <b>len</b> bytes on <b>from</b> using the cipher in <b>env</b>;
- * on success. Does not check for failure.
- */
-void
-crypto_cipher_crypt_inplace(crypto_cipher_t *env, char *buf, size_t len)
-{
- tor_assert(len < SIZE_T_CEILING);
- aes_crypt_inplace(env, buf, len);
-}
-
-/** Encrypt <b>fromlen</b> bytes (at least 1) from <b>from</b> with the key in
- * <b>key</b> to the buffer in <b>to</b> of length
- * <b>tolen</b>. <b>tolen</b> must be at least <b>fromlen</b> plus
- * CIPHER_IV_LEN bytes for the initialization vector. On success, return the
- * number of bytes written, on failure, return -1.
- */
-int
-crypto_cipher_encrypt_with_iv(const char *key,
- char *to, size_t tolen,
- const char *from, size_t fromlen)
-{
- crypto_cipher_t *cipher;
- tor_assert(from);
- tor_assert(to);
- tor_assert(fromlen < INT_MAX);
-
- if (fromlen < 1)
- return -1;
- if (tolen < fromlen + CIPHER_IV_LEN)
- return -1;
-
- char iv[CIPHER_IV_LEN];
- crypto_rand(iv, sizeof(iv));
- cipher = crypto_cipher_new_with_iv(key, iv);
-
- memcpy(to, iv, CIPHER_IV_LEN);
- crypto_cipher_encrypt(cipher, to+CIPHER_IV_LEN, from, fromlen);
- crypto_cipher_free(cipher);
- memwipe(iv, 0, sizeof(iv));
- return (int)(fromlen + CIPHER_IV_LEN);
-}
-
-/** Decrypt <b>fromlen</b> bytes (at least 1+CIPHER_IV_LEN) from <b>from</b>
- * with the key in <b>key</b> to the buffer in <b>to</b> of length
- * <b>tolen</b>. <b>tolen</b> must be at least <b>fromlen</b> minus
- * CIPHER_IV_LEN bytes for the initialization vector. On success, return the
- * number of bytes written, on failure, return -1.
- */
-int
-crypto_cipher_decrypt_with_iv(const char *key,
- char *to, size_t tolen,
- const char *from, size_t fromlen)
-{
- crypto_cipher_t *cipher;
- tor_assert(key);
- tor_assert(from);
- tor_assert(to);
- tor_assert(fromlen < INT_MAX);
-
- if (fromlen <= CIPHER_IV_LEN)
- return -1;
- if (tolen < fromlen - CIPHER_IV_LEN)
- return -1;
-
- cipher = crypto_cipher_new_with_iv(key, from);
-
- crypto_cipher_encrypt(cipher, to, from+CIPHER_IV_LEN, fromlen-CIPHER_IV_LEN);
- crypto_cipher_free(cipher);
- return (int)(fromlen - CIPHER_IV_LEN);
-}
-
-/* DH */
-
-/** Our DH 'g' parameter */
-#define DH_GENERATOR 2
-
-/** Shared P parameter for our circuit-crypto DH key exchanges. */
-static BIGNUM *dh_param_p = NULL;
-/** Shared P parameter for our TLS DH key exchanges. */
-static BIGNUM *dh_param_p_tls = NULL;
-/** Shared G parameter for our DH key exchanges. */
-static BIGNUM *dh_param_g = NULL;
-
-/** Validate a given set of Diffie-Hellman parameters. This is moderately
- * computationally expensive (milliseconds), so should only be called when
- * the DH parameters change. Returns 0 on success, * -1 on failure.
- */
-static int
-crypto_validate_dh_params(const BIGNUM *p, const BIGNUM *g)
-{
- DH *dh = NULL;
- int ret = -1;
-
- /* Copy into a temporary DH object, just so that DH_check() can be called. */
- if (!(dh = DH_new()))
- goto out;
-#ifdef OPENSSL_1_1_API
- BIGNUM *dh_p, *dh_g;
- if (!(dh_p = BN_dup(p)))
- goto out;
- if (!(dh_g = BN_dup(g)))
- goto out;
- if (!DH_set0_pqg(dh, dh_p, NULL, dh_g))
- goto out;
-#else /* !(defined(OPENSSL_1_1_API)) */
- if (!(dh->p = BN_dup(p)))
- goto out;
- if (!(dh->g = BN_dup(g)))
- goto out;
-#endif /* defined(OPENSSL_1_1_API) */
-
- /* Perform the validation. */
- int codes = 0;
- if (!DH_check(dh, &codes))
- goto out;
- if (BN_is_word(g, DH_GENERATOR_2)) {
- /* Per https://wiki.openssl.org/index.php/Diffie-Hellman_parameters
- *
- * OpenSSL checks the prime is congruent to 11 when g = 2; while the
- * IETF's primes are congruent to 23 when g = 2.
- */
- BN_ULONG residue = BN_mod_word(p, 24);
- if (residue == 11 || residue == 23)
- codes &= ~DH_NOT_SUITABLE_GENERATOR;
- }
- if (codes != 0) /* Specifics on why the params suck is irrelevant. */
- goto out;
-
- /* Things are probably not evil. */
- ret = 0;
-
- out:
- if (dh)
- DH_free(dh);
- return ret;
-}
-
-/** Set the global Diffie-Hellman generator, used for both TLS and internal
- * DH stuff.
- */
-static void
-crypto_set_dh_generator(void)
-{
- BIGNUM *generator;
- int r;
-
- if (dh_param_g)
- return;
-
- generator = BN_new();
- tor_assert(generator);
-
- r = BN_set_word(generator, DH_GENERATOR);
- tor_assert(r);
-
- dh_param_g = generator;
-}
-
-/** Set the global TLS Diffie-Hellman modulus. Use the Apache mod_ssl DH
- * modulus. */
-void
-crypto_set_tls_dh_prime(void)
-{
- BIGNUM *tls_prime = NULL;
- int r;
-
- /* If the space is occupied, free the previous TLS DH prime */
- if (BUG(dh_param_p_tls)) {
- /* LCOV_EXCL_START
- *
- * We shouldn't be calling this twice.
- */
- BN_clear_free(dh_param_p_tls);
- dh_param_p_tls = NULL;
- /* LCOV_EXCL_STOP */
- }
-
- tls_prime = BN_new();
- tor_assert(tls_prime);
-
- /* This is the 1024-bit safe prime that Apache uses for its DH stuff; see
- * modules/ssl/ssl_engine_dh.c; Apache also uses a generator of 2 with this
- * prime.
- */
- r = BN_hex2bn(&tls_prime,
- "D67DE440CBBBDC1936D693D34AFD0AD50C84D239A45F520BB88174CB98"
- "BCE951849F912E639C72FB13B4B4D7177E16D55AC179BA420B2A29FE324A"
- "467A635E81FF5901377BEDDCFD33168A461AAD3B72DAE8860078045B07A7"
- "DBCA7874087D1510EA9FCC9DDD330507DD62DB88AEAA747DE0F4D6E2BD68"
- "B0E7393E0F24218EB3");
- tor_assert(r);
-
- tor_assert(tls_prime);
-
- dh_param_p_tls = tls_prime;
- crypto_set_dh_generator();
- tor_assert(0 == crypto_validate_dh_params(dh_param_p_tls, dh_param_g));
-}
-
-/** Initialize dh_param_p and dh_param_g if they are not already
- * set. */
-static void
-init_dh_param(void)
-{
- BIGNUM *circuit_dh_prime;
- int r;
- if (BUG(dh_param_p && dh_param_g))
- return; // LCOV_EXCL_LINE This function isn't supposed to be called twice.
-
- circuit_dh_prime = BN_new();
- tor_assert(circuit_dh_prime);
-
- /* This is from rfc2409, section 6.2. It's a safe prime, and
- supposedly it equals:
- 2^1024 - 2^960 - 1 + 2^64 * { [2^894 pi] + 129093 }.
- */
- r = BN_hex2bn(&circuit_dh_prime,
- "FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E08"
- "8A67CC74020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B"
- "302B0A6DF25F14374FE1356D6D51C245E485B576625E7EC6F44C42E9"
- "A637ED6B0BFF5CB6F406B7EDEE386BFB5A899FA5AE9F24117C4B1FE6"
- "49286651ECE65381FFFFFFFFFFFFFFFF");
- tor_assert(r);
-
- /* Set the new values as the global DH parameters. */
- dh_param_p = circuit_dh_prime;
- crypto_set_dh_generator();
- tor_assert(0 == crypto_validate_dh_params(dh_param_p, dh_param_g));
-
- if (!dh_param_p_tls) {
- crypto_set_tls_dh_prime();
- }
-}
-
-/** Number of bits to use when choosing the x or y value in a Diffie-Hellman
- * handshake. Since we exponentiate by this value, choosing a smaller one
- * lets our handhake go faster.
- */
-#define DH_PRIVATE_KEY_BITS 320
-
-/** Allocate and return a new DH object for a key exchange. Returns NULL on
- * failure.
- */
-crypto_dh_t *
-crypto_dh_new(int dh_type)
-{
- crypto_dh_t *res = tor_malloc_zero(sizeof(crypto_dh_t));
-
- tor_assert(dh_type == DH_TYPE_CIRCUIT || dh_type == DH_TYPE_TLS ||
- dh_type == DH_TYPE_REND);
-
- if (!dh_param_p)
- init_dh_param();
-
- if (!(res->dh = DH_new()))
- goto err;
-
-#ifdef OPENSSL_1_1_API
- BIGNUM *dh_p = NULL, *dh_g = NULL;
-
- if (dh_type == DH_TYPE_TLS) {
- dh_p = BN_dup(dh_param_p_tls);
- } else {
- dh_p = BN_dup(dh_param_p);
- }
- if (!dh_p)
- goto err;
-
- dh_g = BN_dup(dh_param_g);
- if (!dh_g) {
- BN_free(dh_p);
- goto err;
- }
-
- if (!DH_set0_pqg(res->dh, dh_p, NULL, dh_g)) {
- goto err;
- }
-
- if (!DH_set_length(res->dh, DH_PRIVATE_KEY_BITS))
- goto err;
-#else /* !(defined(OPENSSL_1_1_API)) */
- if (dh_type == DH_TYPE_TLS) {
- if (!(res->dh->p = BN_dup(dh_param_p_tls)))
- goto err;
- } else {
- if (!(res->dh->p = BN_dup(dh_param_p)))
- goto err;
- }
-
- if (!(res->dh->g = BN_dup(dh_param_g)))
- goto err;
-
- res->dh->length = DH_PRIVATE_KEY_BITS;
-#endif /* defined(OPENSSL_1_1_API) */
-
- return res;
-
- /* LCOV_EXCL_START
- * This error condition is only reached when an allocation fails */
- err:
- crypto_log_errors(LOG_WARN, "creating DH object");
- if (res->dh) DH_free(res->dh); /* frees p and g too */
- tor_free(res);
- return NULL;
- /* LCOV_EXCL_STOP */
-}
-
-/** Return a copy of <b>dh</b>, sharing its internal state. */
-crypto_dh_t *
-crypto_dh_dup(const crypto_dh_t *dh)
-{
- crypto_dh_t *dh_new = tor_malloc_zero(sizeof(crypto_dh_t));
- tor_assert(dh);
- tor_assert(dh->dh);
- dh_new->dh = dh->dh;
- DH_up_ref(dh->dh);
- return dh_new;
-}
-
-/** Return the length of the DH key in <b>dh</b>, in bytes.
- */
-int
-crypto_dh_get_bytes(crypto_dh_t *dh)
-{
- tor_assert(dh);
- return DH_size(dh->dh);
-}
-
-/** Generate \<x,g^x\> for our part of the key exchange. Return 0 on
- * success, -1 on failure.
- */
-int
-crypto_dh_generate_public(crypto_dh_t *dh)
-{
-#ifndef OPENSSL_1_1_API
- again:
-#endif
- if (!DH_generate_key(dh->dh)) {
- /* LCOV_EXCL_START
- * To test this we would need some way to tell openssl to break DH. */
- crypto_log_errors(LOG_WARN, "generating DH key");
- return -1;
- /* LCOV_EXCL_STOP */
- }
-#ifdef OPENSSL_1_1_API
- /* OpenSSL 1.1.x doesn't appear to let you regenerate a DH key, without
- * recreating the DH object. I have no idea what sort of aliasing madness
- * can occur here, so do the check, and just bail on failure.
- */
- const BIGNUM *pub_key, *priv_key;
- DH_get0_key(dh->dh, &pub_key, &priv_key);
- if (tor_check_dh_key(LOG_WARN, pub_key)<0) {
- log_warn(LD_CRYPTO, "Weird! Our own DH key was invalid. I guess once-in-"
- "the-universe chances really do happen. Treating as a failure.");
- return -1;
- }
-#else /* !(defined(OPENSSL_1_1_API)) */
- if (tor_check_dh_key(LOG_WARN, dh->dh->pub_key)<0) {
- /* LCOV_EXCL_START
- * If this happens, then openssl's DH implementation is busted. */
- log_warn(LD_CRYPTO, "Weird! Our own DH key was invalid. I guess once-in-"
- "the-universe chances really do happen. Trying again.");
- /* Free and clear the keys, so OpenSSL will actually try again. */
- BN_clear_free(dh->dh->pub_key);
- BN_clear_free(dh->dh->priv_key);
- dh->dh->pub_key = dh->dh->priv_key = NULL;
- goto again;
- /* LCOV_EXCL_STOP */
- }
-#endif /* defined(OPENSSL_1_1_API) */
- return 0;
-}
-
-/** Generate g^x as necessary, and write the g^x for the key exchange
- * as a <b>pubkey_len</b>-byte value into <b>pubkey</b>. Return 0 on
- * success, -1 on failure. <b>pubkey_len</b> must be \>= DH_BYTES.
- */
-int
-crypto_dh_get_public(crypto_dh_t *dh, char *pubkey, size_t pubkey_len)
-{
- int bytes;
- tor_assert(dh);
-
- const BIGNUM *dh_pub;
-
-#ifdef OPENSSL_1_1_API
- const BIGNUM *dh_priv;
- DH_get0_key(dh->dh, &dh_pub, &dh_priv);
-#else
- dh_pub = dh->dh->pub_key;
-#endif /* defined(OPENSSL_1_1_API) */
-
- if (!dh_pub) {
- if (crypto_dh_generate_public(dh)<0)
- return -1;
- else {
-#ifdef OPENSSL_1_1_API
- DH_get0_key(dh->dh, &dh_pub, &dh_priv);
-#else
- dh_pub = dh->dh->pub_key;
-#endif
- }
- }
-
- tor_assert(dh_pub);
- bytes = BN_num_bytes(dh_pub);
- tor_assert(bytes >= 0);
- if (pubkey_len < (size_t)bytes) {
- log_warn(LD_CRYPTO,
- "Weird! pubkey_len (%d) was smaller than DH_BYTES (%d)",
- (int) pubkey_len, bytes);
- return -1;
- }
-
- memset(pubkey, 0, pubkey_len);
- BN_bn2bin(dh_pub, (unsigned char*)(pubkey+(pubkey_len-bytes)));
-
- return 0;
-}
-
-/** Check for bad Diffie-Hellman public keys (g^x). Return 0 if the key is
- * okay (in the subgroup [2,p-2]), or -1 if it's bad.
- * See http://www.cl.cam.ac.uk/ftp/users/rja14/psandqs.ps.gz for some tips.
- */
-static int
-tor_check_dh_key(int severity, const BIGNUM *bn)
-{
- BIGNUM *x;
- char *s;
- tor_assert(bn);
- x = BN_new();
- tor_assert(x);
- if (BUG(!dh_param_p))
- init_dh_param(); //LCOV_EXCL_LINE we already checked whether we did this.
- BN_set_word(x, 1);
- if (BN_cmp(bn,x)<=0) {
- log_fn(severity, LD_CRYPTO, "DH key must be at least 2.");
- goto err;
- }
- BN_copy(x,dh_param_p);
- BN_sub_word(x, 1);
- if (BN_cmp(bn,x)>=0) {
- log_fn(severity, LD_CRYPTO, "DH key must be at most p-2.");
- goto err;
- }
- BN_clear_free(x);
- return 0;
- err:
- BN_clear_free(x);
- s = BN_bn2hex(bn);
- log_fn(severity, LD_CRYPTO, "Rejecting insecure DH key [%s]", s);
- OPENSSL_free(s);
- return -1;
-}
-
-/** Given a DH key exchange object, and our peer's value of g^y (as a
- * <b>pubkey_len</b>-byte value in <b>pubkey</b>) generate
- * <b>secret_bytes_out</b> bytes of shared key material and write them
- * to <b>secret_out</b>. Return the number of bytes generated on success,
- * or -1 on failure.
- *
- * (We generate key material by computing
- * SHA1( g^xy || "\x00" ) || SHA1( g^xy || "\x01" ) || ...
- * where || is concatenation.)
- */
-ssize_t
-crypto_dh_compute_secret(int severity, crypto_dh_t *dh,
- const char *pubkey, size_t pubkey_len,
- char *secret_out, size_t secret_bytes_out)
-{
- char *secret_tmp = NULL;
- BIGNUM *pubkey_bn = NULL;
- size_t secret_len=0, secret_tmp_len=0;
- int result=0;
- tor_assert(dh);
- tor_assert(secret_bytes_out/DIGEST_LEN <= 255);
- tor_assert(pubkey_len < INT_MAX);
-
- if (!(pubkey_bn = BN_bin2bn((const unsigned char*)pubkey,
- (int)pubkey_len, NULL)))
- goto error;
- if (tor_check_dh_key(severity, pubkey_bn)<0) {
- /* Check for invalid public keys. */
- log_fn(severity, LD_CRYPTO,"Rejected invalid g^x");
- goto error;
- }
- secret_tmp_len = crypto_dh_get_bytes(dh);
- secret_tmp = tor_malloc(secret_tmp_len);
- result = DH_compute_key((unsigned char*)secret_tmp, pubkey_bn, dh->dh);
- if (result < 0) {
- log_warn(LD_CRYPTO,"DH_compute_key() failed.");
- goto error;
- }
- secret_len = result;
- if (crypto_expand_key_material_TAP((uint8_t*)secret_tmp, secret_len,
- (uint8_t*)secret_out, secret_bytes_out)<0)
- goto error;
- secret_len = secret_bytes_out;
-
- goto done;
- error:
- result = -1;
- done:
- crypto_log_errors(LOG_WARN, "completing DH handshake");
- if (pubkey_bn)
- BN_clear_free(pubkey_bn);
- if (secret_tmp) {
- memwipe(secret_tmp, 0, secret_tmp_len);
- tor_free(secret_tmp);
- }
- if (result < 0)
- return result;
- else
- return secret_len;
-}
-
-/** Given <b>key_in_len</b> bytes of negotiated randomness in <b>key_in</b>
- * ("K"), expand it into <b>key_out_len</b> bytes of negotiated key material in
- * <b>key_out</b> by taking the first <b>key_out_len</b> bytes of
- * H(K | [00]) | H(K | [01]) | ....
- *
- * This is the key expansion algorithm used in the "TAP" circuit extension
- * mechanism; it shouldn't be used for new protocols.
- *
- * Return 0 on success, -1 on failure.
- */
-int
-crypto_expand_key_material_TAP(const uint8_t *key_in, size_t key_in_len,
- uint8_t *key_out, size_t key_out_len)
-{
- int i, r = -1;
- uint8_t *cp, *tmp = tor_malloc(key_in_len+1);
- uint8_t digest[DIGEST_LEN];
-
- /* If we try to get more than this amount of key data, we'll repeat blocks.*/
- tor_assert(key_out_len <= DIGEST_LEN*256);
-
- memcpy(tmp, key_in, key_in_len);
- for (cp = key_out, i=0; cp < key_out+key_out_len;
- ++i, cp += DIGEST_LEN) {
- tmp[key_in_len] = i;
- if (crypto_digest((char*)digest, (const char *)tmp, key_in_len+1) < 0)
- goto exit;
- memcpy(cp, digest, MIN(DIGEST_LEN, key_out_len-(cp-key_out)));
- }
-
- r = 0;
- exit:
- memwipe(tmp, 0, key_in_len+1);
- tor_free(tmp);
- memwipe(digest, 0, sizeof(digest));
- return r;
-}
-
-/** Expand some secret key material according to RFC5869, using SHA256 as the
- * underlying hash. The <b>key_in_len</b> bytes at <b>key_in</b> are the
- * secret key material; the <b>salt_in_len</b> bytes at <b>salt_in</b> and the
- * <b>info_in_len</b> bytes in <b>info_in_len</b> are the algorithm's "salt"
- * and "info" parameters respectively. On success, write <b>key_out_len</b>
- * bytes to <b>key_out</b> and return 0. Assert on failure.
- */
-int
-crypto_expand_key_material_rfc5869_sha256(
- const uint8_t *key_in, size_t key_in_len,
- const uint8_t *salt_in, size_t salt_in_len,
- const uint8_t *info_in, size_t info_in_len,
- uint8_t *key_out, size_t key_out_len)
-{
- uint8_t prk[DIGEST256_LEN];
- uint8_t tmp[DIGEST256_LEN + 128 + 1];
- uint8_t mac[DIGEST256_LEN];
- int i;
- uint8_t *outp;
- size_t tmp_len;
-
- crypto_hmac_sha256((char*)prk,
- (const char*)salt_in, salt_in_len,
- (const char*)key_in, key_in_len);
-
- /* If we try to get more than this amount of key data, we'll repeat blocks.*/
- tor_assert(key_out_len <= DIGEST256_LEN * 256);
- tor_assert(info_in_len <= 128);
- memset(tmp, 0, sizeof(tmp));
- outp = key_out;
- i = 1;
-
- while (key_out_len) {
- size_t n;
- if (i > 1) {
- memcpy(tmp, mac, DIGEST256_LEN);
- memcpy(tmp+DIGEST256_LEN, info_in, info_in_len);
- tmp[DIGEST256_LEN+info_in_len] = i;
- tmp_len = DIGEST256_LEN + info_in_len + 1;
- } else {
- memcpy(tmp, info_in, info_in_len);
- tmp[info_in_len] = i;
- tmp_len = info_in_len + 1;
- }
- crypto_hmac_sha256((char*)mac,
- (const char*)prk, DIGEST256_LEN,
- (const char*)tmp, tmp_len);
- n = key_out_len < DIGEST256_LEN ? key_out_len : DIGEST256_LEN;
- memcpy(outp, mac, n);
- key_out_len -= n;
- outp += n;
- ++i;
- }
-
- memwipe(tmp, 0, sizeof(tmp));
- memwipe(mac, 0, sizeof(mac));
- return 0;
-}
-
-/** Free a DH key exchange object.
- */
-void
-crypto_dh_free_(crypto_dh_t *dh)
-{
- if (!dh)
- return;
- tor_assert(dh->dh);
- DH_free(dh->dh);
- tor_free(dh);
-}
-
-/** @{ */
-/** Uninitialize the crypto library. Return 0 on success. Does not detect
- * failure.
- */
-int
-crypto_global_cleanup(void)
-{
-#ifndef OPENSSL_1_1_API
- EVP_cleanup();
-#endif
-#ifndef NEW_THREAD_API
- ERR_remove_thread_state(NULL);
-#endif
-#ifndef OPENSSL_1_1_API
- ERR_free_strings();
-#endif
-
- if (dh_param_p)
- BN_clear_free(dh_param_p);
- if (dh_param_p_tls)
- BN_clear_free(dh_param_p_tls);
- if (dh_param_g)
- BN_clear_free(dh_param_g);
-
- dh_param_p = dh_param_p_tls = dh_param_g = NULL;
-
-#ifndef DISABLE_ENGINES
-#ifndef OPENSSL_1_1_API
- ENGINE_cleanup();
-#endif
-#endif
-
- CONF_modules_unload(1);
-#ifndef OPENSSL_1_1_API
- CRYPTO_cleanup_all_ex_data();
-#endif
-
- crypto_openssl_free_all();
-
- crypto_early_initialized_ = 0;
- crypto_global_initialized_ = 0;
- have_seeded_siphash = 0;
- siphash_unset_global_key();
-
- return 0;
-}
-
-/** @} */
-
-#ifdef USE_DMALLOC
-/** Tell the crypto library to use Tor's allocation functions rather than
- * calling libc's allocation functions directly. Return 0 on success, -1
- * on failure. */
-int
-crypto_use_tor_alloc_functions(void)
-{
- int r = CRYPTO_set_mem_ex_functions(tor_malloc_, tor_realloc_, tor_free_);
- return r ? 0 : -1;
-}
-#endif /* defined(USE_DMALLOC) */
-
diff --git a/src/common/crypto.h b/src/common/crypto.h
deleted file mode 100644
index c773557310..0000000000
--- a/src/common/crypto.h
+++ /dev/null
@@ -1,114 +0,0 @@
-/* Copyright (c) 2001, Matej Pfajfar.
- * Copyright (c) 2001-2004, Roger Dingledine.
- * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2017, The Tor Project, Inc. */
-/* See LICENSE for licensing information */
-
-/**
- * \file crypto.h
- *
- * \brief Headers for crypto.c
- **/
-
-#ifndef TOR_CRYPTO_H
-#define TOR_CRYPTO_H
-
-#include "orconfig.h"
-
-#include <stdio.h>
-#include "torint.h"
-#include "compat.h"
-#include "util.h"
-#include "crypto_rsa.h"
-
-/** Length of our symmetric cipher's keys of 128-bit. */
-#define CIPHER_KEY_LEN 16
-/** Length of our symmetric cipher's IV of 128-bit. */
-#define CIPHER_IV_LEN 16
-/** Length of our symmetric cipher's keys of 256-bit. */
-#define CIPHER256_KEY_LEN 32
-/** Length of our DH keys. */
-#define DH_BYTES (1024/8)
-
-/** Length of encoded public key fingerprints, including space; but not
- * including terminating NUL. */
-#define FINGERPRINT_LEN 49
-
-typedef struct aes_cnt_cipher crypto_cipher_t;
-typedef struct crypto_dh_t crypto_dh_t;
-
-/* global state */
-int crypto_init_siphash_key(void);
-int crypto_early_init(void) ATTR_WUR;
-int crypto_global_init(int hardwareAccel,
- const char *accelName,
- const char *accelPath) ATTR_WUR;
-#ifdef USE_DMALLOC
-int crypto_use_tor_alloc_functions(void);
-#endif
-
-void crypto_thread_cleanup(void);
-int crypto_global_cleanup(void);
-
-/* environment setup */
-void crypto_set_tls_dh_prime(void);
-crypto_cipher_t *crypto_cipher_new(const char *key);
-crypto_cipher_t *crypto_cipher_new_with_bits(const char *key, int bits);
-crypto_cipher_t *crypto_cipher_new_with_iv(const char *key, const char *iv);
-crypto_cipher_t *crypto_cipher_new_with_iv_and_bits(const uint8_t *key,
- const uint8_t *iv,
- int bits);
-void crypto_cipher_free_(crypto_cipher_t *env);
-#define crypto_cipher_free(c) \
- FREE_AND_NULL(crypto_cipher_t, crypto_cipher_free_, (c))
-
-/* symmetric crypto */
-const char *crypto_cipher_get_key(crypto_cipher_t *env);
-
-int crypto_cipher_encrypt(crypto_cipher_t *env, char *to,
- const char *from, size_t fromlen);
-int crypto_cipher_decrypt(crypto_cipher_t *env, char *to,
- const char *from, size_t fromlen);
-void crypto_cipher_crypt_inplace(crypto_cipher_t *env, char *d, size_t len);
-
-int crypto_cipher_encrypt_with_iv(const char *key,
- char *to, size_t tolen,
- const char *from, size_t fromlen);
-int crypto_cipher_decrypt_with_iv(const char *key,
- char *to, size_t tolen,
- const char *from, size_t fromlen);
-
-/* Key negotiation */
-#define DH_TYPE_CIRCUIT 1
-#define DH_TYPE_REND 2
-#define DH_TYPE_TLS 3
-crypto_dh_t *crypto_dh_new(int dh_type);
-crypto_dh_t *crypto_dh_dup(const crypto_dh_t *dh);
-int crypto_dh_get_bytes(crypto_dh_t *dh);
-int crypto_dh_generate_public(crypto_dh_t *dh);
-int crypto_dh_get_public(crypto_dh_t *dh, char *pubkey_out,
- size_t pubkey_out_len);
-ssize_t crypto_dh_compute_secret(int severity, crypto_dh_t *dh,
- const char *pubkey, size_t pubkey_len,
- char *secret_out, size_t secret_out_len);
-void crypto_dh_free_(crypto_dh_t *dh);
-#define crypto_dh_free(dh) FREE_AND_NULL(crypto_dh_t, crypto_dh_free_, (dh))
-
-int crypto_expand_key_material_TAP(const uint8_t *key_in,
- size_t key_in_len,
- uint8_t *key_out, size_t key_out_len);
-int crypto_expand_key_material_rfc5869_sha256(
- const uint8_t *key_in, size_t key_in_len,
- const uint8_t *salt_in, size_t salt_in_len,
- const uint8_t *info_in, size_t info_in_len,
- uint8_t *key_out, size_t key_out_len);
-
-/* Prototypes for private functions only used by tortls.c, crypto.c, and the
- * unit tests. */
-struct dh_st;
-struct dh_st *crypto_dh_get_dh_(crypto_dh_t *dh);
-
-void crypto_add_spaces_to_fp(char *out, size_t outlen, const char *in);
-
-#endif /* !defined(TOR_CRYPTO_H) */
-
diff --git a/src/common/crypto_curve25519.c b/src/common/crypto_curve25519.c
deleted file mode 100644
index 996d94c6e2..0000000000
--- a/src/common/crypto_curve25519.c
+++ /dev/null
@@ -1,359 +0,0 @@
-/* Copyright (c) 2012-2017, The Tor Project, Inc. */
-/* See LICENSE for licensing information */
-
-/**
- * \file crypto_curve25519.c
- *
- * \brief Wrapper code for a curve25519 implementation.
- *
- * Curve25519 is an Elliptic-Curve Diffie Hellman handshake, designed by
- * Dan Bernstein. For more information, see https://cr.yp.to/ecdh.html
- *
- * Tor uses Curve25519 as the basis of its "ntor" circuit extension
- * handshake, and in related code. The functions in this module are
- * used to find the most suitable available Curve25519 implementation,
- * to provide wrappers around it, and so on.
- */
-
-#define CRYPTO_CURVE25519_PRIVATE
-#include "orconfig.h"
-#ifdef HAVE_SYS_STAT_H
-#include <sys/stat.h>
-#endif
-#include "container.h"
-#include "crypto_curve25519.h"
-#include "crypto_digest.h"
-#include "crypto_format.h"
-#include "crypto_rand.h"
-#include "crypto_util.h"
-#include "util.h"
-#include "torlog.h"
-
-#include "ed25519/donna/ed25519_donna_tor.h"
-
-/* ==============================
- Part 1: wrap a suitable curve25519 implementation as curve25519_impl
- ============================== */
-
-#ifdef USE_CURVE25519_DONNA
-int curve25519_donna(uint8_t *mypublic,
- const uint8_t *secret, const uint8_t *basepoint);
-#endif
-#ifdef USE_CURVE25519_NACL
-#ifdef HAVE_CRYPTO_SCALARMULT_CURVE25519_H
-#include <crypto_scalarmult_curve25519.h>
-#elif defined(HAVE_NACL_CRYPTO_SCALARMULT_CURVE25519_H)
-#include <nacl/crypto_scalarmult_curve25519.h>
-#endif
-#endif /* defined(USE_CURVE25519_NACL) */
-
-static void pick_curve25519_basepoint_impl(void);
-
-/** This is set to 1 if we have an optimized Ed25519-based
- * implementation for multiplying a value by the basepoint; to 0 if we
- * don't, and to -1 if we haven't checked. */
-static int curve25519_use_ed = -1;
-
-/**
- * Helper function: call the most appropriate backend to compute the
- * scalar "secret" times the point "point". Store the result in
- * "output". Return 0 on success, negative on failure.
- **/
-STATIC int
-curve25519_impl(uint8_t *output, const uint8_t *secret,
- const uint8_t *point)
-{
- uint8_t bp[CURVE25519_PUBKEY_LEN];
- int r;
- memcpy(bp, point, CURVE25519_PUBKEY_LEN);
- /* Clear the high bit, in case our backend foolishly looks at it. */
- bp[31] &= 0x7f;
-#ifdef USE_CURVE25519_DONNA
- r = curve25519_donna(output, secret, bp);
-#elif defined(USE_CURVE25519_NACL)
- r = crypto_scalarmult_curve25519(output, secret, bp);
-#else
-#error "No implementation of curve25519 is available."
-#endif /* defined(USE_CURVE25519_DONNA) || ... */
- memwipe(bp, 0, sizeof(bp));
- return r;
-}
-
-/**
- * Helper function: Multiply the scalar "secret" by the Curve25519
- * basepoint (X=9), and store the result in "output". Return 0 on
- * success, -1 on failure.
- */
-STATIC int
-curve25519_basepoint_impl(uint8_t *output, const uint8_t *secret)
-{
- int r = 0;
- if (BUG(curve25519_use_ed == -1)) {
- /* LCOV_EXCL_START - Only reached if we forgot to call curve25519_init() */
- pick_curve25519_basepoint_impl();
- /* LCOV_EXCL_STOP */
- }
-
- /* TODO: Someone should benchmark curved25519_scalarmult_basepoint versus
- * an optimized NaCl build to see which should be used when compiled with
- * NaCl available. I suspected that the ed25519 optimization always wins.
- */
- if (PREDICT_LIKELY(curve25519_use_ed == 1)) {
- curved25519_scalarmult_basepoint_donna(output, secret);
- r = 0;
- } else {
- static const uint8_t basepoint[32] = {9};
- r = curve25519_impl(output, secret, basepoint);
- }
- return r;
-}
-
-/**
- * Override the decision of whether to use the Ed25519-based basepoint
- * multiply function. Used for testing.
- */
-void
-curve25519_set_impl_params(int use_ed)
-{
- curve25519_use_ed = use_ed;
-}
-
-/* ==============================
- Part 2: Wrap curve25519_impl with some convenience types and functions.
- ============================== */
-
-/**
- * Return true iff a curve25519_public_key_t seems valid. (It's not necessary
- * to see if the point is on the curve, since the twist is also secure, but we
- * do need to make sure that it isn't the point at infinity.) */
-int
-curve25519_public_key_is_ok(const curve25519_public_key_t *key)
-{
- return !safe_mem_is_zero(key->public_key, CURVE25519_PUBKEY_LEN);
-}
-
-/**
- * Generate CURVE25519_SECKEY_LEN random bytes in <b>out</b>. If
- * <b>extra_strong</b> is true, this key is possibly going to get used more
- * than once, so use a better-than-usual RNG. Return 0 on success, -1 on
- * failure.
- *
- * This function does not adjust the output of the RNG at all; the will caller
- * will need to clear or set the appropriate bits to make curve25519 work.
- */
-int
-curve25519_rand_seckey_bytes(uint8_t *out, int extra_strong)
-{
- if (extra_strong)
- crypto_strongest_rand(out, CURVE25519_SECKEY_LEN);
- else
- crypto_rand((char*)out, CURVE25519_SECKEY_LEN);
-
- return 0;
-}
-
-/** Generate a new keypair and return the secret key. If <b>extra_strong</b>
- * is true, this key is possibly going to get used more than once, so
- * use a better-than-usual RNG. Return 0 on success, -1 on failure. */
-int
-curve25519_secret_key_generate(curve25519_secret_key_t *key_out,
- int extra_strong)
-{
- if (curve25519_rand_seckey_bytes(key_out->secret_key, extra_strong) < 0)
- return -1;
-
- key_out->secret_key[0] &= 248;
- key_out->secret_key[31] &= 127;
- key_out->secret_key[31] |= 64;
-
- return 0;
-}
-
-/**
- * Given a secret key in <b>seckey</b>, create the corresponding public
- * key in <b>key_out</b>.
- */
-void
-curve25519_public_key_generate(curve25519_public_key_t *key_out,
- const curve25519_secret_key_t *seckey)
-{
- curve25519_basepoint_impl(key_out->public_key, seckey->secret_key);
-}
-
-/**
- * Construct a new keypair in *<b>keypair_out</b>. If <b>extra_strong</b>
- * is true, this key is possibly going to get used more than once, so
- * use a better-than-usual RNG. Return 0 on success, -1 on failure. */
-int
-curve25519_keypair_generate(curve25519_keypair_t *keypair_out,
- int extra_strong)
-{
- if (curve25519_secret_key_generate(&keypair_out->seckey, extra_strong) < 0)
- return -1;
- curve25519_public_key_generate(&keypair_out->pubkey, &keypair_out->seckey);
- return 0;
-}
-
-/** Store the keypair <b>keypair</b>, including its secret and public
- * parts, to the file <b>fname</b>. Use the string tag <b>tag</b> to
- * distinguish this from other Curve25519 keypairs. Return 0 on success,
- * -1 on failure.
- *
- * See crypto_write_tagged_contents_to_file() for more information on
- * the metaformat used for these keys.*/
-int
-curve25519_keypair_write_to_file(const curve25519_keypair_t *keypair,
- const char *fname,
- const char *tag)
-{
- uint8_t contents[CURVE25519_SECKEY_LEN + CURVE25519_PUBKEY_LEN];
- int r;
-
- memcpy(contents, keypair->seckey.secret_key, CURVE25519_SECKEY_LEN);
- memcpy(contents+CURVE25519_SECKEY_LEN,
- keypair->pubkey.public_key, CURVE25519_PUBKEY_LEN);
-
- r = crypto_write_tagged_contents_to_file(fname,
- "c25519v1",
- tag,
- contents,
- sizeof(contents));
-
- memwipe(contents, 0, sizeof(contents));
- return r;
-}
-
-/** Read a curve25519 keypair from a file named <b>fname</b> created by
- * curve25519_keypair_write_to_file(). Store the keypair in
- * <b>keypair_out</b>, and the associated tag string in <b>tag_out</b>.
- * Return 0 on success, and -1 on failure. */
-int
-curve25519_keypair_read_from_file(curve25519_keypair_t *keypair_out,
- char **tag_out,
- const char *fname)
-{
- uint8_t content[CURVE25519_SECKEY_LEN + CURVE25519_PUBKEY_LEN];
- ssize_t len;
- int r = -1;
-
- len = crypto_read_tagged_contents_from_file(fname, "c25519v1", tag_out,
- content, sizeof(content));
- if (len != sizeof(content))
- goto end;
-
- /* Make sure that the public key matches the secret key */
- memcpy(keypair_out->seckey.secret_key, content, CURVE25519_SECKEY_LEN);
- curve25519_public_key_generate(&keypair_out->pubkey, &keypair_out->seckey);
- if (tor_memneq(keypair_out->pubkey.public_key,
- content + CURVE25519_SECKEY_LEN,
- CURVE25519_PUBKEY_LEN))
- goto end;
-
- r = 0;
-
- end:
- memwipe(content, 0, sizeof(content));
- if (r != 0) {
- memset(keypair_out, 0, sizeof(*keypair_out));
- tor_free(*tag_out);
- }
- return r;
-}
-
-/** Perform the curve25519 ECDH handshake with <b>skey</b> and <b>pkey</b>,
- * writing CURVE25519_OUTPUT_LEN bytes of output into <b>output</b>. */
-void
-curve25519_handshake(uint8_t *output,
- const curve25519_secret_key_t *skey,
- const curve25519_public_key_t *pkey)
-{
- curve25519_impl(output, skey->secret_key, pkey->public_key);
-}
-
-/** Check whether the ed25519-based curve25519 basepoint optimization seems to
- * be working. If so, return 0; otherwise return -1. */
-static int
-curve25519_basepoint_spot_check(void)
-{
- static const uint8_t alicesk[32] = {
- 0x77,0x07,0x6d,0x0a,0x73,0x18,0xa5,0x7d,
- 0x3c,0x16,0xc1,0x72,0x51,0xb2,0x66,0x45,
- 0xdf,0x4c,0x2f,0x87,0xeb,0xc0,0x99,0x2a,
- 0xb1,0x77,0xfb,0xa5,0x1d,0xb9,0x2c,0x2a
- };
- static const uint8_t alicepk[32] = {
- 0x85,0x20,0xf0,0x09,0x89,0x30,0xa7,0x54,
- 0x74,0x8b,0x7d,0xdc,0xb4,0x3e,0xf7,0x5a,
- 0x0d,0xbf,0x3a,0x0d,0x26,0x38,0x1a,0xf4,
- 0xeb,0xa4,0xa9,0x8e,0xaa,0x9b,0x4e,0x6a
- };
- const int loop_max=200;
- int save_use_ed = curve25519_use_ed;
- unsigned char e1[32] = { 5 };
- unsigned char e2[32] = { 5 };
- unsigned char x[32],y[32];
- int i;
- int r=0;
-
- /* Check the most basic possible sanity via the test secret/public key pair
- * used in "Cryptography in NaCl - 2. Secret keys and public keys". This
- * may catch catastrophic failures on systems where Curve25519 is expensive,
- * without requiring a ton of key generation.
- */
- curve25519_use_ed = 1;
- r |= curve25519_basepoint_impl(x, alicesk);
- if (fast_memneq(x, alicepk, 32))
- goto fail;
-
- /* Ok, the optimization appears to produce passable results, try a few more
- * values, maybe there's something subtle wrong.
- */
- for (i = 0; i < loop_max; ++i) {
- curve25519_use_ed = 0;
- r |= curve25519_basepoint_impl(x, e1);
- curve25519_use_ed = 1;
- r |= curve25519_basepoint_impl(y, e2);
- if (fast_memneq(x,y,32))
- goto fail;
- memcpy(e1, x, 32);
- memcpy(e2, x, 32);
- }
-
- goto end;
- // LCOV_EXCL_START -- we can only hit this code if there is a bug in our
- // curve25519-basepoint implementation.
- fail:
- r = -1;
- // LCOV_EXCL_STOP
- end:
- curve25519_use_ed = save_use_ed;
- return r;
-}
-
-/** Choose whether to use the ed25519-based curve25519-basepoint
- * implementation. */
-static void
-pick_curve25519_basepoint_impl(void)
-{
- curve25519_use_ed = 1;
-
- if (curve25519_basepoint_spot_check() == 0)
- return;
-
- /* LCOV_EXCL_START
- * only reachable if our basepoint implementation broken */
- log_warn(LD_BUG|LD_CRYPTO, "The ed25519-based curve25519 basepoint "
- "multiplication seems broken; using the curve25519 "
- "implementation.");
- curve25519_use_ed = 0;
- /* LCOV_EXCL_STOP */
-}
-
-/** Initialize the curve25519 implementations. This is necessary if you're
- * going to use them in a multithreaded setting, and not otherwise. */
-void
-curve25519_init(void)
-{
- pick_curve25519_basepoint_impl();
-}
-
diff --git a/src/common/crypto_curve25519.h b/src/common/crypto_curve25519.h
deleted file mode 100644
index 4834fa0836..0000000000
--- a/src/common/crypto_curve25519.h
+++ /dev/null
@@ -1,89 +0,0 @@
-/* Copyright (c) 2012-2017, The Tor Project, Inc. */
-/* See LICENSE for licensing information */
-
-#ifndef TOR_CRYPTO_CURVE25519_H
-#define TOR_CRYPTO_CURVE25519_H
-
-#include "testsupport.h"
-#include "torint.h"
-#include "crypto_digest.h"
-#include "crypto_openssl_mgt.h"
-
-/** Length of a curve25519 public key when encoded. */
-#define CURVE25519_PUBKEY_LEN 32
-/** Length of a curve25519 secret key when encoded. */
-#define CURVE25519_SECKEY_LEN 32
-/** Length of the result of a curve25519 handshake. */
-#define CURVE25519_OUTPUT_LEN 32
-
-/** Wrapper type for a curve25519 public key.
- *
- * (We define a separate type for these to make it less likely that we'll
- * mistake them for secret keys.)
- * */
-typedef struct curve25519_public_key_t {
- uint8_t public_key[CURVE25519_PUBKEY_LEN];
-} curve25519_public_key_t;
-
-/** Wrapper type for a curve25519 secret key
- *
- * (We define a separate type for these to make it less likely that we'll
- * mistake them for public keys.)
- **/
-typedef struct curve25519_secret_key_t {
- uint8_t secret_key[CURVE25519_SECKEY_LEN];
-} curve25519_secret_key_t;
-
-/** A paired public and private key for curve25519. **/
-typedef struct curve25519_keypair_t {
- curve25519_public_key_t pubkey;
- curve25519_secret_key_t seckey;
-} curve25519_keypair_t;
-
-/* These functions require that we actually know how to use curve25519 keys.
- * The other data structures and functions in this header let us parse them,
- * store them, and move them around.
- */
-
-int curve25519_public_key_is_ok(const curve25519_public_key_t *);
-
-int curve25519_secret_key_generate(curve25519_secret_key_t *key_out,
- int extra_strong);
-void curve25519_public_key_generate(curve25519_public_key_t *key_out,
- const curve25519_secret_key_t *seckey);
-int curve25519_keypair_generate(curve25519_keypair_t *keypair_out,
- int extra_strong);
-
-void curve25519_handshake(uint8_t *output,
- const curve25519_secret_key_t *,
- const curve25519_public_key_t *);
-
-int curve25519_keypair_write_to_file(const curve25519_keypair_t *keypair,
- const char *fname,
- const char *tag);
-
-int curve25519_keypair_read_from_file(curve25519_keypair_t *keypair_out,
- char **tag_out,
- const char *fname);
-
-int curve25519_rand_seckey_bytes(uint8_t *out, int extra_strong);
-
-#ifdef CRYPTO_CURVE25519_PRIVATE
-STATIC int curve25519_impl(uint8_t *output, const uint8_t *secret,
- const uint8_t *basepoint);
-
-STATIC int curve25519_basepoint_impl(uint8_t *output, const uint8_t *secret);
-#endif /* defined(CRYPTO_CURVE25519_PRIVATE) */
-
-#define CURVE25519_BASE64_PADDED_LEN 44
-
-int curve25519_public_from_base64(curve25519_public_key_t *pkey,
- const char *input);
-int curve25519_public_to_base64(char *output,
- const curve25519_public_key_t *pkey);
-
-void curve25519_set_impl_params(int use_ed);
-void curve25519_init(void);
-
-#endif /* !defined(TOR_CRYPTO_CURVE25519_H) */
-
diff --git a/src/common/crypto_digest.c b/src/common/crypto_digest.c
deleted file mode 100644
index 9f9a1a1e2c..0000000000
--- a/src/common/crypto_digest.c
+++ /dev/null
@@ -1,583 +0,0 @@
-/* Copyright (c) 2001, Matej Pfajfar.
- * Copyright (c) 2001-2004, Roger Dingledine.
- * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2017, The Tor Project, Inc. */
-/* See LICENSE for licensing information */
-
-/**
- * \file crypto_digest.c
- * \brief Block of functions related with digest and xof utilities and
- * operations.
- **/
-
-#include "container.h"
-#include "crypto_digest.h"
-#include "crypto_openssl_mgt.h"
-#include "crypto_util.h"
-#include "torlog.h"
-
-#include "keccak-tiny/keccak-tiny.h"
-
-DISABLE_GCC_WARNING(redundant-decls)
-
-#include <openssl/hmac.h>
-#include <openssl/sha.h>
-
-ENABLE_GCC_WARNING(redundant-decls)
-
-/* Crypto digest functions */
-
-/** Compute the SHA1 digest of the <b>len</b> bytes on data stored in
- * <b>m</b>. Write the DIGEST_LEN byte result into <b>digest</b>.
- * Return 0 on success, -1 on failure.
- */
-int
-crypto_digest(char *digest, const char *m, size_t len)
-{
- tor_assert(m);
- tor_assert(digest);
- if (SHA1((const unsigned char*)m,len,(unsigned char*)digest) == NULL)
- return -1;
- return 0;
-}
-
-/** Compute a 256-bit digest of <b>len</b> bytes in data stored in <b>m</b>,
- * using the algorithm <b>algorithm</b>. Write the DIGEST_LEN256-byte result
- * into <b>digest</b>. Return 0 on success, -1 on failure. */
-int
-crypto_digest256(char *digest, const char *m, size_t len,
- digest_algorithm_t algorithm)
-{
- tor_assert(m);
- tor_assert(digest);
- tor_assert(algorithm == DIGEST_SHA256 || algorithm == DIGEST_SHA3_256);
-
- int ret = 0;
- if (algorithm == DIGEST_SHA256)
- ret = (SHA256((const uint8_t*)m,len,(uint8_t*)digest) != NULL);
- else
- ret = (sha3_256((uint8_t *)digest, DIGEST256_LEN,(const uint8_t *)m, len)
- > -1);
-
- if (!ret)
- return -1;
- return 0;
-}
-
-/** Compute a 512-bit digest of <b>len</b> bytes in data stored in <b>m</b>,
- * using the algorithm <b>algorithm</b>. Write the DIGEST_LEN512-byte result
- * into <b>digest</b>. Return 0 on success, -1 on failure. */
-int
-crypto_digest512(char *digest, const char *m, size_t len,
- digest_algorithm_t algorithm)
-{
- tor_assert(m);
- tor_assert(digest);
- tor_assert(algorithm == DIGEST_SHA512 || algorithm == DIGEST_SHA3_512);
-
- int ret = 0;
- if (algorithm == DIGEST_SHA512)
- ret = (SHA512((const unsigned char*)m,len,(unsigned char*)digest)
- != NULL);
- else
- ret = (sha3_512((uint8_t*)digest, DIGEST512_LEN, (const uint8_t*)m, len)
- > -1);
-
- if (!ret)
- return -1;
- return 0;
-}
-
-/** Set the common_digests_t in <b>ds_out</b> to contain every digest on the
- * <b>len</b> bytes in <b>m</b> that we know how to compute. Return 0 on
- * success, -1 on failure. */
-int
-crypto_common_digests(common_digests_t *ds_out, const char *m, size_t len)
-{
- tor_assert(ds_out);
- memset(ds_out, 0, sizeof(*ds_out));
- if (crypto_digest(ds_out->d[DIGEST_SHA1], m, len) < 0)
- return -1;
- if (crypto_digest256(ds_out->d[DIGEST_SHA256], m, len, DIGEST_SHA256) < 0)
- return -1;
-
- return 0;
-}
-
-/** Return the name of an algorithm, as used in directory documents. */
-const char *
-crypto_digest_algorithm_get_name(digest_algorithm_t alg)
-{
- switch (alg) {
- case DIGEST_SHA1:
- return "sha1";
- case DIGEST_SHA256:
- return "sha256";
- case DIGEST_SHA512:
- return "sha512";
- case DIGEST_SHA3_256:
- return "sha3-256";
- case DIGEST_SHA3_512:
- return "sha3-512";
- // LCOV_EXCL_START
- default:
- tor_fragile_assert();
- return "??unknown_digest??";
- // LCOV_EXCL_STOP
- }
-}
-
-/** Given the name of a digest algorithm, return its integer value, or -1 if
- * the name is not recognized. */
-int
-crypto_digest_algorithm_parse_name(const char *name)
-{
- if (!strcmp(name, "sha1"))
- return DIGEST_SHA1;
- else if (!strcmp(name, "sha256"))
- return DIGEST_SHA256;
- else if (!strcmp(name, "sha512"))
- return DIGEST_SHA512;
- else if (!strcmp(name, "sha3-256"))
- return DIGEST_SHA3_256;
- else if (!strcmp(name, "sha3-512"))
- return DIGEST_SHA3_512;
- else
- return -1;
-}
-
-/** Given an algorithm, return the digest length in bytes. */
-size_t
-crypto_digest_algorithm_get_length(digest_algorithm_t alg)
-{
- switch (alg) {
- case DIGEST_SHA1:
- return DIGEST_LEN;
- case DIGEST_SHA256:
- return DIGEST256_LEN;
- case DIGEST_SHA512:
- return DIGEST512_LEN;
- case DIGEST_SHA3_256:
- return DIGEST256_LEN;
- case DIGEST_SHA3_512:
- return DIGEST512_LEN;
- default:
- tor_assert(0); // LCOV_EXCL_LINE
- return 0; /* Unreachable */ // LCOV_EXCL_LINE
- }
-}
-
-/** Intermediate information about the digest of a stream of data. */
-struct crypto_digest_t {
- digest_algorithm_t algorithm; /**< Which algorithm is in use? */
- /** State for the digest we're using. Only one member of the
- * union is usable, depending on the value of <b>algorithm</b>. Note also
- * that space for other members might not even be allocated!
- */
- union {
- SHA_CTX sha1; /**< state for SHA1 */
- SHA256_CTX sha2; /**< state for SHA256 */
- SHA512_CTX sha512; /**< state for SHA512 */
- keccak_state sha3; /**< state for SHA3-[256,512] */
- } d;
-};
-
-#ifdef TOR_UNIT_TESTS
-
-digest_algorithm_t
-crypto_digest_get_algorithm(crypto_digest_t *digest)
-{
- tor_assert(digest);
-
- return digest->algorithm;
-}
-
-#endif /* defined(TOR_UNIT_TESTS) */
-
-/**
- * Return the number of bytes we need to malloc in order to get a
- * crypto_digest_t for <b>alg</b>, or the number of bytes we need to wipe
- * when we free one.
- */
-static size_t
-crypto_digest_alloc_bytes(digest_algorithm_t alg)
-{
- /* Helper: returns the number of bytes in the 'f' field of 'st' */
-#define STRUCT_FIELD_SIZE(st, f) (sizeof( ((st*)0)->f ))
- /* Gives the length of crypto_digest_t through the end of the field 'd' */
-#define END_OF_FIELD(f) (offsetof(crypto_digest_t, f) + \
- STRUCT_FIELD_SIZE(crypto_digest_t, f))
- switch (alg) {
- case DIGEST_SHA1:
- return END_OF_FIELD(d.sha1);
- case DIGEST_SHA256:
- return END_OF_FIELD(d.sha2);
- case DIGEST_SHA512:
- return END_OF_FIELD(d.sha512);
- case DIGEST_SHA3_256:
- case DIGEST_SHA3_512:
- return END_OF_FIELD(d.sha3);
- default:
- tor_assert(0); // LCOV_EXCL_LINE
- return 0; // LCOV_EXCL_LINE
- }
-#undef END_OF_FIELD
-#undef STRUCT_FIELD_SIZE
-}
-
-/**
- * Internal function: create and return a new digest object for 'algorithm'.
- * Does not typecheck the algorithm.
- */
-static crypto_digest_t *
-crypto_digest_new_internal(digest_algorithm_t algorithm)
-{
- crypto_digest_t *r = tor_malloc(crypto_digest_alloc_bytes(algorithm));
- r->algorithm = algorithm;
-
- switch (algorithm)
- {
- case DIGEST_SHA1:
- SHA1_Init(&r->d.sha1);
- break;
- case DIGEST_SHA256:
- SHA256_Init(&r->d.sha2);
- break;
- case DIGEST_SHA512:
- SHA512_Init(&r->d.sha512);
- break;
- case DIGEST_SHA3_256:
- keccak_digest_init(&r->d.sha3, 256);
- break;
- case DIGEST_SHA3_512:
- keccak_digest_init(&r->d.sha3, 512);
- break;
- default:
- tor_assert_unreached();
- }
-
- return r;
-}
-
-/** Allocate and return a new digest object to compute SHA1 digests.
- */
-crypto_digest_t *
-crypto_digest_new(void)
-{
- return crypto_digest_new_internal(DIGEST_SHA1);
-}
-
-/** Allocate and return a new digest object to compute 256-bit digests
- * using <b>algorithm</b>.
- *
- * C_RUST_COUPLED: `external::crypto_digest::crypto_digest256_new`
- * C_RUST_COUPLED: `crypto::digest::Sha256::default`
- */
-crypto_digest_t *
-crypto_digest256_new(digest_algorithm_t algorithm)
-{
- tor_assert(algorithm == DIGEST_SHA256 || algorithm == DIGEST_SHA3_256);
- return crypto_digest_new_internal(algorithm);
-}
-
-/** Allocate and return a new digest object to compute 512-bit digests
- * using <b>algorithm</b>. */
-crypto_digest_t *
-crypto_digest512_new(digest_algorithm_t algorithm)
-{
- tor_assert(algorithm == DIGEST_SHA512 || algorithm == DIGEST_SHA3_512);
- return crypto_digest_new_internal(algorithm);
-}
-
-/** Deallocate a digest object.
- */
-void
-crypto_digest_free_(crypto_digest_t *digest)
-{
- if (!digest)
- return;
- size_t bytes = crypto_digest_alloc_bytes(digest->algorithm);
- memwipe(digest, 0, bytes);
- tor_free(digest);
-}
-
-/** Add <b>len</b> bytes from <b>data</b> to the digest object.
- *
- * C_RUST_COUPLED: `external::crypto_digest::crypto_digest_add_bytess`
- * C_RUST_COUPLED: `crypto::digest::Sha256::process`
- */
-void
-crypto_digest_add_bytes(crypto_digest_t *digest, const char *data,
- size_t len)
-{
- tor_assert(digest);
- tor_assert(data);
- /* Using the SHA*_*() calls directly means we don't support doing
- * SHA in hardware. But so far the delay of getting the question
- * to the hardware, and hearing the answer, is likely higher than
- * just doing it ourselves. Hashes are fast.
- */
- switch (digest->algorithm) {
- case DIGEST_SHA1:
- SHA1_Update(&digest->d.sha1, (void*)data, len);
- break;
- case DIGEST_SHA256:
- SHA256_Update(&digest->d.sha2, (void*)data, len);
- break;
- case DIGEST_SHA512:
- SHA512_Update(&digest->d.sha512, (void*)data, len);
- break;
- case DIGEST_SHA3_256: /* FALLSTHROUGH */
- case DIGEST_SHA3_512:
- keccak_digest_update(&digest->d.sha3, (const uint8_t *)data, len);
- break;
- default:
- /* LCOV_EXCL_START */
- tor_fragile_assert();
- break;
- /* LCOV_EXCL_STOP */
- }
-}
-
-/** Compute the hash of the data that has been passed to the digest
- * object; write the first out_len bytes of the result to <b>out</b>.
- * <b>out_len</b> must be \<= DIGEST512_LEN.
- *
- * C_RUST_COUPLED: `external::crypto_digest::crypto_digest_get_digest`
- * C_RUST_COUPLED: `impl digest::FixedOutput for Sha256`
- */
-void
-crypto_digest_get_digest(crypto_digest_t *digest,
- char *out, size_t out_len)
-{
- unsigned char r[DIGEST512_LEN];
- crypto_digest_t tmpenv;
- tor_assert(digest);
- tor_assert(out);
- tor_assert(out_len <= crypto_digest_algorithm_get_length(digest->algorithm));
-
- /* The SHA-3 code handles copying into a temporary ctx, and also can handle
- * short output buffers by truncating appropriately. */
- if (digest->algorithm == DIGEST_SHA3_256 ||
- digest->algorithm == DIGEST_SHA3_512) {
- keccak_digest_sum(&digest->d.sha3, (uint8_t *)out, out_len);
- return;
- }
-
- const size_t alloc_bytes = crypto_digest_alloc_bytes(digest->algorithm);
- /* memcpy into a temporary ctx, since SHA*_Final clears the context */
- memcpy(&tmpenv, digest, alloc_bytes);
- switch (digest->algorithm) {
- case DIGEST_SHA1:
- SHA1_Final(r, &tmpenv.d.sha1);
- break;
- case DIGEST_SHA256:
- SHA256_Final(r, &tmpenv.d.sha2);
- break;
- case DIGEST_SHA512:
- SHA512_Final(r, &tmpenv.d.sha512);
- break;
-//LCOV_EXCL_START
- case DIGEST_SHA3_256: /* FALLSTHROUGH */
- case DIGEST_SHA3_512:
- default:
- log_warn(LD_BUG, "Handling unexpected algorithm %d", digest->algorithm);
- /* This is fatal, because it should never happen. */
- tor_assert_unreached();
- break;
-//LCOV_EXCL_STOP
- }
- memcpy(out, r, out_len);
- memwipe(r, 0, sizeof(r));
-}
-
-/** Allocate and return a new digest object with the same state as
- * <b>digest</b>
- *
- * C_RUST_COUPLED: `external::crypto_digest::crypto_digest_dup`
- * C_RUST_COUPLED: `impl Clone for crypto::digest::Sha256`
- */
-crypto_digest_t *
-crypto_digest_dup(const crypto_digest_t *digest)
-{
- tor_assert(digest);
- const size_t alloc_bytes = crypto_digest_alloc_bytes(digest->algorithm);
- return tor_memdup(digest, alloc_bytes);
-}
-
-/** Temporarily save the state of <b>digest</b> in <b>checkpoint</b>.
- * Asserts that <b>digest</b> is a SHA1 digest object.
- */
-void
-crypto_digest_checkpoint(crypto_digest_checkpoint_t *checkpoint,
- const crypto_digest_t *digest)
-{
- const size_t bytes = crypto_digest_alloc_bytes(digest->algorithm);
- tor_assert(bytes <= sizeof(checkpoint->mem));
- memcpy(checkpoint->mem, digest, bytes);
-}
-
-/** Restore the state of <b>digest</b> from <b>checkpoint</b>.
- * Asserts that <b>digest</b> is a SHA1 digest object. Requires that the
- * state was previously stored with crypto_digest_checkpoint() */
-void
-crypto_digest_restore(crypto_digest_t *digest,
- const crypto_digest_checkpoint_t *checkpoint)
-{
- const size_t bytes = crypto_digest_alloc_bytes(digest->algorithm);
- memcpy(digest, checkpoint->mem, bytes);
-}
-
-/** Replace the state of the digest object <b>into</b> with the state
- * of the digest object <b>from</b>. Requires that 'into' and 'from'
- * have the same digest type.
- */
-void
-crypto_digest_assign(crypto_digest_t *into,
- const crypto_digest_t *from)
-{
- tor_assert(into);
- tor_assert(from);
- tor_assert(into->algorithm == from->algorithm);
- const size_t alloc_bytes = crypto_digest_alloc_bytes(from->algorithm);
- memcpy(into,from,alloc_bytes);
-}
-
-/** Given a list of strings in <b>lst</b>, set the <b>len_out</b>-byte digest
- * at <b>digest_out</b> to the hash of the concatenation of those strings,
- * plus the optional string <b>append</b>, computed with the algorithm
- * <b>alg</b>.
- * <b>out_len</b> must be \<= DIGEST512_LEN. */
-void
-crypto_digest_smartlist(char *digest_out, size_t len_out,
- const smartlist_t *lst,
- const char *append,
- digest_algorithm_t alg)
-{
- crypto_digest_smartlist_prefix(digest_out, len_out, NULL, lst, append, alg);
-}
-
-/** Given a list of strings in <b>lst</b>, set the <b>len_out</b>-byte digest
- * at <b>digest_out</b> to the hash of the concatenation of: the
- * optional string <b>prepend</b>, those strings,
- * and the optional string <b>append</b>, computed with the algorithm
- * <b>alg</b>.
- * <b>len_out</b> must be \<= DIGEST512_LEN. */
-void
-crypto_digest_smartlist_prefix(char *digest_out, size_t len_out,
- const char *prepend,
- const smartlist_t *lst,
- const char *append,
- digest_algorithm_t alg)
-{
- crypto_digest_t *d = crypto_digest_new_internal(alg);
- if (prepend)
- crypto_digest_add_bytes(d, prepend, strlen(prepend));
- SMARTLIST_FOREACH(lst, const char *, cp,
- crypto_digest_add_bytes(d, cp, strlen(cp)));
- if (append)
- crypto_digest_add_bytes(d, append, strlen(append));
- crypto_digest_get_digest(d, digest_out, len_out);
- crypto_digest_free(d);
-}
-
-/** Compute the HMAC-SHA-256 of the <b>msg_len</b> bytes in <b>msg</b>, using
- * the <b>key</b> of length <b>key_len</b>. Store the DIGEST256_LEN-byte
- * result in <b>hmac_out</b>. Asserts on failure.
- */
-void
-crypto_hmac_sha256(char *hmac_out,
- const char *key, size_t key_len,
- const char *msg, size_t msg_len)
-{
- unsigned char *rv = NULL;
- /* 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);
- tor_assert(hmac_out);
- rv = HMAC(EVP_sha256(), key, (int)key_len, (unsigned char*)msg, (int)msg_len,
- (unsigned char*)hmac_out, NULL);
- tor_assert(rv);
-}
-
-/** Compute a MAC using SHA3-256 of <b>msg_len</b> bytes in <b>msg</b> using a
- * <b>key</b> of length <b>key_len</b> and a <b>salt</b> of length
- * <b>salt_len</b>. Store the result of <b>len_out</b> bytes in in
- * <b>mac_out</b>. This function can't fail. */
-void
-crypto_mac_sha3_256(uint8_t *mac_out, size_t len_out,
- const uint8_t *key, size_t key_len,
- const uint8_t *msg, size_t msg_len)
-{
- crypto_digest_t *digest;
-
- const uint64_t key_len_netorder = tor_htonll(key_len);
-
- tor_assert(mac_out);
- tor_assert(key);
- tor_assert(msg);
-
- digest = crypto_digest256_new(DIGEST_SHA3_256);
-
- /* Order matters here that is any subsystem using this function should
- * expect this very precise ordering in the MAC construction. */
- crypto_digest_add_bytes(digest, (const char *) &key_len_netorder,
- sizeof(key_len_netorder));
- crypto_digest_add_bytes(digest, (const char *) key, key_len);
- crypto_digest_add_bytes(digest, (const char *) msg, msg_len);
- crypto_digest_get_digest(digest, (char *) mac_out, len_out);
- crypto_digest_free(digest);
-}
-
-/* xof functions */
-
-/** Internal state for a eXtendable-Output Function (XOF). */
-struct crypto_xof_t {
- keccak_state s;
-};
-
-/** Allocate a new XOF object backed by SHAKE-256. The security level
- * provided is a function of the length of the output used. Read and
- * understand FIPS-202 A.2 "Additional Consideration for Extendable-Output
- * Functions" before using this construct.
- */
-crypto_xof_t *
-crypto_xof_new(void)
-{
- crypto_xof_t *xof;
- xof = tor_malloc(sizeof(crypto_xof_t));
- keccak_xof_init(&xof->s, 256);
- return xof;
-}
-
-/** Absorb bytes into a XOF object. Must not be called after a call to
- * crypto_xof_squeeze_bytes() for the same instance, and will assert
- * if attempted.
- */
-void
-crypto_xof_add_bytes(crypto_xof_t *xof, const uint8_t *data, size_t len)
-{
- int i = keccak_xof_absorb(&xof->s, data, len);
- tor_assert(i == 0);
-}
-
-/** Squeeze bytes out of a XOF object. Calling this routine will render
- * the XOF instance ineligible to absorb further data.
- */
-void
-crypto_xof_squeeze_bytes(crypto_xof_t *xof, uint8_t *out, size_t len)
-{
- int i = keccak_xof_squeeze(&xof->s, out, len);
- tor_assert(i == 0);
-}
-
-/** Cleanse and deallocate a XOF object. */
-void
-crypto_xof_free_(crypto_xof_t *xof)
-{
- if (!xof)
- return;
- memwipe(xof, 0, sizeof(crypto_xof_t));
- tor_free(xof);
-}
-
diff --git a/src/common/crypto_digest.h b/src/common/crypto_digest.h
deleted file mode 100644
index 3bd74acdfa..0000000000
--- a/src/common/crypto_digest.h
+++ /dev/null
@@ -1,136 +0,0 @@
-/* Copyright (c) 2001, Matej Pfajfar.
- * Copyright (c) 2001-2004, Roger Dingledine.
- * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2017, The Tor Project, Inc. */
-/* See LICENSE for licensing information */
-
-/**
- * \file crypto_digest.h
- *
- * \brief Headers for crypto_digest.c
- **/
-
-#ifndef TOR_CRYPTO_DIGEST_H
-#define TOR_CRYPTO_DIGEST_H
-
-#include <stdio.h>
-
-#include "container.h"
-#include "torint.h"
-
-/** 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 it could be any other 256-bit digest.) */
-#define DIGEST256_LEN 32
-/** Length of the output of our 64-bit optimized message digests (SHA512). */
-#define DIGEST512_LEN 64
-
-/** Length of a sha1 message digest when encoded in base32 with trailing =
- * signs removed. */
-#define BASE32_DIGEST_LEN 32
-/** Length of a sha1 message digest when encoded in base64 with trailing =
- * signs removed. */
-#define BASE64_DIGEST_LEN 27
-/** Length of a sha256 message digest when encoded in base64 with trailing =
- * signs removed. */
-#define BASE64_DIGEST256_LEN 43
-/** Length of a sha512 message digest when encoded in base64 with trailing =
- * signs removed. */
-#define BASE64_DIGEST512_LEN 86
-
-/** Length of hex encoding of SHA1 digest, not including final NUL. */
-#define HEX_DIGEST_LEN 40
-/** Length of hex encoding of SHA256 digest, not including final NUL. */
-#define HEX_DIGEST256_LEN 64
-/** Length of hex encoding of SHA512 digest, not including final NUL. */
-#define HEX_DIGEST512_LEN 128
-
-typedef enum {
- DIGEST_SHA1 = 0,
- DIGEST_SHA256 = 1,
- DIGEST_SHA512 = 2,
- DIGEST_SHA3_256 = 3,
- DIGEST_SHA3_512 = 4,
-} digest_algorithm_t;
-#define N_DIGEST_ALGORITHMS (DIGEST_SHA3_512+1)
-#define N_COMMON_DIGEST_ALGORITHMS (DIGEST_SHA256+1)
-
-#define DIGEST_CHECKPOINT_BYTES (SIZEOF_VOID_P + 512)
-/** Structure used to temporarily save the a digest object. Only implemented
- * for SHA1 digest for now. */
-typedef struct crypto_digest_checkpoint_t {
- uint8_t mem[DIGEST_CHECKPOINT_BYTES];
-} crypto_digest_checkpoint_t;
-
-/** A set of all the digests we commonly compute, taken on a single
- * string. Any digests that are shorter than 512 bits are right-padded
- * with 0 bits.
- *
- * Note that this representation wastes 44 bytes for the SHA1 case, so
- * don't use it for anything where we need to allocate a whole bunch at
- * once.
- **/
-typedef struct {
- char d[N_COMMON_DIGEST_ALGORITHMS][DIGEST256_LEN];
-} common_digests_t;
-
-typedef struct crypto_digest_t crypto_digest_t;
-typedef struct crypto_xof_t crypto_xof_t;
-
-/* SHA-1 and other digests */
-int crypto_digest(char *digest, const char *m, size_t len);
-int crypto_digest256(char *digest, const char *m, size_t len,
- digest_algorithm_t algorithm);
-int crypto_digest512(char *digest, const char *m, size_t len,
- digest_algorithm_t algorithm);
-int crypto_common_digests(common_digests_t *ds_out, const char *m, size_t len);
-void crypto_digest_smartlist_prefix(char *digest_out, size_t len_out,
- const char *prepend,
- const struct smartlist_t *lst,
- const char *append,
- digest_algorithm_t alg);
-void crypto_digest_smartlist(char *digest_out, size_t len_out,
- const struct smartlist_t *lst, const char *append,
- digest_algorithm_t alg);
-const char *crypto_digest_algorithm_get_name(digest_algorithm_t alg);
-size_t crypto_digest_algorithm_get_length(digest_algorithm_t alg);
-int crypto_digest_algorithm_parse_name(const char *name);
-crypto_digest_t *crypto_digest_new(void);
-crypto_digest_t *crypto_digest256_new(digest_algorithm_t algorithm);
-crypto_digest_t *crypto_digest512_new(digest_algorithm_t algorithm);
-void crypto_digest_free_(crypto_digest_t *digest);
-#define crypto_digest_free(d) \
- FREE_AND_NULL(crypto_digest_t, crypto_digest_free_, (d))
-void crypto_digest_add_bytes(crypto_digest_t *digest, const char *data,
- size_t len);
-void crypto_digest_get_digest(crypto_digest_t *digest,
- char *out, size_t out_len);
-crypto_digest_t *crypto_digest_dup(const crypto_digest_t *digest);
-void crypto_digest_checkpoint(crypto_digest_checkpoint_t *checkpoint,
- const crypto_digest_t *digest);
-void crypto_digest_restore(crypto_digest_t *digest,
- const crypto_digest_checkpoint_t *checkpoint);
-void crypto_digest_assign(crypto_digest_t *into,
- const crypto_digest_t *from);
-void crypto_hmac_sha256(char *hmac_out,
- const char *key, size_t key_len,
- const char *msg, size_t msg_len);
-void crypto_mac_sha3_256(uint8_t *mac_out, size_t len_out,
- const uint8_t *key, size_t key_len,
- const uint8_t *msg, size_t msg_len);
-
-/* xof functions*/
-crypto_xof_t *crypto_xof_new(void);
-void crypto_xof_add_bytes(crypto_xof_t *xof, const uint8_t *data, size_t len);
-void crypto_xof_squeeze_bytes(crypto_xof_t *xof, uint8_t *out, size_t len);
-void crypto_xof_free_(crypto_xof_t *xof);
-#define crypto_xof_free(xof) \
- FREE_AND_NULL(crypto_xof_t, crypto_xof_free_, (xof))
-
-#ifdef TOR_UNIT_TESTS
-digest_algorithm_t crypto_digest_get_algorithm(crypto_digest_t *digest);
-#endif
-
-#endif /* !defined(TOR_CRYPTO_DIGEST_H) */
-
diff --git a/src/common/crypto_ed25519.c b/src/common/crypto_ed25519.c
deleted file mode 100644
index 9c13e3bdf0..0000000000
--- a/src/common/crypto_ed25519.c
+++ /dev/null
@@ -1,817 +0,0 @@
-/* Copyright (c) 2013-2017, The Tor Project, Inc. */
-/* See LICENSE for licensing information */
-
-/**
- * \file crypto_ed25519.c
- *
- * \brief Wrapper code for an ed25519 implementation.
- *
- * Ed25519 is a Schnorr signature on a Twisted Edwards curve, defined
- * by Dan Bernstein. For more information, see https://ed25519.cr.yp.to/
- *
- * This module wraps our choice of Ed25519 backend, and provides a few
- * convenience functions for checking and generating signatures. It also
- * provides Tor-specific tools for key blinding and for converting Ed25519
- * keys to and from the corresponding Curve25519 keys.
- */
-
-#define CRYPTO_ED25519_PRIVATE
-#include "orconfig.h"
-#ifdef HAVE_SYS_STAT_H
-#include <sys/stat.h>
-#endif
-
-#include "crypto_curve25519.h"
-#include "crypto_digest.h"
-#include "crypto_ed25519.h"
-#include "crypto_format.h"
-#include "crypto_rand.h"
-#include "crypto_util.h"
-#include "torlog.h"
-#include "util.h"
-#include "util_format.h"
-
-#include "ed25519/ref10/ed25519_ref10.h"
-#include "ed25519/donna/ed25519_donna_tor.h"
-
-static void pick_ed25519_impl(void);
-
-/** An Ed25519 implementation, as a set of function pointers. */
-typedef struct {
- int (*selftest)(void);
-
- int (*seckey)(unsigned char *);
- int (*seckey_expand)(unsigned char *, const unsigned char *);
- int (*pubkey)(unsigned char *, const unsigned char *);
- int (*keygen)(unsigned char *, unsigned char *);
-
- int (*open)(const unsigned char *, const unsigned char *, size_t, const
- unsigned char *);
- int (*sign)(unsigned char *, const unsigned char *, size_t,
- const unsigned char *, const unsigned char *);
- int (*open_batch)(const unsigned char **, size_t *, const unsigned char **,
- const unsigned char **, size_t, int *);
-
- int (*blind_secret_key)(unsigned char *, const unsigned char *,
- const unsigned char *);
- int (*blind_public_key)(unsigned char *, const unsigned char *,
- const unsigned char *);
-
- int (*pubkey_from_curve25519_pubkey)(unsigned char *, const unsigned char *,
- int);
-
- int (*ed25519_scalarmult_with_group_order)(unsigned char *,
- const unsigned char *);
-} ed25519_impl_t;
-
-/** The Ref10 Ed25519 implementation. This one is pure C and lightly
- * optimized. */
-static const ed25519_impl_t impl_ref10 = {
- NULL,
-
- ed25519_ref10_seckey,
- ed25519_ref10_seckey_expand,
- ed25519_ref10_pubkey,
- ed25519_ref10_keygen,
-
- ed25519_ref10_open,
- ed25519_ref10_sign,
- NULL,
-
- ed25519_ref10_blind_secret_key,
- ed25519_ref10_blind_public_key,
-
- ed25519_ref10_pubkey_from_curve25519_pubkey,
- ed25519_ref10_scalarmult_with_group_order,
-};
-
-/** The Ref10 Ed25519 implementation. This one is heavily optimized, but still
- * mostly C. The C still tends to be heavily platform-specific. */
-static const ed25519_impl_t impl_donna = {
- ed25519_donna_selftest,
-
- ed25519_donna_seckey,
- ed25519_donna_seckey_expand,
- ed25519_donna_pubkey,
- ed25519_donna_keygen,
-
- ed25519_donna_open,
- ed25519_donna_sign,
- ed25519_sign_open_batch_donna,
-
- ed25519_donna_blind_secret_key,
- ed25519_donna_blind_public_key,
-
- ed25519_donna_pubkey_from_curve25519_pubkey,
- ed25519_donna_scalarmult_with_group_order,
-};
-
-/** Which Ed25519 implementation are we using? NULL if we haven't decided
- * yet. */
-static const ed25519_impl_t *ed25519_impl = NULL;
-
-/** Helper: Return our chosen Ed25519 implementation.
- *
- * This should only be called after we've picked an implementation, but
- * it _does_ recover if you forget this.
- **/
-static inline const ed25519_impl_t *
-get_ed_impl(void)
-{
- if (BUG(ed25519_impl == NULL)) {
- pick_ed25519_impl(); // LCOV_EXCL_LINE - We always call ed25519_init().
- }
- return ed25519_impl;
-}
-
-#ifdef TOR_UNIT_TESTS
-/** For testing: used to remember our actual choice of Ed25519
- * implementation */
-static const ed25519_impl_t *saved_ed25519_impl = NULL;
-/** For testing: Use the Ed25519 implementation called <b>name</b> until
- * crypto_ed25519_testing_restore_impl is called. Recognized names are
- * "donna" and "ref10". */
-void
-crypto_ed25519_testing_force_impl(const char *name)
-{
- tor_assert(saved_ed25519_impl == NULL);
- saved_ed25519_impl = ed25519_impl;
- if (! strcmp(name, "donna")) {
- ed25519_impl = &impl_donna;
- } else {
- tor_assert(!strcmp(name, "ref10"));
- ed25519_impl = &impl_ref10;
- }
-}
-/** For testing: go back to whatever Ed25519 implementation we had picked
- * before crypto_ed25519_testing_force_impl was called.
- */
-void
-crypto_ed25519_testing_restore_impl(void)
-{
- ed25519_impl = saved_ed25519_impl;
- saved_ed25519_impl = NULL;
-}
-#endif /* defined(TOR_UNIT_TESTS) */
-
-/**
- * Initialize a new ed25519 secret key in <b>seckey_out</b>. If
- * <b>extra_strong</b>, take the RNG inputs directly from the operating
- * system. Return 0 on success, -1 on failure.
- */
-int
-ed25519_secret_key_generate(ed25519_secret_key_t *seckey_out,
- int extra_strong)
-{
- int r;
- uint8_t seed[32];
- if (extra_strong)
- crypto_strongest_rand(seed, sizeof(seed));
- else
- crypto_rand((char*)seed, sizeof(seed));
-
- r = get_ed_impl()->seckey_expand(seckey_out->seckey, seed);
- memwipe(seed, 0, sizeof(seed));
-
- return r < 0 ? -1 : 0;
-}
-
-/**
- * Given a 32-byte random seed in <b>seed</b>, expand it into an ed25519
- * secret key in <b>seckey_out</b>. Return 0 on success, -1 on failure.
- */
-int
-ed25519_secret_key_from_seed(ed25519_secret_key_t *seckey_out,
- const uint8_t *seed)
-{
- if (get_ed_impl()->seckey_expand(seckey_out->seckey, seed) < 0)
- return -1;
- return 0;
-}
-
-/**
- * Given a secret key in <b>seckey</b>, expand it into an
- * ed25519 public key. Return 0 on success, -1 on failure.
- */
-int
-ed25519_public_key_generate(ed25519_public_key_t *pubkey_out,
- const ed25519_secret_key_t *seckey)
-{
- if (get_ed_impl()->pubkey(pubkey_out->pubkey, seckey->seckey) < 0)
- return -1;
- return 0;
-}
-
-/** Generate a new ed25519 keypair in <b>keypair_out</b>. If
- * <b>extra_strong</b> is set, try to mix some system entropy into the key
- * generation process. Return 0 on success, -1 on failure. */
-int
-ed25519_keypair_generate(ed25519_keypair_t *keypair_out, int extra_strong)
-{
- if (ed25519_secret_key_generate(&keypair_out->seckey, extra_strong) < 0)
- return -1;
- if (ed25519_public_key_generate(&keypair_out->pubkey,
- &keypair_out->seckey)<0)
- return -1;
- return 0;
-}
-
-/** Return true iff 'pubkey' is set to zero (eg to indicate that it is not
- * set). */
-int
-ed25519_public_key_is_zero(const ed25519_public_key_t *pubkey)
-{
- return tor_mem_is_zero((char*)pubkey->pubkey, ED25519_PUBKEY_LEN);
-}
-
-/* Return a heap-allocated array that contains <b>msg</b> prefixed by the
- * string <b>prefix_str</b>. Set <b>final_msg_len_out</b> to the size of the
- * final array. If an error occurred, return NULL. It's the responsibility of
- * the caller to free the returned array. */
-static uint8_t *
-get_prefixed_msg(const uint8_t *msg, size_t msg_len,
- const char *prefix_str,
- size_t *final_msg_len_out)
-{
- size_t prefixed_msg_len, prefix_len;
- uint8_t *prefixed_msg;
-
- tor_assert(prefix_str);
- tor_assert(final_msg_len_out);
-
- prefix_len = strlen(prefix_str);
-
- /* msg_len + strlen(prefix_str) must not overflow. */
- if (msg_len > SIZE_T_CEILING - prefix_len) {
- return NULL;
- }
-
- prefixed_msg_len = msg_len + prefix_len;
- prefixed_msg = tor_malloc_zero(prefixed_msg_len);
-
- memcpy(prefixed_msg, prefix_str, prefix_len);
- memcpy(prefixed_msg + prefix_len, msg, msg_len);
-
- *final_msg_len_out = prefixed_msg_len;
- return prefixed_msg;
-}
-
-/**
- * Set <b>signature_out</b> to a signature of the <b>len</b>-byte message
- * <b>msg</b>, using the secret and public key in <b>keypair</b>.
- *
- * Return 0 if we successfully signed the message, otherwise return -1.
- */
-int
-ed25519_sign(ed25519_signature_t *signature_out,
- const uint8_t *msg, size_t len,
- const ed25519_keypair_t *keypair)
-{
- if (get_ed_impl()->sign(signature_out->sig, msg, len,
- keypair->seckey.seckey,
- keypair->pubkey.pubkey) < 0) {
- return -1;
- }
-
- return 0;
-}
-
-/**
- * Like ed25519_sign(), but also prefix <b>msg</b> with <b>prefix_str</b>
- * before signing. <b>prefix_str</b> must be a NUL-terminated string.
- */
-MOCK_IMPL(int,
-ed25519_sign_prefixed,(ed25519_signature_t *signature_out,
- const uint8_t *msg, size_t msg_len,
- const char *prefix_str,
- const ed25519_keypair_t *keypair))
-{
- int retval;
- size_t prefixed_msg_len;
- uint8_t *prefixed_msg;
-
- tor_assert(prefix_str);
-
- prefixed_msg = get_prefixed_msg(msg, msg_len, prefix_str,
- &prefixed_msg_len);
- if (BUG(!prefixed_msg)) {
- /* LCOV_EXCL_START -- only possible when the message and prefix are
- * ridiculously huge */
- log_warn(LD_GENERAL, "Failed to get prefixed msg.");
- return -1;
- /* LCOV_EXCL_STOP */
- }
-
- retval = ed25519_sign(signature_out,
- prefixed_msg, prefixed_msg_len,
- keypair);
- tor_free(prefixed_msg);
-
- return retval;
-}
-
-/**
- * Check whether if <b>signature</b> is a valid signature for the
- * <b>len</b>-byte message in <b>msg</b> made with the key <b>pubkey</b>.
- *
- * Return 0 if the signature is valid; -1 if it isn't.
- */
-MOCK_IMPL(int,
-ed25519_checksig,(const ed25519_signature_t *signature,
- const uint8_t *msg, size_t len,
- const ed25519_public_key_t *pubkey))
-{
- return
- get_ed_impl()->open(signature->sig, msg, len, pubkey->pubkey) < 0 ? -1 : 0;
-}
-
-/**
- * Like ed2519_checksig(), but also prefix <b>msg</b> with <b>prefix_str</b>
- * before verifying signature. <b>prefix_str</b> must be a NUL-terminated
- * string.
- */
-int
-ed25519_checksig_prefixed(const ed25519_signature_t *signature,
- const uint8_t *msg, size_t msg_len,
- const char *prefix_str,
- const ed25519_public_key_t *pubkey)
-{
- int retval;
- size_t prefixed_msg_len;
- uint8_t *prefixed_msg;
-
- prefixed_msg = get_prefixed_msg(msg, msg_len, prefix_str,
- &prefixed_msg_len);
- if (BUG(!prefixed_msg)) {
- /* LCOV_EXCL_START -- only possible when the message and prefix are
- * ridiculously huge */
- log_warn(LD_GENERAL, "Failed to get prefixed msg.");
- return -1;
- /* LCOV_EXCL_STOP */
- }
-
- retval = ed25519_checksig(signature,
- prefixed_msg, prefixed_msg_len,
- pubkey);
- tor_free(prefixed_msg);
-
- return retval;
-}
-
-/** Validate every signature among those in <b>checkable</b>, which contains
- * exactly <b>n_checkable</b> elements. If <b>okay_out</b> is non-NULL, set
- * the i'th element of <b>okay_out</b> to 1 if the i'th element of
- * <b>checkable</b> is valid, and to 0 otherwise. Return 0 if every signature
- * was valid. Otherwise return -N, where N is the number of invalid
- * signatures.
- */
-MOCK_IMPL(int,
-ed25519_checksig_batch,(int *okay_out,
- const ed25519_checkable_t *checkable,
- int n_checkable))
-{
- int i, res;
- const ed25519_impl_t *impl = get_ed_impl();
-
- if (impl->open_batch == NULL) {
- /* No batch verification implementation available, fake it by checking the
- * each signature individually.
- */
- res = 0;
- for (i = 0; i < n_checkable; ++i) {
- const ed25519_checkable_t *ch = &checkable[i];
- int r = ed25519_checksig(&ch->signature, ch->msg, ch->len, ch->pubkey);
- if (r < 0)
- --res;
- if (okay_out)
- okay_out[i] = (r == 0);
- }
- } else {
- /* ed25519-donna style batch verification available.
- *
- * Theoretically, this should only be called if n_checkable >= 3, since
- * that's the threshold where the batch verification actually kicks in,
- * but the only difference is a few mallocs/frees.
- */
- const uint8_t **ms;
- size_t *lens;
- const uint8_t **pks;
- const uint8_t **sigs;
- int *oks;
- int all_ok;
-
- ms = tor_calloc(n_checkable, sizeof(uint8_t*));
- lens = tor_calloc(n_checkable, sizeof(size_t));
- pks = tor_calloc(n_checkable, sizeof(uint8_t*));
- sigs = tor_calloc(n_checkable, sizeof(uint8_t*));
- oks = okay_out ? okay_out : tor_calloc(n_checkable, sizeof(int));
-
- for (i = 0; i < n_checkable; ++i) {
- ms[i] = checkable[i].msg;
- lens[i] = checkable[i].len;
- pks[i] = checkable[i].pubkey->pubkey;
- sigs[i] = checkable[i].signature.sig;
- oks[i] = 0;
- }
-
- res = 0;
- all_ok = impl->open_batch(ms, lens, pks, sigs, n_checkable, oks);
- for (i = 0; i < n_checkable; ++i) {
- if (!oks[i])
- --res;
- }
- /* XXX: For now sanity check oks with the return value. Once we have
- * more confidence in the code, if `all_ok == 0` we can skip iterating
- * over oks since all the signatures were found to be valid.
- */
- tor_assert(((res == 0) && !all_ok) || ((res < 0) && all_ok));
-
- tor_free(ms);
- tor_free(lens);
- tor_free(pks);
- tor_free(sigs);
- if (! okay_out)
- tor_free(oks);
- }
-
- return res;
-}
-
-/**
- * Given a curve25519 keypair in <b>inp</b>, generate a corresponding
- * ed25519 keypair in <b>out</b>, and set <b>signbit_out</b> to the
- * sign bit of the X coordinate of the ed25519 key.
- *
- * NOTE THAT IT IS PROBABLY NOT SAFE TO USE THE GENERATED KEY FOR ANYTHING
- * OUTSIDE OF WHAT'S PRESENTED IN PROPOSAL 228. In particular, it's probably
- * not a great idea to use it to sign attacker-supplied anything.
- */
-int
-ed25519_keypair_from_curve25519_keypair(ed25519_keypair_t *out,
- int *signbit_out,
- const curve25519_keypair_t *inp)
-{
- const char string[] = "Derive high part of ed25519 key from curve25519 key";
- ed25519_public_key_t pubkey_check;
- crypto_digest_t *ctx;
- uint8_t sha512_output[DIGEST512_LEN];
-
- memcpy(out->seckey.seckey, inp->seckey.secret_key, 32);
-
- ctx = crypto_digest512_new(DIGEST_SHA512);
- crypto_digest_add_bytes(ctx, (const char*)out->seckey.seckey, 32);
- crypto_digest_add_bytes(ctx, (const char*)string, sizeof(string));
- crypto_digest_get_digest(ctx, (char *)sha512_output, sizeof(sha512_output));
- crypto_digest_free(ctx);
- memcpy(out->seckey.seckey + 32, sha512_output, 32);
-
- ed25519_public_key_generate(&out->pubkey, &out->seckey);
-
- *signbit_out = out->pubkey.pubkey[31] >> 7;
-
- ed25519_public_key_from_curve25519_public_key(&pubkey_check, &inp->pubkey,
- *signbit_out);
-
- tor_assert(fast_memeq(pubkey_check.pubkey, out->pubkey.pubkey, 32));
-
- memwipe(&pubkey_check, 0, sizeof(pubkey_check));
- memwipe(sha512_output, 0, sizeof(sha512_output));
-
- return 0;
-}
-
-/**
- * Given a curve25519 public key and sign bit of X coordinate of the ed25519
- * public key, generate the corresponding ed25519 public key.
- */
-int
-ed25519_public_key_from_curve25519_public_key(ed25519_public_key_t *pubkey,
- const curve25519_public_key_t *pubkey_in,
- int signbit)
-{
- return get_ed_impl()->pubkey_from_curve25519_pubkey(pubkey->pubkey,
- pubkey_in->public_key,
- signbit);
-}
-
-/**
- * Given an ed25519 keypair in <b>inp</b>, generate a corresponding
- * ed25519 keypair in <b>out</b>, blinded by the corresponding 32-byte input
- * in 'param'.
- *
- * Tor uses key blinding for the "next-generation" hidden services design:
- * service descriptors are encrypted with a key derived from the service's
- * long-term public key, and then signed with (and stored at a position
- * indexed by) a short-term key derived by blinding the long-term keys.
- *
- * Return 0 if blinding was successful, else return -1. */
-int
-ed25519_keypair_blind(ed25519_keypair_t *out,
- const ed25519_keypair_t *inp,
- const uint8_t *param)
-{
- ed25519_public_key_t pubkey_check;
-
- get_ed_impl()->blind_secret_key(out->seckey.seckey,
- inp->seckey.seckey, param);
-
- if (ed25519_public_blind(&pubkey_check, &inp->pubkey, param) < 0) {
- return -1;
- }
- ed25519_public_key_generate(&out->pubkey, &out->seckey);
-
- tor_assert(fast_memeq(pubkey_check.pubkey, out->pubkey.pubkey, 32));
-
- memwipe(&pubkey_check, 0, sizeof(pubkey_check));
-
- return 0;
-}
-
-/**
- * Given an ed25519 public key in <b>inp</b>, generate a corresponding blinded
- * public key in <b>out</b>, blinded with the 32-byte parameter in
- * <b>param</b>. Return 0 on success, -1 on railure.
- */
-int
-ed25519_public_blind(ed25519_public_key_t *out,
- const ed25519_public_key_t *inp,
- const uint8_t *param)
-{
- return get_ed_impl()->blind_public_key(out->pubkey, inp->pubkey, param);
-}
-
-/**
- * Store seckey unencrypted to <b>filename</b>, marking it with <b>tag</b>.
- * Return 0 on success, -1 on failure.
- */
-int
-ed25519_seckey_write_to_file(const ed25519_secret_key_t *seckey,
- const char *filename,
- const char *tag)
-{
- return crypto_write_tagged_contents_to_file(filename,
- "ed25519v1-secret",
- tag,
- seckey->seckey,
- sizeof(seckey->seckey));
-}
-
-/**
- * Read seckey unencrypted from <b>filename</b>, storing it into
- * <b>seckey_out</b>. Set *<b>tag_out</b> to the tag it was marked with.
- * Return 0 on success, -1 on failure.
- */
-int
-ed25519_seckey_read_from_file(ed25519_secret_key_t *seckey_out,
- char **tag_out,
- const char *filename)
-{
- ssize_t len;
-
- len = crypto_read_tagged_contents_from_file(filename, "ed25519v1-secret",
- tag_out, seckey_out->seckey,
- sizeof(seckey_out->seckey));
- if (len == sizeof(seckey_out->seckey)) {
- return 0;
- } else if (len >= 0) {
- errno = EINVAL;
- }
-
- tor_free(*tag_out);
- return -1;
-}
-
-/**
- * Store pubkey unencrypted to <b>filename</b>, marking it with <b>tag</b>.
- * Return 0 on success, -1 on failure.
- */
-int
-ed25519_pubkey_write_to_file(const ed25519_public_key_t *pubkey,
- const char *filename,
- const char *tag)
-{
- return crypto_write_tagged_contents_to_file(filename,
- "ed25519v1-public",
- tag,
- pubkey->pubkey,
- sizeof(pubkey->pubkey));
-}
-
-/**
- * Store pubkey unencrypted to <b>filename</b>, marking it with <b>tag</b>.
- * Return 0 on success, -1 on failure.
- */
-int
-ed25519_pubkey_read_from_file(ed25519_public_key_t *pubkey_out,
- char **tag_out,
- const char *filename)
-{
- ssize_t len;
-
- len = crypto_read_tagged_contents_from_file(filename, "ed25519v1-public",
- tag_out, pubkey_out->pubkey,
- sizeof(pubkey_out->pubkey));
- if (len == sizeof(pubkey_out->pubkey)) {
- return 0;
- } else if (len >= 0) {
- errno = EINVAL;
- }
-
- tor_free(*tag_out);
- return -1;
-}
-
-/** Release all storage held for <b>kp</b>. */
-void
-ed25519_keypair_free_(ed25519_keypair_t *kp)
-{
- if (! kp)
- return;
-
- memwipe(kp, 0, sizeof(*kp));
- tor_free(kp);
-}
-
-/** Return true iff <b>key1</b> and <b>key2</b> are the same public key. */
-int
-ed25519_pubkey_eq(const ed25519_public_key_t *key1,
- const ed25519_public_key_t *key2)
-{
- tor_assert(key1);
- tor_assert(key2);
- return tor_memeq(key1->pubkey, key2->pubkey, ED25519_PUBKEY_LEN);
-}
-
-/**
- * Set <b>dest</b> to contain the same key as <b>src</b>.
- */
-void
-ed25519_pubkey_copy(ed25519_public_key_t *dest,
- const ed25519_public_key_t *src)
-{
- tor_assert(dest);
- tor_assert(src);
- memcpy(dest, src, sizeof(ed25519_public_key_t));
-}
-
-/** Check whether the given Ed25519 implementation seems to be working.
- * If so, return 0; otherwise return -1. */
-MOCK_IMPL(STATIC int,
-ed25519_impl_spot_check,(void))
-{
- static const uint8_t alicesk[32] = {
- 0xc5,0xaa,0x8d,0xf4,0x3f,0x9f,0x83,0x7b,
- 0xed,0xb7,0x44,0x2f,0x31,0xdc,0xb7,0xb1,
- 0x66,0xd3,0x85,0x35,0x07,0x6f,0x09,0x4b,
- 0x85,0xce,0x3a,0x2e,0x0b,0x44,0x58,0xf7
- };
- static const uint8_t alicepk[32] = {
- 0xfc,0x51,0xcd,0x8e,0x62,0x18,0xa1,0xa3,
- 0x8d,0xa4,0x7e,0xd0,0x02,0x30,0xf0,0x58,
- 0x08,0x16,0xed,0x13,0xba,0x33,0x03,0xac,
- 0x5d,0xeb,0x91,0x15,0x48,0x90,0x80,0x25
- };
- static const uint8_t alicemsg[2] = { 0xaf, 0x82 };
- static const uint8_t alicesig[64] = {
- 0x62,0x91,0xd6,0x57,0xde,0xec,0x24,0x02,
- 0x48,0x27,0xe6,0x9c,0x3a,0xbe,0x01,0xa3,
- 0x0c,0xe5,0x48,0xa2,0x84,0x74,0x3a,0x44,
- 0x5e,0x36,0x80,0xd7,0xdb,0x5a,0xc3,0xac,
- 0x18,0xff,0x9b,0x53,0x8d,0x16,0xf2,0x90,
- 0xae,0x67,0xf7,0x60,0x98,0x4d,0xc6,0x59,
- 0x4a,0x7c,0x15,0xe9,0x71,0x6e,0xd2,0x8d,
- 0xc0,0x27,0xbe,0xce,0xea,0x1e,0xc4,0x0a
- };
- const ed25519_impl_t *impl = get_ed_impl();
- uint8_t sk[ED25519_SECKEY_LEN];
- uint8_t pk[ED25519_PUBKEY_LEN];
- uint8_t sig[ED25519_SIG_LEN];
- int r = 0;
-
- /* Some implementations (eg: The modified Ed25519-donna) have handy self-test
- * code that sanity-checks the internals. If present, use that to screen out
- * catastrophic errors like massive compiler failure.
- */
- if (impl->selftest && impl->selftest() != 0)
- goto fail;
-
- /* Validate results versus known answer tests. People really should be
- * running "make test" instead of relying on this, but it's better than
- * nothing.
- *
- * Test vectors taken from "EdDSA & Ed25519 - 6. Test Vectors for Ed25519
- * (TEST3)" (draft-josefsson-eddsa-ed25519-03).
- */
-
- /* Key expansion, public key derivation. */
- if (impl->seckey_expand(sk, alicesk) < 0)
- goto fail;
- if (impl->pubkey(pk, sk) < 0)
- goto fail;
- if (fast_memneq(pk, alicepk, ED25519_PUBKEY_LEN))
- goto fail;
-
- /* Signing, verification. */
- if (impl->sign(sig, alicemsg, sizeof(alicemsg), sk, pk) < 0)
- return -1;
- if (fast_memneq(sig, alicesig, ED25519_SIG_LEN))
- return -1;
- if (impl->open(sig, alicemsg, sizeof(alicemsg), pk) < 0)
- return -1;
-
- /* XXX/yawning: Someone that's more paranoid than I am, can write "Assume
- * ref0 is canonical, and fuzz impl against it" if they want, but I doubt
- * that will catch anything that the known answer tests won't.
- */
- goto end;
-
- // LCOV_EXCL_START -- We can only reach this if our ed25519 implementation is
- // broken.
- fail:
- r = -1;
- // LCOV_EXCL_STOP
- end:
- return r;
-}
-
-/** Force the Ed25519 implementation to a given one, without sanity checking
- * the output. Used for testing.
- */
-void
-ed25519_set_impl_params(int use_donna)
-{
- if (use_donna)
- ed25519_impl = &impl_donna;
- else
- ed25519_impl = &impl_ref10;
-}
-
-/** Choose whether to use the Ed25519-donna implementation. */
-static void
-pick_ed25519_impl(void)
-{
- ed25519_impl = &impl_donna;
-
- if (ed25519_impl_spot_check() == 0)
- return;
-
- /* LCOV_EXCL_START
- * unreachable unless ed25519_donna is broken */
- log_warn(LD_CRYPTO, "The Ed25519-donna implementation seems broken; using "
- "the ref10 implementation.");
- ed25519_impl = &impl_ref10;
- /* LCOV_EXCL_STOP */
-}
-
-/* Initialize the Ed25519 implementation. This is necessary if you're
- * going to use them in a multithreaded setting, and not otherwise. */
-void
-ed25519_init(void)
-{
- pick_ed25519_impl();
-}
-
-/* Return true if <b>point</b> is the identity element of the ed25519 group. */
-static int
-ed25519_point_is_identity_element(const uint8_t *point)
-{
- /* The identity element in ed25159 is the point with coordinates (0,1). */
- static const uint8_t ed25519_identity[32] = {
- 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
- tor_assert(sizeof(ed25519_identity) == ED25519_PUBKEY_LEN);
- return tor_memeq(point, ed25519_identity, sizeof(ed25519_identity));
-}
-
-/** Validate <b>pubkey</b> to ensure that it has no torsion component.
- * Return 0 if <b>pubkey</b> is valid, else return -1. */
-int
-ed25519_validate_pubkey(const ed25519_public_key_t *pubkey)
-{
- uint8_t result[32] = {9};
-
- /* First check that we were not given the identity element */
- if (ed25519_point_is_identity_element(pubkey->pubkey)) {
- log_warn(LD_CRYPTO, "ed25519 pubkey is the identity");
- return -1;
- }
-
- /* For any point on the curve, doing l*point should give the identity element
- * (where l is the group order). Do the computation and check that the
- * identity element is returned. */
- if (get_ed_impl()->ed25519_scalarmult_with_group_order(result,
- pubkey->pubkey) < 0) {
- log_warn(LD_CRYPTO, "ed25519 group order scalarmult failed");
- return -1;
- }
-
- if (!ed25519_point_is_identity_element(result)) {
- log_warn(LD_CRYPTO, "ed25519 validation failed");
- return -1;
- }
-
- return 0;
-}
-
diff --git a/src/common/crypto_ed25519.h b/src/common/crypto_ed25519.h
deleted file mode 100644
index 74269ccffd..0000000000
--- a/src/common/crypto_ed25519.h
+++ /dev/null
@@ -1,145 +0,0 @@
-/* Copyright (c) 2012-2017, The Tor Project, Inc. */
-/* See LICENSE for licensing information */
-
-#ifndef TOR_CRYPTO_ED25519_H
-#define TOR_CRYPTO_ED25519_H
-
-#include "testsupport.h"
-#include "torint.h"
-#include "crypto_curve25519.h"
-#include "util.h"
-
-#define ED25519_PUBKEY_LEN 32
-#define ED25519_SECKEY_LEN 64
-#define ED25519_SECKEY_SEED_LEN 32
-#define ED25519_SIG_LEN 64
-
-/** An Ed25519 signature. */
-typedef struct {
- uint8_t sig[ED25519_SIG_LEN];
-} ed25519_signature_t;
-
-/** An Ed25519 public key */
-typedef struct {
- uint8_t pubkey[ED25519_PUBKEY_LEN];
-} ed25519_public_key_t;
-
-/** An Ed25519 secret key */
-typedef struct {
- /** Note that we store secret keys in an expanded format that doesn't match
- * the format from standard ed25519. Ed25519 stores a 32-byte value k and
- * expands it into a 64-byte H(k), using the first 32 bytes for a multiplier
- * of the base point, and second 32 bytes as an input to a hash function
- * for deriving r. But because we implement key blinding, we need to store
- * keys in the 64-byte expanded form. */
- uint8_t seckey[ED25519_SECKEY_LEN];
-} ed25519_secret_key_t;
-
-/** An Ed25519 keypair. */
-typedef struct {
- ed25519_public_key_t pubkey;
- ed25519_secret_key_t seckey;
-} ed25519_keypair_t;
-
-int ed25519_secret_key_generate(ed25519_secret_key_t *seckey_out,
- int extra_strong);
-int ed25519_secret_key_from_seed(ed25519_secret_key_t *seckey_out,
- const uint8_t *seed);
-
-int ed25519_public_key_generate(ed25519_public_key_t *pubkey_out,
- const ed25519_secret_key_t *seckey);
-int ed25519_keypair_generate(ed25519_keypair_t *keypair_out, int extra_strong);
-int ed25519_sign(ed25519_signature_t *signature_out,
- const uint8_t *msg, size_t len,
- const ed25519_keypair_t *key);
-MOCK_DECL(int,ed25519_checksig,(const ed25519_signature_t *signature,
- const uint8_t *msg, size_t len,
- const ed25519_public_key_t *pubkey));
-
-MOCK_DECL(int,
-ed25519_sign_prefixed,(ed25519_signature_t *signature_out,
- const uint8_t *msg, size_t len,
- const char *prefix_str,
- const ed25519_keypair_t *keypair));
-
-int
-ed25519_checksig_prefixed(const ed25519_signature_t *signature,
- const uint8_t *msg, size_t len,
- const char *prefix_str,
- const ed25519_public_key_t *pubkey);
-
-int ed25519_public_key_is_zero(const ed25519_public_key_t *pubkey);
-
-/**
- * A collection of information necessary to check an Ed25519 signature. Used
- * for batch verification.
- */
-typedef struct {
- /** The public key that supposedly generated the signature. */
- const ed25519_public_key_t *pubkey;
- /** The signature to check. */
- ed25519_signature_t signature;
- /** The message that the signature is supposed to have been applied to. */
- const uint8_t *msg;
- /** The length of the message. */
- size_t len;
-} ed25519_checkable_t;
-
-MOCK_DECL(int, ed25519_checksig_batch,(int *okay_out,
- const ed25519_checkable_t *checkable,
- int n_checkable));
-
-int ed25519_keypair_from_curve25519_keypair(ed25519_keypair_t *out,
- int *signbit_out,
- const curve25519_keypair_t *inp);
-
-int ed25519_public_key_from_curve25519_public_key(ed25519_public_key_t *pubkey,
- const curve25519_public_key_t *pubkey_in,
- int signbit);
-int ed25519_keypair_blind(ed25519_keypair_t *out,
- const ed25519_keypair_t *inp,
- const uint8_t *param);
-int ed25519_public_blind(ed25519_public_key_t *out,
- const ed25519_public_key_t *inp,
- const uint8_t *param);
-
-/* XXXX read encrypted, write encrypted. */
-
-int ed25519_seckey_write_to_file(const ed25519_secret_key_t *seckey,
- const char *filename,
- const char *tag);
-int ed25519_seckey_read_from_file(ed25519_secret_key_t *seckey_out,
- char **tag_out,
- const char *filename);
-int ed25519_pubkey_write_to_file(const ed25519_public_key_t *pubkey,
- const char *filename,
- const char *tag);
-int ed25519_pubkey_read_from_file(ed25519_public_key_t *pubkey_out,
- char **tag_out,
- const char *filename);
-
-void ed25519_keypair_free_(ed25519_keypair_t *kp);
-#define ed25519_keypair_free(kp) \
- FREE_AND_NULL(ed25519_keypair_t, ed25519_keypair_free_, (kp))
-
-int ed25519_pubkey_eq(const ed25519_public_key_t *key1,
- const ed25519_public_key_t *key2);
-void ed25519_pubkey_copy(ed25519_public_key_t *dest,
- const ed25519_public_key_t *src);
-
-void ed25519_set_impl_params(int use_donna);
-void ed25519_init(void);
-
-int ed25519_validate_pubkey(const ed25519_public_key_t *pubkey);
-
-#ifdef TOR_UNIT_TESTS
-void crypto_ed25519_testing_force_impl(const char *name);
-void crypto_ed25519_testing_restore_impl(void);
-#endif
-
-#ifdef CRYPTO_ED25519_PRIVATE
-MOCK_DECL(STATIC int, ed25519_impl_spot_check, (void));
-#endif
-
-#endif /* !defined(TOR_CRYPTO_ED25519_H) */
-
diff --git a/src/common/crypto_format.c b/src/common/crypto_format.c
deleted file mode 100644
index 460e85bac1..0000000000
--- a/src/common/crypto_format.c
+++ /dev/null
@@ -1,299 +0,0 @@
-/* Copyright (c) 2001, Matej Pfajfar.
- * Copyright (c) 2001-2004, Roger Dingledine.
- * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2017, The Tor Project, Inc. */
-/* See LICENSE for licensing information */
-
-/**
- * \file crypto_format.c
- *
- * \brief Formatting and parsing code for crypto-related data structures.
- */
-
-#include "orconfig.h"
-#ifdef HAVE_SYS_STAT_H
-#include <sys/stat.h>
-#endif
-#include "container.h"
-#include "crypto_curve25519.h"
-#include "crypto_digest.h"
-#include "crypto_ed25519.h"
-#include "crypto_format.h"
-#include "crypto_util.h"
-#include "util.h"
-#include "util_format.h"
-#include "torlog.h"
-
-/** Write the <b>datalen</b> bytes from <b>data</b> to the file named
- * <b>fname</b> in the tagged-data format. This format contains a
- * 32-byte header, followed by the data itself. The header is the
- * NUL-padded string "== <b>typestring</b>: <b>tag</b> ==". The length
- * of <b>typestring</b> and <b>tag</b> must therefore be no more than
- * 24.
- **/
-int
-crypto_write_tagged_contents_to_file(const char *fname,
- const char *typestring,
- const char *tag,
- const uint8_t *data,
- size_t datalen)
-{
- char header[32];
- smartlist_t *chunks = smartlist_new();
- sized_chunk_t ch0, ch1;
- int r = -1;
-
- memset(header, 0, sizeof(header));
- if (tor_snprintf(header, sizeof(header),
- "== %s: %s ==", typestring, tag) < 0)
- goto end;
- ch0.bytes = header;
- ch0.len = 32;
- ch1.bytes = (const char*) data;
- ch1.len = datalen;
- smartlist_add(chunks, &ch0);
- smartlist_add(chunks, &ch1);
-
- r = write_chunks_to_file(fname, chunks, 1, 0);
-
- end:
- smartlist_free(chunks);
- return r;
-}
-
-/** Read a tagged-data file from <b>fname</b> into the
- * <b>data_out_len</b>-byte buffer in <b>data_out</b>. Check that the
- * typestring matches <b>typestring</b>; store the tag into a newly allocated
- * string in <b>tag_out</b>. Return -1 on failure, and the number of bytes of
- * data on success. Preserves the errno from reading the file. */
-ssize_t
-crypto_read_tagged_contents_from_file(const char *fname,
- const char *typestring,
- char **tag_out,
- uint8_t *data_out,
- ssize_t data_out_len)
-{
- char prefix[33];
- char *content = NULL;
- struct stat st;
- ssize_t r = -1;
- size_t st_size = 0;
- int saved_errno = 0;
-
- *tag_out = NULL;
- st.st_size = 0;
- content = read_file_to_str(fname, RFTS_BIN|RFTS_IGNORE_MISSING, &st);
- if (! content) {
- saved_errno = errno;
- goto end;
- }
- if (st.st_size < 32 || st.st_size > 32 + data_out_len) {
- saved_errno = EINVAL;
- goto end;
- }
- st_size = (size_t)st.st_size;
-
- memcpy(prefix, content, 32);
- prefix[32] = 0;
- /* Check type, extract tag. */
- if (strcmpstart(prefix, "== ") || strcmpend(prefix, " ==") ||
- ! tor_mem_is_zero(prefix+strlen(prefix), 32-strlen(prefix))) {
- saved_errno = EINVAL;
- goto end;
- }
-
- if (strcmpstart(prefix+3, typestring) ||
- 3+strlen(typestring) >= 32 ||
- strcmpstart(prefix+3+strlen(typestring), ": ")) {
- saved_errno = EINVAL;
- goto end;
- }
-
- *tag_out = tor_strndup(prefix+5+strlen(typestring),
- strlen(prefix)-8-strlen(typestring));
-
- memcpy(data_out, content+32, st_size-32);
- r = st_size - 32;
-
- end:
- if (content)
- memwipe(content, 0, st_size);
- tor_free(content);
- if (saved_errno)
- errno = saved_errno;
- return r;
-}
-
-/** Encode <b>pkey</b> as a base64-encoded string, without trailing "="
- * characters, in the buffer <b>output</b>, which must have at least
- * CURVE25519_BASE64_PADDED_LEN+1 bytes available. Return 0 on success, -1 on
- * failure. */
-int
-curve25519_public_to_base64(char *output,
- const curve25519_public_key_t *pkey)
-{
- char buf[128];
- base64_encode(buf, sizeof(buf),
- (const char*)pkey->public_key, CURVE25519_PUBKEY_LEN, 0);
- buf[CURVE25519_BASE64_PADDED_LEN] = '\0';
- memcpy(output, buf, CURVE25519_BASE64_PADDED_LEN+1);
- return 0;
-}
-
-/** Try to decode a base64-encoded curve25519 public key from <b>input</b>
- * into the object at <b>pkey</b>. Return 0 on success, -1 on failure.
- * Accepts keys with or without a trailing "=". */
-int
-curve25519_public_from_base64(curve25519_public_key_t *pkey,
- const char *input)
-{
- size_t len = strlen(input);
- if (len == CURVE25519_BASE64_PADDED_LEN - 1) {
- /* not padded */
- return digest256_from_base64((char*)pkey->public_key, input);
- } else if (len == CURVE25519_BASE64_PADDED_LEN) {
- char buf[128];
- if (base64_decode(buf, sizeof(buf), input, len) != CURVE25519_PUBKEY_LEN)
- return -1;
- memcpy(pkey->public_key, buf, CURVE25519_PUBKEY_LEN);
- return 0;
- } else {
- return -1;
- }
-}
-
-/** For logging convenience: Convert <b>pkey</b> to a statically allocated
- * base64 string and return it. Not threadsafe. Format not meant to be
- * computer-readable; it may change in the future. Subsequent calls invalidate
- * previous returns. */
-const char *
-ed25519_fmt(const ed25519_public_key_t *pkey)
-{
- static char formatted[ED25519_BASE64_LEN+1];
- if (pkey) {
- if (ed25519_public_key_is_zero(pkey)) {
- strlcpy(formatted, "<unset>", sizeof(formatted));
- } else {
- int r = ed25519_public_to_base64(formatted, pkey);
- tor_assert(!r);
- }
- } else {
- strlcpy(formatted, "<null>", sizeof(formatted));
- }
- return formatted;
-}
-
-/** Try to decode the string <b>input</b> into an ed25519 public key. On
- * success, store the value in <b>pkey</b> and return 0. Otherwise return
- * -1. */
-int
-ed25519_public_from_base64(ed25519_public_key_t *pkey,
- const char *input)
-{
- return digest256_from_base64((char*)pkey->pubkey, input);
-}
-
-/** Encode the public key <b>pkey</b> into the buffer at <b>output</b>,
- * which must have space for ED25519_BASE64_LEN bytes of encoded key,
- * plus one byte for a terminating NUL. Return 0 on success, -1 on failure.
- */
-int
-ed25519_public_to_base64(char *output,
- const ed25519_public_key_t *pkey)
-{
- return digest256_to_base64(output, (const char *)pkey->pubkey);
-}
-
-/** Encode the signature <b>sig</b> into the buffer at <b>output</b>,
- * which must have space for ED25519_SIG_BASE64_LEN bytes of encoded signature,
- * plus one byte for a terminating NUL. Return 0 on success, -1 on failure.
- */
-int
-ed25519_signature_to_base64(char *output,
- const ed25519_signature_t *sig)
-{
- char buf[256];
- int n = base64_encode_nopad(buf, sizeof(buf), sig->sig, ED25519_SIG_LEN);
- tor_assert(n == ED25519_SIG_BASE64_LEN);
- memcpy(output, buf, ED25519_SIG_BASE64_LEN+1);
- return 0;
-}
-
-/** Try to decode the string <b>input</b> into an ed25519 signature. On
- * success, store the value in <b>sig</b> and return 0. Otherwise return
- * -1. */
-int
-ed25519_signature_from_base64(ed25519_signature_t *sig,
- const char *input)
-{
-
- if (strlen(input) != ED25519_SIG_BASE64_LEN)
- return -1;
- char buf[ED25519_SIG_BASE64_LEN+3];
- memcpy(buf, input, ED25519_SIG_BASE64_LEN);
- buf[ED25519_SIG_BASE64_LEN+0] = '=';
- buf[ED25519_SIG_BASE64_LEN+1] = '=';
- buf[ED25519_SIG_BASE64_LEN+2] = 0;
- char decoded[128];
- int n = base64_decode(decoded, sizeof(decoded), buf, strlen(buf));
- if (n < 0 || n != ED25519_SIG_LEN)
- return -1;
- memcpy(sig->sig, decoded, ED25519_SIG_LEN);
-
- return 0;
-}
-
-/** Base64 encode DIGEST_LINE bytes from <b>digest</b>, remove the trailing =
- * characters, and store the nul-terminated result in the first
- * BASE64_DIGEST_LEN+1 bytes of <b>d64</b>. */
-/* XXXX unify with crypto_format.c code */
-int
-digest_to_base64(char *d64, const char *digest)
-{
- char buf[256];
- base64_encode(buf, sizeof(buf), digest, DIGEST_LEN, 0);
- buf[BASE64_DIGEST_LEN] = '\0';
- memcpy(d64, buf, BASE64_DIGEST_LEN+1);
- return 0;
-}
-
-/** Given a base64 encoded, nul-terminated digest in <b>d64</b> (without
- * trailing newline or = characters), decode it and store the result in the
- * first DIGEST_LEN bytes at <b>digest</b>. */
-/* XXXX unify with crypto_format.c code */
-int
-digest_from_base64(char *digest, const char *d64)
-{
- if (base64_decode(digest, DIGEST_LEN, d64, strlen(d64)) == DIGEST_LEN)
- return 0;
- else
- return -1;
-}
-
-/** Base64 encode DIGEST256_LINE bytes from <b>digest</b>, remove the
- * trailing = characters, and store the nul-terminated result in the first
- * BASE64_DIGEST256_LEN+1 bytes of <b>d64</b>. */
- /* XXXX unify with crypto_format.c code */
-int
-digest256_to_base64(char *d64, const char *digest)
-{
- char buf[256];
- base64_encode(buf, sizeof(buf), digest, DIGEST256_LEN, 0);
- buf[BASE64_DIGEST256_LEN] = '\0';
- memcpy(d64, buf, BASE64_DIGEST256_LEN+1);
- return 0;
-}
-
-/** Given a base64 encoded, nul-terminated digest in <b>d64</b> (without
- * trailing newline or = characters), decode it and store the result in the
- * first DIGEST256_LEN bytes at <b>digest</b>. */
-/* XXXX unify with crypto_format.c code */
-int
-digest256_from_base64(char *digest, const char *d64)
-{
- if (base64_decode(digest, DIGEST256_LEN, d64, strlen(d64)) == DIGEST256_LEN)
- return 0;
- else
- return -1;
-}
-
diff --git a/src/common/crypto_format.h b/src/common/crypto_format.h
deleted file mode 100644
index bbd85dc720..0000000000
--- a/src/common/crypto_format.h
+++ /dev/null
@@ -1,47 +0,0 @@
-/* Copyright (c) 2001, Matej Pfajfar.
- * Copyright (c) 2001-2004, Roger Dingledine.
- * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2017, The Tor Project, Inc. */
-/* See LICENSE for licensing information */
-
-#ifndef TOR_CRYPTO_FORMAT_H
-#define TOR_CRYPTO_FORMAT_H
-
-#include "testsupport.h"
-#include "torint.h"
-#include "crypto_ed25519.h"
-
-int crypto_write_tagged_contents_to_file(const char *fname,
- const char *typestring,
- const char *tag,
- const uint8_t *data,
- size_t datalen);
-
-ssize_t crypto_read_tagged_contents_from_file(const char *fname,
- const char *typestring,
- char **tag_out,
- uint8_t *data_out,
- ssize_t data_out_len);
-
-#define ED25519_BASE64_LEN 43
-int ed25519_public_from_base64(ed25519_public_key_t *pkey,
- const char *input);
-int ed25519_public_to_base64(char *output,
- const ed25519_public_key_t *pkey);
-const char *ed25519_fmt(const ed25519_public_key_t *pkey);
-
-/* XXXX move these to crypto_format.h */
-#define ED25519_SIG_BASE64_LEN 86
-
-int ed25519_signature_from_base64(ed25519_signature_t *sig,
- const char *input);
-int ed25519_signature_to_base64(char *output,
- const ed25519_signature_t *sig);
-
-int digest_to_base64(char *d64, const char *digest);
-int digest_from_base64(char *digest, const char *d64);
-int digest256_to_base64(char *d64, const char *digest);
-int digest256_from_base64(char *digest, const char *d64);
-
-#endif /* !defined(TOR_CRYPTO_FORMAT_H) */
-
diff --git a/src/common/crypto_openssl_mgt.c b/src/common/crypto_openssl_mgt.c
deleted file mode 100644
index ea3519efa2..0000000000
--- a/src/common/crypto_openssl_mgt.c
+++ /dev/null
@@ -1,161 +0,0 @@
-/* Copyright (c) 2001, Matej Pfajfar.
- * Copyright (c) 2001-2004, Roger Dingledine.
- * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2017, The Tor Project, Inc. */
-/* See LICENSE for licensing information */
-
-/**
- * \file crypto_openssl.c
- *
- * \brief Block of functions related to operations from OpenSSL.
- **/
-
-#include "compat_openssl.h"
-#include "crypto_openssl_mgt.h"
-
-DISABLE_GCC_WARNING(redundant-decls)
-
-#include <openssl/err.h>
-#include <openssl/rsa.h>
-#include <openssl/pem.h>
-#include <openssl/evp.h>
-#include <openssl/engine.h>
-#include <openssl/rand.h>
-#include <openssl/bn.h>
-#include <openssl/dh.h>
-#include <openssl/conf.h>
-#include <openssl/hmac.h>
-#include <openssl/crypto.h>
-
-ENABLE_GCC_WARNING(redundant-decls)
-
-#ifndef NEW_THREAD_API
-/** A number of preallocated mutexes for use by OpenSSL. */
-static tor_mutex_t **openssl_mutexes_ = NULL;
-/** How many mutexes have we allocated for use by OpenSSL? */
-static int n_openssl_mutexes_ = 0;
-#endif /* !defined(NEW_THREAD_API) */
-
-/** Declare STATIC functions */
-STATIC char * parse_openssl_version_str(const char *raw_version);
-#ifndef NEW_THREAD_API
-STATIC void openssl_locking_cb_(int mode, int n, const char *file, int line);
-STATIC void tor_set_openssl_thread_id(CRYPTO_THREADID *threadid);
-#endif
-
-/* Returns a trimmed and human-readable version of an openssl version string
-* <b>raw_version</b>. They are usually in the form of 'OpenSSL 1.0.0b 10
-* May 2012' and this will parse them into a form similar to '1.0.0b' */
-STATIC char *
-parse_openssl_version_str(const char *raw_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)
- return tor_strndup(raw_version,
- end_of_version-raw_version);
- else
- return tor_strdup(raw_version);
-}
-
-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 = OpenSSL_version(OPENSSL_VERSION);
- crypto_openssl_version_str = parse_openssl_version_str(raw_version);
- }
- return crypto_openssl_version_str;
-}
-
-static char *crypto_openssl_header_version_str = NULL;
-/* Return a human-readable version of the compile-time openssl version
-* number. */
-const char *
-crypto_openssl_get_header_version_str(void)
-{
- if (crypto_openssl_header_version_str == NULL) {
- crypto_openssl_header_version_str =
- parse_openssl_version_str(OPENSSL_VERSION_TEXT);
- }
- return crypto_openssl_header_version_str;
-}
-
-#ifndef OPENSSL_THREADS
-#error OpenSSL has been built without thread support. Tor requires an \
- OpenSSL library with thread support enabled.
-#endif
-
-#ifndef NEW_THREAD_API
-/** Helper: OpenSSL uses this callback to manipulate mutexes. */
-STATIC void
-openssl_locking_cb_(int mode, int n, const char *file, int line)
-{
- (void)file;
- (void)line;
- 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]);
- else
- tor_mutex_release(openssl_mutexes_[n]);
-}
-
-STATIC void
-tor_set_openssl_thread_id(CRYPTO_THREADID *threadid)
-{
- CRYPTO_THREADID_set_numeric(threadid, tor_get_thread_id());
-}
-#endif /* !defined(NEW_THREAD_API) */
-
-/** Helper: Construct mutexes, and set callbacks to help OpenSSL handle being
- * multithreaded. Returns 0. */
-int
-setup_openssl_threading(void)
-{
-#ifndef NEW_THREAD_API
- int i;
- int n = CRYPTO_num_locks();
- n_openssl_mutexes_ = n;
- openssl_mutexes_ = tor_calloc(n, sizeof(tor_mutex_t *));
- for (i=0; i < n; ++i)
- openssl_mutexes_[i] = tor_mutex_new();
- CRYPTO_set_locking_callback(openssl_locking_cb_);
- CRYPTO_THREADID_set_callback(tor_set_openssl_thread_id);
-#endif /* !defined(NEW_THREAD_API) */
- return 0;
-}
-
-/** free OpenSSL variables */
-void
-crypto_openssl_free_all(void)
-{
- tor_free(crypto_openssl_version_str);
- tor_free(crypto_openssl_header_version_str);
-
-#ifndef NEW_THREAD_API
- if (n_openssl_mutexes_) {
- int n = n_openssl_mutexes_;
- tor_mutex_t **ms = openssl_mutexes_;
- int i;
- openssl_mutexes_ = NULL;
- n_openssl_mutexes_ = 0;
- for (i=0;i<n;++i) {
- tor_mutex_free(ms[i]);
- }
- tor_free(ms);
- }
-#endif /* !defined(NEW_THREAD_API) */
-}
-
diff --git a/src/common/crypto_openssl_mgt.h b/src/common/crypto_openssl_mgt.h
deleted file mode 100644
index 09b6737962..0000000000
--- a/src/common/crypto_openssl_mgt.h
+++ /dev/null
@@ -1,85 +0,0 @@
-/* Copyright (c) 2001, Matej Pfajfar.
- * Copyright (c) 2001-2004, Roger Dingledine.
- * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2017, The Tor Project, Inc. */
-/* See LICENSE for licensing information */
-
-/**
- * \file crypto_openssl.h
- *
- * \brief Headers for crypto_openssl.c
- **/
-
-#ifndef TOR_CRYPTO_OPENSSL_H
-#define TOR_CRYPTO_OPENSSL_H
-
-#include <stdio.h>
-#include "util.h"
-
-#include <openssl/engine.h>
-
-/*
- Macro to create an arbitrary OpenSSL version number as used by
- OPENSSL_VERSION_NUMBER or SSLeay(), since the actual numbers are a bit hard
- to read.
-
- Don't use this directly, instead use one of the other OPENSSL_V macros
- below.
-
- The format is: 4 bits major, 8 bits minor, 8 bits fix, 8 bits patch, 4 bit
- status.
- */
-#define OPENSSL_VER(a,b,c,d,e) \
- (((a)<<28) | \
- ((b)<<20) | \
- ((c)<<12) | \
- ((d)<< 4) | \
- (e))
-/** An openssl release number. For example, OPENSSL_V(0,9,8,'j') is the
- * version for the released version of 0.9.8j */
-#define OPENSSL_V(a,b,c,d) \
- OPENSSL_VER((a),(b),(c),(d)-'a'+1,0xf)
-/** An openssl release number for the first release in the series. For
- * example, OPENSSL_V_NOPATCH(1,0,0) is the first released version of OpenSSL
- * 1.0.0. */
-#define OPENSSL_V_NOPATCH(a,b,c) \
- OPENSSL_VER((a),(b),(c),0,0xf)
-/** The first version that would occur for any alpha or beta in an openssl
- * series. For example, OPENSSL_V_SERIES(0,9,8) is greater than any released
- * 0.9.7, and less than any released 0.9.8. */
-#define OPENSSL_V_SERIES(a,b,c) \
- OPENSSL_VER((a),(b),(c),0,0)
-
-#ifdef ANDROID
-/* Android's OpenSSL seems to have removed all of its Engine support. */
-#define DISABLE_ENGINES
-#endif
-
-#if OPENSSL_VERSION_NUMBER >= OPENSSL_VER(1,1,0,0,5) && \
- !defined(LIBRESSL_VERSION_NUMBER)
-/* OpenSSL as of 1.1.0pre4 has an "new" thread API, which doesn't require
- * seting up various callbacks.
- *
- * OpenSSL 1.1.0pre4 has a messed up `ERR_remove_thread_state()` prototype,
- * while the previous one was restored in pre5, and the function made a no-op
- * (along with a deprecated annotation, which produces a compiler warning).
- *
- * While it is possible to support all three versions of the thread API,
- * a version that existed only for one snapshot pre-release is kind of
- * pointless, so let's not.
- */
-#define NEW_THREAD_API
-#endif /* OPENSSL_VERSION_NUMBER >= OPENSSL_VER(1,1,0,0,5) && ... */
-
-/* global openssl state */
-const char * crypto_openssl_get_version_str(void);
-const char * crypto_openssl_get_header_version_str(void);
-
-/* OpenSSL threading setup function */
-int setup_openssl_threading(void);
-
-/* Tor OpenSSL utility functions */
-void crypto_openssl_free_all(void);
-
-#endif /* !defined(TOR_CRYPTO_OPENSSL_H) */
-
diff --git a/src/common/crypto_pwbox.c b/src/common/crypto_pwbox.c
deleted file mode 100644
index c2bd1d26cb..0000000000
--- a/src/common/crypto_pwbox.c
+++ /dev/null
@@ -1,215 +0,0 @@
-/* Copyright (c) 2014-2017, The Tor Project, Inc. */
-/* See LICENSE for licensing information */
-
-/**
- * \file crypto_pwbox.c
- *
- * \brief Code for encrypting secrets in a password-protected form and saving
- * them to disk.
- */
-
-#include "crypto.h"
-#include "crypto_digest.h"
-#include "crypto_pwbox.h"
-#include "crypto_rand.h"
-#include "crypto_s2k.h"
-#include "crypto_util.h"
-#include "di_ops.h"
-#include "util.h"
-#include "pwbox.h"
-
-/* 8 bytes "TORBOX00"
- 1 byte: header len (H)
- H bytes: header, denoting secret key algorithm.
- 16 bytes: IV
- Round up to multiple of 128 bytes, then encrypt:
- 4 bytes: data len
- data
- zeros
- 32 bytes: HMAC-SHA256 of all previous bytes.
-*/
-
-#define MAX_OVERHEAD (S2K_MAXLEN + 8 + 1 + 32 + CIPHER_IV_LEN)
-
-/**
- * Make an authenticated passphrase-encrypted blob to encode the
- * <b>input_len</b> bytes in <b>input</b> using the passphrase
- * <b>secret</b> of <b>secret_len</b> bytes. Allocate a new chunk of memory
- * to hold the encrypted data, and store a pointer to that memory in
- * *<b>out</b>, and its size in <b>outlen_out</b>. Use <b>s2k_flags</b> as an
- * argument to the passphrase-hashing function.
- */
-int
-crypto_pwbox(uint8_t **out, size_t *outlen_out,
- const uint8_t *input, size_t input_len,
- const char *secret, size_t secret_len,
- unsigned s2k_flags)
-{
- uint8_t *result = NULL, *encrypted_portion;
- size_t encrypted_len = 128 * CEIL_DIV(input_len+4, 128);
- ssize_t result_len;
- int spec_len;
- uint8_t keys[CIPHER_KEY_LEN + DIGEST256_LEN];
- pwbox_encoded_t *enc = NULL;
- ssize_t enc_len;
-
- crypto_cipher_t *cipher;
- int rv;
-
- enc = pwbox_encoded_new();
-
- pwbox_encoded_setlen_skey_header(enc, S2K_MAXLEN);
-
- spec_len = secret_to_key_make_specifier(
- pwbox_encoded_getarray_skey_header(enc),
- S2K_MAXLEN,
- s2k_flags);
- if (BUG(spec_len < 0 || spec_len > S2K_MAXLEN))
- goto err;
- pwbox_encoded_setlen_skey_header(enc, spec_len);
- enc->header_len = spec_len;
-
- crypto_rand((char*)enc->iv, sizeof(enc->iv));
-
- pwbox_encoded_setlen_data(enc, encrypted_len);
- encrypted_portion = pwbox_encoded_getarray_data(enc);
-
- set_uint32(encrypted_portion, htonl((uint32_t)input_len));
- memcpy(encrypted_portion+4, input, input_len);
-
- /* Now that all the data is in position, derive some keys, encrypt, and
- * digest */
- const int s2k_rv = secret_to_key_derivekey(keys, sizeof(keys),
- pwbox_encoded_getarray_skey_header(enc),
- spec_len,
- secret, secret_len);
- if (BUG(s2k_rv < 0))
- goto err;
-
- cipher = crypto_cipher_new_with_iv((char*)keys, (char*)enc->iv);
- crypto_cipher_crypt_inplace(cipher, (char*)encrypted_portion, encrypted_len);
- crypto_cipher_free(cipher);
-
- result_len = pwbox_encoded_encoded_len(enc);
- if (BUG(result_len < 0))
- goto err;
- result = tor_malloc(result_len);
- enc_len = pwbox_encoded_encode(result, result_len, enc);
- if (BUG(enc_len < 0))
- goto err;
- tor_assert(enc_len == result_len);
-
- crypto_hmac_sha256((char*) result + result_len - 32,
- (const char*)keys + CIPHER_KEY_LEN,
- DIGEST256_LEN,
- (const char*)result,
- result_len - 32);
-
- *out = result;
- *outlen_out = result_len;
- rv = 0;
- goto out;
-
- /* LCOV_EXCL_START
-
- This error case is often unreachable if we're correctly coded, unless
- somebody adds a new error case somewhere, or unless you're building
- without scrypto support.
-
- - make_specifier can't fail, unless S2K_MAX_LEN is too short.
- - secret_to_key_derivekey can't really fail unless we're missing
- scrypt, or the underlying function fails, or we pass it a bogus
- algorithm or parameters.
- - pwbox_encoded_encoded_len can't fail unless we're using trunnel
- incorrectly.
- - pwbox_encoded_encode can't fail unless we're using trunnel wrong,
- or it's buggy.
- */
- err:
- tor_free(result);
- rv = -1;
- /* LCOV_EXCL_STOP */
- out:
- pwbox_encoded_free(enc);
- memwipe(keys, 0, sizeof(keys));
- return rv;
-}
-
-/**
- * Try to decrypt the passphrase-encrypted blob of <b>input_len</b> bytes in
- * <b>input</b> using the passphrase <b>secret</b> of <b>secret_len</b> bytes.
- * On success, return 0 and allocate a new chunk of memory to hold the
- * decrypted data, and store a pointer to that memory in *<b>out</b>, and its
- * size in <b>outlen_out</b>. On failure, return UNPWBOX_BAD_SECRET if
- * the passphrase might have been wrong, and UNPWBOX_CORRUPT if the object is
- * definitely corrupt.
- */
-int
-crypto_unpwbox(uint8_t **out, size_t *outlen_out,
- const uint8_t *inp, size_t input_len,
- const char *secret, size_t secret_len)
-{
- uint8_t *result = NULL;
- const uint8_t *encrypted;
- uint8_t keys[CIPHER_KEY_LEN + DIGEST256_LEN];
- uint8_t hmac[DIGEST256_LEN];
- uint32_t result_len;
- size_t encrypted_len;
- crypto_cipher_t *cipher = NULL;
- int rv = UNPWBOX_CORRUPTED;
- ssize_t got_len;
-
- pwbox_encoded_t *enc = NULL;
-
- got_len = pwbox_encoded_parse(&enc, inp, input_len);
- if (got_len < 0 || (size_t)got_len != input_len)
- goto err;
-
- /* Now derive the keys and check the hmac. */
- if (secret_to_key_derivekey(keys, sizeof(keys),
- pwbox_encoded_getarray_skey_header(enc),
- pwbox_encoded_getlen_skey_header(enc),
- secret, secret_len) < 0)
- goto err;
-
- crypto_hmac_sha256((char *)hmac,
- (const char*)keys + CIPHER_KEY_LEN, DIGEST256_LEN,
- (const char*)inp, input_len - DIGEST256_LEN);
-
- if (tor_memneq(hmac, enc->hmac, DIGEST256_LEN)) {
- rv = UNPWBOX_BAD_SECRET;
- goto err;
- }
-
- /* How long is the plaintext? */
- encrypted = pwbox_encoded_getarray_data(enc);
- encrypted_len = pwbox_encoded_getlen_data(enc);
- if (encrypted_len < 4)
- goto err;
-
- cipher = crypto_cipher_new_with_iv((char*)keys, (char*)enc->iv);
- crypto_cipher_decrypt(cipher, (char*)&result_len, (char*)encrypted, 4);
- result_len = ntohl(result_len);
- if (encrypted_len < result_len + 4)
- goto err;
-
- /* Allocate a buffer and decrypt */
- result = tor_malloc_zero(result_len);
- crypto_cipher_decrypt(cipher, (char*)result, (char*)encrypted+4, result_len);
-
- *out = result;
- *outlen_out = result_len;
-
- rv = UNPWBOX_OKAY;
- goto out;
-
- err:
- tor_free(result);
-
- out:
- crypto_cipher_free(cipher);
- pwbox_encoded_free(enc);
- memwipe(keys, 0, sizeof(keys));
- return rv;
-}
-
diff --git a/src/common/crypto_pwbox.h b/src/common/crypto_pwbox.h
deleted file mode 100644
index a26b6d2c17..0000000000
--- a/src/common/crypto_pwbox.h
+++ /dev/null
@@ -1,23 +0,0 @@
-/* Copyright (c) 2014-2017, The Tor Project, Inc. */
-/* See LICENSE for licensing information */
-
-#ifndef CRYPTO_PWBOX_H_INCLUDED_
-#define CRYPTO_PWBOX_H_INCLUDED_
-
-#include "torint.h"
-
-#define UNPWBOX_OKAY 0
-#define UNPWBOX_BAD_SECRET -1
-#define UNPWBOX_CORRUPTED -2
-
-int crypto_pwbox(uint8_t **out, size_t *outlen_out,
- const uint8_t *inp, size_t input_len,
- const char *secret, size_t secret_len,
- unsigned s2k_flags);
-
-int crypto_unpwbox(uint8_t **out, size_t *outlen_out,
- const uint8_t *inp, size_t input_len,
- const char *secret, size_t secret_len);
-
-#endif /* !defined(CRYPTO_PWBOX_H_INCLUDED_) */
-
diff --git a/src/common/crypto_rand.c b/src/common/crypto_rand.c
deleted file mode 100644
index df2e2f65d3..0000000000
--- a/src/common/crypto_rand.c
+++ /dev/null
@@ -1,615 +0,0 @@
-/* Copyright (c) 2001, Matej Pfajfar.
- * Copyright (c) 2001-2004, Roger Dingledine.
- * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2018, The Tor Project, Inc. */
-/* See LICENSE for licensing information */
-
-/**
- * \file crypto_rand.c
- *
- * \brief Functions for initialising and seeding (pseudo-)random
- * number generators, and working with randomness.
- **/
-
-#ifndef CRYPTO_RAND_PRIVATE
-#define CRYPTO_RAND_PRIVATE
-
-#include "crypto_rand.h"
-
-#ifdef _WIN32
-#include <windows.h>
-#include <wincrypt.h>
-#endif /* defined(_WIN32) */
-
-#include "container.h"
-#include "compat.h"
-#include "compat_openssl.h"
-#include "crypto_util.h"
-#include "sandbox.h"
-#include "testsupport.h"
-#include "torlog.h"
-#include "util.h"
-#include "util_format.h"
-
-DISABLE_GCC_WARNING(redundant-decls)
-#include <openssl/rand.h>
-ENABLE_GCC_WARNING(redundant-decls)
-
-#if __GNUC__ && GCC_VERSION >= 402
-#if GCC_VERSION >= 406
-#pragma GCC diagnostic pop
-#else
-#pragma GCC diagnostic warning "-Wredundant-decls"
-#endif
-#endif /* __GNUC__ && GCC_VERSION >= 402 */
-
-#ifdef HAVE_FCNTL_H
-#include <fcntl.h>
-#endif
-#ifdef HAVE_SYS_FCNTL_H
-#include <sys/fcntl.h>
-#endif
-#ifdef HAVE_SYS_STAT_H
-#include <sys/stat.h>
-#endif
-#ifdef HAVE_UNISTD_H
-#include <unistd.h>
-#endif
-#ifdef HAVE_SYS_SYSCALL_H
-#include <sys/syscall.h>
-#endif
-#ifdef HAVE_SYS_RANDOM_H
-#include <sys/random.h>
-#endif
-
-/**
- * How many bytes of entropy we add at once.
- *
- * This is how much entropy OpenSSL likes to add right now, so maybe it will
- * work for us too.
- **/
-#define ADD_ENTROPY 32
-
-/**
- * Longest recognized DNS query.
- **/
-#define MAX_DNS_LABEL_SIZE 63
-
-/**
- * Largest strong entropy request permitted.
- **/
-#define MAX_STRONGEST_RAND_SIZE 256
-
-/**
- * Set the seed of the weak RNG to a random value.
- **/
-void
-crypto_seed_weak_rng(tor_weak_rng_t *rng)
-{
- unsigned seed;
- crypto_rand((void*)&seed, sizeof(seed));
- tor_init_weak_random(rng, seed);
-}
-
-#ifdef TOR_UNIT_TESTS
-int break_strongest_rng_syscall = 0;
-int break_strongest_rng_fallback = 0;
-#endif
-
-/**
- * Try to get <b>out_len</b> bytes of the strongest entropy we can generate,
- * via system calls, storing it into <b>out</b>. Return 0 on success, -1 on
- * failure. A maximum request size of 256 bytes is imposed.
- **/
-static int
-crypto_strongest_rand_syscall(uint8_t *out, size_t out_len)
-{
- tor_assert(out_len <= MAX_STRONGEST_RAND_SIZE);
-
- /* We only log at notice-level here because in the case that this function
- * fails the crypto_strongest_rand_raw() caller will log with a warning-level
- * message and let crypto_strongest_rand() error out and finally terminating
- * Tor with an assertion error.
- */
-
-#ifdef TOR_UNIT_TESTS
- if (break_strongest_rng_syscall)
- return -1;
-#endif
-
-#if defined(_WIN32)
- static int provider_set = 0;
- static HCRYPTPROV provider;
-
- if (!provider_set) {
- if (!CryptAcquireContext(&provider, NULL, NULL, PROV_RSA_FULL,
- CRYPT_VERIFYCONTEXT)) {
- log_notice(LD_CRYPTO, "Unable to set Windows CryptoAPI provider [1].");
- return -1;
- }
- provider_set = 1;
- }
- if (!CryptGenRandom(provider, out_len, out)) {
- log_notice(LD_CRYPTO, "Unable get entropy from the Windows CryptoAPI.");
- return -1;
- }
-
- return 0;
-#elif defined(__linux__) && defined(SYS_getrandom)
- static int getrandom_works = 1; /* Be optimistic about our chances... */
-
- /* getrandom() isn't as straightforward as getentropy(), and has
- * no glibc wrapper.
- *
- * As far as I can tell from getrandom(2) and the source code, the
- * requests we issue will always succeed (though it will block on the
- * call if /dev/urandom isn't seeded yet), since we are NOT specifying
- * GRND_NONBLOCK and the request is <= 256 bytes.
- *
- * The manpage is unclear on what happens if a signal interrupts the call
- * while the request is blocked due to lack of entropy....
- *
- * We optimistically assume that getrandom() is available and functional
- * because it is the way of the future, and 2 branch mispredicts pale in
- * comparison to the overheads involved with failing to open
- * /dev/srandom followed by opening and reading from /dev/urandom.
- */
- if (PREDICT_LIKELY(getrandom_works)) {
- long ret;
- /* A flag of '0' here means to read from '/dev/urandom', and to
- * block if insufficient entropy is available to service the
- * request.
- */
- const unsigned int flags = 0;
- do {
- ret = syscall(SYS_getrandom, out, out_len, flags);
- } while (ret == -1 && ((errno == EINTR) ||(errno == EAGAIN)));
-
- if (PREDICT_UNLIKELY(ret == -1)) {
- /* LCOV_EXCL_START we can't actually make the syscall fail in testing. */
- tor_assert(errno != EAGAIN);
- tor_assert(errno != EINTR);
-
- /* Useful log message for errno. */
- if (errno == ENOSYS) {
- log_notice(LD_CRYPTO, "Can't get entropy from getrandom()."
- " You are running a version of Tor built to support"
- " getrandom(), but the kernel doesn't implement this"
- " function--probably because it is too old?"
- " Trying fallback method instead.");
- } else {
- log_notice(LD_CRYPTO, "Can't get entropy from getrandom(): %s."
- " Trying fallback method instead.",
- strerror(errno));
- }
-
- getrandom_works = 0; /* Don't bother trying again. */
- return -1;
- /* LCOV_EXCL_STOP */
- }
-
- tor_assert(ret == (long)out_len);
- return 0;
- }
-
- return -1; /* getrandom() previously failed unexpectedly. */
-#elif defined(HAVE_GETENTROPY)
- /* getentropy() is what Linux's getrandom() wants to be when it grows up.
- * the only gotcha is that requests are limited to 256 bytes.
- */
- return getentropy(out, out_len);
-#else
- (void) out;
-#endif /* defined(_WIN32) || ... */
-
- /* This platform doesn't have a supported syscall based random. */
- return -1;
-}
-
-/**
- * Try to get <b>out_len</b> bytes of the strongest entropy we can generate,
- * via the per-platform fallback mechanism, storing it into <b>out</b>.
- * Return 0 on success, -1 on failure. A maximum request size of 256 bytes
- * is imposed.
- **/
-static int
-crypto_strongest_rand_fallback(uint8_t *out, size_t out_len)
-{
-#ifdef TOR_UNIT_TESTS
- if (break_strongest_rng_fallback)
- return -1;
-#endif
-
-#ifdef _WIN32
- /* Windows exclusively uses crypto_strongest_rand_syscall(). */
- (void)out;
- (void)out_len;
- return -1;
-#else /* !(defined(_WIN32)) */
- static const char *filenames[] = {
- "/dev/srandom", "/dev/urandom", "/dev/random", NULL
- };
- int fd, i;
- size_t n;
-
- for (i = 0; filenames[i]; ++i) {
- log_debug(LD_FS, "Considering %s as entropy source", filenames[i]);
- fd = open(sandbox_intern_string(filenames[i]), O_RDONLY, 0);
- if (fd<0) continue;
- log_info(LD_CRYPTO, "Reading entropy from \"%s\"", filenames[i]);
- n = read_all(fd, (char*)out, out_len, 0);
- close(fd);
- if (n != out_len) {
- /* LCOV_EXCL_START
- * We can't make /dev/foorandom actually fail. */
- log_notice(LD_CRYPTO,
- "Error reading from entropy source %s (read only %lu bytes).",
- filenames[i],
- (unsigned long)n);
- return -1;
- /* LCOV_EXCL_STOP */
- }
-
- return 0;
- }
-
- return -1;
-#endif /* defined(_WIN32) */
-}
-
-/**
- * Try to get <b>out_len</b> bytes of the strongest entropy we can generate,
- * storing it into <b>out</b>. Return 0 on success, -1 on failure. A maximum
- * request size of 256 bytes is imposed.
- **/
-STATIC int
-crypto_strongest_rand_raw(uint8_t *out, size_t out_len)
-{
- static const size_t sanity_min_size = 16;
- static const int max_attempts = 3;
- tor_assert(out_len <= MAX_STRONGEST_RAND_SIZE);
-
- /* For buffers >= 16 bytes (128 bits), we sanity check the output by
- * zero filling the buffer and ensuring that it actually was at least
- * partially modified.
- *
- * Checking that any individual byte is non-zero seems like it would
- * fail too often (p = out_len * 1/256) for comfort, but this is an
- * "adjust according to taste" sort of check.
- */
- memwipe(out, 0, out_len);
- for (int i = 0; i < max_attempts; i++) {
- /* Try to use the syscall/OS favored mechanism to get strong entropy. */
- if (crypto_strongest_rand_syscall(out, out_len) != 0) {
- /* Try to use the less-favored mechanism to get strong entropy. */
- if (crypto_strongest_rand_fallback(out, out_len) != 0) {
- /* Welp, we tried. Hopefully the calling code terminates the process
- * since we're basically boned without good entropy.
- */
- log_warn(LD_CRYPTO,
- "Cannot get strong entropy: no entropy source found.");
- return -1;
- }
- }
-
- if ((out_len < sanity_min_size) || !tor_mem_is_zero((char*)out, out_len))
- return 0;
- }
-
- /* LCOV_EXCL_START
- *
- * We tried max_attempts times to fill a buffer >= 128 bits long,
- * and each time it returned all '0's. Either the system entropy
- * source is busted, or the user should go out and buy a ticket to
- * every lottery on the planet.
- */
- log_warn(LD_CRYPTO, "Strong OS entropy returned all zero buffer.");
-
- return -1;
- /* LCOV_EXCL_STOP */
-}
-
-/**
- * Try to get <b>out_len</b> bytes of the strongest entropy we can generate,
- * storing it into <b>out</b>.
- **/
-void
-crypto_strongest_rand(uint8_t *out, size_t out_len)
-{
-#define DLEN SHA512_DIGEST_LENGTH
- /* We're going to hash DLEN bytes from the system RNG together with some
- * bytes from the openssl PRNG, in order to yield DLEN bytes.
- */
- uint8_t inp[DLEN*2];
- uint8_t tmp[DLEN];
- tor_assert(out);
- while (out_len) {
- crypto_rand((char*) inp, DLEN);
- if (crypto_strongest_rand_raw(inp+DLEN, DLEN) < 0) {
- // LCOV_EXCL_START
- log_err(LD_CRYPTO, "Failed to load strong entropy when generating an "
- "important key. Exiting.");
- /* Die with an assertion so we get a stack trace. */
- tor_assert(0);
- // LCOV_EXCL_STOP
- }
- if (out_len >= DLEN) {
- SHA512(inp, sizeof(inp), out);
- out += DLEN;
- out_len -= DLEN;
- } else {
- SHA512(inp, sizeof(inp), tmp);
- memcpy(out, tmp, out_len);
- break;
- }
- }
- memwipe(tmp, 0, sizeof(tmp));
- memwipe(inp, 0, sizeof(inp));
-#undef DLEN
-}
-
-/**
- * Seed OpenSSL's random number generator with bytes from the operating
- * system. Return 0 on success, -1 on failure.
- **/
-int
-crypto_seed_rng(void)
-{
- int rand_poll_ok = 0, load_entropy_ok = 0;
- uint8_t buf[ADD_ENTROPY];
-
- /* OpenSSL has a RAND_poll function that knows about more kinds of
- * entropy than we do. We'll try calling that, *and* calling our own entropy
- * functions. If one succeeds, we'll accept the RNG as seeded. */
- rand_poll_ok = RAND_poll();
- if (rand_poll_ok == 0)
- log_warn(LD_CRYPTO, "RAND_poll() failed."); // LCOV_EXCL_LINE
-
- load_entropy_ok = !crypto_strongest_rand_raw(buf, sizeof(buf));
- if (load_entropy_ok) {
- RAND_seed(buf, sizeof(buf));
- }
-
- memwipe(buf, 0, sizeof(buf));
-
- if ((rand_poll_ok || load_entropy_ok) && RAND_status() == 1)
- return 0;
- else
- return -1;
-}
-
-/**
- * Write <b>n</b> bytes of strong random data to <b>to</b>. Supports mocking
- * for unit tests.
- *
- * This function is not allowed to fail; if it would fail to generate strong
- * entropy, it must terminate the process instead.
- **/
-MOCK_IMPL(void,
-crypto_rand, (char *to, size_t n))
-{
- crypto_rand_unmocked(to, n);
-}
-
-/**
- * Write <b>n</b> bytes of strong random data to <b>to</b>. Most callers
- * will want crypto_rand instead.
- *
- * This function is not allowed to fail; if it would fail to generate strong
- * entropy, it must terminate the process instead.
- **/
-void
-crypto_rand_unmocked(char *to, size_t n)
-{
- int r;
- if (n == 0)
- return;
-
- tor_assert(n < INT_MAX);
- tor_assert(to);
- r = RAND_bytes((unsigned char*)to, (int)n);
- /* We consider a PRNG failure non-survivable. Let's assert so that we get a
- * stack trace about where it happened.
- */
- tor_assert(r >= 0);
-}
-
-/**
- * Return a pseudorandom integer, chosen uniformly from the values
- * between 0 and <b>max</b>-1 inclusive. <b>max</b> must be between 1 and
- * INT_MAX+1, inclusive.
- */
-int
-crypto_rand_int(unsigned int max)
-{
- unsigned int val;
- unsigned int cutoff;
- tor_assert(max <= ((unsigned int)INT_MAX)+1);
- tor_assert(max > 0); /* don't div by 0 */
-
- /* We ignore any values that are >= 'cutoff,' to avoid biasing the
- * distribution with clipping at the upper end of unsigned int's
- * range.
- */
- cutoff = UINT_MAX - (UINT_MAX%max);
- while (1) {
- crypto_rand((char*)&val, sizeof(val));
- if (val < cutoff)
- return val % max;
- }
-}
-
-/**
- * Return a pseudorandom integer, chosen uniformly from the values i such
- * that min <= i < max.
- *
- * <b>min</b> MUST be in range [0, <b>max</b>).
- * <b>max</b> MUST be in range (min, INT_MAX].
- **/
-int
-crypto_rand_int_range(unsigned int min, unsigned int max)
-{
- tor_assert(min < max);
- tor_assert(max <= INT_MAX);
-
- /* The overflow is avoided here because crypto_rand_int() returns a value
- * between 0 and (max - min) inclusive. */
- return min + crypto_rand_int(max - min);
-}
-
-/**
- * As crypto_rand_int_range, but supports uint64_t.
- **/
-uint64_t
-crypto_rand_uint64_range(uint64_t min, uint64_t max)
-{
- tor_assert(min < max);
- return min + crypto_rand_uint64(max - min);
-}
-
-/**
- * As crypto_rand_int_range, but supports time_t.
- **/
-time_t
-crypto_rand_time_range(time_t min, time_t max)
-{
- tor_assert(min < max);
- return min + (time_t)crypto_rand_uint64(max - min);
-}
-
-/**
- * Return a pseudorandom 64-bit integer, chosen uniformly from the values
- * between 0 and <b>max</b>-1 inclusive.
- **/
-uint64_t
-crypto_rand_uint64(uint64_t max)
-{
- uint64_t val;
- uint64_t cutoff;
- tor_assert(max < UINT64_MAX);
- tor_assert(max > 0); /* don't div by 0 */
-
- /* We ignore any values that are >= 'cutoff,' to avoid biasing the
- * distribution with clipping at the upper end of unsigned int's
- * range.
- */
- cutoff = UINT64_MAX - (UINT64_MAX%max);
- while (1) {
- crypto_rand((char*)&val, sizeof(val));
- if (val < cutoff)
- return val % max;
- }
-}
-
-/**
- * Return a pseudorandom double d, chosen uniformly from the range
- * 0.0 <= d < 1.0.
- **/
-double
-crypto_rand_double(void)
-{
- /* We just use an unsigned int here; we don't really care about getting
- * more than 32 bits of resolution */
- unsigned int u;
- crypto_rand((char*)&u, sizeof(u));
-#if SIZEOF_INT == 4
-#define UINT_MAX_AS_DOUBLE 4294967296.0
-#elif SIZEOF_INT == 8
-#define UINT_MAX_AS_DOUBLE 1.8446744073709552e+19
-#else
-#error SIZEOF_INT is neither 4 nor 8
-#endif /* SIZEOF_INT == 4 || ... */
- return ((double)u) / UINT_MAX_AS_DOUBLE;
-}
-
-/**
- * Generate and return a new random hostname starting with <b>prefix</b>,
- * ending with <b>suffix</b>, and containing no fewer than
- * <b>min_rand_len</b> and no more than <b>max_rand_len</b> random base32
- * characters. Does not check for failure.
- *
- * Clip <b>max_rand_len</b> to MAX_DNS_LABEL_SIZE.
- **/
-char *
-crypto_random_hostname(int min_rand_len, int max_rand_len, const char *prefix,
- const char *suffix)
-{
- char *result, *rand_bytes;
- int randlen, rand_bytes_len;
- size_t resultlen, prefixlen;
-
- if (max_rand_len > MAX_DNS_LABEL_SIZE)
- max_rand_len = MAX_DNS_LABEL_SIZE;
- if (min_rand_len > max_rand_len)
- min_rand_len = max_rand_len;
-
- randlen = crypto_rand_int_range(min_rand_len, max_rand_len+1);
-
- prefixlen = strlen(prefix);
- resultlen = prefixlen + strlen(suffix) + randlen + 16;
-
- rand_bytes_len = ((randlen*5)+7)/8;
- if (rand_bytes_len % 5)
- rand_bytes_len += 5 - (rand_bytes_len%5);
- rand_bytes = tor_malloc(rand_bytes_len);
- crypto_rand(rand_bytes, rand_bytes_len);
-
- result = tor_malloc(resultlen);
- memcpy(result, prefix, prefixlen);
- base32_encode(result+prefixlen, resultlen-prefixlen,
- rand_bytes, rand_bytes_len);
- tor_free(rand_bytes);
- strlcpy(result+prefixlen+randlen, suffix, resultlen-(prefixlen+randlen));
-
- return result;
-}
-
-/**
- * Return a randomly chosen element of <b>sl</b>; or NULL if <b>sl</b>
- * is empty.
- **/
-void *
-smartlist_choose(const smartlist_t *sl)
-{
- int len = smartlist_len(sl);
- if (len)
- return smartlist_get(sl,crypto_rand_int(len));
- return NULL; /* no elements to choose from */
-}
-
-/**
- * Scramble the elements of <b>sl</b> into a random order.
- **/
-void
-smartlist_shuffle(smartlist_t *sl)
-{
- int i;
- /* From the end of the list to the front, choose at random from the
- positions we haven't looked at yet, and swap that position into the
- current position. Remember to give "no swap" the same probability as
- any other swap. */
- for (i = smartlist_len(sl)-1; i > 0; --i) {
- int j = crypto_rand_int(i+1);
- smartlist_swap(sl, i, j);
- }
-}
-
-/** Make sure that openssl is using its default PRNG. Return 1 if we had to
- * adjust it; 0 otherwise. */
-int
-crypto_force_rand_ssleay(void)
-{
- RAND_METHOD *default_method;
- default_method = RAND_OpenSSL();
- if (RAND_get_rand_method() != default_method) {
- log_notice(LD_CRYPTO, "It appears that one of our engines has provided "
- "a replacement the OpenSSL RNG. Resetting it to the default "
- "implementation.");
- RAND_set_rand_method(default_method);
- return 1;
- }
- return 0;
-}
-
-#endif /* !defined(CRYPTO_RAND_PRIVATE) */
-
diff --git a/src/common/crypto_rand.h b/src/common/crypto_rand.h
deleted file mode 100644
index bb02e51001..0000000000
--- a/src/common/crypto_rand.h
+++ /dev/null
@@ -1,52 +0,0 @@
-/* Copyright (c) 2001, Matej Pfajfar.
- * Copyright (c) 2001-2004, Roger Dingledine.
- * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2018, The Tor Project, Inc. */
-/* See LICENSE for licensing information */
-
-/**
- * \file crypto_rand.h
- *
- * \brief Common functions for using (pseudo-)random number generators.
- **/
-
-#ifndef TOR_CRYPTO_RAND_H
-#define TOR_CRYPTO_RAND_H
-
-#include "torint.h"
-#include "util.h"
-
-/* random numbers */
-int crypto_seed_rng(void) ATTR_WUR;
-MOCK_DECL(void,crypto_rand,(char *to, size_t n));
-void crypto_rand_unmocked(char *to, size_t n);
-void crypto_strongest_rand(uint8_t *out, size_t out_len);
-int crypto_rand_int(unsigned int max);
-int crypto_rand_int_range(unsigned int min, unsigned int max);
-uint64_t crypto_rand_uint64_range(uint64_t min, uint64_t max);
-time_t crypto_rand_time_range(time_t min, time_t max);
-uint64_t crypto_rand_uint64(uint64_t max);
-double crypto_rand_double(void);
-struct tor_weak_rng_t;
-void crypto_seed_weak_rng(struct tor_weak_rng_t *rng);
-
-char *crypto_random_hostname(int min_rand_len, int max_rand_len,
- const char *prefix, const char *suffix);
-
-struct smartlist_t;
-void *smartlist_choose(const struct smartlist_t *sl);
-void smartlist_shuffle(struct smartlist_t *sl);
-int crypto_force_rand_ssleay(void);
-
-#ifdef CRYPTO_RAND_PRIVATE
-
-STATIC int crypto_strongest_rand_raw(uint8_t *out, size_t out_len);
-
-#ifdef TOR_UNIT_TESTS
-extern int break_strongest_rng_syscall;
-extern int break_strongest_rng_fallback;
-#endif
-#endif /* defined(CRYPTO_RAND_PRIVATE) */
-
-#endif /* !defined(TOR_CRYPTO_RAND_H) */
-
diff --git a/src/common/crypto_rsa.c b/src/common/crypto_rsa.c
deleted file mode 100644
index f66cdef3c5..0000000000
--- a/src/common/crypto_rsa.c
+++ /dev/null
@@ -1,1183 +0,0 @@
-/* Copyright (c) 2001, Matej Pfajfar.
- * Copyright (c) 2001-2004, Roger Dingledine.
- * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2017, The Tor Project, Inc. */
-/* See LICENSE for licensing information */
-
-/**
- * \file crypto_rsa.c
- * \brief Block of functions related with RSA utilities and operations.
- **/
-
-#include "crypto.h"
-#include "crypto_curve25519.h"
-#include "crypto_digest.h"
-#include "crypto_format.h"
-#include "compat_openssl.h"
-#include "crypto_rand.h"
-#include "crypto_rsa.h"
-#include "crypto_util.h"
-
-DISABLE_GCC_WARNING(redundant-decls)
-
-#include <openssl/err.h>
-#include <openssl/rsa.h>
-#include <openssl/pem.h>
-#include <openssl/evp.h>
-#include <openssl/engine.h>
-#include <openssl/rand.h>
-#include <openssl/bn.h>
-#include <openssl/dh.h>
-#include <openssl/conf.h>
-#include <openssl/hmac.h>
-
-ENABLE_GCC_WARNING(redundant-decls)
-
-#include "torlog.h"
-#include "util.h"
-#include "util_format.h"
-
-/** Declaration for crypto_pk_t structure. */
-struct crypto_pk_t
-{
- int refs; /**< reference count, so we don't have to copy keys */
- RSA *key; /**< The key itself */
-};
-
-/** Log all pending crypto errors at level <b>severity</b>. Use
- * <b>doing</b> to describe our current activities.
- */
-static void
-crypto_log_errors(int severity, const char *doing)
-{
- unsigned long err;
- const char *msg, *lib, *func;
- while ((err = ERR_get_error()) != 0) {
- msg = (const char*)ERR_reason_error_string(err);
- lib = (const char*)ERR_lib_error_string(err);
- func = (const char*)ERR_func_error_string(err);
- if (!msg) msg = "(null)";
- if (!lib) lib = "(null)";
- if (!func) func = "(null)";
- if (BUG(!doing)) doing = "(null)";
- tor_log(severity, LD_CRYPTO, "crypto error while %s: %s (in %s:%s)",
- doing, msg, lib, func);
- }
-}
-
-/** Return the number of bytes added by padding method <b>padding</b>.
- */
-int
-crypto_get_rsa_padding_overhead(int padding)
-{
- switch (padding)
- {
- case RSA_PKCS1_OAEP_PADDING: return PKCS1_OAEP_PADDING_OVERHEAD;
- default: tor_assert(0); return -1; // LCOV_EXCL_LINE
- }
-}
-
-/** Given a padding method <b>padding</b>, return the correct OpenSSL constant.
- */
-int
-crypto_get_rsa_padding(int padding)
-{
- switch (padding)
- {
- case PK_PKCS1_OAEP_PADDING: return RSA_PKCS1_OAEP_PADDING;
- default: tor_assert(0); return -1; // LCOV_EXCL_LINE
- }
-}
-
-/** used internally: quicly validate a crypto_pk_t object as a private key.
- * Return 1 iff the public key is valid, 0 if obviously invalid.
- */
-static int
-crypto_pk_private_ok(const crypto_pk_t *k)
-{
-#ifdef OPENSSL_1_1_API
- if (!k || !k->key)
- return 0;
-
- const BIGNUM *p, *q;
- RSA_get0_factors(k->key, &p, &q);
- return p != NULL; /* XXX/yawning: Should we check q? */
-#else /* !(defined(OPENSSL_1_1_API)) */
- return k && k->key && k->key->p;
-#endif /* defined(OPENSSL_1_1_API) */
-}
-
-/** used by tortls.c: wrap an RSA* in a crypto_pk_t. */
-crypto_pk_t *
-crypto_new_pk_from_rsa_(RSA *rsa)
-{
- crypto_pk_t *env;
- tor_assert(rsa);
- env = tor_malloc(sizeof(crypto_pk_t));
- env->refs = 1;
- env->key = rsa;
- return env;
-}
-
-/** Helper, used by tor-gencert.c. Return the RSA from a
- * crypto_pk_t. */
-RSA *
-crypto_pk_get_rsa_(crypto_pk_t *env)
-{
- return env->key;
-}
-
-/** 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. Return a valid
- * pointer on success, and NULL on failure. */
-MOCK_IMPL(EVP_PKEY *,
-crypto_pk_get_evp_pkey_,(crypto_pk_t *env, int private))
-{
- RSA *key = NULL;
- EVP_PKEY *pkey = NULL;
- tor_assert(env->key);
- if (private) {
- if (!(key = RSAPrivateKey_dup(env->key)))
- goto error;
- } else {
- if (!(key = RSAPublicKey_dup(env->key)))
- goto error;
- }
- if (!(pkey = EVP_PKEY_new()))
- goto error;
- if (!(EVP_PKEY_assign_RSA(pkey, key)))
- goto error;
- return pkey;
- error:
- if (pkey)
- EVP_PKEY_free(pkey);
- if (key)
- RSA_free(key);
- return NULL;
-}
-
-/** Allocate and return storage for a public key. The key itself will not yet
- * be set.
- */
-MOCK_IMPL(crypto_pk_t *,
-crypto_pk_new,(void))
-{
- RSA *rsa;
-
- rsa = RSA_new();
- tor_assert(rsa);
- return crypto_new_pk_from_rsa_(rsa);
-}
-
-/** Release a reference to an asymmetric key; when all the references
- * are released, free the key.
- */
-void
-crypto_pk_free_(crypto_pk_t *env)
-{
- if (!env)
- return;
-
- if (--env->refs > 0)
- return;
- tor_assert(env->refs == 0);
-
- if (env->key)
- RSA_free(env->key);
-
- tor_free(env);
-}
-
-/** Generate a <b>bits</b>-bit new public/private keypair in <b>env</b>.
- * Return 0 on success, -1 on failure.
- */
-MOCK_IMPL(int,
-crypto_pk_generate_key_with_bits,(crypto_pk_t *env, int bits))
-{
- tor_assert(env);
-
- if (env->key) {
- RSA_free(env->key);
- env->key = NULL;
- }
-
- {
- BIGNUM *e = BN_new();
- RSA *r = NULL;
- if (!e)
- goto done;
- if (! BN_set_word(e, 65537))
- goto done;
- r = RSA_new();
- if (!r)
- goto done;
- if (RSA_generate_key_ex(r, bits, e, NULL) == -1)
- goto done;
-
- env->key = r;
- r = NULL;
- done:
- if (e)
- BN_clear_free(e);
- if (r)
- RSA_free(r);
- }
-
- if (!env->key) {
- crypto_log_errors(LOG_WARN, "generating RSA key");
- return -1;
- }
-
- return 0;
-}
-
-/** A PEM callback that always reports a failure to get a password */
-static int
-pem_no_password_cb(char *buf, int size, int rwflag, void *u)
-{
- (void)buf;
- (void)size;
- (void)rwflag;
- (void)u;
- return -1;
-}
-
-/** Read a PEM-encoded private key from the <b>len</b>-byte string <b>s</b>
- * into <b>env</b>. Return 0 on success, -1 on failure. If len is -1,
- * the string is nul-terminated.
- */
-int
-crypto_pk_read_private_key_from_string(crypto_pk_t *env,
- const char *s, ssize_t len)
-{
- BIO *b;
-
- tor_assert(env);
- tor_assert(s);
- tor_assert(len < INT_MAX && len < SSIZE_T_CEILING);
-
- /* Create a read-only memory BIO, backed by the string 's' */
- b = BIO_new_mem_buf((char*)s, (int)len);
- if (!b)
- return -1;
-
- if (env->key)
- RSA_free(env->key);
-
- env->key = PEM_read_bio_RSAPrivateKey(b,NULL,pem_no_password_cb,NULL);
-
- BIO_free(b);
-
- if (!env->key) {
- crypto_log_errors(LOG_WARN, "Error parsing private key");
- return -1;
- }
- return 0;
-}
-
-/** Read a PEM-encoded private key from the file named by
- * <b>keyfile</b> into <b>env</b>. Return 0 on success, -1 on failure.
- */
-int
-crypto_pk_read_private_key_from_filename(crypto_pk_t *env,
- const char *keyfile)
-{
- char *contents;
- int r;
-
- /* Read the file into a string. */
- contents = read_file_to_str(keyfile, 0, NULL);
- if (!contents) {
- log_warn(LD_CRYPTO, "Error reading private key from \"%s\"", keyfile);
- return -1;
- }
-
- /* Try to parse it. */
- r = crypto_pk_read_private_key_from_string(env, contents, -1);
- memwipe(contents, 0, strlen(contents));
- tor_free(contents);
- if (r)
- return -1; /* read_private_key_from_string already warned, so we don't.*/
-
- /* Make sure it's valid. */
- if (crypto_pk_check_key(env) <= 0)
- return -1;
-
- return 0;
-}
-
-/** Helper function to implement crypto_pk_write_*_key_to_string. Return 0 on
- * success, -1 on failure. */
-static int
-crypto_pk_write_key_to_string_impl(crypto_pk_t *env, char **dest,
- size_t *len, int is_public)
-{
- BUF_MEM *buf;
- BIO *b;
- int r;
-
- tor_assert(env);
- tor_assert(env->key);
- tor_assert(dest);
-
- b = BIO_new(BIO_s_mem()); /* Create a memory BIO */
- if (!b)
- return -1;
-
- /* Now you can treat b as if it were a file. Just use the
- * PEM_*_bio_* functions instead of the non-bio variants.
- */
- if (is_public)
- r = PEM_write_bio_RSAPublicKey(b, env->key);
- else
- r = PEM_write_bio_RSAPrivateKey(b, env->key, NULL,NULL,0,NULL,NULL);
-
- if (!r) {
- crypto_log_errors(LOG_WARN, "writing RSA key to string");
- BIO_free(b);
- return -1;
- }
-
- BIO_get_mem_ptr(b, &buf);
-
- *dest = tor_malloc(buf->length+1);
- memcpy(*dest, buf->data, buf->length);
- (*dest)[buf->length] = 0; /* nul terminate it */
- *len = buf->length;
-
- BIO_free(b);
-
- return 0;
-}
-
-/** PEM-encode the public key portion of <b>env</b> and write it to a
- * newly allocated string. On success, set *<b>dest</b> to the new
- * string, *<b>len</b> to the string's length, and return 0. On
- * failure, return -1.
- */
-int
-crypto_pk_write_public_key_to_string(crypto_pk_t *env, char **dest,
- size_t *len)
-{
- return crypto_pk_write_key_to_string_impl(env, dest, len, 1);
-}
-
-/** PEM-encode the private key portion of <b>env</b> and write it to a
- * newly allocated string. On success, set *<b>dest</b> to the new
- * string, *<b>len</b> to the string's length, and return 0. On
- * failure, return -1.
- */
-int
-crypto_pk_write_private_key_to_string(crypto_pk_t *env, char **dest,
- size_t *len)
-{
- return crypto_pk_write_key_to_string_impl(env, dest, len, 0);
-}
-
-/** Read a PEM-encoded public key from the first <b>len</b> characters of
- * <b>src</b>, and store the result in <b>env</b>. Return 0 on success, -1 on
- * failure.
- */
-int
-crypto_pk_read_public_key_from_string(crypto_pk_t *env, const char *src,
- size_t len)
-{
- BIO *b;
-
- tor_assert(env);
- tor_assert(src);
- tor_assert(len<INT_MAX);
-
- b = BIO_new(BIO_s_mem()); /* Create a memory BIO */
- if (!b)
- return -1;
-
- BIO_write(b, src, (int)len);
-
- if (env->key)
- RSA_free(env->key);
- env->key = PEM_read_bio_RSAPublicKey(b, NULL, pem_no_password_cb, NULL);
- BIO_free(b);
- if (!env->key) {
- crypto_log_errors(LOG_WARN, "reading public key from string");
- return -1;
- }
-
- return 0;
-}
-
-/** Write the private key from <b>env</b> into the file named by <b>fname</b>,
- * PEM-encoded. Return 0 on success, -1 on failure.
- */
-int
-crypto_pk_write_private_key_to_filename(crypto_pk_t *env,
- const char *fname)
-{
- BIO *bio;
- char *cp;
- long len;
- char *s;
- int r;
-
- tor_assert(crypto_pk_private_ok(env));
-
- if (!(bio = BIO_new(BIO_s_mem())))
- return -1;
- if (PEM_write_bio_RSAPrivateKey(bio, env->key, NULL,NULL,0,NULL,NULL)
- == 0) {
- crypto_log_errors(LOG_WARN, "writing private key");
- BIO_free(bio);
- return -1;
- }
- len = BIO_get_mem_data(bio, &cp);
- tor_assert(len >= 0);
- s = tor_malloc(len+1);
- memcpy(s, cp, len);
- s[len]='\0';
- r = write_str_to_file(fname, s, 0);
- BIO_free(bio);
- memwipe(s, 0, strlen(s));
- tor_free(s);
- return r;
-}
-
-/** Return true iff <b>env</b> has a valid key.
- */
-int
-crypto_pk_check_key(crypto_pk_t *env)
-{
- int r;
- tor_assert(env);
-
- r = RSA_check_key(env->key);
- if (r <= 0)
- crypto_log_errors(LOG_WARN,"checking RSA key");
- return r;
-}
-
-/** Return true iff <b>key</b> contains the private-key portion of the RSA
- * key. */
-int
-crypto_pk_key_is_private(const crypto_pk_t *key)
-{
- tor_assert(key);
- return crypto_pk_private_ok(key);
-}
-
-/** Return true iff <b>env</b> contains a public key whose public exponent
- * equals 65537.
- */
-int
-crypto_pk_public_exponent_ok(crypto_pk_t *env)
-{
- tor_assert(env);
- tor_assert(env->key);
-
- const BIGNUM *e;
-
-#ifdef OPENSSL_1_1_API
- const BIGNUM *n, *d;
- RSA_get0_key(env->key, &n, &e, &d);
-#else
- e = env->key->e;
-#endif /* defined(OPENSSL_1_1_API) */
- return BN_is_word(e, 65537);
-}
-
-/** 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(const crypto_pk_t *a, const 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;
-
- result = tor_memcmp(&a_is_non_null, &b_is_non_null, sizeof(a_is_non_null));
- if (an_argument_is_null)
- return result;
-
- const BIGNUM *a_n, *a_e;
- const BIGNUM *b_n, *b_e;
-
-#ifdef OPENSSL_1_1_API
- const BIGNUM *a_d, *b_d;
- RSA_get0_key(a->key, &a_n, &a_e, &a_d);
- RSA_get0_key(b->key, &b_n, &b_e, &b_d);
-#else
- a_n = a->key->n;
- a_e = a->key->e;
- b_n = b->key->n;
- b_e = b->key->e;
-#endif /* defined(OPENSSL_1_1_API) */
-
- tor_assert(a_n != NULL && a_e != NULL);
- tor_assert(b_n != NULL && b_e != NULL);
-
- result = BN_cmp(a_n, b_n);
- if (result)
- return result;
- return BN_cmp(a_e, b_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(const crypto_pk_t *a, const 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(const crypto_pk_t *env)
-{
- tor_assert(env);
- tor_assert(env->key);
-
- return (size_t) RSA_size((RSA*)env->key);
-}
-
-/** Return the size of the public key modulus of <b>env</b>, in bits. */
-int
-crypto_pk_num_bits(crypto_pk_t *env)
-{
- tor_assert(env);
- tor_assert(env->key);
-
-#ifdef OPENSSL_1_1_API
- /* It's so stupid that there's no other way to check that n is valid
- * before calling RSA_bits().
- */
- const BIGNUM *n, *e, *d;
- RSA_get0_key(env->key, &n, &e, &d);
- tor_assert(n != NULL);
-
- return RSA_bits(env->key);
-#else /* !(defined(OPENSSL_1_1_API)) */
- tor_assert(env->key->n);
- return BN_num_bits(env->key->n);
-#endif /* defined(OPENSSL_1_1_API) */
-}
-
-/** Increase the reference count of <b>env</b>, and return it.
- */
-crypto_pk_t *
-crypto_pk_dup_key(crypto_pk_t *env)
-{
- tor_assert(env);
- tor_assert(env->key);
-
- env->refs++;
- return env;
-}
-
-#ifdef TOR_UNIT_TESTS
-/** For testing: replace dest with src. (Dest must have a refcount
- * of 1) */
-void
-crypto_pk_assign_(crypto_pk_t *dest, const crypto_pk_t *src)
-{
- tor_assert(dest);
- tor_assert(dest->refs == 1);
- tor_assert(src);
- RSA_free(dest->key);
- dest->key = RSAPrivateKey_dup(src->key);
-}
-#endif /* defined(TOR_UNIT_TESTS) */
-
-/** Make a real honest-to-goodness copy of <b>env</b>, and return it.
- * Returns NULL on failure. */
-crypto_pk_t *
-crypto_pk_copy_full(crypto_pk_t *env)
-{
- RSA *new_key;
- int privatekey = 0;
- tor_assert(env);
- tor_assert(env->key);
-
- if (crypto_pk_private_ok(env)) {
- new_key = RSAPrivateKey_dup(env->key);
- privatekey = 1;
- } else {
- new_key = RSAPublicKey_dup(env->key);
- }
- if (!new_key) {
- /* LCOV_EXCL_START
- *
- * We can't cause RSA*Key_dup() to fail, so we can't really test this.
- */
- log_err(LD_CRYPTO, "Unable to duplicate a %s key: openssl failed.",
- privatekey?"private":"public");
- crypto_log_errors(LOG_ERR,
- privatekey ? "Duplicating a private key" :
- "Duplicating a public key");
- tor_fragile_assert();
- return NULL;
- /* LCOV_EXCL_STOP */
- }
-
- return crypto_new_pk_from_rsa_(new_key);
-}
-
-/** Perform a hybrid (public/secret) encryption on <b>fromlen</b>
- * bytes of data from <b>from</b>, with padding type 'padding',
- * storing the results on <b>to</b>.
- *
- * Returns the number of bytes written on success, -1 on failure.
- *
- * The encrypted data consists of:
- * - The source data, padded and encrypted with the public key, if the
- * padded source data is no longer than the public key, and <b>force</b>
- * is false, OR
- * - The beginning of the source data prefixed with a 16-byte symmetric key,
- * padded and encrypted with the public key; followed by the rest of
- * the source data encrypted in AES-CTR mode with the symmetric key.
- *
- * NOTE that this format does not authenticate the symmetrically encrypted
- * part of the data, and SHOULD NOT BE USED for new protocols.
- */
-int
-crypto_pk_obsolete_public_hybrid_encrypt(crypto_pk_t *env,
- char *to, size_t tolen,
- const char *from,
- size_t fromlen,
- int padding, int force)
-{
- int overhead, outlen, r;
- size_t pkeylen, symlen;
- crypto_cipher_t *cipher = NULL;
- char *buf = NULL;
-
- tor_assert(env);
- tor_assert(from);
- tor_assert(to);
- tor_assert(fromlen < SIZE_T_CEILING);
-
- overhead = crypto_get_rsa_padding_overhead(crypto_get_rsa_padding(padding));
- pkeylen = crypto_pk_keysize(env);
-
- if (!force && fromlen+overhead <= pkeylen) {
- /* It all fits in a single encrypt. */
- return crypto_pk_public_encrypt(env,to,
- tolen,
- from,fromlen,padding);
- }
- tor_assert(tolen >= fromlen + overhead + CIPHER_KEY_LEN);
- tor_assert(tolen >= pkeylen);
-
- char key[CIPHER_KEY_LEN];
- crypto_rand(key, sizeof(key)); /* generate a new key. */
- cipher = crypto_cipher_new(key);
-
- buf = tor_malloc(pkeylen+1);
- memcpy(buf, key, CIPHER_KEY_LEN);
- memcpy(buf+CIPHER_KEY_LEN, from, pkeylen-overhead-CIPHER_KEY_LEN);
-
- /* Length of symmetrically encrypted data. */
- symlen = fromlen-(pkeylen-overhead-CIPHER_KEY_LEN);
-
- outlen = crypto_pk_public_encrypt(env,to,tolen,buf,pkeylen-overhead,padding);
- if (outlen!=(int)pkeylen) {
- goto err;
- }
- r = crypto_cipher_encrypt(cipher, to+outlen,
- from+pkeylen-overhead-CIPHER_KEY_LEN, symlen);
-
- if (r<0) goto err;
- memwipe(buf, 0, pkeylen);
- memwipe(key, 0, sizeof(key));
- tor_free(buf);
- crypto_cipher_free(cipher);
- tor_assert(outlen+symlen < INT_MAX);
- return (int)(outlen + symlen);
- err:
-
- memwipe(buf, 0, pkeylen);
- memwipe(key, 0, sizeof(key));
- tor_free(buf);
- crypto_cipher_free(cipher);
- return -1;
-}
-
-/** Invert crypto_pk_obsolete_public_hybrid_encrypt. Returns the number of
- * bytes written on success, -1 on failure.
- *
- * NOTE that this format does not authenticate the symmetrically encrypted
- * part of the data, and SHOULD NOT BE USED for new protocols.
- */
-int
-crypto_pk_obsolete_private_hybrid_decrypt(crypto_pk_t *env,
- char *to,
- size_t tolen,
- const char *from,
- size_t fromlen,
- int padding, int warnOnFailure)
-{
- int outlen, r;
- size_t pkeylen;
- crypto_cipher_t *cipher = NULL;
- char *buf = NULL;
-
- tor_assert(fromlen < SIZE_T_CEILING);
- pkeylen = crypto_pk_keysize(env);
-
- if (fromlen <= pkeylen) {
- return crypto_pk_private_decrypt(env,to,tolen,from,fromlen,padding,
- warnOnFailure);
- }
-
- buf = tor_malloc(pkeylen);
- outlen = crypto_pk_private_decrypt(env,buf,pkeylen,from,pkeylen,padding,
- warnOnFailure);
- if (outlen<0) {
- log_fn(warnOnFailure?LOG_WARN:LOG_DEBUG, LD_CRYPTO,
- "Error decrypting public-key data");
- goto err;
- }
- if (outlen < CIPHER_KEY_LEN) {
- log_fn(warnOnFailure?LOG_WARN:LOG_INFO, LD_CRYPTO,
- "No room for a symmetric key");
- goto err;
- }
- cipher = crypto_cipher_new(buf);
- if (!cipher) {
- goto err;
- }
- memcpy(to,buf+CIPHER_KEY_LEN,outlen-CIPHER_KEY_LEN);
- outlen -= CIPHER_KEY_LEN;
- tor_assert(tolen - outlen >= fromlen - pkeylen);
- r = crypto_cipher_decrypt(cipher, to+outlen, from+pkeylen, fromlen-pkeylen);
- if (r<0)
- goto err;
- memwipe(buf,0,pkeylen);
- tor_free(buf);
- crypto_cipher_free(cipher);
- tor_assert(outlen + fromlen < INT_MAX);
- return (int)(outlen + (fromlen-pkeylen));
- err:
- memwipe(buf,0,pkeylen);
- tor_free(buf);
- crypto_cipher_free(cipher);
- return -1;
-}
-
-/** Encrypt <b>fromlen</b> bytes from <b>from</b> with the public key
- * in <b>env</b>, using the padding method <b>padding</b>. On success,
- * write the result to <b>to</b>, and return the number of bytes
- * written. On failure, return -1.
- *
- * <b>tolen</b> is the number of writable bytes in <b>to</b>, and must be
- * at least the length of the modulus of <b>env</b>.
- */
-int
-crypto_pk_public_encrypt(crypto_pk_t *env, char *to, size_t tolen,
- const char *from, size_t fromlen, int padding)
-{
- int r;
- tor_assert(env);
- tor_assert(from);
- tor_assert(to);
- tor_assert(fromlen<INT_MAX);
- tor_assert(tolen >= crypto_pk_keysize(env));
-
- r = RSA_public_encrypt((int)fromlen,
- (unsigned char*)from, (unsigned char*)to,
- env->key, crypto_get_rsa_padding(padding));
- if (r<0) {
- crypto_log_errors(LOG_WARN, "performing RSA encryption");
- return -1;
- }
- return r;
-}
-
-/** Decrypt <b>fromlen</b> bytes from <b>from</b> with the private key
- * in <b>env</b>, using the padding method <b>padding</b>. On success,
- * write the result to <b>to</b>, and return the number of bytes
- * written. On failure, return -1.
- *
- * <b>tolen</b> is the number of writable bytes in <b>to</b>, and must be
- * at least the length of the modulus of <b>env</b>.
- */
-int
-crypto_pk_private_decrypt(crypto_pk_t *env, char *to,
- size_t tolen,
- const char *from, size_t fromlen,
- int padding, int warnOnFailure)
-{
- int r;
- tor_assert(env);
- tor_assert(from);
- tor_assert(to);
- tor_assert(env->key);
- tor_assert(fromlen<INT_MAX);
- tor_assert(tolen >= crypto_pk_keysize(env));
- if (!crypto_pk_key_is_private(env))
- /* Not a private key */
- return -1;
-
- r = RSA_private_decrypt((int)fromlen,
- (unsigned char*)from, (unsigned char*)to,
- env->key, crypto_get_rsa_padding(padding));
-
- if (r<0) {
- crypto_log_errors(warnOnFailure?LOG_WARN:LOG_DEBUG,
- "performing RSA decryption");
- return -1;
- }
- return r;
-}
-
-/** Check the signature in <b>from</b> (<b>fromlen</b> bytes long) with the
- * public key in <b>env</b>, using PKCS1 padding. On success, write the
- * signed data to <b>to</b>, and return the number of bytes written.
- * On failure, return -1.
- *
- * <b>tolen</b> is the number of writable bytes in <b>to</b>, and must be
- * at least the length of the modulus of <b>env</b>.
- */
-MOCK_IMPL(int,
-crypto_pk_public_checksig,(const crypto_pk_t *env, char *to,
- size_t tolen,
- const char *from, size_t fromlen))
-{
- int r;
- tor_assert(env);
- tor_assert(from);
- tor_assert(to);
- tor_assert(fromlen < INT_MAX);
- tor_assert(tolen >= crypto_pk_keysize(env));
- r = RSA_public_decrypt((int)fromlen,
- (unsigned char*)from, (unsigned char*)to,
- env->key, RSA_PKCS1_PADDING);
-
- if (r<0) {
- crypto_log_errors(LOG_INFO, "checking RSA signature");
- return -1;
- }
- return r;
-}
-
-/** Sign <b>fromlen</b> bytes of data from <b>from</b> with the private key in
- * <b>env</b>, using PKCS1 padding. On success, write the signature to
- * <b>to</b>, and return the number of bytes written. On failure, return
- * -1.
- *
- * <b>tolen</b> is the number of writable bytes in <b>to</b>, and must be
- * at least the length of the modulus of <b>env</b>.
- */
-int
-crypto_pk_private_sign(const crypto_pk_t *env, char *to, size_t tolen,
- const char *from, size_t fromlen)
-{
- int r;
- tor_assert(env);
- tor_assert(from);
- tor_assert(to);
- tor_assert(fromlen < INT_MAX);
- tor_assert(tolen >= crypto_pk_keysize(env));
- if (!crypto_pk_key_is_private(env))
- /* Not a private key */
- return -1;
-
- r = RSA_private_encrypt((int)fromlen,
- (unsigned char*)from, (unsigned char*)to,
- (RSA*)env->key, RSA_PKCS1_PADDING);
- if (r<0) {
- crypto_log_errors(LOG_WARN, "generating RSA signature");
- return -1;
- }
- return r;
-}
-
-/** ASN.1-encode the public portion of <b>pk</b> into <b>dest</b>.
- * Return -1 on error, or the number of characters used on success.
- */
-int
-crypto_pk_asn1_encode(const crypto_pk_t *pk, char *dest, size_t dest_len)
-{
- int len;
- unsigned char *buf = NULL;
-
- len = i2d_RSAPublicKey(pk->key, &buf);
- if (len < 0 || buf == NULL)
- return -1;
-
- if ((size_t)len > dest_len || dest_len > SIZE_T_CEILING) {
- OPENSSL_free(buf);
- return -1;
- }
- /* We don't encode directly into 'dest', because that would be illegal
- * type-punning. (C99 is smarter than me, C99 is smarter than me...)
- */
- memcpy(dest,buf,len);
- OPENSSL_free(buf);
- return len;
-}
-
-/** Decode an ASN.1-encoded public key from <b>str</b>; return the result on
- * success and NULL on failure.
- */
-crypto_pk_t *
-crypto_pk_asn1_decode(const char *str, size_t len)
-{
- RSA *rsa;
- unsigned char *buf;
- const unsigned char *cp;
- cp = buf = tor_malloc(len);
- memcpy(buf,str,len);
- rsa = d2i_RSAPublicKey(NULL, &cp, len);
- tor_free(buf);
- if (!rsa) {
- crypto_log_errors(LOG_WARN,"decoding public key");
- return NULL;
- }
- return crypto_new_pk_from_rsa_(rsa);
-}
-
-/** Given a private or public key <b>pk</b>, put a fingerprint of the
- * public key into <b>fp_out</b> (must have at least FINGERPRINT_LEN+1 bytes of
- * space). Return 0 on success, -1 on failure.
- *
- * Fingerprints are computed as the SHA1 digest of the ASN.1 encoding
- * of the public key, converted to hexadecimal, in upper case, with a
- * space after every four digits.
- *
- * If <b>add_space</b> is false, omit the spaces.
- */
-int
-crypto_pk_get_fingerprint(crypto_pk_t *pk, char *fp_out, int add_space)
-{
- char digest[DIGEST_LEN];
- char hexdigest[HEX_DIGEST_LEN+1];
- if (crypto_pk_get_digest(pk, digest)) {
- return -1;
- }
- base16_encode(hexdigest,sizeof(hexdigest),digest,DIGEST_LEN);
- if (add_space) {
- crypto_add_spaces_to_fp(fp_out, FINGERPRINT_LEN+1, hexdigest);
- } else {
- strncpy(fp_out, hexdigest, HEX_DIGEST_LEN+1);
- }
- return 0;
-}
-
-/** Given a private or public key <b>pk</b>, put a hashed fingerprint of
- * the public key into <b>fp_out</b> (must have at least FINGERPRINT_LEN+1
- * bytes of space). Return 0 on success, -1 on failure.
- *
- * Hashed fingerprints are computed as the SHA1 digest of the SHA1 digest
- * of the ASN.1 encoding of the public key, converted to hexadecimal, in
- * upper case.
- */
-int
-crypto_pk_get_hashed_fingerprint(crypto_pk_t *pk, char *fp_out)
-{
- char digest[DIGEST_LEN], hashed_digest[DIGEST_LEN];
- if (crypto_pk_get_digest(pk, digest)) {
- return -1;
- }
- if (crypto_digest(hashed_digest, digest, DIGEST_LEN) < 0) {
- return -1;
- }
- base16_encode(fp_out, FINGERPRINT_LEN + 1, hashed_digest, DIGEST_LEN);
- return 0;
-}
-
-/** Check a siglen-byte long signature at <b>sig</b> against
- * <b>datalen</b> bytes of data at <b>data</b>, using the public key
- * in <b>env</b>. Return 0 if <b>sig</b> is a correct signature for
- * SHA1(data). Else return -1.
- */
-MOCK_IMPL(int,
-crypto_pk_public_checksig_digest,(crypto_pk_t *env, const char *data,
- size_t datalen, const char *sig,
- size_t siglen))
-{
- char digest[DIGEST_LEN];
- char *buf;
- size_t buflen;
- int r;
-
- tor_assert(env);
- tor_assert(data);
- tor_assert(sig);
- tor_assert(datalen < SIZE_T_CEILING);
- tor_assert(siglen < SIZE_T_CEILING);
-
- if (crypto_digest(digest,data,datalen)<0) {
- log_warn(LD_BUG, "couldn't compute digest");
- return -1;
- }
- buflen = crypto_pk_keysize(env);
- buf = tor_malloc(buflen);
- r = crypto_pk_public_checksig(env,buf,buflen,sig,siglen);
- if (r != DIGEST_LEN) {
- log_warn(LD_CRYPTO, "Invalid signature");
- tor_free(buf);
- return -1;
- }
- if (tor_memneq(buf, digest, DIGEST_LEN)) {
- log_warn(LD_CRYPTO, "Signature mismatched with digest.");
- tor_free(buf);
- return -1;
- }
- tor_free(buf);
-
- return 0;
-}
-
-/** Compute a SHA1 digest of <b>fromlen</b> bytes of data stored at
- * <b>from</b>; sign the data with the private key in <b>env</b>, and
- * store it in <b>to</b>. Return the number of bytes written on
- * success, and -1 on failure.
- *
- * <b>tolen</b> is the number of writable bytes in <b>to</b>, and must be
- * at least the length of the modulus of <b>env</b>.
- */
-int
-crypto_pk_private_sign_digest(crypto_pk_t *env, char *to, size_t tolen,
- const char *from, size_t fromlen)
-{
- int r;
- char digest[DIGEST_LEN];
- if (crypto_digest(digest,from,fromlen)<0)
- return -1;
- r = crypto_pk_private_sign(env,to,tolen,digest,DIGEST_LEN);
- memwipe(digest, 0, sizeof(digest));
- return r;
-}
-
-/** Given a private or public key <b>pk</b>, put a SHA1 hash of the
- * public key into <b>digest_out</b> (must have DIGEST_LEN bytes of space).
- * Return 0 on success, -1 on failure.
- */
-int
-crypto_pk_get_digest(const crypto_pk_t *pk, char *digest_out)
-{
- char *buf;
- size_t buflen;
- int len;
- int rv = -1;
-
- buflen = crypto_pk_keysize(pk)*2;
- buf = tor_malloc(buflen);
- len = crypto_pk_asn1_encode(pk, buf, buflen);
- if (len < 0)
- goto done;
-
- if (crypto_digest(digest_out, buf, len) < 0)
- goto done;
-
- rv = 0;
- done:
- tor_free(buf);
- return rv;
-}
-
-/** Compute all digests of the DER encoding of <b>pk</b>, and store them
- * in <b>digests_out</b>. Return 0 on success, -1 on failure. */
-int
-crypto_pk_get_common_digests(crypto_pk_t *pk, common_digests_t *digests_out)
-{
- char *buf;
- size_t buflen;
- int len;
- int rv = -1;
-
- buflen = crypto_pk_keysize(pk)*2;
- buf = tor_malloc(buflen);
- len = crypto_pk_asn1_encode(pk, buf, buflen);
- if (len < 0)
- goto done;
-
- if (crypto_common_digests(digests_out, (char*)buf, len) < 0)
- goto done;
-
- rv = 0;
- done:
- tor_free(buf);
- return rv;
-}
-
-/** Given a crypto_pk_t <b>pk</b>, allocate a new buffer containing the
- * Base64 encoding of the DER representation of the private key as a NUL
- * terminated string, and return it via <b>priv_out</b>. Return 0 on
- * success, -1 on failure.
- *
- * It is the caller's responsibility to sanitize and free the resulting buffer.
- */
-int
-crypto_pk_base64_encode(const crypto_pk_t *pk, char **priv_out)
-{
- unsigned char *der = NULL;
- int der_len;
- int ret = -1;
-
- *priv_out = NULL;
-
- der_len = i2d_RSAPrivateKey(pk->key, &der);
- if (der_len < 0 || der == NULL)
- return ret;
-
- size_t priv_len = base64_encode_size(der_len, 0) + 1;
- char *priv = tor_malloc_zero(priv_len);
- if (base64_encode(priv, priv_len, (char *)der, der_len, 0) >= 0) {
- *priv_out = priv;
- ret = 0;
- } else {
- tor_free(priv);
- }
-
- memwipe(der, 0, der_len);
- OPENSSL_free(der);
- return ret;
-}
-
-/** Given a string containing the Base64 encoded DER representation of the
- * private key <b>str</b>, decode and return the result on success, or NULL
- * on failure.
- */
-crypto_pk_t *
-crypto_pk_base64_decode(const char *str, size_t len)
-{
- crypto_pk_t *pk = NULL;
-
- char *der = tor_malloc_zero(len + 1);
- int der_len = base64_decode(der, len, str, len);
- if (der_len <= 0) {
- log_warn(LD_CRYPTO, "Stored RSA private key seems corrupted (base64).");
- goto out;
- }
-
- const unsigned char *dp = (unsigned char*)der; /* Shut the compiler up. */
- RSA *rsa = d2i_RSAPrivateKey(NULL, &dp, der_len);
- if (!rsa) {
- crypto_log_errors(LOG_WARN, "decoding private key");
- goto out;
- }
-
- pk = crypto_new_pk_from_rsa_(rsa);
-
- /* Make sure it's valid. */
- if (crypto_pk_check_key(pk) <= 0) {
- crypto_pk_free(pk);
- pk = NULL;
- goto out;
- }
-
- out:
- memwipe(der, 0, len + 1);
- tor_free(der);
- return pk;
-}
-
diff --git a/src/common/crypto_rsa.h b/src/common/crypto_rsa.h
deleted file mode 100644
index e952089318..0000000000
--- a/src/common/crypto_rsa.h
+++ /dev/null
@@ -1,119 +0,0 @@
-/* Copyright (c) 2001, Matej Pfajfar.
- * Copyright (c) 2001-2004, Roger Dingledine.
- * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2017, The Tor Project, Inc. */
-/* See LICENSE for licensing information */
-
-/**
- * \file crypto_rsa.h
- *
- * \brief Headers for crypto_rsa.c
- **/
-
-#ifndef TOR_CRYPTO_RSA_H
-#define TOR_CRYPTO_RSA_H
-
-#include "orconfig.h"
-
-#include "crypto_digest.h"
-#include <stdio.h>
-#include "torint.h"
-#include "testsupport.h"
-#include "compat.h"
-#include "util.h"
-#include "torlog.h"
-
-/** Length of our public keys. */
-#define PK_BYTES (1024/8)
-
-/** Constant used to indicate OAEP padding for public-key encryption */
-#define PK_PKCS1_OAEP_PADDING 60002
-
-/** Number of bytes added for PKCS1-OAEP padding. */
-#define PKCS1_OAEP_PADDING_OVERHEAD 42
-
-/** A public key, or a public/private key-pair. */
-typedef struct crypto_pk_t crypto_pk_t;
-
-/* RSA environment setup */
-MOCK_DECL(crypto_pk_t *,crypto_pk_new,(void));
-void crypto_pk_free_(crypto_pk_t *env);
-#define crypto_pk_free(pk) FREE_AND_NULL(crypto_pk_t, crypto_pk_free_, (pk))
-int crypto_get_rsa_padding_overhead(int padding);
-int crypto_get_rsa_padding(int padding);
-
-/* public key crypto */
-MOCK_DECL(int, crypto_pk_generate_key_with_bits,(crypto_pk_t *env, int bits));
-#define crypto_pk_generate_key(env) \
- crypto_pk_generate_key_with_bits((env), (PK_BYTES*8))
-
-int crypto_pk_read_private_key_from_filename(crypto_pk_t *env,
- const char *keyfile);
-int crypto_pk_write_public_key_to_string(crypto_pk_t *env,
- char **dest, size_t *len);
-int crypto_pk_write_private_key_to_string(crypto_pk_t *env,
- char **dest, size_t *len);
-int crypto_pk_read_public_key_from_string(crypto_pk_t *env,
- const char *src, size_t len);
-int crypto_pk_read_private_key_from_string(crypto_pk_t *env,
- const char *s, ssize_t len);
-int crypto_pk_write_private_key_to_filename(crypto_pk_t *env,
- const char *fname);
-
-int crypto_pk_check_key(crypto_pk_t *env);
-int crypto_pk_cmp_keys(const crypto_pk_t *a, const crypto_pk_t *b);
-int crypto_pk_eq_keys(const crypto_pk_t *a, const crypto_pk_t *b);
-size_t crypto_pk_keysize(const crypto_pk_t *env);
-int crypto_pk_num_bits(crypto_pk_t *env);
-crypto_pk_t *crypto_pk_dup_key(crypto_pk_t *orig);
-crypto_pk_t *crypto_pk_copy_full(crypto_pk_t *orig);
-int crypto_pk_key_is_private(const crypto_pk_t *key);
-int crypto_pk_public_exponent_ok(crypto_pk_t *env);
-int crypto_pk_obsolete_public_hybrid_encrypt(crypto_pk_t *env, char *to,
- size_t tolen,
- const char *from, size_t fromlen,
- int padding, int force);
-int crypto_pk_obsolete_private_hybrid_decrypt(crypto_pk_t *env, char *to,
- size_t tolen,
- const char *from, size_t fromlen,
- int padding, int warnOnFailure);
-int crypto_pk_public_encrypt(crypto_pk_t *env, char *to, size_t tolen,
- const char *from, size_t fromlen, int padding);
-int crypto_pk_private_decrypt(crypto_pk_t *env, char *to, size_t tolen,
- const char *from, size_t fromlen,
- int padding, int warnOnFailure);
-MOCK_DECL(int, crypto_pk_public_checksig,(const crypto_pk_t *env,
- char *to, size_t tolen,
- const char *from, size_t fromlen));
-int crypto_pk_private_sign(const crypto_pk_t *env, char *to, size_t tolen,
- const char *from, size_t fromlen);
-int crypto_pk_asn1_encode(const crypto_pk_t *pk, char *dest, size_t dest_len);
-crypto_pk_t *crypto_pk_asn1_decode(const char *str, size_t len);
-int crypto_pk_get_fingerprint(crypto_pk_t *pk, char *fp_out,int add_space);
-int crypto_pk_get_hashed_fingerprint(crypto_pk_t *pk, char *fp_out);
-
-MOCK_DECL(int, crypto_pk_public_checksig_digest,(crypto_pk_t *env,
- const char *data, size_t datalen, const char *sig, size_t siglen));
-int crypto_pk_private_sign_digest(crypto_pk_t *env, char *to, size_t tolen,
- const char *from, size_t fromlen);
-int crypto_pk_get_digest(const crypto_pk_t *pk, char *digest_out);
-int crypto_pk_get_common_digests(crypto_pk_t *pk,
- common_digests_t *digests_out);
-int crypto_pk_base64_encode(const crypto_pk_t *pk, char **priv_out);
-crypto_pk_t *crypto_pk_base64_decode(const char *str, size_t len);
-
-/* Prototypes for private functions only used by tortls.c, crypto.c, and the
- * unit tests. */
-struct rsa_st;
-struct rsa_st *crypto_pk_get_rsa_(crypto_pk_t *env);
-crypto_pk_t *crypto_new_pk_from_rsa_(struct rsa_st *rsa);
-MOCK_DECL(struct evp_pkey_st *, crypto_pk_get_evp_pkey_,(crypto_pk_t *env,
- int private));
-struct evp_pkey_st;
-
-#ifdef TOR_UNIT_TESTS
-void crypto_pk_assign_(crypto_pk_t *dest, const crypto_pk_t *src);
-#endif
-
-#endif
-
diff --git a/src/common/crypto_s2k.c b/src/common/crypto_s2k.c
deleted file mode 100644
index 8543760ec5..0000000000
--- a/src/common/crypto_s2k.c
+++ /dev/null
@@ -1,475 +0,0 @@
-/* Copyright (c) 2001, Matej Pfajfar.
- * Copyright (c) 2001-2004, Roger Dingledine.
- * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2017, The Tor Project, Inc. */
-/* See LICENSE for licensing information */
-
-/**
- * \file crypto_s2k.c
- *
- * \brief Functions for deriving keys from human-readable passphrases.
- */
-
-#define CRYPTO_S2K_PRIVATE
-
-#include "compat.h"
-#include "crypto.h"
-#include "crypto_digest.h"
-#include "crypto_rand.h"
-#include "crypto_s2k.h"
-#include "crypto_util.h"
-#include "util.h"
-
-#include <openssl/evp.h>
-
-#if defined(HAVE_LIBSCRYPT_H) && defined(HAVE_LIBSCRYPT_SCRYPT)
-#define HAVE_SCRYPT
-#include <libscrypt.h>
-#endif
-
-/* Encoded secrets take the form:
-
- u8 type;
- u8 salt_and_parameters[depends on type];
- u8 key[depends on type];
-
- As a special case, if the encoded secret is exactly 29 bytes long,
- type 0 is understood.
-
- Recognized types are:
- 00 -- RFC2440. salt_and_parameters is 9 bytes. key is 20 bytes.
- salt_and_parameters is 8 bytes random salt,
- 1 byte iteration info.
- 01 -- PKBDF2_SHA1. salt_and_parameters is 17 bytes. key is 20 bytes.
- salt_and_parameters is 16 bytes random salt,
- 1 byte iteration info.
- 02 -- SCRYPT_SALSA208_SHA256. salt_and_parameters is 18 bytes. key is
- 32 bytes.
- salt_and_parameters is 18 bytes random salt, 2 bytes iteration
- info.
-*/
-
-#define S2K_TYPE_RFC2440 0
-#define S2K_TYPE_PBKDF2 1
-#define S2K_TYPE_SCRYPT 2
-
-#define PBKDF2_SPEC_LEN 17
-#define PBKDF2_KEY_LEN 20
-
-#define SCRYPT_SPEC_LEN 18
-#define SCRYPT_KEY_LEN 32
-
-/** Given an algorithm ID (one of S2K_TYPE_*), return the length of the
- * specifier part of it, without the prefix type byte. Return -1 if it is not
- * a valid algorithm ID. */
-static int
-secret_to_key_spec_len(uint8_t type)
-{
- switch (type) {
- case S2K_TYPE_RFC2440:
- return S2K_RFC2440_SPECIFIER_LEN;
- case S2K_TYPE_PBKDF2:
- return PBKDF2_SPEC_LEN;
- case S2K_TYPE_SCRYPT:
- return SCRYPT_SPEC_LEN;
- default:
- return -1;
- }
-}
-
-/** Given an algorithm ID (one of S2K_TYPE_*), return the length of the
- * its preferred output. */
-static int
-secret_to_key_key_len(uint8_t type)
-{
- switch (type) {
- case S2K_TYPE_RFC2440:
- return DIGEST_LEN;
- case S2K_TYPE_PBKDF2:
- return DIGEST_LEN;
- case S2K_TYPE_SCRYPT:
- return DIGEST256_LEN;
- // LCOV_EXCL_START
- default:
- tor_fragile_assert();
- return -1;
- // LCOV_EXCL_STOP
- }
-}
-
-/** Given a specifier in <b>spec_and_key</b> of length
- * <b>spec_and_key_len</b>, along with its prefix algorithm ID byte, and along
- * with a key if <b>key_included</b> is true, check whether the whole
- * specifier-and-key is of valid length, and return the algorithm type if it
- * is. Set *<b>legacy_out</b> to 1 iff this is a legacy password hash or
- * legacy specifier. Return an error code on failure.
- */
-static int
-secret_to_key_get_type(const uint8_t *spec_and_key, size_t spec_and_key_len,
- int key_included, int *legacy_out)
-{
- size_t legacy_len = S2K_RFC2440_SPECIFIER_LEN;
- uint8_t type;
- int total_len;
-
- if (key_included)
- legacy_len += DIGEST_LEN;
-
- if (spec_and_key_len == legacy_len) {
- *legacy_out = 1;
- return S2K_TYPE_RFC2440;
- }
-
- *legacy_out = 0;
- if (spec_and_key_len == 0)
- return S2K_BAD_LEN;
-
- type = spec_and_key[0];
- total_len = secret_to_key_spec_len(type);
- if (total_len < 0)
- return S2K_BAD_ALGORITHM;
- if (key_included) {
- int keylen = secret_to_key_key_len(type);
- if (keylen < 0)
- return S2K_BAD_ALGORITHM;
- total_len += keylen;
- }
-
- if ((size_t)total_len + 1 == spec_and_key_len)
- return type;
- else
- return S2K_BAD_LEN;
-}
-
-/**
- * Write a new random s2k specifier of type <b>type</b>, without prefixing
- * type byte, to <b>spec_out</b>, which must have enough room. May adjust
- * parameter choice based on <b>flags</b>.
- */
-static int
-make_specifier(uint8_t *spec_out, uint8_t type, unsigned flags)
-{
- int speclen = secret_to_key_spec_len(type);
- if (speclen < 0)
- return S2K_BAD_ALGORITHM;
-
- crypto_rand((char*)spec_out, speclen);
- switch (type) {
- case S2K_TYPE_RFC2440:
- /* Hash 64 k of data. */
- spec_out[S2K_RFC2440_SPECIFIER_LEN-1] = 96;
- break;
- case S2K_TYPE_PBKDF2:
- /* 131 K iterations */
- spec_out[PBKDF2_SPEC_LEN-1] = 17;
- break;
- case S2K_TYPE_SCRYPT:
- if (flags & S2K_FLAG_LOW_MEM) {
- /* N = 1<<12 */
- spec_out[SCRYPT_SPEC_LEN-2] = 12;
- } else {
- /* N = 1<<15 */
- spec_out[SCRYPT_SPEC_LEN-2] = 15;
- }
- /* r = 8; p = 2. */
- spec_out[SCRYPT_SPEC_LEN-1] = (3u << 4) | (1u << 0);
- break;
- // LCOV_EXCL_START - we should have returned above.
- default:
- tor_fragile_assert();
- return S2K_BAD_ALGORITHM;
- // LCOV_EXCL_STOP
- }
-
- return speclen;
-}
-
-/** Implement RFC2440-style iterated-salted S2K conversion: convert the
- * <b>secret_len</b>-byte <b>secret</b> into a <b>key_out_len</b> byte
- * <b>key_out</b>. As in RFC2440, the first 8 bytes of s2k_specifier
- * are a salt; the 9th byte describes how much iteration to do.
- * If <b>key_out_len</b> &gt; DIGEST_LEN, use HDKF to expand the result.
- */
-void
-secret_to_key_rfc2440(char *key_out, size_t key_out_len, const char *secret,
- size_t secret_len, const char *s2k_specifier)
-{
- crypto_digest_t *d;
- uint8_t c;
- size_t count, tmplen;
- char *tmp;
- uint8_t buf[DIGEST_LEN];
- tor_assert(key_out_len < SIZE_T_CEILING);
-
-#define EXPBIAS 6
- c = s2k_specifier[8];
- count = ((uint32_t)16 + (c & 15)) << ((c >> 4) + EXPBIAS);
-#undef EXPBIAS
-
- d = crypto_digest_new();
- tmplen = 8+secret_len;
- tmp = tor_malloc(tmplen);
- memcpy(tmp,s2k_specifier,8);
- memcpy(tmp+8,secret,secret_len);
- secret_len += 8;
- while (count) {
- if (count >= secret_len) {
- crypto_digest_add_bytes(d, tmp, secret_len);
- count -= secret_len;
- } else {
- crypto_digest_add_bytes(d, tmp, count);
- count = 0;
- }
- }
- crypto_digest_get_digest(d, (char*)buf, sizeof(buf));
-
- if (key_out_len <= sizeof(buf)) {
- memcpy(key_out, buf, key_out_len);
- } else {
- crypto_expand_key_material_rfc5869_sha256(buf, DIGEST_LEN,
- (const uint8_t*)s2k_specifier, 8,
- (const uint8_t*)"EXPAND", 6,
- (uint8_t*)key_out, key_out_len);
- }
- memwipe(tmp, 0, tmplen);
- memwipe(buf, 0, sizeof(buf));
- tor_free(tmp);
- crypto_digest_free(d);
-}
-
-/**
- * Helper: given a valid specifier without prefix type byte in <b>spec</b>,
- * whose length must be correct, and given a secret passphrase <b>secret</b>
- * of length <b>secret_len</b>, compute the key and store it into
- * <b>key_out</b>, which must have enough room for secret_to_key_key_len(type)
- * bytes. Return the number of bytes written on success and an error code
- * on failure.
- */
-STATIC int
-secret_to_key_compute_key(uint8_t *key_out, size_t key_out_len,
- const uint8_t *spec, size_t spec_len,
- const char *secret, size_t secret_len,
- int type)
-{
- int rv;
- if (key_out_len > INT_MAX)
- return S2K_BAD_LEN;
-
- switch (type) {
- case S2K_TYPE_RFC2440:
- secret_to_key_rfc2440((char*)key_out, key_out_len, secret, secret_len,
- (const char*)spec);
- return (int)key_out_len;
-
- case S2K_TYPE_PBKDF2: {
- uint8_t log_iters;
- if (spec_len < 1 || secret_len > INT_MAX || spec_len > INT_MAX)
- return S2K_BAD_LEN;
- log_iters = spec[spec_len-1];
- if (log_iters > 31)
- return S2K_BAD_PARAMS;
- rv = PKCS5_PBKDF2_HMAC_SHA1(secret, (int)secret_len,
- spec, (int)spec_len-1,
- (1<<log_iters),
- (int)key_out_len, key_out);
- if (rv < 0)
- return S2K_FAILED;
- return (int)key_out_len;
- }
-
- case S2K_TYPE_SCRYPT: {
-#ifdef HAVE_SCRYPT
- uint8_t log_N, log_r, log_p;
- uint64_t N;
- uint32_t r, p;
- if (spec_len < 2)
- return S2K_BAD_LEN;
- log_N = spec[spec_len-2];
- log_r = (spec[spec_len-1]) >> 4;
- log_p = (spec[spec_len-1]) & 15;
- if (log_N > 63)
- return S2K_BAD_PARAMS;
- N = ((uint64_t)1) << log_N;
- r = 1u << log_r;
- p = 1u << log_p;
- rv = libscrypt_scrypt((const uint8_t*)secret, secret_len,
- spec, spec_len-2, N, r, p, key_out, key_out_len);
- if (rv != 0)
- return S2K_FAILED;
- return (int)key_out_len;
-#else /* !(defined(HAVE_SCRYPT)) */
- return S2K_NO_SCRYPT_SUPPORT;
-#endif /* defined(HAVE_SCRYPT) */
- }
- default:
- return S2K_BAD_ALGORITHM;
- }
-}
-
-/**
- * Given a specifier previously constructed with secret_to_key_make_specifier
- * in <b>spec</b> of length <b>spec_len</b>, and a secret password in
- * <b>secret</b> of length <b>secret_len</b>, generate <b>key_out_len</b>
- * bytes of cryptographic material in <b>key_out</b>. The native output of
- * the secret-to-key function will be truncated if key_out_len is short, and
- * expanded with HKDF if key_out_len is long. Returns S2K_OKAY on success,
- * and an error code on failure.
- */
-int
-secret_to_key_derivekey(uint8_t *key_out, size_t key_out_len,
- const uint8_t *spec, size_t spec_len,
- const char *secret, size_t secret_len)
-{
- int legacy_format = 0;
- int type = secret_to_key_get_type(spec, spec_len, 0, &legacy_format);
- int r;
-
- if (type < 0)
- return type;
-#ifndef HAVE_SCRYPT
- if (type == S2K_TYPE_SCRYPT)
- return S2K_NO_SCRYPT_SUPPORT;
- #endif
-
- if (! legacy_format) {
- ++spec;
- --spec_len;
- }
-
- r = secret_to_key_compute_key(key_out, key_out_len, spec, spec_len,
- secret, secret_len, type);
- if (r < 0)
- return r;
- else
- return S2K_OKAY;
-}
-
-/**
- * Construct a new s2k algorithm specifier and salt in <b>buf</b>, according
- * to the bitwise-or of some S2K_FLAG_* options in <b>flags</b>. Up to
- * <b>buf_len</b> bytes of storage may be used in <b>buf</b>. Return the
- * number of bytes used on success and an error code on failure.
- */
-int
-secret_to_key_make_specifier(uint8_t *buf, size_t buf_len, unsigned flags)
-{
- int rv;
- int spec_len;
-#ifdef HAVE_SCRYPT
- uint8_t type = S2K_TYPE_SCRYPT;
-#else
- uint8_t type = S2K_TYPE_RFC2440;
-#endif
-
- if (flags & S2K_FLAG_NO_SCRYPT)
- type = S2K_TYPE_RFC2440;
- if (flags & S2K_FLAG_USE_PBKDF2)
- type = S2K_TYPE_PBKDF2;
-
- spec_len = secret_to_key_spec_len(type);
-
- if ((int)buf_len < spec_len + 1)
- return S2K_TRUNCATED;
-
- buf[0] = type;
- rv = make_specifier(buf+1, type, flags);
- if (rv < 0)
- return rv;
- else
- return rv + 1;
-}
-
-/**
- * Hash a passphrase from <b>secret</b> of length <b>secret_len</b>, according
- * to the bitwise-or of some S2K_FLAG_* options in <b>flags</b>, and store the
- * hash along with salt and hashing parameters into <b>buf</b>. Up to
- * <b>buf_len</b> bytes of storage may be used in <b>buf</b>. Set
- * *<b>len_out</b> to the number of bytes used and return S2K_OKAY on success;
- * and return an error code on failure.
- */
-int
-secret_to_key_new(uint8_t *buf,
- size_t buf_len,
- size_t *len_out,
- const char *secret, size_t secret_len,
- unsigned flags)
-{
- int key_len;
- int spec_len;
- int type;
- int rv;
-
- spec_len = secret_to_key_make_specifier(buf, buf_len, flags);
-
- if (spec_len < 0)
- return spec_len;
-
- type = buf[0];
- key_len = secret_to_key_key_len(type);
-
- if (key_len < 0)
- return key_len;
-
- if ((int)buf_len < key_len + spec_len)
- return S2K_TRUNCATED;
-
- rv = secret_to_key_compute_key(buf + spec_len, key_len,
- buf + 1, spec_len-1,
- secret, secret_len, type);
- if (rv < 0)
- return rv;
-
- *len_out = spec_len + key_len;
-
- return S2K_OKAY;
-}
-
-/**
- * Given a hashed passphrase in <b>spec_and_key</b> of length
- * <b>spec_and_key_len</b> as generated by secret_to_key_new(), verify whether
- * it is a hash of the passphrase <b>secret</b> of length <b>secret_len</b>.
- * Return S2K_OKAY on a match, S2K_BAD_SECRET on a well-formed hash that
- * doesn't match this secret, and another error code on other errors.
- */
-int
-secret_to_key_check(const uint8_t *spec_and_key, size_t spec_and_key_len,
- const char *secret, size_t secret_len)
-{
- int is_legacy = 0;
- int type = secret_to_key_get_type(spec_and_key, spec_and_key_len,
- 1, &is_legacy);
- uint8_t buf[32];
- int spec_len;
- int key_len;
- int rv;
-
- if (type < 0)
- return type;
-
- if (! is_legacy) {
- spec_and_key++;
- spec_and_key_len--;
- }
-
- spec_len = secret_to_key_spec_len(type);
- key_len = secret_to_key_key_len(type);
- tor_assert(spec_len > 0);
- tor_assert(key_len > 0);
- tor_assert(key_len <= (int) sizeof(buf));
- tor_assert((int)spec_and_key_len == spec_len + key_len);
- rv = secret_to_key_compute_key(buf, key_len,
- spec_and_key, spec_len,
- secret, secret_len, type);
- if (rv < 0)
- goto done;
-
- if (tor_memeq(buf, spec_and_key + spec_len, key_len))
- rv = S2K_OKAY;
- else
- rv = S2K_BAD_SECRET;
-
- done:
- memwipe(buf, 0, sizeof(buf));
- return rv;
-}
-
diff --git a/src/common/crypto_s2k.h b/src/common/crypto_s2k.h
deleted file mode 100644
index 849ff59ce8..0000000000
--- a/src/common/crypto_s2k.h
+++ /dev/null
@@ -1,73 +0,0 @@
-/* Copyright (c) 2001, Matej Pfajfar.
- * Copyright (c) 2001-2004, Roger Dingledine.
- * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2017, The Tor Project, Inc. */
-/* See LICENSE for licensing information */
-
-#ifndef TOR_CRYPTO_S2K_H_INCLUDED
-#define TOR_CRYPTO_S2K_H_INCLUDED
-
-#include <stdio.h>
-#include "torint.h"
-
-/** Length of RFC2440-style S2K specifier: the first 8 bytes are a salt, the
- * 9th describes how much iteration to do. */
-#define S2K_RFC2440_SPECIFIER_LEN 9
-void secret_to_key_rfc2440(
- char *key_out, size_t key_out_len, const char *secret,
- size_t secret_len, const char *s2k_specifier);
-
-/** Flag for secret-to-key function: do not use scrypt. */
-#define S2K_FLAG_NO_SCRYPT (1u<<0)
-/** Flag for secret-to-key functions: if using a memory-tuned s2k function,
- * assume that we have limited memory. */
-#define S2K_FLAG_LOW_MEM (1u<<1)
-/** Flag for secret-to-key functions: force use of pbkdf2. Without this, we
- * default to scrypt, then RFC2440. */
-#define S2K_FLAG_USE_PBKDF2 (1u<<2)
-
-/** Maximum possible output length from secret_to_key_new. */
-#define S2K_MAXLEN 64
-
-/** Error code from secret-to-key functions: all is well */
-#define S2K_OKAY 0
-/** Error code from secret-to-key functions: generic failure */
-#define S2K_FAILED -1
-/** Error code from secret-to-key functions: provided secret didn't match */
-#define S2K_BAD_SECRET -2
-/** Error code from secret-to-key functions: didn't recognize the algorithm */
-#define S2K_BAD_ALGORITHM -3
-/** Error code from secret-to-key functions: specifier wasn't valid */
-#define S2K_BAD_PARAMS -4
-/** Error code from secret-to-key functions: compiled without scrypt */
-#define S2K_NO_SCRYPT_SUPPORT -5
-/** Error code from secret-to-key functions: not enough space to write output.
- */
-#define S2K_TRUNCATED -6
-/** Error code from secret-to-key functions: Wrong length for specifier. */
-#define S2K_BAD_LEN -7
-
-int secret_to_key_new(uint8_t *buf,
- size_t buf_len,
- size_t *len_out,
- const char *secret, size_t secret_len,
- unsigned flags);
-
-int secret_to_key_make_specifier(uint8_t *buf, size_t buf_len, unsigned flags);
-
-int secret_to_key_check(const uint8_t *spec_and_key, size_t spec_and_key_len,
- const char *secret, size_t secret_len);
-
-int secret_to_key_derivekey(uint8_t *key_out, size_t key_out_len,
- const uint8_t *spec, size_t spec_len,
- const char *secret, size_t secret_len);
-
-#ifdef CRYPTO_S2K_PRIVATE
-STATIC int secret_to_key_compute_key(uint8_t *key_out, size_t key_out_len,
- const uint8_t *spec, size_t spec_len,
- const char *secret, size_t secret_len,
- int type);
-#endif /* defined(CRYPTO_S2K_PRIVATE) */
-
-#endif /* !defined(TOR_CRYPTO_S2K_H_INCLUDED) */
-
diff --git a/src/common/crypto_util.c b/src/common/crypto_util.c
deleted file mode 100644
index b0d5b6b2f7..0000000000
--- a/src/common/crypto_util.c
+++ /dev/null
@@ -1,107 +0,0 @@
-/* Copyright (c) 2001, Matej Pfajfar.
- * Copyright (c) 2001-2004, Roger Dingledine.
- * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2018, The Tor Project, Inc. */
-/* See LICENSE for licensing information */
-
-/**
- * \file crypto_util.c
- *
- * \brief Common cryptographic utilities.
- **/
-
-#ifndef CRYPTO_UTIL_PRIVATE
-#define CRYPTO_UTIL_PRIVATE
-
-#include "crypto_util.h"
-
-#include <string.h>
-
-#ifdef _WIN32
-#include <winsock2.h>
-#include <windows.h>
-#include <wincrypt.h>
-#endif /* defined(_WIN32) */
-
-#include "util.h"
-
-DISABLE_GCC_WARNING(redundant-decls)
-
-#include <openssl/crypto.h>
-
-ENABLE_GCC_WARNING(redundant-decls)
-
-/**
- * Destroy the <b>sz</b> bytes of data stored at <b>mem</b>, setting them to
- * the value <b>byte</b>.
- * If <b>mem</b> is NULL or <b>sz</b> is zero, nothing happens.
- *
- * This function is preferable to memset, since many compilers will happily
- * optimize out memset() when they can convince themselves that the data being
- * cleared will never be read.
- *
- * Right now, our convention is to use this function when we are wiping data
- * that's about to become inaccessible, such as stack buffers that are about
- * to go out of scope or structures that are about to get freed. (In
- * practice, it appears that the compilers we're currently using will optimize
- * out the memset()s for stack-allocated buffers, but not those for
- * about-to-be-freed structures. That could change, though, so we're being
- * wary.) If there are live reads for the data, then you can just use
- * memset().
- */
-void
-memwipe(void *mem, uint8_t byte, size_t sz)
-{
- if (sz == 0) {
- return;
- }
- /* If sz is nonzero, then mem must not be NULL. */
- tor_assert(mem != NULL);
-
- /* Data this large is likely to be an underflow. */
- tor_assert(sz < SIZE_T_CEILING);
-
- /* Because whole-program-optimization exists, we may not be able to just
- * have this function call "memset". A smart compiler could inline it, then
- * eliminate dead memsets, and declare itself to be clever. */
-
-#if defined(SecureZeroMemory) || defined(HAVE_SECUREZEROMEMORY)
- /* Here's what you do on windows. */
- SecureZeroMemory(mem,sz);
-#elif defined(HAVE_RTLSECUREZEROMEMORY)
- RtlSecureZeroMemory(mem,sz);
-#elif defined(HAVE_EXPLICIT_BZERO)
- /* The BSDs provide this. */
- explicit_bzero(mem, sz);
-#elif defined(HAVE_MEMSET_S)
- /* This is in the C99 standard. */
- memset_s(mem, sz, 0, sz);
-#else
- /* This is a slow and ugly function from OpenSSL that fills 'mem' with junk
- * based on the pointer value, then uses that junk to update a global
- * variable. It's an elaborate ruse to trick the compiler into not
- * optimizing out the "wipe this memory" code. Read it if you like zany
- * programming tricks! In later versions of Tor, we should look for better
- * not-optimized-out memory wiping stuff...
- *
- * ...or maybe not. In practice, there are pure-asm implementations of
- * OPENSSL_cleanse() on most platforms, which ought to do the job.
- **/
-
- OPENSSL_cleanse(mem, sz);
-#endif /* defined(SecureZeroMemory) || defined(HAVE_SECUREZEROMEMORY) || ... */
-
- /* Just in case some caller of memwipe() is relying on getting a buffer
- * filled with a particular value, fill the buffer.
- *
- * If this function gets inlined, this memset might get eliminated, but
- * that's okay: We only care about this particular memset in the case where
- * the caller should have been using memset(), and the memset() wouldn't get
- * eliminated. In other words, this is here so that we won't break anything
- * if somebody accidentally calls memwipe() instead of memset().
- **/
- memset(mem, byte, sz);
-}
-
-#endif /* !defined(CRYPTO_UTIL_PRIVATE) */
-
diff --git a/src/common/crypto_util.h b/src/common/crypto_util.h
deleted file mode 100644
index 922942b371..0000000000
--- a/src/common/crypto_util.h
+++ /dev/null
@@ -1,27 +0,0 @@
-/* Copyright (c) 2001, Matej Pfajfar.
- * Copyright (c) 2001-2004, Roger Dingledine.
- * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2018, The Tor Project, Inc. */
-/* See LICENSE for licensing information */
-
-/**
- * \file crypto_util.h
- *
- * \brief Common functions for cryptographic routines.
- **/
-
-#ifndef TOR_CRYPTO_UTIL_H
-#define TOR_CRYPTO_UTIL_H
-
-#include "torint.h"
-
-/** OpenSSL-based utility functions. */
-void memwipe(void *mem, uint8_t byte, size_t sz);
-
-#ifdef CRYPTO_UTIL_PRIVATE
-#ifdef TOR_UNIT_TESTS
-#endif /* defined(TOR_UNIT_TESTS) */
-#endif /* defined(CRYPTO_UTIL_PRIVATE) */
-
-#endif /* !defined(TOR_CRYPTO_UTIL_H) */
-
diff --git a/src/common/di_ops.c b/src/common/di_ops.c
deleted file mode 100644
index 90e9357c8e..0000000000
--- a/src/common/di_ops.c
+++ /dev/null
@@ -1,274 +0,0 @@
-/* Copyright (c) 2011-2017, The Tor Project, Inc. */
-/* See LICENSE for licensing information */
-
-/**
- * \file di_ops.c
- * \brief Functions for data-independent operations.
- **/
-
-#include "orconfig.h"
-#include "di_ops.h"
-#include "torlog.h"
-#include "util.h"
-
-/**
- * Timing-safe version of memcmp. As memcmp, compare the <b>sz</b> bytes at
- * <b>a</b> with the <b>sz</b> bytes at <b>b</b>, and return less than 0 if
- * the bytes at <b>a</b> lexically precede those at <b>b</b>, 0 if the byte
- * ranges are equal, and greater than zero if the bytes at <b>a</b> lexically
- * follow those at <b>b</b>.
- *
- * This implementation differs from memcmp in that its timing behavior is not
- * data-dependent: it should return in the same amount of time regardless of
- * the contents of <b>a</b> and <b>b</b>.
- */
-int
-tor_memcmp(const void *a, const void *b, size_t len)
-{
-#ifdef HAVE_TIMINGSAFE_MEMCMP
- return timingsafe_memcmp(a, b, len);
-#else
- const uint8_t *x = a;
- const uint8_t *y = b;
- size_t i = len;
- int retval = 0;
-
- /* This loop goes from the end of the arrays to the start. At the
- * start of every iteration, before we decrement i, we have set
- * "retval" equal to the result of memcmp(a+i,b+i,len-i). During the
- * loop, we update retval by leaving it unchanged if x[i]==y[i] and
- * setting it to x[i]-y[i] if x[i]!= y[i].
- *
- * The following assumes we are on a system with two's-complement
- * arithmetic. We check for this at configure-time with the check
- * that sets USING_TWOS_COMPLEMENT. If we aren't two's complement, then
- * torint.h will stop compilation with an error.
- */
- while (i--) {
- int v1 = x[i];
- int v2 = y[i];
- int equal_p = v1 ^ v2;
-
- /* The following sets bits 8 and above of equal_p to 'equal_p ==
- * 0', and thus to v1 == v2. (To see this, note that if v1 ==
- * v2, then v1^v2 == equal_p == 0, so equal_p-1 == -1, which is the
- * same as ~0 on a two's-complement machine. Then note that if
- * v1 != v2, then 0 < v1 ^ v2 < 256, so 0 <= equal_p - 1 < 255.)
- */
- --equal_p;
-
- equal_p >>= 8;
- /* Thanks to (sign-preserving) arithmetic shift, equal_p is now
- * equal to -(v1 == v2), which is exactly what we need below.
- * (Since we're assuming two's-complement arithmetic, -1 is the
- * same as ~0 (all bits set).)
- *
- * (The result of an arithmetic shift on a negative value is
- * actually implementation-defined in standard C. So how do we
- * get away with assuming it? Easy. We check.) */
-#if ((-60 >> 8) != -1)
-#error "According to cpp, right-shift doesn't perform sign-extension."
-#endif
-#ifndef RSHIFT_DOES_SIGN_EXTEND
-#error "According to configure, right-shift doesn't perform sign-extension."
-#endif
-
- /* If v1 == v2, equal_p is ~0, so this will leave retval
- * unchanged; otherwise, equal_p is 0, so this will zero it. */
- retval &= equal_p;
-
- /* If v1 == v2, then this adds 0, and leaves retval unchanged.
- * Otherwise, we just zeroed retval, so this sets it to v1 - v2. */
- retval += (v1 - v2);
-
- /* There. Now retval is equal to its previous value if v1 == v2, and
- * equal to v1 - v2 if v1 != v2. */
- }
-
- return retval;
-#endif /* defined(HAVE_TIMINGSAFE_MEMCMP) */
-}
-
-/**
- * Timing-safe memory comparison. Return true if the <b>sz</b> bytes at
- * <b>a</b> are the same as the <b>sz</b> bytes at <b>b</b>, and 0 otherwise.
- *
- * This implementation differs from !memcmp(a,b,sz) in that its timing
- * behavior is not data-dependent: it should return in the same amount of time
- * regardless of the contents of <b>a</b> and <b>b</b>. It differs from
- * !tor_memcmp(a,b,sz) by being faster.
- */
-int
-tor_memeq(const void *a, const void *b, size_t sz)
-{
- /* Treat a and b as byte ranges. */
- const uint8_t *ba = a, *bb = b;
- uint32_t any_difference = 0;
- while (sz--) {
- /* Set byte_diff to all of those bits that are different in *ba and *bb,
- * and advance both ba and bb. */
- const uint8_t byte_diff = *ba++ ^ *bb++;
-
- /* Set bits in any_difference if they are set in byte_diff. */
- any_difference |= byte_diff;
- }
-
- /* Now any_difference is 0 if there are no bits different between
- * a and b, and is nonzero if there are bits different between a
- * and b. Now for paranoia's sake, let's convert it to 0 or 1.
- *
- * (If we say "!any_difference", the compiler might get smart enough
- * to optimize-out our data-independence stuff above.)
- *
- * To unpack:
- *
- * If any_difference == 0:
- * any_difference - 1 == ~0
- * (any_difference - 1) >> 8 == 0x00ffffff
- * 1 & ((any_difference - 1) >> 8) == 1
- *
- * If any_difference != 0:
- * 0 < any_difference < 256, so
- * 0 <= any_difference - 1 < 255
- * (any_difference - 1) >> 8 == 0
- * 1 & ((any_difference - 1) >> 8) == 0
- */
-
- /*coverity[overflow]*/
- return 1 & ((any_difference - 1) >> 8);
-}
-
-/* Implement di_digest256_map_t as a linked list of entries. */
-struct di_digest256_map_t {
- struct di_digest256_map_t *next;
- uint8_t key[32];
- void *val;
-};
-
-/** Release all storage held in <b>map</b>, calling free_fn on each value
- * as we go. */
-void
-dimap_free_(di_digest256_map_t *map, dimap_free_fn free_fn)
-{
- while (map) {
- di_digest256_map_t *victim = map;
- map = map->next;
- if (free_fn)
- free_fn(victim->val);
- tor_free(victim);
- }
-}
-
-/** Adjust the map at *<b>map</b>, adding an entry for <b>key</b> ->
- * <b>val</b>, where <b>key</b> is a DIGEST256_LEN-byte key.
- *
- * The caller MUST NOT add a key that already appears in the map.
- */
-void
-dimap_add_entry(di_digest256_map_t **map,
- const uint8_t *key, void *val)
-{
- di_digest256_map_t *new_ent;
- {
- void *old_val = dimap_search(*map, key, NULL);
- tor_assert(! old_val);
- tor_assert(val);
- }
- new_ent = tor_malloc_zero(sizeof(di_digest256_map_t));
- new_ent->next = *map;
- memcpy(new_ent->key, key, 32);
- new_ent->val = val;
- *map = new_ent;
-}
-
-/** Search the map at <b>map</b> for an entry whose key is <b>key</b> (a
- * DIGEST256_LEN-byte key) returning the corresponding value if we found one,
- * and returning <b>dflt_val</b> if the key wasn't found.
- *
- * This operation takes an amount of time dependent only on the length of
- * <b>map</b>, not on the position or presence of <b>key</b> within <b>map</b>.
- */
-void *
-dimap_search(const di_digest256_map_t *map, const uint8_t *key,
- void *dflt_val)
-{
- uintptr_t result = (uintptr_t)dflt_val;
-
- while (map) {
- uintptr_t r = (uintptr_t) tor_memeq(map->key, key, 32);
- r -= 1; /* Now r is (uintptr_t)-1 if memeq returned false, and
- * 0 if memeq returned true. */
-
- result &= r;
- result |= ((uintptr_t)(map->val)) & ~r;
-
- map = map->next;
- }
-
- return (void *)result;
-}
-
-/**
- * Return true iff the <b>sz</b> bytes at <b>mem</b> are all zero. Runs in
- * time independent of the contents of <b>mem</b>.
- */
-int
-safe_mem_is_zero(const void *mem, size_t sz)
-{
- uint32_t total = 0;
- const uint8_t *ptr = mem;
-
- while (sz--) {
- total |= *ptr++;
- }
-
- /*coverity[overflow]*/
- return 1 & ((total - 1) >> 8);
-}
-
-/** Time-invariant 64-bit greater-than; works on two integers in the range
- * (0,INT64_MAX). */
-#if SIZEOF_VOID_P == 8
-#define gt_i64_timei(a,b) ((a) > (b))
-#else
-static inline int
-gt_i64_timei(uint64_t a, uint64_t b)
-{
- int64_t diff = (int64_t) (b - a);
- int res = diff >> 63;
- return res & 1;
-}
-#endif /* SIZEOF_VOID_P == 8 */
-
-/**
- * Given an array of list of <b>n_entries</b> uint64_t values, whose sum is
- * <b>total</b>, find the first i such that the total of all elements 0...i is
- * greater than rand_val.
- *
- * Try to perform this operation in a constant-time way.
- */
-int
-select_array_member_cumulative_timei(const uint64_t *entries, int n_entries,
- uint64_t total, uint64_t rand_val)
-{
- int i, i_chosen=-1, n_chosen=0;
- uint64_t total_so_far = 0;
-
- for (i = 0; i < n_entries; ++i) {
- total_so_far += entries[i];
- if (gt_i64_timei(total_so_far, rand_val)) {
- i_chosen = i;
- n_chosen++;
- /* Set rand_val to INT64_MAX rather than stopping the loop. This way,
- * the time we spend in the loop does not leak which element we chose. */
- rand_val = INT64_MAX;
- }
- }
- tor_assert(total_so_far == total);
- tor_assert(n_chosen == 1);
- tor_assert(i_chosen >= 0);
- tor_assert(i_chosen < n_entries);
-
- return i_chosen;
-}
-
diff --git a/src/common/di_ops.h b/src/common/di_ops.h
deleted file mode 100644
index 67d9c9f0df..0000000000
--- a/src/common/di_ops.h
+++ /dev/null
@@ -1,55 +0,0 @@
-/* Copyright (c) 2003-2004, Roger Dingledine
- * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2017, The Tor Project, Inc. */
-/* See LICENSE for licensing information */
-
-/**
- * \file di_ops.h
- * \brief Headers for di_ops.c
- **/
-
-#ifndef TOR_DI_OPS_H
-#define TOR_DI_OPS_H
-
-#include "orconfig.h"
-#include "torint.h"
-
-int tor_memcmp(const void *a, const void *b, size_t sz);
-int tor_memeq(const void *a, const void *b, size_t sz);
-#define tor_memneq(a,b,sz) (!tor_memeq((a),(b),(sz)))
-
-/** Alias for the platform's memcmp() function. This function is
- * <em>not</em> data-independent: we define this alias so that we can
- * mark cases where we are deliberately using a data-dependent memcmp()
- * implementation.
- */
-#define fast_memcmp(a,b,c) (memcmp((a),(b),(c)))
-#define fast_memeq(a,b,c) (0==memcmp((a),(b),(c)))
-#define fast_memneq(a,b,c) (0!=memcmp((a),(b),(c)))
-
-int safe_mem_is_zero(const void *mem, size_t sz);
-
-/** A type for a map from DIGEST256_LEN-byte blobs to void*, such that
- * data lookups take an amount of time proportional only to the size
- * of the map, and not to the position or presence of the item in the map.
- *
- * Not efficient for large maps! */
-typedef struct di_digest256_map_t di_digest256_map_t;
-typedef void (*dimap_free_fn)(void *);
-
-void dimap_free_(di_digest256_map_t *map, dimap_free_fn free_fn);
-#define dimap_free(map, free_fn) \
- do { \
- dimap_free_((map), (free_fn)); \
- (map) = NULL; \
- } while (0)
-void dimap_add_entry(di_digest256_map_t **map,
- const uint8_t *key, void *val);
-void *dimap_search(const di_digest256_map_t *map, const uint8_t *key,
- void *dflt_val);
-int select_array_member_cumulative_timei(const uint64_t *entries,
- int n_entries,
- uint64_t total, uint64_t rand_val);
-
-#endif /* !defined(TOR_DI_OPS_H) */
-
diff --git a/src/common/handles.h b/src/common/handles.h
deleted file mode 100644
index aef8cd89ef..0000000000
--- a/src/common/handles.h
+++ /dev/null
@@ -1,153 +0,0 @@
-/* Copyright (c) 2016-2017, The Tor Project, Inc. */
-/* See LICENSE for licensing information */
-
-/**
- * \file handles.h
- * \brief Macros for C weak-handle implementation.
- *
- * A 'handle' is a pointer to an object that is allowed to go away while
- * the handle stays alive. When you dereference the handle, you might get
- * the object, or you might get "NULL".
- *
- * Use this pattern when an object has a single obvious lifespan, so you don't
- * want to use reference counting, but when other objects might need to refer
- * to the first object without caring about its lifetime.
- *
- * To enable a type to have handles, add a HANDLE_ENTRY() field in its
- * definition, as in:
- *
- * struct walrus {
- * HANDLE_ENTRY(wlr, walrus);
- * // ...
- * };
- *
- * And invoke HANDLE_DECL(wlr, walrus, [static]) to declare the handle
- * manipulation functions (typically in a header):
- *
- * // opaque handle to walrus.
- * typedef struct wlr_handle_t wlr_handle_t;
- *
- * // make a new handle
- * struct wlr_handle_t *wlr_handle_new(struct walrus *);
- *
- * // release a handle
- * void wlr_handle_free(wlr_handle_t *);
- *
- * // return the pointed-to walrus, or NULL.
- * struct walrus *wlr_handle_get(wlr_handle_t *).
- *
- * // call this function when you're about to free the walrus;
- * // it invalidates all handles. (IF YOU DON'T, YOU WILL HAVE
- * // DANGLING REFERENCES)
- * void wlr_handles_clear(struct walrus *);
- *
- * Finally, use HANDLE_IMPL() to define the above functions in some
- * appropriate C file: HANDLE_IMPL(wlr, walrus, [static])
- *
- **/
-
-#ifndef TOR_HANDLE_H
-#define TOR_HANDLE_H
-
-#include "orconfig.h"
-#include "tor_queue.h"
-#include "util.h"
-
-#define HANDLE_ENTRY(name, structname) \
- struct name ## _handle_head_t *handle_head
-
-#define HANDLE_DECL(name, structname, linkage) \
- typedef struct name ## _handle_t name ## _handle_t; \
- linkage name ## _handle_t *name ## _handle_new(struct structname *object); \
- linkage void name ## _handle_free_(name ## _handle_t *); \
- linkage struct structname *name ## _handle_get(name ## _handle_t *); \
- linkage void name ## _handles_clear(struct structname *object);
-
-/*
- * Implementation notes: there are lots of possible implementations here. We
- * could keep a linked list of handles, each with a backpointer to the object,
- * and set all of their backpointers to NULL when the object is freed. Or we
- * could have the clear function invalidate the object, but not actually let
- * the object get freed until the all the handles went away. We could even
- * have a hash-table mapping unique identifiers to objects, and have each
- * handle be a copy of the unique identifier. (We'll want to build that last
- * one eventually if we want cross-process handles.)
- *
- * But instead we're opting for a single independent 'head' that knows how
- * many handles there are, and where the object is (or isn't). This makes
- * all of our functions O(1), and most as fast as a single pointer access.
- *
- * The handles themselves are opaque structures holding a pointer to the head.
- * We could instead have each foo_handle_t* be identical to foo_handle_head_t
- * *, and save some allocations ... but doing so would make handle leaks
- * harder to debug. As it stands, every handle leak is a memory leak, and
- * existing memory debugging tools should help with those. We can revisit
- * this decision if handles are too slow.
- */
-
-#define HANDLE_IMPL(name, structname, linkage) \
- /* The 'head' object for a handle-accessible type. This object */ \
- /* persists for as long as the object, or any handles, exist. */ \
- typedef struct name ## _handle_head_t { \
- struct structname *object; /* pointed-to object, or NULL */ \
- unsigned int references; /* number of existing handles */ \
- } name ## _handle_head_t; \
- \
- struct name ## _handle_t { \
- struct name ## _handle_head_t *head; /* reference to the 'head'. */ \
- }; \
- \
- linkage struct name ## _handle_t * \
- name ## _handle_new(struct structname *object) \
- { \
- tor_assert(object); \
- name ## _handle_head_t *head = object->handle_head; \
- if (PREDICT_UNLIKELY(head == NULL)) { \
- head = object->handle_head = tor_malloc_zero(sizeof(*head)); \
- head->object = object; \
- } \
- name ## _handle_t *new_ref = tor_malloc_zero(sizeof(*new_ref)); \
- new_ref->head = head; \
- ++head->references; \
- return new_ref; \
- } \
- \
- linkage void \
- name ## _handle_free_(struct name ## _handle_t *ref) \
- { \
- if (! ref) return; \
- name ## _handle_head_t *head = ref->head; \
- tor_assert(head); \
- --head->references; \
- tor_free(ref); \
- if (head->object == NULL && head->references == 0) { \
- tor_free(head); \
- return; \
- } \
- } \
- \
- linkage struct structname * \
- name ## _handle_get(struct name ## _handle_t *ref) \
- { \
- tor_assert(ref); \
- name ## _handle_head_t *head = ref->head; \
- tor_assert(head); \
- return head->object; \
- } \
- \
- linkage void \
- name ## _handles_clear(struct structname *object) \
- { \
- tor_assert(object); \
- name ## _handle_head_t *head = object->handle_head; \
- if (! head) \
- return; \
- object->handle_head = NULL; \
- head->object = NULL; \
- if (head->references == 0) { \
- tor_free(head); \
- } \
- }
-
-#endif /* !defined(TOR_HANDLE_H) */
-
diff --git a/src/common/include.am b/src/common/include.am
deleted file mode 100644
index cfaf993674..0000000000
--- a/src/common/include.am
+++ /dev/null
@@ -1,213 +0,0 @@
-
-noinst_LIBRARIES += \
- src/common/libor.a \
- src/common/libor-ctime.a \
- src/common/libor-crypto.a \
- src/common/libor-event.a
-
-if UNITTESTS_ENABLED
-noinst_LIBRARIES += \
- src/common/libor-testing.a \
- src/common/libor-ctime-testing.a \
- src/common/libor-crypto-testing.a \
- src/common/libor-event-testing.a
-endif
-
-EXTRA_DIST += src/common/Makefile.nmake
-
-#CFLAGS = -Wall -Wpointer-arith -O2
-AM_CPPFLAGS += -I$(srcdir)/src/common -Isrc/common -I$(srcdir)/src/ext/trunnel -I$(srcdir)/src/trunnel
-
-if USE_OPENBSD_MALLOC
-libor_extra_source=src/ext/OpenBSD_malloc_Linux.c
-else
-libor_extra_source=
-endif
-
-src_common_libcurve25519_donna_a_CFLAGS=
-
-if BUILD_CURVE25519_DONNA
-src_common_libcurve25519_donna_a_SOURCES=\
- src/ext/curve25519_donna/curve25519-donna.c
-# See bug 13538 -- this code is known to have signed overflow issues.
-src_common_libcurve25519_donna_a_CFLAGS+=\
- @F_OMIT_FRAME_POINTER@ @CFLAGS_CONSTTIME@
-noinst_LIBRARIES+=src/common/libcurve25519_donna.a
-LIBDONNA=src/common/libcurve25519_donna.a
-else
-if BUILD_CURVE25519_DONNA_C64
-src_common_libcurve25519_donna_a_CFLAGS+=@CFLAGS_CONSTTIME@
-src_common_libcurve25519_donna_a_SOURCES=\
- src/ext/curve25519_donna/curve25519-donna-c64.c
-noinst_LIBRARIES+=src/common/libcurve25519_donna.a
-LIBDONNA=src/common/libcurve25519_donna.a
-else
-LIBDONNA=
-endif
-endif
-
-LIBDONNA += $(LIBED25519_REF10)
-LIBDONNA += $(LIBED25519_DONNA)
-
-if THREADS_PTHREADS
-threads_impl_source=src/common/compat_pthreads.c
-endif
-if THREADS_WIN32
-threads_impl_source=src/common/compat_winthreads.c
-endif
-
-if BUILD_READPASSPHRASE_C
-readpassphrase_source=src/ext/readpassphrase.c
-else
-readpassphrase_source=
-endif
-
-if ADD_MULODI4
-mulodi4_source=src/ext/mulodi/mulodi4.c
-else
-mulodi4_source=
-endif
-
-LIBOR_CTIME_A_SRC = \
- $(mulodi4_source) \
- src/ext/csiphash.c \
- src/common/di_ops.c
-
-src_common_libor_ctime_a_SOURCES = $(LIBOR_CTIME_A_SRC)
-if UNITTESTS_ENABLED
-src_common_libor_ctime_testing_a_SOURCES = $(LIBOR_CTIME_A_SRC)
-else
-src_common_libor_ctime_testing_a_SOURCES =
-endif
-src_common_libor_ctime_a_CFLAGS = @CFLAGS_CONSTTIME@
-src_common_libor_ctime_testing_a_CFLAGS = @CFLAGS_CONSTTIME@ $(TEST_CFLAGS)
-
-LIBOR_A_SRC = \
- src/common/address.c \
- src/common/address_set.c \
- src/common/backtrace.c \
- src/common/buffers.c \
- src/common/compat.c \
- src/common/compat_threads.c \
- src/common/compat_time.c \
- src/common/confline.c \
- src/common/container.c \
- src/common/log.c \
- src/common/memarea.c \
- src/common/pubsub.c \
- src/common/util.c \
- src/common/util_bug.c \
- src/common/util_format.c \
- src/common/util_process.c \
- src/common/sandbox.c \
- src/common/storagedir.c \
- src/common/token_bucket.c \
- src/common/workqueue.c \
- $(libor_extra_source) \
- $(threads_impl_source) \
- $(readpassphrase_source)
-
-src/common/src_common_libor_testing_a-log.$(OBJEXT) \
- src/common/log.$(OBJEXT): micro-revision.i
-
-LIBOR_CRYPTO_A_SRC = \
- src/common/aes.c \
- src/common/buffers_tls.c \
- src/common/compress.c \
- src/common/compress_lzma.c \
- src/common/compress_none.c \
- src/common/compress_zlib.c \
- src/common/compress_zstd.c \
- src/common/crypto.c \
- src/common/crypto_digest.c \
- src/common/crypto_format.c \
- src/common/crypto_openssl_mgt.c \
- src/common/crypto_pwbox.c \
- src/common/crypto_rand.c \
- src/common/crypto_rsa.c \
- src/common/crypto_s2k.c \
- src/common/crypto_util.c \
- src/common/tortls.c \
- src/common/crypto_curve25519.c \
- src/common/crypto_ed25519.c
-
-LIBOR_EVENT_A_SRC = \
- src/common/compat_libevent.c \
- src/common/procmon.c \
- src/common/timers.c \
- src/ext/timeouts/timeout.c
-
-src_common_libor_a_SOURCES = $(LIBOR_A_SRC)
-src_common_libor_crypto_a_SOURCES = $(LIBOR_CRYPTO_A_SRC)
-src_common_libor_event_a_SOURCES = $(LIBOR_EVENT_A_SRC)
-
-if UNITTESTS_ENABLED
-src_common_libor_testing_a_SOURCES = $(LIBOR_A_SRC)
-src_common_libor_crypto_testing_a_SOURCES = $(LIBOR_CRYPTO_A_SRC)
-src_common_libor_event_testing_a_SOURCES = $(LIBOR_EVENT_A_SRC)
-else
-src_common_libor_testing_a_SOURCES =
-src_common_libor_crypto_testing_a_SOURCES =
-src_common_libor_event_testing_a_SOURCES =
-endif
-
-src_common_libor_testing_a_CPPFLAGS = $(AM_CPPFLAGS) $(TEST_CPPFLAGS)
-src_common_libor_crypto_testing_a_CPPFLAGS = $(AM_CPPFLAGS) $(TEST_CPPFLAGS)
-src_common_libor_event_testing_a_CPPFLAGS = $(AM_CPPFLAGS) $(TEST_CPPFLAGS)
-src_common_libor_testing_a_CFLAGS = $(AM_CFLAGS) $(TEST_CFLAGS)
-src_common_libor_crypto_testing_a_CFLAGS = $(AM_CFLAGS) $(TEST_CFLAGS)
-src_common_libor_event_testing_a_CFLAGS = $(AM_CFLAGS) $(TEST_CFLAGS)
-
-COMMONHEADERS = \
- src/common/address.h \
- src/common/address_set.h \
- src/common/backtrace.h \
- src/common/buffers.h \
- src/common/buffers_tls.h \
- src/common/aes.h \
- src/common/ciphers.inc \
- src/common/compat.h \
- src/common/compat_libevent.h \
- src/common/compat_openssl.h \
- src/common/compat_threads.h \
- src/common/compat_time.h \
- src/common/compress.h \
- src/common/compress_lzma.h \
- src/common/compress_none.h \
- src/common/compress_zlib.h \
- src/common/compress_zstd.h \
- src/common/confline.h \
- src/common/container.h \
- src/common/crypto.h \
- src/common/crypto_digest.h \
- src/common/crypto_curve25519.h \
- src/common/crypto_ed25519.h \
- src/common/crypto_format.h \
- src/common/crypto_openssl_mgt.h \
- src/common/crypto_pwbox.h \
- src/common/crypto_rand.h \
- src/common/crypto_rsa.h \
- src/common/crypto_s2k.h \
- src/common/crypto_util.h \
- src/common/di_ops.h \
- src/common/handles.h \
- src/common/memarea.h \
- src/common/linux_syscalls.inc \
- src/common/procmon.h \
- src/common/pubsub.h \
- src/common/sandbox.h \
- src/common/storagedir.h \
- src/common/testsupport.h \
- src/common/timers.h \
- src/common/token_bucket.h \
- src/common/torint.h \
- src/common/torlog.h \
- src/common/tortls.h \
- src/common/util.h \
- src/common/util_bug.h \
- src/common/util_format.h \
- src/common/util_process.h \
- src/common/workqueue.h
-
-noinst_HEADERS+= $(COMMONHEADERS)
-
diff --git a/src/common/linux_syscalls.inc b/src/common/linux_syscalls.inc
deleted file mode 100644
index cf47c73809..0000000000
--- a/src/common/linux_syscalls.inc
+++ /dev/null
@@ -1,1153 +0,0 @@
-/* Automatically generated with
- gen_linux_syscalls.pl /usr/include/asm/unistd*.h
- Do not edit.
- */
-static const struct {
- int syscall_num; const char *syscall_name;
-} SYSCALLS_BY_NUMBER[] = {
-#ifdef __NR__llseek
- { __NR__llseek, "_llseek" },
-#endif
-#ifdef __NR__newselect
- { __NR__newselect, "_newselect" },
-#endif
-#ifdef __NR__sysctl
- { __NR__sysctl, "_sysctl" },
-#endif
-#ifdef __NR_accept
- { __NR_accept, "accept" },
-#endif
-#ifdef __NR_accept4
- { __NR_accept4, "accept4" },
-#endif
-#ifdef __NR_access
- { __NR_access, "access" },
-#endif
-#ifdef __NR_acct
- { __NR_acct, "acct" },
-#endif
-#ifdef __NR_add_key
- { __NR_add_key, "add_key" },
-#endif
-#ifdef __NR_adjtimex
- { __NR_adjtimex, "adjtimex" },
-#endif
-#ifdef __NR_afs_syscall
- { __NR_afs_syscall, "afs_syscall" },
-#endif
-#ifdef __NR_alarm
- { __NR_alarm, "alarm" },
-#endif
-#ifdef __NR_arch_prctl
- { __NR_arch_prctl, "arch_prctl" },
-#endif
-#ifdef __NR_bdflush
- { __NR_bdflush, "bdflush" },
-#endif
-#ifdef __NR_bind
- { __NR_bind, "bind" },
-#endif
-#ifdef __NR_break
- { __NR_break, "break" },
-#endif
-#ifdef __NR_brk
- { __NR_brk, "brk" },
-#endif
-#ifdef __NR_capget
- { __NR_capget, "capget" },
-#endif
-#ifdef __NR_capset
- { __NR_capset, "capset" },
-#endif
-#ifdef __NR_chdir
- { __NR_chdir, "chdir" },
-#endif
-#ifdef __NR_chmod
- { __NR_chmod, "chmod" },
-#endif
-#ifdef __NR_chown
- { __NR_chown, "chown" },
-#endif
-#ifdef __NR_chown32
- { __NR_chown32, "chown32" },
-#endif
-#ifdef __NR_chroot
- { __NR_chroot, "chroot" },
-#endif
-#ifdef __NR_clock_adjtime
- { __NR_clock_adjtime, "clock_adjtime" },
-#endif
-#ifdef __NR_clock_getres
- { __NR_clock_getres, "clock_getres" },
-#endif
-#ifdef __NR_clock_gettime
- { __NR_clock_gettime, "clock_gettime" },
-#endif
-#ifdef __NR_clock_nanosleep
- { __NR_clock_nanosleep, "clock_nanosleep" },
-#endif
-#ifdef __NR_clock_settime
- { __NR_clock_settime, "clock_settime" },
-#endif
-#ifdef __NR_clone
- { __NR_clone, "clone" },
-#endif
-#ifdef __NR_close
- { __NR_close, "close" },
-#endif
-#ifdef __NR_connect
- { __NR_connect, "connect" },
-#endif
-#ifdef __NR_creat
- { __NR_creat, "creat" },
-#endif
-#ifdef __NR_create_module
- { __NR_create_module, "create_module" },
-#endif
-#ifdef __NR_delete_module
- { __NR_delete_module, "delete_module" },
-#endif
-#ifdef __NR_dup
- { __NR_dup, "dup" },
-#endif
-#ifdef __NR_dup2
- { __NR_dup2, "dup2" },
-#endif
-#ifdef __NR_dup3
- { __NR_dup3, "dup3" },
-#endif
-#ifdef __NR_epoll_create
- { __NR_epoll_create, "epoll_create" },
-#endif
-#ifdef __NR_epoll_create1
- { __NR_epoll_create1, "epoll_create1" },
-#endif
-#ifdef __NR_epoll_ctl
- { __NR_epoll_ctl, "epoll_ctl" },
-#endif
-#ifdef __NR_epoll_ctl_old
- { __NR_epoll_ctl_old, "epoll_ctl_old" },
-#endif
-#ifdef __NR_epoll_pwait
- { __NR_epoll_pwait, "epoll_pwait" },
-#endif
-#ifdef __NR_epoll_wait
- { __NR_epoll_wait, "epoll_wait" },
-#endif
-#ifdef __NR_epoll_wait_old
- { __NR_epoll_wait_old, "epoll_wait_old" },
-#endif
-#ifdef __NR_eventfd
- { __NR_eventfd, "eventfd" },
-#endif
-#ifdef __NR_eventfd2
- { __NR_eventfd2, "eventfd2" },
-#endif
-#ifdef __NR_execve
- { __NR_execve, "execve" },
-#endif
-#ifdef __NR_exit
- { __NR_exit, "exit" },
-#endif
-#ifdef __NR_exit_group
- { __NR_exit_group, "exit_group" },
-#endif
-#ifdef __NR_faccessat
- { __NR_faccessat, "faccessat" },
-#endif
-#ifdef __NR_fadvise64
- { __NR_fadvise64, "fadvise64" },
-#endif
-#ifdef __NR_fadvise64_64
- { __NR_fadvise64_64, "fadvise64_64" },
-#endif
-#ifdef __NR_fallocate
- { __NR_fallocate, "fallocate" },
-#endif
-#ifdef __NR_fanotify_init
- { __NR_fanotify_init, "fanotify_init" },
-#endif
-#ifdef __NR_fanotify_mark
- { __NR_fanotify_mark, "fanotify_mark" },
-#endif
-#ifdef __NR_fchdir
- { __NR_fchdir, "fchdir" },
-#endif
-#ifdef __NR_fchmod
- { __NR_fchmod, "fchmod" },
-#endif
-#ifdef __NR_fchmodat
- { __NR_fchmodat, "fchmodat" },
-#endif
-#ifdef __NR_fchown
- { __NR_fchown, "fchown" },
-#endif
-#ifdef __NR_fchown32
- { __NR_fchown32, "fchown32" },
-#endif
-#ifdef __NR_fchownat
- { __NR_fchownat, "fchownat" },
-#endif
-#ifdef __NR_fcntl
- { __NR_fcntl, "fcntl" },
-#endif
-#ifdef __NR_fcntl64
- { __NR_fcntl64, "fcntl64" },
-#endif
-#ifdef __NR_fdatasync
- { __NR_fdatasync, "fdatasync" },
-#endif
-#ifdef __NR_fgetxattr
- { __NR_fgetxattr, "fgetxattr" },
-#endif
-#ifdef __NR_finit_module
- { __NR_finit_module, "finit_module" },
-#endif
-#ifdef __NR_flistxattr
- { __NR_flistxattr, "flistxattr" },
-#endif
-#ifdef __NR_flock
- { __NR_flock, "flock" },
-#endif
-#ifdef __NR_fork
- { __NR_fork, "fork" },
-#endif
-#ifdef __NR_fremovexattr
- { __NR_fremovexattr, "fremovexattr" },
-#endif
-#ifdef __NR_fsetxattr
- { __NR_fsetxattr, "fsetxattr" },
-#endif
-#ifdef __NR_fstat
- { __NR_fstat, "fstat" },
-#endif
-#ifdef __NR_fstat64
- { __NR_fstat64, "fstat64" },
-#endif
-#ifdef __NR_fstatat64
- { __NR_fstatat64, "fstatat64" },
-#endif
-#ifdef __NR_fstatfs
- { __NR_fstatfs, "fstatfs" },
-#endif
-#ifdef __NR_fstatfs64
- { __NR_fstatfs64, "fstatfs64" },
-#endif
-#ifdef __NR_fsync
- { __NR_fsync, "fsync" },
-#endif
-#ifdef __NR_ftime
- { __NR_ftime, "ftime" },
-#endif
-#ifdef __NR_ftruncate
- { __NR_ftruncate, "ftruncate" },
-#endif
-#ifdef __NR_ftruncate64
- { __NR_ftruncate64, "ftruncate64" },
-#endif
-#ifdef __NR_futex
- { __NR_futex, "futex" },
-#endif
-#ifdef __NR_futimesat
- { __NR_futimesat, "futimesat" },
-#endif
-#ifdef __NR_get_kernel_syms
- { __NR_get_kernel_syms, "get_kernel_syms" },
-#endif
-#ifdef __NR_get_mempolicy
- { __NR_get_mempolicy, "get_mempolicy" },
-#endif
-#ifdef __NR_get_robust_list
- { __NR_get_robust_list, "get_robust_list" },
-#endif
-#ifdef __NR_get_thread_area
- { __NR_get_thread_area, "get_thread_area" },
-#endif
-#ifdef __NR_getcpu
- { __NR_getcpu, "getcpu" },
-#endif
-#ifdef __NR_getcwd
- { __NR_getcwd, "getcwd" },
-#endif
-#ifdef __NR_getdents
- { __NR_getdents, "getdents" },
-#endif
-#ifdef __NR_getdents64
- { __NR_getdents64, "getdents64" },
-#endif
-#ifdef __NR_getegid
- { __NR_getegid, "getegid" },
-#endif
-#ifdef __NR_getegid32
- { __NR_getegid32, "getegid32" },
-#endif
-#ifdef __NR_geteuid
- { __NR_geteuid, "geteuid" },
-#endif
-#ifdef __NR_geteuid32
- { __NR_geteuid32, "geteuid32" },
-#endif
-#ifdef __NR_getgid
- { __NR_getgid, "getgid" },
-#endif
-#ifdef __NR_getgid32
- { __NR_getgid32, "getgid32" },
-#endif
-#ifdef __NR_getgroups
- { __NR_getgroups, "getgroups" },
-#endif
-#ifdef __NR_getgroups32
- { __NR_getgroups32, "getgroups32" },
-#endif
-#ifdef __NR_getitimer
- { __NR_getitimer, "getitimer" },
-#endif
-#ifdef __NR_getpeername
- { __NR_getpeername, "getpeername" },
-#endif
-#ifdef __NR_getpgid
- { __NR_getpgid, "getpgid" },
-#endif
-#ifdef __NR_getpgrp
- { __NR_getpgrp, "getpgrp" },
-#endif
-#ifdef __NR_getpid
- { __NR_getpid, "getpid" },
-#endif
-#ifdef __NR_getpmsg
- { __NR_getpmsg, "getpmsg" },
-#endif
-#ifdef __NR_getppid
- { __NR_getppid, "getppid" },
-#endif
-#ifdef __NR_getpriority
- { __NR_getpriority, "getpriority" },
-#endif
-#ifdef __NR_getresgid
- { __NR_getresgid, "getresgid" },
-#endif
-#ifdef __NR_getresgid32
- { __NR_getresgid32, "getresgid32" },
-#endif
-#ifdef __NR_getresuid
- { __NR_getresuid, "getresuid" },
-#endif
-#ifdef __NR_getresuid32
- { __NR_getresuid32, "getresuid32" },
-#endif
-#ifdef __NR_getrlimit
- { __NR_getrlimit, "getrlimit" },
-#endif
-#ifdef __NR_getrusage
- { __NR_getrusage, "getrusage" },
-#endif
-#ifdef __NR_getsid
- { __NR_getsid, "getsid" },
-#endif
-#ifdef __NR_getsockname
- { __NR_getsockname, "getsockname" },
-#endif
-#ifdef __NR_getsockopt
- { __NR_getsockopt, "getsockopt" },
-#endif
-#ifdef __NR_gettid
- { __NR_gettid, "gettid" },
-#endif
-#ifdef __NR_gettimeofday
- { __NR_gettimeofday, "gettimeofday" },
-#endif
-#ifdef __NR_getuid
- { __NR_getuid, "getuid" },
-#endif
-#ifdef __NR_getuid32
- { __NR_getuid32, "getuid32" },
-#endif
-#ifdef __NR_getxattr
- { __NR_getxattr, "getxattr" },
-#endif
-#ifdef __NR_gtty
- { __NR_gtty, "gtty" },
-#endif
-#ifdef __NR_idle
- { __NR_idle, "idle" },
-#endif
-#ifdef __NR_init_module
- { __NR_init_module, "init_module" },
-#endif
-#ifdef __NR_inotify_add_watch
- { __NR_inotify_add_watch, "inotify_add_watch" },
-#endif
-#ifdef __NR_inotify_init
- { __NR_inotify_init, "inotify_init" },
-#endif
-#ifdef __NR_inotify_init1
- { __NR_inotify_init1, "inotify_init1" },
-#endif
-#ifdef __NR_inotify_rm_watch
- { __NR_inotify_rm_watch, "inotify_rm_watch" },
-#endif
-#ifdef __NR_io_cancel
- { __NR_io_cancel, "io_cancel" },
-#endif
-#ifdef __NR_io_destroy
- { __NR_io_destroy, "io_destroy" },
-#endif
-#ifdef __NR_io_getevents
- { __NR_io_getevents, "io_getevents" },
-#endif
-#ifdef __NR_io_setup
- { __NR_io_setup, "io_setup" },
-#endif
-#ifdef __NR_io_submit
- { __NR_io_submit, "io_submit" },
-#endif
-#ifdef __NR_ioctl
- { __NR_ioctl, "ioctl" },
-#endif
-#ifdef __NR_ioperm
- { __NR_ioperm, "ioperm" },
-#endif
-#ifdef __NR_iopl
- { __NR_iopl, "iopl" },
-#endif
-#ifdef __NR_ioprio_get
- { __NR_ioprio_get, "ioprio_get" },
-#endif
-#ifdef __NR_ioprio_set
- { __NR_ioprio_set, "ioprio_set" },
-#endif
-#ifdef __NR_ipc
- { __NR_ipc, "ipc" },
-#endif
-#ifdef __NR_kcmp
- { __NR_kcmp, "kcmp" },
-#endif
-#ifdef __NR_kexec_load
- { __NR_kexec_load, "kexec_load" },
-#endif
-#ifdef __NR_keyctl
- { __NR_keyctl, "keyctl" },
-#endif
-#ifdef __NR_kill
- { __NR_kill, "kill" },
-#endif
-#ifdef __NR_lchown
- { __NR_lchown, "lchown" },
-#endif
-#ifdef __NR_lchown32
- { __NR_lchown32, "lchown32" },
-#endif
-#ifdef __NR_lgetxattr
- { __NR_lgetxattr, "lgetxattr" },
-#endif
-#ifdef __NR_link
- { __NR_link, "link" },
-#endif
-#ifdef __NR_linkat
- { __NR_linkat, "linkat" },
-#endif
-#ifdef __NR_listen
- { __NR_listen, "listen" },
-#endif
-#ifdef __NR_listxattr
- { __NR_listxattr, "listxattr" },
-#endif
-#ifdef __NR_llistxattr
- { __NR_llistxattr, "llistxattr" },
-#endif
-#ifdef __NR_lock
- { __NR_lock, "lock" },
-#endif
-#ifdef __NR_lookup_dcookie
- { __NR_lookup_dcookie, "lookup_dcookie" },
-#endif
-#ifdef __NR_lremovexattr
- { __NR_lremovexattr, "lremovexattr" },
-#endif
-#ifdef __NR_lseek
- { __NR_lseek, "lseek" },
-#endif
-#ifdef __NR_lsetxattr
- { __NR_lsetxattr, "lsetxattr" },
-#endif
-#ifdef __NR_lstat
- { __NR_lstat, "lstat" },
-#endif
-#ifdef __NR_lstat64
- { __NR_lstat64, "lstat64" },
-#endif
-#ifdef __NR_madvise
- { __NR_madvise, "madvise" },
-#endif
-#ifdef __NR_mbind
- { __NR_mbind, "mbind" },
-#endif
-#ifdef __NR_migrate_pages
- { __NR_migrate_pages, "migrate_pages" },
-#endif
-#ifdef __NR_mincore
- { __NR_mincore, "mincore" },
-#endif
-#ifdef __NR_mkdir
- { __NR_mkdir, "mkdir" },
-#endif
-#ifdef __NR_mkdirat
- { __NR_mkdirat, "mkdirat" },
-#endif
-#ifdef __NR_mknod
- { __NR_mknod, "mknod" },
-#endif
-#ifdef __NR_mknodat
- { __NR_mknodat, "mknodat" },
-#endif
-#ifdef __NR_mlock
- { __NR_mlock, "mlock" },
-#endif
-#ifdef __NR_mlockall
- { __NR_mlockall, "mlockall" },
-#endif
-#ifdef __NR_mmap
- { __NR_mmap, "mmap" },
-#endif
-#ifdef __NR_mmap2
- { __NR_mmap2, "mmap2" },
-#endif
-#ifdef __NR_modify_ldt
- { __NR_modify_ldt, "modify_ldt" },
-#endif
-#ifdef __NR_mount
- { __NR_mount, "mount" },
-#endif
-#ifdef __NR_move_pages
- { __NR_move_pages, "move_pages" },
-#endif
-#ifdef __NR_mprotect
- { __NR_mprotect, "mprotect" },
-#endif
-#ifdef __NR_mpx
- { __NR_mpx, "mpx" },
-#endif
-#ifdef __NR_mq_getsetattr
- { __NR_mq_getsetattr, "mq_getsetattr" },
-#endif
-#ifdef __NR_mq_notify
- { __NR_mq_notify, "mq_notify" },
-#endif
-#ifdef __NR_mq_open
- { __NR_mq_open, "mq_open" },
-#endif
-#ifdef __NR_mq_timedreceive
- { __NR_mq_timedreceive, "mq_timedreceive" },
-#endif
-#ifdef __NR_mq_timedsend
- { __NR_mq_timedsend, "mq_timedsend" },
-#endif
-#ifdef __NR_mq_unlink
- { __NR_mq_unlink, "mq_unlink" },
-#endif
-#ifdef __NR_mremap
- { __NR_mremap, "mremap" },
-#endif
-#ifdef __NR_msgctl
- { __NR_msgctl, "msgctl" },
-#endif
-#ifdef __NR_msgget
- { __NR_msgget, "msgget" },
-#endif
-#ifdef __NR_msgrcv
- { __NR_msgrcv, "msgrcv" },
-#endif
-#ifdef __NR_msgsnd
- { __NR_msgsnd, "msgsnd" },
-#endif
-#ifdef __NR_msync
- { __NR_msync, "msync" },
-#endif
-#ifdef __NR_munlock
- { __NR_munlock, "munlock" },
-#endif
-#ifdef __NR_munlockall
- { __NR_munlockall, "munlockall" },
-#endif
-#ifdef __NR_munmap
- { __NR_munmap, "munmap" },
-#endif
-#ifdef __NR_name_to_handle_at
- { __NR_name_to_handle_at, "name_to_handle_at" },
-#endif
-#ifdef __NR_nanosleep
- { __NR_nanosleep, "nanosleep" },
-#endif
-#ifdef __NR_newfstatat
- { __NR_newfstatat, "newfstatat" },
-#endif
-#ifdef __NR_nfsservctl
- { __NR_nfsservctl, "nfsservctl" },
-#endif
-#ifdef __NR_nice
- { __NR_nice, "nice" },
-#endif
-#ifdef __NR_oldfstat
- { __NR_oldfstat, "oldfstat" },
-#endif
-#ifdef __NR_oldlstat
- { __NR_oldlstat, "oldlstat" },
-#endif
-#ifdef __NR_oldolduname
- { __NR_oldolduname, "oldolduname" },
-#endif
-#ifdef __NR_oldstat
- { __NR_oldstat, "oldstat" },
-#endif
-#ifdef __NR_olduname
- { __NR_olduname, "olduname" },
-#endif
-#ifdef __NR_open
- { __NR_open, "open" },
-#endif
-#ifdef __NR_open_by_handle_at
- { __NR_open_by_handle_at, "open_by_handle_at" },
-#endif
-#ifdef __NR_openat
- { __NR_openat, "openat" },
-#endif
-#ifdef __NR_pause
- { __NR_pause, "pause" },
-#endif
-#ifdef __NR_perf_event_open
- { __NR_perf_event_open, "perf_event_open" },
-#endif
-#ifdef __NR_personality
- { __NR_personality, "personality" },
-#endif
-#ifdef __NR_pipe
- { __NR_pipe, "pipe" },
-#endif
-#ifdef __NR_pipe2
- { __NR_pipe2, "pipe2" },
-#endif
-#ifdef __NR_pivot_root
- { __NR_pivot_root, "pivot_root" },
-#endif
-#ifdef __NR_poll
- { __NR_poll, "poll" },
-#endif
-#ifdef __NR_ppoll
- { __NR_ppoll, "ppoll" },
-#endif
-#ifdef __NR_prctl
- { __NR_prctl, "prctl" },
-#endif
-#ifdef __NR_pread64
- { __NR_pread64, "pread64" },
-#endif
-#ifdef __NR_preadv
- { __NR_preadv, "preadv" },
-#endif
-#ifdef __NR_prlimit64
- { __NR_prlimit64, "prlimit64" },
-#endif
-#ifdef __NR_process_vm_readv
- { __NR_process_vm_readv, "process_vm_readv" },
-#endif
-#ifdef __NR_process_vm_writev
- { __NR_process_vm_writev, "process_vm_writev" },
-#endif
-#ifdef __NR_prof
- { __NR_prof, "prof" },
-#endif
-#ifdef __NR_profil
- { __NR_profil, "profil" },
-#endif
-#ifdef __NR_pselect6
- { __NR_pselect6, "pselect6" },
-#endif
-#ifdef __NR_ptrace
- { __NR_ptrace, "ptrace" },
-#endif
-#ifdef __NR_putpmsg
- { __NR_putpmsg, "putpmsg" },
-#endif
-#ifdef __NR_pwrite64
- { __NR_pwrite64, "pwrite64" },
-#endif
-#ifdef __NR_pwritev
- { __NR_pwritev, "pwritev" },
-#endif
-#ifdef __NR_query_module
- { __NR_query_module, "query_module" },
-#endif
-#ifdef __NR_quotactl
- { __NR_quotactl, "quotactl" },
-#endif
-#ifdef __NR_read
- { __NR_read, "read" },
-#endif
-#ifdef __NR_readahead
- { __NR_readahead, "readahead" },
-#endif
-#ifdef __NR_readdir
- { __NR_readdir, "readdir" },
-#endif
-#ifdef __NR_readlink
- { __NR_readlink, "readlink" },
-#endif
-#ifdef __NR_readlinkat
- { __NR_readlinkat, "readlinkat" },
-#endif
-#ifdef __NR_readv
- { __NR_readv, "readv" },
-#endif
-#ifdef __NR_reboot
- { __NR_reboot, "reboot" },
-#endif
-#ifdef __NR_recvfrom
- { __NR_recvfrom, "recvfrom" },
-#endif
-#ifdef __NR_recvmmsg
- { __NR_recvmmsg, "recvmmsg" },
-#endif
-#ifdef __NR_recvmsg
- { __NR_recvmsg, "recvmsg" },
-#endif
-#ifdef __NR_remap_file_pages
- { __NR_remap_file_pages, "remap_file_pages" },
-#endif
-#ifdef __NR_removexattr
- { __NR_removexattr, "removexattr" },
-#endif
-#ifdef __NR_rename
- { __NR_rename, "rename" },
-#endif
-#ifdef __NR_renameat
- { __NR_renameat, "renameat" },
-#endif
-#ifdef __NR_request_key
- { __NR_request_key, "request_key" },
-#endif
-#ifdef __NR_restart_syscall
- { __NR_restart_syscall, "restart_syscall" },
-#endif
-#ifdef __NR_rmdir
- { __NR_rmdir, "rmdir" },
-#endif
-#ifdef __NR_rt_sigaction
- { __NR_rt_sigaction, "rt_sigaction" },
-#endif
-#ifdef __NR_rt_sigpending
- { __NR_rt_sigpending, "rt_sigpending" },
-#endif
-#ifdef __NR_rt_sigprocmask
- { __NR_rt_sigprocmask, "rt_sigprocmask" },
-#endif
-#ifdef __NR_rt_sigqueueinfo
- { __NR_rt_sigqueueinfo, "rt_sigqueueinfo" },
-#endif
-#ifdef __NR_rt_sigreturn
- { __NR_rt_sigreturn, "rt_sigreturn" },
-#endif
-#ifdef __NR_rt_sigsuspend
- { __NR_rt_sigsuspend, "rt_sigsuspend" },
-#endif
-#ifdef __NR_rt_sigtimedwait
- { __NR_rt_sigtimedwait, "rt_sigtimedwait" },
-#endif
-#ifdef __NR_rt_tgsigqueueinfo
- { __NR_rt_tgsigqueueinfo, "rt_tgsigqueueinfo" },
-#endif
-#ifdef __NR_sched_get_priority_max
- { __NR_sched_get_priority_max, "sched_get_priority_max" },
-#endif
-#ifdef __NR_sched_get_priority_min
- { __NR_sched_get_priority_min, "sched_get_priority_min" },
-#endif
-#ifdef __NR_sched_getaffinity
- { __NR_sched_getaffinity, "sched_getaffinity" },
-#endif
-#ifdef __NR_sched_getparam
- { __NR_sched_getparam, "sched_getparam" },
-#endif
-#ifdef __NR_sched_getscheduler
- { __NR_sched_getscheduler, "sched_getscheduler" },
-#endif
-#ifdef __NR_sched_rr_get_interval
- { __NR_sched_rr_get_interval, "sched_rr_get_interval" },
-#endif
-#ifdef __NR_sched_setaffinity
- { __NR_sched_setaffinity, "sched_setaffinity" },
-#endif
-#ifdef __NR_sched_setparam
- { __NR_sched_setparam, "sched_setparam" },
-#endif
-#ifdef __NR_sched_setscheduler
- { __NR_sched_setscheduler, "sched_setscheduler" },
-#endif
-#ifdef __NR_sched_yield
- { __NR_sched_yield, "sched_yield" },
-#endif
-#ifdef __NR_security
- { __NR_security, "security" },
-#endif
-#ifdef __NR_select
- { __NR_select, "select" },
-#endif
-#ifdef __NR_semctl
- { __NR_semctl, "semctl" },
-#endif
-#ifdef __NR_semget
- { __NR_semget, "semget" },
-#endif
-#ifdef __NR_semop
- { __NR_semop, "semop" },
-#endif
-#ifdef __NR_semtimedop
- { __NR_semtimedop, "semtimedop" },
-#endif
-#ifdef __NR_sendfile
- { __NR_sendfile, "sendfile" },
-#endif
-#ifdef __NR_sendfile64
- { __NR_sendfile64, "sendfile64" },
-#endif
-#ifdef __NR_sendmmsg
- { __NR_sendmmsg, "sendmmsg" },
-#endif
-#ifdef __NR_sendmsg
- { __NR_sendmsg, "sendmsg" },
-#endif
-#ifdef __NR_sendto
- { __NR_sendto, "sendto" },
-#endif
-#ifdef __NR_set_mempolicy
- { __NR_set_mempolicy, "set_mempolicy" },
-#endif
-#ifdef __NR_set_robust_list
- { __NR_set_robust_list, "set_robust_list" },
-#endif
-#ifdef __NR_set_thread_area
- { __NR_set_thread_area, "set_thread_area" },
-#endif
-#ifdef __NR_set_tid_address
- { __NR_set_tid_address, "set_tid_address" },
-#endif
-#ifdef __NR_setdomainname
- { __NR_setdomainname, "setdomainname" },
-#endif
-#ifdef __NR_setfsgid
- { __NR_setfsgid, "setfsgid" },
-#endif
-#ifdef __NR_setfsgid32
- { __NR_setfsgid32, "setfsgid32" },
-#endif
-#ifdef __NR_setfsuid
- { __NR_setfsuid, "setfsuid" },
-#endif
-#ifdef __NR_setfsuid32
- { __NR_setfsuid32, "setfsuid32" },
-#endif
-#ifdef __NR_setgid
- { __NR_setgid, "setgid" },
-#endif
-#ifdef __NR_setgid32
- { __NR_setgid32, "setgid32" },
-#endif
-#ifdef __NR_setgroups
- { __NR_setgroups, "setgroups" },
-#endif
-#ifdef __NR_setgroups32
- { __NR_setgroups32, "setgroups32" },
-#endif
-#ifdef __NR_sethostname
- { __NR_sethostname, "sethostname" },
-#endif
-#ifdef __NR_setitimer
- { __NR_setitimer, "setitimer" },
-#endif
-#ifdef __NR_setns
- { __NR_setns, "setns" },
-#endif
-#ifdef __NR_setpgid
- { __NR_setpgid, "setpgid" },
-#endif
-#ifdef __NR_setpriority
- { __NR_setpriority, "setpriority" },
-#endif
-#ifdef __NR_setregid
- { __NR_setregid, "setregid" },
-#endif
-#ifdef __NR_setregid32
- { __NR_setregid32, "setregid32" },
-#endif
-#ifdef __NR_setresgid
- { __NR_setresgid, "setresgid" },
-#endif
-#ifdef __NR_setresgid32
- { __NR_setresgid32, "setresgid32" },
-#endif
-#ifdef __NR_setresuid
- { __NR_setresuid, "setresuid" },
-#endif
-#ifdef __NR_setresuid32
- { __NR_setresuid32, "setresuid32" },
-#endif
-#ifdef __NR_setreuid
- { __NR_setreuid, "setreuid" },
-#endif
-#ifdef __NR_setreuid32
- { __NR_setreuid32, "setreuid32" },
-#endif
-#ifdef __NR_setrlimit
- { __NR_setrlimit, "setrlimit" },
-#endif
-#ifdef __NR_setsid
- { __NR_setsid, "setsid" },
-#endif
-#ifdef __NR_setsockopt
- { __NR_setsockopt, "setsockopt" },
-#endif
-#ifdef __NR_settimeofday
- { __NR_settimeofday, "settimeofday" },
-#endif
-#ifdef __NR_setuid
- { __NR_setuid, "setuid" },
-#endif
-#ifdef __NR_setuid32
- { __NR_setuid32, "setuid32" },
-#endif
-#ifdef __NR_setxattr
- { __NR_setxattr, "setxattr" },
-#endif
-#ifdef __NR_sgetmask
- { __NR_sgetmask, "sgetmask" },
-#endif
-#ifdef __NR_shmat
- { __NR_shmat, "shmat" },
-#endif
-#ifdef __NR_shmctl
- { __NR_shmctl, "shmctl" },
-#endif
-#ifdef __NR_shmdt
- { __NR_shmdt, "shmdt" },
-#endif
-#ifdef __NR_shmget
- { __NR_shmget, "shmget" },
-#endif
-#ifdef __NR_shutdown
- { __NR_shutdown, "shutdown" },
-#endif
-#ifdef __NR_sigaction
- { __NR_sigaction, "sigaction" },
-#endif
-#ifdef __NR_sigaltstack
- { __NR_sigaltstack, "sigaltstack" },
-#endif
-#ifdef __NR_signal
- { __NR_signal, "signal" },
-#endif
-#ifdef __NR_signalfd
- { __NR_signalfd, "signalfd" },
-#endif
-#ifdef __NR_signalfd4
- { __NR_signalfd4, "signalfd4" },
-#endif
-#ifdef __NR_sigpending
- { __NR_sigpending, "sigpending" },
-#endif
-#ifdef __NR_sigprocmask
- { __NR_sigprocmask, "sigprocmask" },
-#endif
-#ifdef __NR_sigreturn
- { __NR_sigreturn, "sigreturn" },
-#endif
-#ifdef __NR_sigsuspend
- { __NR_sigsuspend, "sigsuspend" },
-#endif
-#ifdef __NR_socket
- { __NR_socket, "socket" },
-#endif
-#ifdef __NR_socketcall
- { __NR_socketcall, "socketcall" },
-#endif
-#ifdef __NR_socketpair
- { __NR_socketpair, "socketpair" },
-#endif
-#ifdef __NR_splice
- { __NR_splice, "splice" },
-#endif
-#ifdef __NR_ssetmask
- { __NR_ssetmask, "ssetmask" },
-#endif
-#ifdef __NR_stat
- { __NR_stat, "stat" },
-#endif
-#ifdef __NR_stat64
- { __NR_stat64, "stat64" },
-#endif
-#ifdef __NR_statfs
- { __NR_statfs, "statfs" },
-#endif
-#ifdef __NR_statfs64
- { __NR_statfs64, "statfs64" },
-#endif
-#ifdef __NR_stime
- { __NR_stime, "stime" },
-#endif
-#ifdef __NR_stty
- { __NR_stty, "stty" },
-#endif
-#ifdef __NR_swapoff
- { __NR_swapoff, "swapoff" },
-#endif
-#ifdef __NR_swapon
- { __NR_swapon, "swapon" },
-#endif
-#ifdef __NR_symlink
- { __NR_symlink, "symlink" },
-#endif
-#ifdef __NR_symlinkat
- { __NR_symlinkat, "symlinkat" },
-#endif
-#ifdef __NR_sync
- { __NR_sync, "sync" },
-#endif
-#ifdef __NR_sync_file_range
- { __NR_sync_file_range, "sync_file_range" },
-#endif
-#ifdef __NR_syncfs
- { __NR_syncfs, "syncfs" },
-#endif
-#ifdef __NR_sysfs
- { __NR_sysfs, "sysfs" },
-#endif
-#ifdef __NR_sysinfo
- { __NR_sysinfo, "sysinfo" },
-#endif
-#ifdef __NR_syslog
- { __NR_syslog, "syslog" },
-#endif
-#ifdef __NR_tee
- { __NR_tee, "tee" },
-#endif
-#ifdef __NR_tgkill
- { __NR_tgkill, "tgkill" },
-#endif
-#ifdef __NR_time
- { __NR_time, "time" },
-#endif
-#ifdef __NR_timer_create
- { __NR_timer_create, "timer_create" },
-#endif
-#ifdef __NR_timer_delete
- { __NR_timer_delete, "timer_delete" },
-#endif
-#ifdef __NR_timer_getoverrun
- { __NR_timer_getoverrun, "timer_getoverrun" },
-#endif
-#ifdef __NR_timer_gettime
- { __NR_timer_gettime, "timer_gettime" },
-#endif
-#ifdef __NR_timer_settime
- { __NR_timer_settime, "timer_settime" },
-#endif
-#ifdef __NR_timerfd_create
- { __NR_timerfd_create, "timerfd_create" },
-#endif
-#ifdef __NR_timerfd_gettime
- { __NR_timerfd_gettime, "timerfd_gettime" },
-#endif
-#ifdef __NR_timerfd_settime
- { __NR_timerfd_settime, "timerfd_settime" },
-#endif
-#ifdef __NR_times
- { __NR_times, "times" },
-#endif
-#ifdef __NR_tkill
- { __NR_tkill, "tkill" },
-#endif
-#ifdef __NR_truncate
- { __NR_truncate, "truncate" },
-#endif
-#ifdef __NR_truncate64
- { __NR_truncate64, "truncate64" },
-#endif
-#ifdef __NR_tuxcall
- { __NR_tuxcall, "tuxcall" },
-#endif
-#ifdef __NR_ugetrlimit
- { __NR_ugetrlimit, "ugetrlimit" },
-#endif
-#ifdef __NR_ulimit
- { __NR_ulimit, "ulimit" },
-#endif
-#ifdef __NR_umask
- { __NR_umask, "umask" },
-#endif
-#ifdef __NR_umount
- { __NR_umount, "umount" },
-#endif
-#ifdef __NR_umount2
- { __NR_umount2, "umount2" },
-#endif
-#ifdef __NR_uname
- { __NR_uname, "uname" },
-#endif
-#ifdef __NR_unlink
- { __NR_unlink, "unlink" },
-#endif
-#ifdef __NR_unlinkat
- { __NR_unlinkat, "unlinkat" },
-#endif
-#ifdef __NR_unshare
- { __NR_unshare, "unshare" },
-#endif
-#ifdef __NR_uselib
- { __NR_uselib, "uselib" },
-#endif
-#ifdef __NR_ustat
- { __NR_ustat, "ustat" },
-#endif
-#ifdef __NR_utime
- { __NR_utime, "utime" },
-#endif
-#ifdef __NR_utimensat
- { __NR_utimensat, "utimensat" },
-#endif
-#ifdef __NR_utimes
- { __NR_utimes, "utimes" },
-#endif
-#ifdef __NR_vfork
- { __NR_vfork, "vfork" },
-#endif
-#ifdef __NR_vhangup
- { __NR_vhangup, "vhangup" },
-#endif
-#ifdef __NR_vm86
- { __NR_vm86, "vm86" },
-#endif
-#ifdef __NR_vm86old
- { __NR_vm86old, "vm86old" },
-#endif
-#ifdef __NR_vmsplice
- { __NR_vmsplice, "vmsplice" },
-#endif
-#ifdef __NR_vserver
- { __NR_vserver, "vserver" },
-#endif
-#ifdef __NR_wait4
- { __NR_wait4, "wait4" },
-#endif
-#ifdef __NR_waitid
- { __NR_waitid, "waitid" },
-#endif
-#ifdef __NR_waitpid
- { __NR_waitpid, "waitpid" },
-#endif
-#ifdef __NR_write
- { __NR_write, "write" },
-#endif
-#ifdef __NR_writev
- { __NR_writev, "writev" },
-#endif
- {0, NULL}
-};
-
diff --git a/src/common/log.c b/src/common/log.c
deleted file mode 100644
index ebd50f62d3..0000000000
--- a/src/common/log.c
+++ /dev/null
@@ -1,1539 +0,0 @@
-/* Copyright (c) 2001, Matej Pfajfar.
- * Copyright (c) 2001-2004, Roger Dingledine.
- * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2017, The Tor Project, Inc. */
-/* See LICENSE for licensing information */
-
-/**
- * \file log.c
- * \brief Functions to send messages to log files or the console.
- **/
-
-#include "orconfig.h"
-#include <stdarg.h>
-#include <assert.h>
-// #include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#ifdef HAVE_SYS_TIME_H
-#include <sys/time.h>
-#endif
-#ifdef HAVE_TIME_H
-#include <time.h>
-#endif
-#ifdef HAVE_UNISTD_H
-#include <unistd.h>
-#endif
-#ifdef HAVE_SYS_TYPES_H
-#include <sys/types.h>
-#endif
-#ifdef HAVE_FCNTL_H
-#include <fcntl.h>
-#endif
-#include "compat.h"
-#include "util.h"
-#define LOG_PRIVATE
-#include "torlog.h"
-#include "container.h"
-#ifdef HAVE_ANDROID_LOG_H
-#include <android/log.h>
-#endif // HAVE_ANDROID_LOG_H.
-
-/** Given a severity, yields an index into log_severity_list_t.masks to use
- * for that severity. */
-#define SEVERITY_MASK_IDX(sev) ((sev) - LOG_ERR)
-
-/** @{ */
-/** The string we stick at the end of a log message when it is too long,
- * and its length. */
-#define TRUNCATED_STR "[...truncated]"
-#define TRUNCATED_STR_LEN 14
-/** @} */
-
-#define raw_assert(x) assert(x) // assert OK
-
-/** Defining compile-time constants for Tor log levels (used by the Rust
- * log wrapper at src/rust/tor_log) */
-const int LOG_WARN_ = LOG_WARN;
-const int LOG_NOTICE_ = LOG_NOTICE;
-const log_domain_mask_t LD_GENERAL_ = LD_GENERAL;
-const log_domain_mask_t LD_NET_ = LD_NET;
-
-/** Information for a single logfile; only used in log.c */
-typedef struct logfile_t {
- struct logfile_t *next; /**< Next logfile_t in the linked list. */
- char *filename; /**< Filename to open. */
- int fd; /**< fd to receive log messages, or -1 for none. */
- int seems_dead; /**< Boolean: true if the stream seems to be kaput. */
- int needs_close; /**< Boolean: true if the stream gets closed on shutdown. */
- int is_temporary; /**< Boolean: close after initializing logging subsystem.*/
- int is_syslog; /**< Boolean: send messages to syslog. */
- int is_android; /**< Boolean: send messages to Android's log subsystem. */
- char *android_tag; /**< Identity Tag used in Android's log subsystem. */
- log_callback callback; /**< If not NULL, send messages to this function. */
- log_severity_list_t *severities; /**< Which severity of messages should we
- * log for each log domain? */
-} logfile_t;
-
-static void log_free_(logfile_t *victim);
-#define log_free(lg) \
- FREE_AND_NULL(logfile_t, log_free_, (lg))
-
-/** Helper: map a log severity to descriptive string. */
-static inline const char *
-sev_to_string(int severity)
-{
- switch (severity) {
- case LOG_DEBUG: return "debug";
- case LOG_INFO: return "info";
- case LOG_NOTICE: return "notice";
- case LOG_WARN: return "warn";
- case LOG_ERR: return "err";
- default: /* Call assert, not tor_assert, since tor_assert
- * calls log on failure. */
- raw_assert(0); return "UNKNOWN"; // LCOV_EXCL_LINE
- }
-}
-
-/** Helper: decide whether to include the function name in the log message. */
-static inline int
-should_log_function_name(log_domain_mask_t domain, int severity)
-{
- switch (severity) {
- case LOG_DEBUG:
- case LOG_INFO:
- /* All debugging messages occur in interesting places. */
- return (domain & LD_NOFUNCNAME) == 0;
- case LOG_NOTICE:
- case LOG_WARN:
- case LOG_ERR:
- /* We care about places where bugs occur. */
- return (domain & (LD_BUG|LD_NOFUNCNAME)) == LD_BUG;
- default:
- /* Call assert, not tor_assert, since tor_assert calls log on failure. */
- raw_assert(0); return 0; // LCOV_EXCL_LINE
- }
-}
-
-#ifdef HAVE_ANDROID_LOG_H
-/** Helper function to convert Tor's log severity into the matching
- * Android log priority.
- */
-static int
-severity_to_android_log_priority(int severity)
-{
- switch (severity) {
- case LOG_DEBUG:
- return ANDROID_LOG_VERBOSE;
- case LOG_INFO:
- return ANDROID_LOG_DEBUG;
- case LOG_NOTICE:
- return ANDROID_LOG_INFO;
- case LOG_WARN:
- return ANDROID_LOG_WARN;
- case LOG_ERR:
- return ANDROID_LOG_ERROR;
- default:
- // LCOV_EXCL_START
- raw_assert(0);
- return 0;
- // LCOV_EXCL_STOP
- }
-}
-#endif // HAVE_ANDROID_LOG_H.
-
-/** A mutex to guard changes to logfiles and logging. */
-static tor_mutex_t log_mutex;
-/** True iff we have initialized log_mutex */
-static int log_mutex_initialized = 0;
-
-/** Linked list of logfile_t. */
-static logfile_t *logfiles = NULL;
-/** Boolean: do we report logging domains? */
-static int log_domains_are_logged = 0;
-
-#ifdef HAVE_SYSLOG_H
-/** The number of open syslog log handlers that we have. When this reaches 0,
- * we can close our connection to the syslog facility. */
-static int syslog_count = 0;
-#endif
-
-/** Represents a log message that we are going to send to callback-driven
- * loggers once we can do so in a non-reentrant way. */
-typedef struct pending_log_message_t {
- int severity; /**< The severity of the message */
- log_domain_mask_t domain; /**< The domain of the message */
- char *fullmsg; /**< The message, with all decorations */
- char *msg; /**< The content of the message */
-} pending_log_message_t;
-
-/** Log messages waiting to be replayed onto callback-based logs */
-static smartlist_t *pending_cb_messages = NULL;
-
-/** Callback to invoke when pending_cb_messages becomes nonempty. */
-static pending_callback_callback pending_cb_cb = NULL;
-
-/** Log messages waiting to be replayed once the logging system is initialized.
- */
-static smartlist_t *pending_startup_messages = NULL;
-
-/** Number of bytes of messages queued in pending_startup_messages. (This is
- * the length of the messages, not the number of bytes used to store
- * them.) */
-static size_t pending_startup_messages_len;
-
-/** True iff we should store messages while waiting for the logs to get
- * configured. */
-static int queue_startup_messages = 1;
-
-/** True iff __PRETTY_FUNCTION__ includes parenthesized arguments. */
-static int pretty_fn_has_parens = 0;
-
-/** Don't store more than this many bytes of messages while waiting for the
- * logs to get configured. */
-#define MAX_STARTUP_MSG_LEN (1<<16)
-
-/** Lock the log_mutex to prevent others from changing the logfile_t list */
-#define LOCK_LOGS() STMT_BEGIN \
- tor_assert(log_mutex_initialized); \
- tor_mutex_acquire(&log_mutex); \
- STMT_END
-/** Unlock the log_mutex */
-#define UNLOCK_LOGS() STMT_BEGIN \
- tor_assert(log_mutex_initialized); \
- tor_mutex_release(&log_mutex); \
- STMT_END
-
-/** 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;
-
-static void delete_log(logfile_t *victim);
-static void close_log(logfile_t *victim);
-
-static char *domain_to_string(log_domain_mask_t domain,
- char *buf, size_t buflen);
-static inline char *format_msg(char *buf, size_t buf_len,
- log_domain_mask_t domain, int severity, const char *funcname,
- const char *suffix,
- const char *format, va_list ap, size_t *msg_len_out)
- CHECK_PRINTF(7,0);
-
-/** Name of the application: used to generate the message we write at the
- * start of each new log. */
-static char *appname = NULL;
-
-/** Set the "application name" for the logs to <b>name</b>: we'll use this
- * name in the message we write when starting up, and at the start of each new
- * log.
- *
- * Tor uses this string to write the version number to the log file. */
-void
-log_set_application_name(const char *name)
-{
- tor_free(appname);
- appname = name ? tor_strdup(name) : NULL;
-}
-
-/** Return true if some of the running logs might be interested in a log
- * message of the given severity in the given domains. If this function
- * returns true, the log message might be ignored anyway, but if it returns
- * false, it is definitely_ safe not to log the message. */
-int
-log_message_is_interesting(int severity, log_domain_mask_t domain)
-{
- (void) domain;
- return (severity <= log_global_min_severity_);
-}
-
-/**
- * As tor_log, but takes an optional function name, and does not treat its
- * <b>string</b> as a printf format.
- *
- * For use by Rust integration.
- */
-void
-tor_log_string(int severity, log_domain_mask_t domain,
- const char *function, const char *string)
-{
- log_fn_(severity, domain, function, "%s", string);
-}
-
-/** Log time granularity in milliseconds. */
-static int log_time_granularity = 1;
-
-/** Define log time granularity for all logs to be <b>granularity_msec</b>
- * milliseconds. */
-void
-set_log_time_granularity(int granularity_msec)
-{
- log_time_granularity = granularity_msec;
-}
-
-/** Helper: Write the standard prefix for log lines to a
- * <b>buf_len</b> character buffer in <b>buf</b>.
- */
-static inline size_t
-log_prefix_(char *buf, size_t buf_len, int severity)
-{
- time_t t;
- struct timeval now;
- struct tm tm;
- size_t n;
- int r, ms;
-
- tor_gettimeofday(&now);
- t = (time_t)now.tv_sec;
- ms = (int)now.tv_usec / 1000;
- if (log_time_granularity >= 1000) {
- t -= t % (log_time_granularity / 1000);
- ms = 0;
- } else {
- ms -= ((int)now.tv_usec / 1000) % log_time_granularity;
- }
-
- n = strftime(buf, buf_len, "%b %d %H:%M:%S", tor_localtime_r(&t, &tm));
- r = tor_snprintf(buf+n, buf_len-n, ".%.3i [%s] ", ms,
- sev_to_string(severity));
-
- if (r<0)
- return buf_len-1;
- else
- return n+r;
-}
-
-/** If lf refers to an actual file that we have just opened, and the file
- * contains no data, log an "opening new logfile" message at the top.
- *
- * Return -1 if the log is broken and needs to be deleted, else return 0.
- */
-static int
-log_tor_version(logfile_t *lf, int reset)
-{
- char buf[256];
- size_t n;
- int is_new;
-
- if (!lf->needs_close)
- /* If it doesn't get closed, it isn't really a file. */
- return 0;
- if (lf->is_temporary)
- /* If it's temporary, it isn't really a file. */
- return 0;
-
- is_new = lf->fd >= 0 && tor_fd_getpos(lf->fd) == 0;
-
- if (reset && !is_new)
- /* 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);
- if (appname) {
- tor_snprintf(buf+n, sizeof(buf)-n,
- "%s opening %slog file.\n", appname, is_new?"new ":"");
- } else {
- tor_snprintf(buf+n, sizeof(buf)-n,
- "Tor %s opening %slog file.\n", VERSION, is_new?"new ":"");
- }
- if (write_all(lf->fd, buf, strlen(buf), 0) < 0) /* error */
- return -1; /* failed */
- return 0;
-}
-
-static const char bug_suffix[] = " (on Tor " VERSION
-#ifndef _MSC_VER
- " "
-#include "micro-revision.i"
-#endif
- ")";
-
-/** Helper: Format a log message into a fixed-sized buffer. (This is
- * factored out of <b>logv</b> so that we never format a message more
- * than once.) Return a pointer to the first character of the message
- * portion of the formatted string.
- */
-static inline char *
-format_msg(char *buf, size_t buf_len,
- log_domain_mask_t domain, int severity, const char *funcname,
- const char *suffix,
- const char *format, va_list ap, size_t *msg_len_out)
-{
- size_t n;
- int r;
- char *end_of_prefix;
- char *buf_end;
-
- raw_assert(buf_len >= 16); /* prevent integer underflow and stupidity */
- 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);
- end_of_prefix = buf+n;
-
- if (log_domains_are_logged) {
- char *cp = buf+n;
- if (cp == buf_end) goto format_msg_no_room_for_domains;
- *cp++ = '{';
- if (cp == buf_end) goto format_msg_no_room_for_domains;
- cp = domain_to_string(domain, cp, (buf+buf_len-cp));
- if (cp == buf_end) goto format_msg_no_room_for_domains;
- *cp++ = '}';
- if (cp == buf_end) goto format_msg_no_room_for_domains;
- *cp++ = ' ';
- if (cp == buf_end) goto format_msg_no_room_for_domains;
- end_of_prefix = cp;
- n = cp-buf;
- format_msg_no_room_for_domains:
- /* This will leave end_of_prefix and n unchanged, and thus cause
- * whatever log domain string we had written to be clobbered. */
- ;
- }
-
- if (funcname && should_log_function_name(domain, severity)) {
- r = tor_snprintf(buf+n, buf_len-n,
- pretty_fn_has_parens ? "%s: " : "%s(): ",
- funcname);
- if (r<0)
- n = strlen(buf);
- else
- n += r;
- }
-
- if (domain == LD_BUG && buf_len-n > 6) {
- memcpy(buf+n, "Bug: ", 6);
- n += 5;
- }
-
- r = tor_vsnprintf(buf+n,buf_len-n,format,ap);
- if (r < 0) {
- /* The message was too long; overwrite the end of the buffer with
- * "[...truncated]" */
- if (buf_len >= TRUNCATED_STR_LEN) {
- size_t offset = buf_len-TRUNCATED_STR_LEN;
- /* We have an extra 2 characters after buf_len to hold the \n\0,
- * so it's safe to add 1 to the size here. */
- strlcpy(buf+offset, TRUNCATED_STR, buf_len-offset+1);
- }
- /* Set 'n' to the end of the buffer, where we'll be writing \n\0.
- * Since we already subtracted 2 from buf_len, this is safe.*/
- n = buf_len;
- } else {
- n += r;
- if (suffix) {
- size_t suffix_len = strlen(suffix);
- if (buf_len-n >= suffix_len) {
- memcpy(buf+n, suffix, suffix_len);
- n += suffix_len;
- }
- }
- }
-
- if (domain == LD_BUG &&
- buf_len - n > strlen(bug_suffix)+1) {
- memcpy(buf+n, bug_suffix, strlen(bug_suffix));
- n += strlen(bug_suffix);
- }
-
- buf[n]='\n';
- buf[n+1]='\0';
- *msg_len_out = n+1;
- return end_of_prefix;
-}
-
-/* Create a new pending_log_message_t with appropriate values */
-static pending_log_message_t *
-pending_log_message_new(int severity, log_domain_mask_t domain,
- const char *fullmsg, const char *shortmsg)
-{
- pending_log_message_t *m = tor_malloc(sizeof(pending_log_message_t));
- m->severity = severity;
- m->domain = domain;
- m->fullmsg = fullmsg ? tor_strdup(fullmsg) : NULL;
- m->msg = tor_strdup(shortmsg);
- return m;
-}
-
-#define pending_log_message_free(msg) \
- FREE_AND_NULL(pending_log_message_t, pending_log_message_free_, (msg))
-
-/** Release all storage held by <b>msg</b>. */
-static void
-pending_log_message_free_(pending_log_message_t *msg)
-{
- if (!msg)
- return;
- tor_free(msg->msg);
- tor_free(msg->fullmsg);
- tor_free(msg);
-}
-
-/** Helper function: returns true iff the log file, given in <b>lf</b>, is
- * handled externally via the system log API, the Android logging API, or is an
- * external callback function. */
-static inline int
-logfile_is_external(const logfile_t *lf)
-{
- raw_assert(lf);
- return lf->is_syslog || lf->is_android || lf->callback;
-}
-
-/** Return true iff <b>lf</b> would like to receive a message with the
- * specified <b>severity</b> in the specified <b>domain</b>.
- */
-static inline int
-logfile_wants_message(const logfile_t *lf, int severity,
- log_domain_mask_t domain)
-{
- if (! (lf->severities->masks[SEVERITY_MASK_IDX(severity)] & domain)) {
- return 0;
- }
- if (! (lf->fd >= 0 || logfile_is_external(lf))) {
- return 0;
- }
- if (lf->seems_dead) {
- return 0;
- }
-
- return 1;
-}
-
-/** Send a message to <b>lf</b>. The full message, with time prefix and
- * severity, is in <b>buf</b>. The message itself is in
- * <b>msg_after_prefix</b>. If <b>callbacks_deferred</b> points to true, then
- * we already deferred this message for pending callbacks and don't need to do
- * it again. Otherwise, if we need to do it, do it, and set
- * <b>callbacks_deferred</b> to 1. */
-static inline void
-logfile_deliver(logfile_t *lf, const char *buf, size_t msg_len,
- const char *msg_after_prefix, log_domain_mask_t domain,
- int severity, int *callbacks_deferred)
-{
-
- if (lf->is_syslog) {
-#ifdef HAVE_SYSLOG_H
-#ifdef MAXLINE
- /* Some syslog implementations have limits on the length of what you can
- * pass them, and some very old ones do not detect overflow so well.
- * Regrettably, they call their maximum line length MAXLINE. */
-#if MAXLINE < 64
-#warn "MAXLINE is a very low number; it might not be from syslog.h after all"
-#endif
- char *m = msg_after_prefix;
- if (msg_len >= MAXLINE)
- m = tor_strndup(msg_after_prefix, MAXLINE-1);
- syslog(severity, "%s", m);
- if (m != msg_after_prefix) {
- tor_free(m);
- }
-#else /* !(defined(MAXLINE)) */
- /* We have syslog but not MAXLINE. That's promising! */
- syslog(severity, "%s", msg_after_prefix);
-#endif /* defined(MAXLINE) */
-#endif /* defined(HAVE_SYSLOG_H) */
- } else if (lf->is_android) {
-#ifdef HAVE_ANDROID_LOG_H
- int priority = severity_to_android_log_priority(severity);
- __android_log_write(priority, lf->android_tag, msg_after_prefix);
-#endif // HAVE_ANDROID_LOG_H.
- } else if (lf->callback) {
- if (domain & LD_NOCB) {
- if (!*callbacks_deferred && pending_cb_messages) {
- smartlist_add(pending_cb_messages,
- pending_log_message_new(severity,domain,NULL,msg_after_prefix));
- *callbacks_deferred = 1;
- if (smartlist_len(pending_cb_messages) == 1 && pending_cb_cb) {
- pending_cb_cb();
- }
- }
- } else {
- lf->callback(severity, domain, msg_after_prefix);
- }
- } else {
- if (write_all(lf->fd, buf, msg_len, 0) < 0) { /* error */
- /* don't log the error! mark this log entry to be blown away, and
- * continue. */
- lf->seems_dead = 1;
- }
- }
-}
-
-/** Helper: sends a message to the appropriate logfiles, at loglevel
- * <b>severity</b>. If provided, <b>funcname</b> is prepended to the
- * message. The actual message is derived as from tor_snprintf(format,ap).
- */
-MOCK_IMPL(STATIC void,
-logv,(int severity, log_domain_mask_t domain, const char *funcname,
- const char *suffix, const char *format, va_list ap))
-{
- char buf[10240];
- size_t msg_len = 0;
- int formatted = 0;
- logfile_t *lf;
- char *end_of_prefix=NULL;
- int callbacks_deferred = 0;
-
- /* Call assert, not tor_assert, since tor_assert calls log on failure. */
- raw_assert(format);
- /* check that severity is sane. Overrunning the masks array leads to
- * interesting and hard to diagnose effects */
- raw_assert(severity >= LOG_ERR && severity <= LOG_DEBUG);
- /* check that we've initialised the log mutex before we try to lock it */
- raw_assert(log_mutex_initialized);
- LOCK_LOGS();
-
- if ((! (domain & LD_NOCB)) && pending_cb_messages
- && smartlist_len(pending_cb_messages))
- flush_pending_log_callbacks();
-
- if (queue_startup_messages &&
- pending_startup_messages_len < MAX_STARTUP_MSG_LEN) {
- end_of_prefix =
- format_msg(buf, sizeof(buf), domain, severity, funcname, suffix,
- format, ap, &msg_len);
- formatted = 1;
-
- smartlist_add(pending_startup_messages,
- pending_log_message_new(severity,domain,buf,end_of_prefix));
- pending_startup_messages_len += msg_len;
- }
-
- for (lf = logfiles; lf; lf = lf->next) {
- if (! logfile_wants_message(lf, severity, domain))
- continue;
-
- if (!formatted) {
- end_of_prefix =
- format_msg(buf, sizeof(buf), domain, severity, funcname, suffix,
- format, ap, &msg_len);
- formatted = 1;
- }
-
- logfile_deliver(lf, buf, msg_len, end_of_prefix, domain, severity,
- &callbacks_deferred);
- }
- UNLOCK_LOGS();
-}
-
-/** Output a message to the log. It gets logged to all logfiles that
- * care about messages with <b>severity</b> in <b>domain</b>. The content
- * is formatted printf-style based on <b>format</b> and extra arguments.
- * */
-void
-tor_log(int severity, log_domain_mask_t domain, const char *format, ...)
-{
- va_list ap;
- if (severity > log_global_min_severity_)
- return;
- va_start(ap,format);
-#ifdef TOR_UNIT_TESTS
- if (domain & LD_NO_MOCK)
- logv__real(severity, domain, NULL, NULL, format, ap);
- else
-#endif
- logv(severity, domain, NULL, NULL, format, ap);
- va_end(ap);
-}
-
-/** Maximum number of fds that will get notifications if we crash */
-#define MAX_SIGSAFE_FDS 8
-/** Array of fds to log crash-style warnings to. */
-static int sigsafe_log_fds[MAX_SIGSAFE_FDS] = { STDERR_FILENO };
-/** The number of elements used in sigsafe_log_fds */
-static int n_sigsafe_log_fds = 1;
-
-/** Write <b>s</b> to each element of sigsafe_log_fds. Return 0 on success, -1
- * on failure. */
-static int
-tor_log_err_sigsafe_write(const char *s)
-{
- int i;
- ssize_t r;
- size_t len = strlen(s);
- int err = 0;
- for (i=0; i < n_sigsafe_log_fds; ++i) {
- r = write(sigsafe_log_fds[i], s, len);
- err += (r != (ssize_t)len);
- }
- return err ? -1 : 0;
-}
-
-/** Given a list of string arguments ending with a NULL, writes them
- * to our logs and to stderr (if possible). This function is safe to call
- * from within a signal handler. */
-void
-tor_log_err_sigsafe(const char *m, ...)
-{
- va_list ap;
- const char *x;
- char timebuf[33];
- time_t now = time(NULL);
-
- if (!m)
- return;
- if (log_time_granularity >= 2000) {
- int g = log_time_granularity / 1000;
- now -= now % g;
- }
- timebuf[0] = now < 0 ? '-' : ' ';
- if (now < 0) now = -now;
- timebuf[1] = '\0';
- format_dec_number_sigsafe(now, timebuf+1, sizeof(timebuf)-1);
- tor_log_err_sigsafe_write("\n=========================================="
- "================== T=");
- tor_log_err_sigsafe_write(timebuf);
- tor_log_err_sigsafe_write("\n");
- tor_log_err_sigsafe_write(m);
- va_start(ap, m);
- while ((x = va_arg(ap, const char*))) {
- tor_log_err_sigsafe_write(x);
- }
- va_end(ap);
-}
-
-/** Set *<b>out</b> to a pointer to an array of the fds to log errors to from
- * inside a signal handler. Return the number of elements in the array. */
-int
-tor_log_get_sigsafe_err_fds(const int **out)
-{
- *out = sigsafe_log_fds;
- return n_sigsafe_log_fds;
-}
-
-/** Helper function; return true iff the <b>n</b>-element array <b>array</b>
- * contains <b>item</b>. */
-static int
-int_array_contains(const int *array, int n, int item)
-{
- int j;
- for (j = 0; j < n; ++j) {
- if (array[j] == item)
- return 1;
- }
- return 0;
-}
-
-/** Function to call whenever the list of logs changes to get ready to log
- * from signal handlers. */
-void
-tor_log_update_sigsafe_err_fds(void)
-{
- const logfile_t *lf;
- int found_real_stderr = 0;
-
- LOCK_LOGS();
- /* Reserve the first one for stderr. This is safe because when we daemonize,
- * we dup2 /dev/null to stderr, */
- sigsafe_log_fds[0] = STDERR_FILENO;
- n_sigsafe_log_fds = 1;
-
- for (lf = logfiles; lf; lf = lf->next) {
- /* Don't try callback to the control port, or syslogs: We can't
- * do them from a signal handler. Don't try stdout: we always do stderr.
- */
- if (lf->is_temporary || logfile_is_external(lf)
- || lf->seems_dead || lf->fd < 0)
- continue;
- if (lf->severities->masks[SEVERITY_MASK_IDX(LOG_ERR)] &
- (LD_BUG|LD_GENERAL)) {
- if (lf->fd == STDERR_FILENO)
- found_real_stderr = 1;
- /* Avoid duplicates */
- if (int_array_contains(sigsafe_log_fds, n_sigsafe_log_fds, lf->fd))
- continue;
- sigsafe_log_fds[n_sigsafe_log_fds++] = lf->fd;
- if (n_sigsafe_log_fds == MAX_SIGSAFE_FDS)
- break;
- }
- }
-
- if (!found_real_stderr &&
- int_array_contains(sigsafe_log_fds, n_sigsafe_log_fds, STDOUT_FILENO)) {
- /* Don't use a virtual stderr when we're also logging to stdout. */
- raw_assert(n_sigsafe_log_fds >= 2); /* Don't tor_assert inside log fns */
- sigsafe_log_fds[0] = sigsafe_log_fds[--n_sigsafe_log_fds];
- }
-
- UNLOCK_LOGS();
-}
-
-/** Add to <b>out</b> a copy of every currently configured log file name. Used
- * to enable access to these filenames with the sandbox code. */
-void
-tor_log_get_logfile_names(smartlist_t *out)
-{
- logfile_t *lf;
- tor_assert(out);
-
- LOCK_LOGS();
-
- for (lf = logfiles; lf; lf = lf->next) {
- if (lf->is_temporary || logfile_is_external(lf))
- continue;
- if (lf->filename == NULL)
- continue;
- smartlist_add_strdup(out, lf->filename);
- }
-
- UNLOCK_LOGS();
-}
-
-/** Implementation of the log_fn backend, used when we have
- * 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,
- const char *format, ...)
-{
- va_list ap;
- if (severity > log_global_min_severity_)
- return;
- va_start(ap,format);
- logv(severity, domain, fn, NULL, format, ap);
- va_end(ap);
-}
-void
-log_fn_ratelim_(ratelim_t *ratelim, int severity, log_domain_mask_t domain,
- const char *fn, const char *format, ...)
-{
- va_list ap;
- char *m;
- if (severity > log_global_min_severity_)
- return;
- m = rate_limit_log(ratelim, approx_time());
- if (m == NULL)
- return;
- va_start(ap, format);
- logv(severity, domain, fn, m, format, ap);
- va_end(ap);
- tor_free(m);
-}
-
-/** Free all storage held by <b>victim</b>. */
-static void
-log_free_(logfile_t *victim)
-{
- if (!victim)
- return;
- tor_free(victim->severities);
- tor_free(victim->filename);
- tor_free(victim->android_tag);
- tor_free(victim);
-}
-
-/** Close all open log files, and free other static memory. */
-void
-logs_free_all(void)
-{
- logfile_t *victim, *next;
- smartlist_t *messages, *messages2;
- LOCK_LOGS();
- next = logfiles;
- logfiles = NULL;
- messages = pending_cb_messages;
- pending_cb_messages = NULL;
- pending_cb_cb = NULL;
- messages2 = pending_startup_messages;
- pending_startup_messages = NULL;
- UNLOCK_LOGS();
- while (next) {
- victim = next;
- next = next->next;
- close_log(victim);
- log_free(victim);
- }
- tor_free(appname);
-
- SMARTLIST_FOREACH(messages, pending_log_message_t *, msg, {
- pending_log_message_free(msg);
- });
- smartlist_free(messages);
-
- if (messages2) {
- SMARTLIST_FOREACH(messages2, pending_log_message_t *, msg, {
- pending_log_message_free(msg);
- });
- smartlist_free(messages2);
- }
-
- /* We _could_ destroy the log mutex here, but that would screw up any logs
- * that happened between here and the end of execution. */
-}
-
-/** Remove and free the log entry <b>victim</b> from the linked-list
- * logfiles (it is probably present, but it might not be due to thread
- * racing issues). After this function is called, the caller shouldn't
- * refer to <b>victim</b> anymore.
- *
- * Long-term, we need to do something about races in the log subsystem
- * in general. See bug 222 for more details.
- */
-static void
-delete_log(logfile_t *victim)
-{
- logfile_t *tmpl;
- if (victim == logfiles)
- logfiles = victim->next;
- else {
- for (tmpl = logfiles; tmpl && tmpl->next != victim; tmpl=tmpl->next) ;
-// tor_assert(tmpl);
-// tor_assert(tmpl->next == victim);
- if (!tmpl)
- return;
- tmpl->next = victim->next;
- }
- log_free(victim);
-}
-
-/** Helper: release system resources (but not memory) held by a single
- * logfile_t. */
-static void
-close_log(logfile_t *victim)
-{
- if (victim->needs_close && victim->fd >= 0) {
- close(victim->fd);
- victim->fd = -1;
- } else if (victim->is_syslog) {
-#ifdef HAVE_SYSLOG_H
- if (--syslog_count == 0) {
- /* There are no other syslogs; close the logging facility. */
- closelog();
- }
-#endif /* defined(HAVE_SYSLOG_H) */
- }
-}
-
-/** Adjust a log severity configuration in <b>severity_out</b> to contain
- * every domain between <b>loglevelMin</b> and <b>loglevelMax</b>, inclusive.
- */
-void
-set_log_severity_config(int loglevelMin, int loglevelMax,
- log_severity_list_t *severity_out)
-{
- int i;
- tor_assert(loglevelMin >= loglevelMax);
- tor_assert(loglevelMin >= LOG_ERR && loglevelMin <= LOG_DEBUG);
- tor_assert(loglevelMax >= LOG_ERR && loglevelMax <= LOG_DEBUG);
- memset(severity_out, 0, sizeof(log_severity_list_t));
- for (i = loglevelMin; i >= loglevelMax; --i) {
- severity_out->masks[SEVERITY_MASK_IDX(i)] = ~0u;
- }
-}
-
-/** Add a log handler named <b>name</b> to send all messages in <b>severity</b>
- * to <b>fd</b>. Copies <b>severity</b>. Helper: does no locking. */
-static void
-add_stream_log_impl(const log_severity_list_t *severity,
- const char *name, int fd)
-{
- logfile_t *lf;
- lf = tor_malloc_zero(sizeof(logfile_t));
- lf->fd = fd;
- lf->filename = tor_strdup(name);
- lf->severities = tor_memdup(severity, sizeof(log_severity_list_t));
- lf->next = logfiles;
-
- logfiles = lf;
- log_global_min_severity_ = get_min_log_level();
-}
-
-/** Add a log handler named <b>name</b> to send all messages in <b>severity</b>
- * to <b>fd</b>. Steals a reference to <b>severity</b>; the caller must
- * not use it after calling this function. */
-void
-add_stream_log(const log_severity_list_t *severity, const char *name, int fd)
-{
- LOCK_LOGS();
- add_stream_log_impl(severity, name, fd);
- UNLOCK_LOGS();
-}
-
-/** Initialize the global logging facility */
-void
-init_logging(int disable_startup_queue)
-{
- if (!log_mutex_initialized) {
- tor_mutex_init(&log_mutex);
- log_mutex_initialized = 1;
- }
-#ifdef __GNUC__
- if (strchr(__PRETTY_FUNCTION__, '(')) {
- pretty_fn_has_parens = 1;
- }
-#endif
- if (pending_cb_messages == NULL)
- pending_cb_messages = smartlist_new();
- if (disable_startup_queue)
- queue_startup_messages = 0;
- if (pending_startup_messages == NULL && queue_startup_messages) {
- pending_startup_messages = smartlist_new();
- }
-}
-
-/** Set whether we report logging domains as a part of our log messages.
- */
-void
-logs_set_domain_logging(int enabled)
-{
- LOCK_LOGS();
- log_domains_are_logged = enabled;
- UNLOCK_LOGS();
-}
-
-/** Add a log handler to receive messages during startup (before the real
- * logs are initialized).
- */
-void
-add_temp_log(int min_severity)
-{
- log_severity_list_t *s = tor_malloc_zero(sizeof(log_severity_list_t));
- set_log_severity_config(min_severity, LOG_ERR, s);
- LOCK_LOGS();
- add_stream_log_impl(s, "<temp>", fileno(stdout));
- tor_free(s);
- logfiles->is_temporary = 1;
- UNLOCK_LOGS();
-}
-
-/**
- * Register "cb" as the callback to call when there are new pending log
- * callbacks to be flushed with flush_pending_log_callbacks().
- *
- * Note that this callback, if present, can be invoked from any thread.
- *
- * This callback must not log.
- *
- * It is intentional that this function contains the name "callback" twice: it
- * sets a "callback" to be called on the condition that there is a "pending
- * callback".
- **/
-void
-logs_set_pending_callback_callback(pending_callback_callback cb)
-{
- pending_cb_cb = cb;
-}
-
-/**
- * Add a log handler to send messages in <b>severity</b>
- * to the function <b>cb</b>.
- */
-int
-add_callback_log(const log_severity_list_t *severity, log_callback cb)
-{
- logfile_t *lf;
- lf = tor_malloc_zero(sizeof(logfile_t));
- lf->fd = -1;
- lf->severities = tor_memdup(severity, sizeof(log_severity_list_t));
- lf->filename = tor_strdup("<callback>");
- lf->callback = cb;
- lf->next = logfiles;
-
- LOCK_LOGS();
- logfiles = lf;
- log_global_min_severity_ = get_min_log_level();
- UNLOCK_LOGS();
- return 0;
-}
-
-/** Adjust the configured severity of any logs whose callback function is
- * <b>cb</b>. */
-void
-change_callback_log_severity(int loglevelMin, int loglevelMax,
- log_callback cb)
-{
- logfile_t *lf;
- log_severity_list_t severities;
- set_log_severity_config(loglevelMin, loglevelMax, &severities);
- LOCK_LOGS();
- for (lf = logfiles; lf; lf = lf->next) {
- if (lf->callback == cb) {
- memcpy(lf->severities, &severities, sizeof(severities));
- }
- }
- log_global_min_severity_ = get_min_log_level();
- UNLOCK_LOGS();
-}
-
-/** If there are any log messages that were generated with LD_NOCB waiting to
- * be sent to callback-based loggers, send them now. */
-void
-flush_pending_log_callbacks(void)
-{
- logfile_t *lf;
- smartlist_t *messages, *messages_tmp;
-
- LOCK_LOGS();
- if (!pending_cb_messages || 0 == smartlist_len(pending_cb_messages)) {
- UNLOCK_LOGS();
- return;
- }
-
- messages = pending_cb_messages;
- pending_cb_messages = smartlist_new();
- do {
- SMARTLIST_FOREACH_BEGIN(messages, pending_log_message_t *, msg) {
- const int severity = msg->severity;
- const int domain = msg->domain;
- for (lf = logfiles; lf; lf = lf->next) {
- if (! lf->callback || lf->seems_dead ||
- ! (lf->severities->masks[SEVERITY_MASK_IDX(severity)] & domain)) {
- continue;
- }
- lf->callback(severity, domain, msg->msg);
- }
- pending_log_message_free(msg);
- } SMARTLIST_FOREACH_END(msg);
- smartlist_clear(messages);
-
- messages_tmp = pending_cb_messages;
- pending_cb_messages = messages;
- messages = messages_tmp;
- } while (smartlist_len(messages));
-
- smartlist_free(messages);
-
- UNLOCK_LOGS();
-}
-
-/** Flush all the messages we stored from startup while waiting for log
- * initialization.
- */
-void
-flush_log_messages_from_startup(void)
-{
- logfile_t *lf;
-
- LOCK_LOGS();
- queue_startup_messages = 0;
- pending_startup_messages_len = 0;
- if (! pending_startup_messages)
- goto out;
-
- SMARTLIST_FOREACH_BEGIN(pending_startup_messages, pending_log_message_t *,
- msg) {
- int callbacks_deferred = 0;
- for (lf = logfiles; lf; lf = lf->next) {
- if (! logfile_wants_message(lf, msg->severity, msg->domain))
- continue;
-
- /* We configure a temporary startup log that goes to stdout, so we
- * shouldn't replay to stdout/stderr*/
- if (lf->fd == STDOUT_FILENO || lf->fd == STDERR_FILENO) {
- continue;
- }
-
- logfile_deliver(lf, msg->fullmsg, strlen(msg->fullmsg), msg->msg,
- msg->domain, msg->severity, &callbacks_deferred);
- }
- pending_log_message_free(msg);
- } SMARTLIST_FOREACH_END(msg);
- smartlist_free(pending_startup_messages);
- pending_startup_messages = NULL;
-
- out:
- UNLOCK_LOGS();
-}
-
-/** Close any log handlers added by add_temp_log() or marked by
- * mark_logs_temp(). */
-void
-close_temp_logs(void)
-{
- logfile_t *lf, **p;
-
- LOCK_LOGS();
- for (p = &logfiles; *p; ) {
- if ((*p)->is_temporary) {
- lf = *p;
- /* we use *p here to handle the edge case of the head of the list */
- *p = (*p)->next;
- close_log(lf);
- log_free(lf);
- } else {
- p = &((*p)->next);
- }
- }
-
- log_global_min_severity_ = get_min_log_level();
- UNLOCK_LOGS();
-}
-
-/** Make all currently temporary logs (set to be closed by close_temp_logs)
- * live again, and close all non-temporary logs. */
-void
-rollback_log_changes(void)
-{
- logfile_t *lf;
- LOCK_LOGS();
- for (lf = logfiles; lf; lf = lf->next)
- lf->is_temporary = ! lf->is_temporary;
- UNLOCK_LOGS();
- close_temp_logs();
-}
-
-/** Configure all log handles to be closed by close_temp_logs(). */
-void
-mark_logs_temp(void)
-{
- logfile_t *lf;
- LOCK_LOGS();
- for (lf = logfiles; lf; lf = lf->next)
- lf->is_temporary = 1;
- UNLOCK_LOGS();
-}
-
-/**
- * Add a log handler to send messages to <b>filename</b>. If opening the
- * logfile fails, -1 is returned and errno is set appropriately (by open(2)).
- */
-int
-add_file_log(const log_severity_list_t *severity, const char *filename,
- const int truncate_log)
-{
- int fd;
- logfile_t *lf;
-
- int open_flags = O_WRONLY|O_CREAT;
- open_flags |= truncate_log ? O_TRUNC : O_APPEND;
-
- fd = tor_open_cloexec(filename, open_flags, 0640);
- if (fd<0)
- return -1;
- if (tor_fd_seekend(fd)<0) {
- close(fd);
- return -1;
- }
-
- LOCK_LOGS();
- add_stream_log_impl(severity, filename, fd);
- logfiles->needs_close = 1;
- lf = logfiles;
- log_global_min_severity_ = get_min_log_level();
-
- if (log_tor_version(lf, 0) < 0) {
- delete_log(lf);
- }
- UNLOCK_LOGS();
-
- return 0;
-}
-
-#ifdef HAVE_SYSLOG_H
-/**
- * Add a log handler to send messages to they system log facility.
- *
- * If this is the first log handler, opens syslog with ident Tor or
- * Tor-<syslog_identity_tag> if that is not NULL.
- */
-int
-add_syslog_log(const log_severity_list_t *severity,
- const char* syslog_identity_tag)
-{
- logfile_t *lf;
- if (syslog_count++ == 0) {
- /* This is the first syslog. */
- static char buf[256];
- if (syslog_identity_tag) {
- tor_snprintf(buf, sizeof(buf), "Tor-%s", syslog_identity_tag);
- } else {
- tor_snprintf(buf, sizeof(buf), "Tor");
- }
- openlog(buf, LOG_PID | LOG_NDELAY, LOGFACILITY);
- }
-
- lf = tor_malloc_zero(sizeof(logfile_t));
- lf->fd = -1;
- lf->severities = tor_memdup(severity, sizeof(log_severity_list_t));
- lf->filename = tor_strdup("<syslog>");
- lf->is_syslog = 1;
-
- LOCK_LOGS();
- lf->next = logfiles;
- logfiles = lf;
- log_global_min_severity_ = get_min_log_level();
- UNLOCK_LOGS();
- return 0;
-}
-#endif /* defined(HAVE_SYSLOG_H) */
-
-#ifdef HAVE_ANDROID_LOG_H
-/**
- * Add a log handler to send messages to the Android platform log facility.
- */
-int
-add_android_log(const log_severity_list_t *severity,
- const char *android_tag)
-{
- logfile_t *lf = NULL;
-
- lf = tor_malloc_zero(sizeof(logfile_t));
- lf->fd = -1;
- lf->severities = tor_memdup(severity, sizeof(log_severity_list_t));
- lf->filename = tor_strdup("<android>");
- lf->is_android = 1;
-
- if (android_tag == NULL)
- lf->android_tag = tor_strdup("Tor");
- else {
- char buf[256];
- tor_snprintf(buf, sizeof(buf), "Tor-%s", android_tag);
- lf->android_tag = tor_strdup(buf);
- }
-
- LOCK_LOGS();
- lf->next = logfiles;
- logfiles = lf;
- log_global_min_severity_ = get_min_log_level();
- UNLOCK_LOGS();
- return 0;
-}
-#endif // HAVE_ANDROID_LOG_H.
-
-/** If <b>level</b> is a valid log severity, return the corresponding
- * numeric value. Otherwise, return -1. */
-int
-parse_log_level(const char *level)
-{
- if (!strcasecmp(level, "err"))
- return LOG_ERR;
- if (!strcasecmp(level, "warn"))
- return LOG_WARN;
- if (!strcasecmp(level, "notice"))
- return LOG_NOTICE;
- if (!strcasecmp(level, "info"))
- return LOG_INFO;
- if (!strcasecmp(level, "debug"))
- return LOG_DEBUG;
- return -1;
-}
-
-/** Return the string equivalent of a given log level. */
-const char *
-log_level_to_string(int level)
-{
- return sev_to_string(level);
-}
-
-/** NULL-terminated array of names for log domains such that domain_list[dom]
- * is a description of <b>dom</b>.
- *
- * Remember to update doc/tor.1.txt if you modify this list.
- * */
-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", "CHANNEL",
- "SCHED", "GUARD", "CONSDIFF", "DOS", NULL
-};
-
-/** Return a bitmask for the log domain for which <b>domain</b> is the name,
- * or 0 if there is no such name. */
-static log_domain_mask_t
-parse_log_domain(const char *domain)
-{
- int i;
- for (i=0; domain_list[i]; ++i) {
- if (!strcasecmp(domain, domain_list[i]))
- return (1u<<i);
- }
- return 0;
-}
-
-/** Translate a bitmask of log domains to a string. */
-static char *
-domain_to_string(log_domain_mask_t domain, char *buf, size_t buflen)
-{
- char *cp = buf;
- char *eos = buf+buflen;
-
- buf[0] = '\0';
- if (! domain)
- return buf;
- while (1) {
- const char *d;
- int bit = tor_log2(domain);
- size_t n;
- if ((unsigned)bit >= ARRAY_LENGTH(domain_list)-1 ||
- bit >= N_LOGGING_DOMAINS) {
- tor_snprintf(buf, buflen, "<BUG:Unknown domain %lx>", (long)domain);
- return buf+strlen(buf);
- }
- d = domain_list[bit];
- n = strlcpy(cp, d, eos-cp);
- if (n >= buflen) {
- tor_snprintf(buf, buflen, "<BUG:Truncating domain %lx>", (long)domain);
- return buf+strlen(buf);
- }
- cp += n;
- domain &= ~(1<<bit);
-
- if (domain == 0 || (eos-cp) < 2)
- return cp;
-
- memcpy(cp, ",", 2); /*Nul-terminated ,"*/
- cp++;
- }
-}
-
-/** Parse a log severity pattern in *<b>cfg_ptr</b>. Advance cfg_ptr after
- * the end of the severityPattern. Set the value of <b>severity_out</b> to
- * the parsed pattern. Return 0 on success, -1 on failure.
- *
- * The syntax for a SeverityPattern is:
- * <pre>
- * SeverityPattern = *(DomainSeverity SP)* DomainSeverity
- * DomainSeverity = (DomainList SP)? SeverityRange
- * SeverityRange = MinSeverity ("-" MaxSeverity )?
- * DomainList = "[" (SP? DomainSpec SP? ",") SP? DomainSpec "]"
- * DomainSpec = "*" | Domain | "~" Domain
- * </pre>
- * A missing MaxSeverity defaults to ERR. Severities and domains are
- * case-insensitive. "~" indicates negation for a domain; negation happens
- * last inside a DomainList. Only one SeverityRange without a DomainList is
- * allowed per line.
- */
-int
-parse_log_severity_config(const char **cfg_ptr,
- log_severity_list_t *severity_out)
-{
- const char *cfg = *cfg_ptr;
- int got_anything = 0;
- int got_an_unqualified_range = 0;
- memset(severity_out, 0, sizeof(*severity_out));
-
- cfg = eat_whitespace(cfg);
- while (*cfg) {
- const char *dash, *space;
- char *sev_lo, *sev_hi;
- int low, high, i;
- log_domain_mask_t domains = ~0u;
-
- if (*cfg == '[') {
- int err = 0;
- char *domains_str;
- smartlist_t *domains_list;
- log_domain_mask_t neg_domains = 0;
- const char *closebracket = strchr(cfg, ']');
- if (!closebracket)
- return -1;
- domains = 0;
- domains_str = tor_strndup(cfg+1, closebracket-cfg-1);
- domains_list = smartlist_new();
- smartlist_split_string(domains_list, domains_str, ",", SPLIT_SKIP_SPACE,
- -1);
- tor_free(domains_str);
- SMARTLIST_FOREACH_BEGIN(domains_list, const char *, domain) {
- if (!strcmp(domain, "*")) {
- domains = ~0u;
- } else {
- int d;
- int negate=0;
- if (*domain == '~') {
- negate = 1;
- ++domain;
- }
- d = parse_log_domain(domain);
- if (!d) {
- log_warn(LD_CONFIG, "No such logging domain as %s", domain);
- err = 1;
- } else {
- if (negate)
- neg_domains |= d;
- else
- domains |= d;
- }
- }
- } SMARTLIST_FOREACH_END(domain);
- SMARTLIST_FOREACH(domains_list, char *, d, tor_free(d));
- smartlist_free(domains_list);
- if (err)
- return -1;
- if (domains == 0 && neg_domains)
- domains = ~neg_domains;
- else
- domains &= ~neg_domains;
- cfg = eat_whitespace(closebracket+1);
- } else {
- ++got_an_unqualified_range;
- }
- if (!strcasecmpstart(cfg, "file") ||
- !strcasecmpstart(cfg, "stderr") ||
- !strcasecmpstart(cfg, "stdout") ||
- !strcasecmpstart(cfg, "syslog") ||
- !strcasecmpstart(cfg, "android")) {
- goto done;
- }
- if (got_an_unqualified_range > 1)
- return -1;
-
- space = find_whitespace(cfg);
- dash = strchr(cfg, '-');
- if (dash && dash < space) {
- sev_lo = tor_strndup(cfg, dash-cfg);
- sev_hi = tor_strndup(dash+1, space-(dash+1));
- } else {
- sev_lo = tor_strndup(cfg, space-cfg);
- sev_hi = tor_strdup("ERR");
- }
- low = parse_log_level(sev_lo);
- high = parse_log_level(sev_hi);
- tor_free(sev_lo);
- tor_free(sev_hi);
- if (low == -1)
- return -1;
- if (high == -1)
- return -1;
-
- got_anything = 1;
- for (i=low; i >= high; --i)
- severity_out->masks[SEVERITY_MASK_IDX(i)] |= domains;
-
- cfg = eat_whitespace(space);
- }
-
- done:
- *cfg_ptr = cfg;
- return got_anything ? 0 : -1;
-}
-
-/** Return the least severe log level that any current log is interested in. */
-int
-get_min_log_level(void)
-{
- logfile_t *lf;
- int i;
- int min = LOG_ERR;
- for (lf = logfiles; lf; lf = lf->next) {
- for (i = LOG_DEBUG; i > min; --i)
- if (lf->severities->masks[SEVERITY_MASK_IDX(i)])
- min = i;
- }
- return min;
-}
-
-/** Switch all logs to output at most verbose level. */
-void
-switch_logs_debug(void)
-{
- logfile_t *lf;
- int i;
- LOCK_LOGS();
- for (lf = logfiles; lf; lf=lf->next) {
- for (i = LOG_DEBUG; i >= LOG_ERR; --i)
- lf->severities->masks[SEVERITY_MASK_IDX(i)] = ~0u;
- }
- log_global_min_severity_ = get_min_log_level();
- UNLOCK_LOGS();
-}
-
-/** Truncate all the log files. */
-void
-truncate_logs(void)
-{
- logfile_t *lf;
- for (lf = logfiles; lf; lf = lf->next) {
- if (lf->fd >= 0) {
- tor_ftruncate(lf->fd);
- }
- }
-}
-
diff --git a/src/common/memarea.c b/src/common/memarea.c
deleted file mode 100644
index 68c1625fe4..0000000000
--- a/src/common/memarea.c
+++ /dev/null
@@ -1,398 +0,0 @@
-/* Copyright (c) 2008-2017, The Tor Project, Inc. */
-/* See LICENSE for licensing information */
-
-/** \file memarea.c
- * \brief Implementation for memarea_t, an allocator for allocating lots of
- * small objects that will be freed all at once.
- */
-
-#include "orconfig.h"
-#include <stddef.h>
-#include <stdlib.h>
-#include "memarea.h"
-#include "util.h"
-#include "compat.h"
-#include "torlog.h"
-#include "container.h"
-
-#ifndef DISABLE_MEMORY_SENTINELS
-
-/** If true, we try to detect any attempts to write beyond the length of a
- * memarea. */
-#define USE_SENTINELS
-
-/** All returned pointers should be aligned to the nearest multiple of this
- * value. */
-#define MEMAREA_ALIGN SIZEOF_VOID_P
-
-/** A value which, when masked out of a pointer, produces a maximally aligned
- * pointer. */
-#if MEMAREA_ALIGN == 4
-#define MEMAREA_ALIGN_MASK ((uintptr_t)3)
-#elif MEMAREA_ALIGN == 8
-#define MEMAREA_ALIGN_MASK ((uintptr_t)7)
-#else
-#error "void* is neither 4 nor 8 bytes long. I don't know how to align stuff."
-#endif /* MEMAREA_ALIGN == 4 || ... */
-
-#if defined(__GNUC__) && defined(FLEXIBLE_ARRAY_MEMBER)
-#define USE_ALIGNED_ATTRIBUTE
-/** Name for the 'memory' member of a memory chunk. */
-#define U_MEM mem
-#else
-#define U_MEM u.mem
-#endif /* defined(__GNUC__) && defined(FLEXIBLE_ARRAY_MEMBER) */
-
-#ifdef USE_SENTINELS
-/** Magic value that we stick at the end of a memarea so we can make sure
- * there are no run-off-the-end bugs. */
-#define SENTINEL_VAL 0x90806622u
-/** How many bytes per area do we devote to the sentinel? */
-#define SENTINEL_LEN sizeof(uint32_t)
-/** Given a mem_area_chunk_t with SENTINEL_LEN extra bytes allocated at the
- * end, set those bytes. */
-#define SET_SENTINEL(chunk) \
- STMT_BEGIN \
- set_uint32( &(chunk)->U_MEM[chunk->mem_size], SENTINEL_VAL ); \
- STMT_END
-/** Assert that the sentinel on a memarea is set correctly. */
-#define CHECK_SENTINEL(chunk) \
- STMT_BEGIN \
- uint32_t sent_val = get_uint32(&(chunk)->U_MEM[chunk->mem_size]); \
- tor_assert(sent_val == SENTINEL_VAL); \
- STMT_END
-#else /* !(defined(USE_SENTINELS)) */
-#define SENTINEL_LEN 0
-#define SET_SENTINEL(chunk) STMT_NIL
-#define CHECK_SENTINEL(chunk) STMT_NIL
-#endif /* defined(USE_SENTINELS) */
-
-/** Increment <b>ptr</b> until it is aligned to MEMAREA_ALIGN. */
-static inline void *
-realign_pointer(void *ptr)
-{
- uintptr_t x = (uintptr_t)ptr;
- x = (x+MEMAREA_ALIGN_MASK) & ~MEMAREA_ALIGN_MASK;
- /* Reinstate this if bug 930 ever reappears
- tor_assert(((void*)x) >= ptr);
- */
- return (void*)x;
-}
-
-/** Implements part of a memarea. New memory is carved off from chunk->mem in
- * increasing order until a request is too big, at which point a new chunk is
- * allocated. */
-typedef struct memarea_chunk_t {
- /** Next chunk in this area. Only kept around so we can free it. */
- struct memarea_chunk_t *next_chunk;
- size_t mem_size; /**< How much RAM is available in mem, total? */
- char *next_mem; /**< Next position in mem to allocate data at. If it's
- * equal to mem+mem_size, this chunk is full. */
-#ifdef USE_ALIGNED_ATTRIBUTE
- /** Actual content of the memory chunk. */
- char mem[FLEXIBLE_ARRAY_MEMBER] __attribute__((aligned(MEMAREA_ALIGN)));
-#else
- union {
- char mem[1]; /**< Memory space in this chunk. */
- void *void_for_alignment_; /**< Dummy; used to make sure mem is aligned. */
- } u; /**< Union used to enforce alignment when we don't have support for
- * doing it right. */
-#endif /* defined(USE_ALIGNED_ATTRIBUTE) */
-} memarea_chunk_t;
-
-/** How many bytes are needed for overhead before we get to the memory part
- * of a chunk? */
-#define CHUNK_HEADER_SIZE offsetof(memarea_chunk_t, U_MEM)
-
-/** What's the smallest that we'll allocate a chunk? */
-#define CHUNK_SIZE 4096
-
-/** A memarea_t is an allocation region for a set of small memory requests
- * that will all be freed at once. */
-struct memarea_t {
- memarea_chunk_t *first; /**< Top of the chunk stack: never NULL. */
-};
-
-/** Helper: allocate a new memarea chunk of around <b>chunk_size</b> bytes. */
-static memarea_chunk_t *
-alloc_chunk(size_t sz)
-{
- tor_assert(sz < SIZE_T_CEILING);
-
- size_t chunk_size = sz < CHUNK_SIZE ? CHUNK_SIZE : sz;
- memarea_chunk_t *res;
- chunk_size += SENTINEL_LEN;
- 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;
- tor_assert(res->next_mem+res->mem_size+SENTINEL_LEN ==
- ((char*)res)+chunk_size);
- tor_assert(realign_pointer(res->next_mem) == res->next_mem);
- SET_SENTINEL(res);
- return res;
-}
-
-/** Release <b>chunk</b> from a memarea. */
-static void
-memarea_chunk_free_unchecked(memarea_chunk_t *chunk)
-{
- CHECK_SENTINEL(chunk);
- tor_free(chunk);
-}
-
-/** Allocate and return new memarea. */
-memarea_t *
-memarea_new(void)
-{
- memarea_t *head = tor_malloc(sizeof(memarea_t));
- head->first = alloc_chunk(CHUNK_SIZE);
- return head;
-}
-
-/** Free <b>area</b>, invalidating all pointers returned from memarea_alloc()
- * and friends for this area */
-void
-memarea_drop_all_(memarea_t *area)
-{
- memarea_chunk_t *chunk, *next;
- for (chunk = area->first; chunk; chunk = next) {
- next = chunk->next_chunk;
- memarea_chunk_free_unchecked(chunk);
- }
- area->first = NULL; /*fail fast on */
- tor_free(area);
-}
-
-/** Forget about having allocated anything in <b>area</b>, and free some of
- * the backing storage associated with it, as appropriate. Invalidates all
- * pointers returned from memarea_alloc() for this area. */
-void
-memarea_clear(memarea_t *area)
-{
- memarea_chunk_t *chunk, *next;
- if (area->first->next_chunk) {
- for (chunk = area->first->next_chunk; chunk; chunk = next) {
- next = chunk->next_chunk;
- memarea_chunk_free_unchecked(chunk);
- }
- area->first->next_chunk = NULL;
- }
- area->first->next_mem = area->first->U_MEM;
-}
-
-/** Return true iff <b>p</b> is in a range that has been returned by an
- * allocation from <b>area</b>. */
-int
-memarea_owns_ptr(const memarea_t *area, const void *p)
-{
- memarea_chunk_t *chunk;
- const char *ptr = p;
- for (chunk = area->first; chunk; chunk = chunk->next_chunk) {
- if (ptr >= chunk->U_MEM && ptr < chunk->next_mem)
- return 1;
- }
- return 0;
-}
-
-/** Return a pointer to a chunk of memory in <b>area</b> of at least <b>sz</b>
- * bytes. <b>sz</b> should be significantly smaller than the area's chunk
- * size, though we can deal if it isn't. */
-void *
-memarea_alloc(memarea_t *area, size_t sz)
-{
- memarea_chunk_t *chunk = area->first;
- char *result;
- tor_assert(chunk);
- CHECK_SENTINEL(chunk);
- tor_assert(sz < SIZE_T_CEILING);
- if (sz == 0)
- sz = 1;
- tor_assert(chunk->next_mem <= chunk->U_MEM + chunk->mem_size);
- const size_t space_remaining =
- (chunk->U_MEM + chunk->mem_size) - chunk->next_mem;
- if (sz > space_remaining) {
- if (sz+CHUNK_HEADER_SIZE >= CHUNK_SIZE) {
- /* This allocation is too big. Stick it in a special chunk, and put
- * that chunk second in the list. */
- memarea_chunk_t *new_chunk = alloc_chunk(sz+CHUNK_HEADER_SIZE);
- new_chunk->next_chunk = chunk->next_chunk;
- chunk->next_chunk = new_chunk;
- chunk = new_chunk;
- } else {
- memarea_chunk_t *new_chunk = alloc_chunk(CHUNK_SIZE);
- new_chunk->next_chunk = chunk;
- area->first = chunk = new_chunk;
- }
- tor_assert(chunk->mem_size >= sz);
- }
- result = chunk->next_mem;
- chunk->next_mem = chunk->next_mem + sz;
- /* Reinstate these if bug 930 ever comes back
- tor_assert(chunk->next_mem >= chunk->U_MEM);
- tor_assert(chunk->next_mem <= chunk->U_MEM+chunk->mem_size);
- */
- chunk->next_mem = realign_pointer(chunk->next_mem);
- return result;
-}
-
-/** As memarea_alloc(), but clears the memory it returns. */
-void *
-memarea_alloc_zero(memarea_t *area, size_t sz)
-{
- void *result = memarea_alloc(area, sz);
- memset(result, 0, sz);
- return result;
-}
-
-/** As memdup, but returns the memory from <b>area</b>. */
-void *
-memarea_memdup(memarea_t *area, const void *s, size_t n)
-{
- char *result = memarea_alloc(area, n);
- memcpy(result, s, n);
- return result;
-}
-
-/** As strdup, but returns the memory from <b>area</b>. */
-char *
-memarea_strdup(memarea_t *area, const char *s)
-{
- return memarea_memdup(area, s, strlen(s)+1);
-}
-
-/** As strndup, but returns the memory from <b>area</b>. */
-char *
-memarea_strndup(memarea_t *area, const char *s, size_t n)
-{
- size_t ln = 0;
- char *result;
- tor_assert(n < SIZE_T_CEILING);
- for (ln = 0; ln < n && s[ln]; ++ln)
- ;
- result = memarea_alloc(area, ln+1);
- memcpy(result, s, ln);
- result[ln]='\0';
- return result;
-}
-
-/** Set <b>allocated_out</b> to the number of bytes allocated in <b>area</b>,
- * and <b>used_out</b> to the number of bytes currently used. */
-void
-memarea_get_stats(memarea_t *area, size_t *allocated_out, size_t *used_out)
-{
- size_t a = 0, u = 0;
- memarea_chunk_t *chunk;
- for (chunk = area->first; chunk; chunk = chunk->next_chunk) {
- CHECK_SENTINEL(chunk);
- a += CHUNK_HEADER_SIZE + chunk->mem_size;
- tor_assert(chunk->next_mem >= chunk->U_MEM);
- u += CHUNK_HEADER_SIZE + (chunk->next_mem - chunk->U_MEM);
- }
- *allocated_out = a;
- *used_out = u;
-}
-
-/** Assert that <b>area</b> is okay. */
-void
-memarea_assert_ok(memarea_t *area)
-{
- memarea_chunk_t *chunk;
- tor_assert(area->first);
-
- for (chunk = area->first; chunk; chunk = chunk->next_chunk) {
- CHECK_SENTINEL(chunk);
- tor_assert(chunk->next_mem >= chunk->U_MEM);
- tor_assert(chunk->next_mem <=
- (char*) realign_pointer(chunk->U_MEM+chunk->mem_size));
- }
-}
-
-#else /* !(!defined(DISABLE_MEMORY_SENTINELS)) */
-
-struct memarea_t {
- smartlist_t *pieces;
-};
-
-memarea_t *
-memarea_new(void)
-{
- memarea_t *ma = tor_malloc_zero(sizeof(memarea_t));
- ma->pieces = smartlist_new();
- return ma;
-}
-void
-memarea_drop_all_(memarea_t *area)
-{
- memarea_clear(area);
- smartlist_free(area->pieces);
- tor_free(area);
-}
-void
-memarea_clear(memarea_t *area)
-{
- SMARTLIST_FOREACH(area->pieces, void *, p, tor_free_(p));
- smartlist_clear(area->pieces);
-}
-int
-memarea_owns_ptr(const memarea_t *area, const void *ptr)
-{
- SMARTLIST_FOREACH(area->pieces, const void *, p, if (ptr == p) return 1;);
- return 0;
-}
-
-void *
-memarea_alloc(memarea_t *area, size_t sz)
-{
- void *result = tor_malloc(sz);
- smartlist_add(area->pieces, result);
- return result;
-}
-
-void *
-memarea_alloc_zero(memarea_t *area, size_t sz)
-{
- void *result = tor_malloc_zero(sz);
- smartlist_add(area->pieces, result);
- return result;
-}
-void *
-memarea_memdup(memarea_t *area, const void *s, size_t n)
-{
- void *r = memarea_alloc(area, n);
- memcpy(r, s, n);
- return r;
-}
-char *
-memarea_strdup(memarea_t *area, const char *s)
-{
- size_t n = strlen(s);
- char *r = memarea_alloc(area, n+1);
- memcpy(r, s, n);
- r[n] = 0;
- return r;
-}
-char *
-memarea_strndup(memarea_t *area, const char *s, size_t n)
-{
- size_t ln = strnlen(s, n);
- char *r = memarea_alloc(area, ln+1);
- memcpy(r, s, ln);
- r[ln] = 0;
- return r;
-}
-void
-memarea_get_stats(memarea_t *area,
- size_t *allocated_out, size_t *used_out)
-{
- (void)area;
- *allocated_out = *used_out = 128;
-}
-void
-memarea_assert_ok(memarea_t *area)
-{
- (void)area;
-}
-
-#endif /* !defined(DISABLE_MEMORY_SENTINELS) */
-
diff --git a/src/common/memarea.h b/src/common/memarea.h
deleted file mode 100644
index 5207e8a5bd..0000000000
--- a/src/common/memarea.h
+++ /dev/null
@@ -1,29 +0,0 @@
-/* Copyright (c) 2008-2017, The Tor Project, Inc. */
-/* See LICENSE for licensing information */
-/* Tor dependencies */
-
-#ifndef TOR_MEMAREA_H
-#define TOR_MEMAREA_H
-
-typedef struct memarea_t memarea_t;
-
-memarea_t *memarea_new(void);
-void memarea_drop_all_(memarea_t *area);
-#define memarea_drop_all(area) \
- do { \
- memarea_drop_all_(area); \
- (area) = NULL; \
- } while (0)
-void memarea_clear(memarea_t *area);
-int memarea_owns_ptr(const memarea_t *area, const void *ptr);
-void *memarea_alloc(memarea_t *area, size_t sz);
-void *memarea_alloc_zero(memarea_t *area, size_t sz);
-void *memarea_memdup(memarea_t *area, const void *s, size_t n);
-char *memarea_strdup(memarea_t *area, const char *s);
-char *memarea_strndup(memarea_t *area, const char *s, size_t n);
-void memarea_get_stats(memarea_t *area,
- size_t *allocated_out, size_t *used_out);
-void memarea_assert_ok(memarea_t *area);
-
-#endif /* !defined(TOR_MEMAREA_H) */
-
diff --git a/src/common/procmon.c b/src/common/procmon.c
deleted file mode 100644
index 73c14cd584..0000000000
--- a/src/common/procmon.c
+++ /dev/null
@@ -1,332 +0,0 @@
-/* Copyright (c) 2011-2017, The Tor Project, Inc. */
-/* See LICENSE for licensing information */
-
-/**
- * \file procmon.c
- * \brief Process-termination monitor functions
- **/
-
-#include "procmon.h"
-
-#include "util.h"
-
-#ifdef HAVE_SIGNAL_H
-#include <signal.h>
-#endif
-#ifdef HAVE_ERRNO_H
-#include <errno.h>
-#endif
-
-#ifdef _WIN32
-#include <windows.h>
-#endif
-
-#if (0 == SIZEOF_PID_T) && defined(_WIN32)
-/* Windows does not define pid_t sometimes, but _getpid() returns an int.
- * Everybody else needs to have a pid_t. */
-typedef int pid_t;
-#define PID_T_FORMAT "%d"
-#elif (SIZEOF_PID_T == SIZEOF_INT) || (SIZEOF_PID_T == SIZEOF_SHORT)
-#define PID_T_FORMAT "%d"
-#elif (SIZEOF_PID_T == SIZEOF_LONG)
-#define PID_T_FORMAT "%ld"
-#elif (SIZEOF_PID_T == SIZEOF_INT64_T)
-#define PID_T_FORMAT I64_FORMAT
-#else
-#error Unknown: SIZEOF_PID_T
-#endif /* (0 == SIZEOF_PID_T) && defined(_WIN32) || ... */
-
-/* Define to 1 if process-termination monitors on this OS and Libevent
- version must poll for process termination themselves. */
-#define PROCMON_POLLS 1
-/* Currently we need to poll in some way on all systems. */
-
-#ifdef PROCMON_POLLS
-static void tor_process_monitor_poll_cb(periodic_timer_t *ev,
- void *procmon_);
-#endif
-
-/* This struct may contain pointers into the original process
- * specifier string, but it should *never* contain anything which
- * needs to be freed. */
-/* DOCDOC parsed_process_specifier_t */
-struct parsed_process_specifier_t {
- pid_t pid;
-};
-
-/** Parse the process specifier given in <b>process_spec</b> into
- * *<b>ppspec</b>. Return 0 on success; return -1 and store an error
- * message into *<b>msg</b> on failure. The caller must not free the
- * returned error message. */
-static int
-parse_process_specifier(const char *process_spec,
- struct parsed_process_specifier_t *ppspec,
- const char **msg)
-{
- long pid_l;
- int pid_ok = 0;
- char *pspec_next;
-
- /* If we're lucky, long will turn out to be large enough to hold a
- * PID everywhere that Tor runs. */
- pid_l = tor_parse_long(process_spec, 10, 1, LONG_MAX, &pid_ok, &pspec_next);
-
- /* Reserve room in the ‘process specifier’ for additional
- * (platform-specific) identifying information beyond the PID, to
- * make our process-existence checks a bit less racy in a future
- * version. */
- if ((*pspec_next != 0) && (*pspec_next != ' ') && (*pspec_next != ':')) {
- pid_ok = 0;
- }
-
- ppspec->pid = (pid_t)(pid_l);
- if (!pid_ok || (pid_l != (long)(ppspec->pid))) {
- *msg = "invalid PID";
- goto err;
- }
-
- return 0;
- err:
- return -1;
-}
-
-/* DOCDOC tor_process_monitor_t */
-struct tor_process_monitor_t {
- /** Log domain for warning messages. */
- log_domain_mask_t log_domain;
-
- /** All systems: The best we can do in general is poll for the
- * process's existence by PID periodically, and hope that the kernel
- * doesn't reassign the same PID to another process between our
- * polls. */
- pid_t pid;
-
-#ifdef _WIN32
- /** Windows-only: Should we poll hproc? If false, poll pid
- * instead. */
- int poll_hproc;
-
- /** Windows-only: Get a handle to the process (if possible) and
- * periodically check whether the process we have a handle to has
- * ended. */
- HANDLE hproc;
- /* XXXX We should have Libevent watch hproc for us,
- * if/when some version of Libevent can be told to do so. */
-#endif /* defined(_WIN32) */
-
- /* XXXX On Linux, we can and should receive the 22nd
- * (space-delimited) field (‘starttime’) of /proc/$PID/stat from the
- * owning controller and store it, and poll once in a while to see
- * whether it has changed -- if so, the kernel has *definitely*
- * reassigned the owning controller's PID and we should exit. On
- * FreeBSD, we can do the same trick using either the 8th
- * space-delimited field of /proc/$PID/status on the seven FBSD
- * systems whose admins have mounted procfs, or the start-time field
- * of the process-information structure returned by kvmgetprocs() on
- * any system. The latter is ickier. */
-
- /* XXXX On FreeBSD (and possibly other kqueue systems), we can and
- * should arrange to receive EVFILT_PROC NOTE_EXIT notifications for
- * pid, so we don't have to do such a heavyweight poll operation in
- * order to avoid the PID-reassignment race condition. (We would
- * still need to poll our own kqueue periodically until some version
- * of Libevent 2.x learns to receive these events for us.) */
-
- /** A Libevent event structure, to either poll for the process's
- * existence or receive a notification when the process ends. */
- periodic_timer_t *e;
-
- /** A callback to be called when the process ends. */
- tor_procmon_callback_t cb;
- void *cb_arg; /**< A user-specified pointer to be passed to cb. */
-};
-
-/** Verify that the process specifier given in <b>process_spec</b> is
- * syntactically valid. Return 0 on success; return -1 and store an
- * error message into *<b>msg</b> on failure. The caller must not
- * free the returned error message. */
-int
-tor_validate_process_specifier(const char *process_spec,
- const char **msg)
-{
- struct parsed_process_specifier_t ppspec;
-
- tor_assert(msg != NULL);
- *msg = NULL;
-
- return parse_process_specifier(process_spec, &ppspec, msg);
-}
-
-/* DOCDOC poll_interval_tv */
-static const struct timeval poll_interval_tv = {15, 0};
-
-/** Create a process-termination monitor for the process specifier
- * given in <b>process_spec</b>. Return a newly allocated
- * tor_process_monitor_t on success; return NULL and store an error
- * message into *<b>msg</b> on failure. The caller must not free
- * the returned error message.
- *
- * When the monitored process terminates, call
- * <b>cb</b>(<b>cb_arg</b>).
- */
-tor_process_monitor_t *
-tor_process_monitor_new(struct event_base *base,
- const char *process_spec,
- log_domain_mask_t log_domain,
- tor_procmon_callback_t cb, void *cb_arg,
- const char **msg)
-{
- tor_process_monitor_t *procmon = tor_malloc_zero(
- sizeof(tor_process_monitor_t));
- struct parsed_process_specifier_t ppspec;
-
- tor_assert(msg != NULL);
- *msg = NULL;
-
- if (procmon == NULL) {
- *msg = "out of memory";
- goto err;
- }
-
- procmon->log_domain = log_domain;
-
- if (parse_process_specifier(process_spec, &ppspec, msg))
- goto err;
-
- procmon->pid = ppspec.pid;
-
-#ifdef _WIN32
- procmon->hproc = OpenProcess(PROCESS_QUERY_INFORMATION | SYNCHRONIZE,
- FALSE,
- procmon->pid);
-
- if (procmon->hproc != NULL) {
- procmon->poll_hproc = 1;
- log_info(procmon->log_domain, "Successfully opened handle to process "
- PID_T_FORMAT"; "
- "monitoring it.",
- procmon->pid);
- } else {
- /* If we couldn't get a handle to the process, we'll try again the
- * first time we poll. */
- log_info(procmon->log_domain, "Failed to open handle to process "
- PID_T_FORMAT"; will "
- "try again later.",
- procmon->pid);
- }
-#endif /* defined(_WIN32) */
-
- procmon->cb = cb;
- procmon->cb_arg = cb_arg;
-
-#ifdef PROCMON_POLLS
- procmon->e = periodic_timer_new(base,
- &poll_interval_tv,
- tor_process_monitor_poll_cb, procmon);
-#else /* !(defined(PROCMON_POLLS)) */
-#error OOPS?
-#endif /* defined(PROCMON_POLLS) */
-
- return procmon;
- err:
- tor_process_monitor_free(procmon);
- return NULL;
-}
-
-#ifdef PROCMON_POLLS
-/** Libevent callback to poll for the existence of the process
- * monitored by <b>procmon_</b>. */
-static void
-tor_process_monitor_poll_cb(periodic_timer_t *event, void *procmon_)
-{
- (void)event;
- tor_process_monitor_t *procmon = (tor_process_monitor_t *)(procmon_);
- int its_dead_jim;
-
- tor_assert(procmon != NULL);
-
-#ifdef _WIN32
- if (procmon->poll_hproc) {
- DWORD exit_code;
- if (!GetExitCodeProcess(procmon->hproc, &exit_code)) {
- char *errmsg = format_win32_error(GetLastError());
- log_warn(procmon->log_domain, "Error \"%s\" occurred while polling "
- "handle for monitored process "PID_T_FORMAT"; assuming "
- "it's dead.",
- errmsg, procmon->pid);
- tor_free(errmsg);
- its_dead_jim = 1;
- } else {
- its_dead_jim = (exit_code != STILL_ACTIVE);
- }
- } else {
- /* All we can do is try to open the process, and look at the error
- * code if it fails again. */
- procmon->hproc = OpenProcess(PROCESS_QUERY_INFORMATION | SYNCHRONIZE,
- FALSE,
- procmon->pid);
-
- if (procmon->hproc != NULL) {
- log_info(procmon->log_domain, "Successfully opened handle to monitored "
- "process "PID_T_FORMAT".",
- procmon->pid);
- its_dead_jim = 0;
- procmon->poll_hproc = 1;
- } else {
- DWORD err_code = GetLastError();
- char *errmsg = format_win32_error(err_code);
-
- /* When I tested OpenProcess's error codes on Windows 7, I
- * received error code 5 (ERROR_ACCESS_DENIED) for PIDs of
- * existing processes that I could not open and error code 87
- * (ERROR_INVALID_PARAMETER) for PIDs that were not in use.
- * Since the nonexistent-process error code is sane, I'm going
- * to assume that all errors other than ERROR_INVALID_PARAMETER
- * mean that the process we are monitoring is still alive. */
- its_dead_jim = (err_code == ERROR_INVALID_PARAMETER);
-
- if (!its_dead_jim)
- log_info(procmon->log_domain, "Failed to open handle to monitored "
- "process "PID_T_FORMAT", and error code %lu (%s) is not "
- "'invalid parameter' -- assuming the process is still alive.",
- procmon->pid,
- err_code, errmsg);
-
- tor_free(errmsg);
- }
- }
-#else /* !(defined(_WIN32)) */
- /* Unix makes this part easy, if a bit racy. */
- its_dead_jim = kill(procmon->pid, 0);
- its_dead_jim = its_dead_jim && (errno == ESRCH);
-#endif /* defined(_WIN32) */
-
- tor_log(its_dead_jim ? LOG_NOTICE : LOG_INFO,
- procmon->log_domain, "Monitored process "PID_T_FORMAT" is %s.",
- procmon->pid,
- its_dead_jim ? "dead" : "still alive");
-
- if (its_dead_jim) {
- procmon->cb(procmon->cb_arg);
- }
-}
-#endif /* defined(PROCMON_POLLS) */
-
-/** Free the process-termination monitor <b>procmon</b>. */
-void
-tor_process_monitor_free_(tor_process_monitor_t *procmon)
-{
- if (procmon == NULL)
- return;
-
-#ifdef _WIN32
- if (procmon->hproc != NULL)
- CloseHandle(procmon->hproc);
-#endif
-
- if (procmon->e != NULL)
- periodic_timer_free(procmon->e);
-
- tor_free(procmon);
-}
-
diff --git a/src/common/procmon.h b/src/common/procmon.h
deleted file mode 100644
index 63777e4111..0000000000
--- a/src/common/procmon.h
+++ /dev/null
@@ -1,35 +0,0 @@
-/* Copyright (c) 2011-2017, The Tor Project, Inc. */
-/* See LICENSE for licensing information */
-
-/**
- * \file procmon.h
- * \brief Headers for procmon.c
- **/
-
-#ifndef TOR_PROCMON_H
-#define TOR_PROCMON_H
-
-#include "compat.h"
-#include "compat_libevent.h"
-
-#include "torlog.h"
-
-typedef struct tor_process_monitor_t tor_process_monitor_t;
-
-/* DOCDOC tor_procmon_callback_t */
-typedef void (*tor_procmon_callback_t)(void *);
-
-int tor_validate_process_specifier(const char *process_spec,
- const char **msg);
-tor_process_monitor_t *tor_process_monitor_new(struct event_base *base,
- const char *process_spec,
- log_domain_mask_t log_domain,
- tor_procmon_callback_t cb,
- void *cb_arg,
- const char **msg);
-void tor_process_monitor_free_(tor_process_monitor_t *procmon);
-#define tor_process_monitor_free(procmon) \
- FREE_AND_NULL(tor_process_monitor_t, tor_process_monitor_free_, (procmon))
-
-#endif /* !defined(TOR_PROCMON_H) */
-
diff --git a/src/common/pubsub.c b/src/common/pubsub.c
deleted file mode 100644
index 336e8a6e7f..0000000000
--- a/src/common/pubsub.c
+++ /dev/null
@@ -1,129 +0,0 @@
-/* Copyright (c) 2016-2017, The Tor Project, Inc. */
-/* See LICENSE for licensing information */
-
-/**
- * \file pubsub.c
- *
- * \brief DOCDOC
- */
-
-#include "orconfig.h"
-#include "pubsub.h"
-#include "container.h"
-
-/** Helper: insert <b>s</b> into <b>topic's</b> list of subscribers, keeping
- * them sorted in priority order. */
-static void
-subscriber_insert(pubsub_topic_t *topic, pubsub_subscriber_t *s)
-{
- int i;
- smartlist_t *sl = topic->subscribers;
- for (i = 0; i < smartlist_len(sl); ++i) {
- pubsub_subscriber_t *other = smartlist_get(sl, i);
- if (s->priority < other->priority) {
- break;
- }
- }
- smartlist_insert(sl, i, s);
-}
-
-/**
- * Add a new subscriber to <b>topic</b>, where (when an event is triggered),
- * we'll notify the function <b>fn</b> by passing it <b>subscriber_data</b>.
- * Return a handle to the subscribe which can later be passed to
- * pubsub_unsubscribe_().
- *
- * Functions are called in priority order, from lowest to highest.
- *
- * See pubsub.h for <b>subscribe_flags</b>.
- */
-const pubsub_subscriber_t *
-pubsub_subscribe_(pubsub_topic_t *topic,
- pubsub_subscriber_fn_t fn,
- void *subscriber_data,
- unsigned subscribe_flags,
- unsigned priority)
-{
- tor_assert(! topic->locked);
- if (subscribe_flags & SUBSCRIBE_ATSTART) {
- tor_assert(topic->n_events_fired == 0);
- }
- pubsub_subscriber_t *r = tor_malloc_zero(sizeof(*r));
- r->priority = priority;
- r->subscriber_flags = subscribe_flags;
- r->fn = fn;
- r->subscriber_data = subscriber_data;
- if (topic->subscribers == NULL) {
- topic->subscribers = smartlist_new();
- }
- subscriber_insert(topic, r);
- return r;
-}
-
-/**
- * Remove the subscriber <b>s</b> from <b>topic</b>. After calling this
- * function, <b>s</b> may no longer be used.
- */
-int
-pubsub_unsubscribe_(pubsub_topic_t *topic,
- const pubsub_subscriber_t *s)
-{
- tor_assert(! topic->locked);
- smartlist_t *sl = topic->subscribers;
- if (sl == NULL)
- return -1;
- int i = smartlist_pos(sl, s);
- if (i == -1)
- return -1;
- pubsub_subscriber_t *tmp = smartlist_get(sl, i);
- tor_assert(tmp == s);
- smartlist_del_keeporder(sl, i);
- tor_free(tmp);
- return 0;
-}
-
-/**
- * For every subscriber s in <b>topic</b>, invoke notify_fn on s and
- * event_data. Return 0 if there were no nonzero return values, and -1 if
- * there were any.
- */
-int
-pubsub_notify_(pubsub_topic_t *topic, pubsub_notify_fn_t notify_fn,
- void *event_data, unsigned notify_flags)
-{
- tor_assert(! topic->locked);
- (void) notify_flags;
- smartlist_t *sl = topic->subscribers;
- int n_bad = 0;
- ++topic->n_events_fired;
- if (sl == NULL)
- return -1;
- topic->locked = 1;
- SMARTLIST_FOREACH_BEGIN(sl, pubsub_subscriber_t *, s) {
- int r = notify_fn(s, event_data);
- if (r != 0)
- ++n_bad;
- } SMARTLIST_FOREACH_END(s);
- topic->locked = 0;
- return (n_bad == 0) ? 0 : -1;
-}
-
-/**
- * Release all storage held by <b>topic</b>.
- */
-void
-pubsub_clear_(pubsub_topic_t *topic)
-{
- tor_assert(! topic->locked);
-
- smartlist_t *sl = topic->subscribers;
- if (sl == NULL)
- return;
- SMARTLIST_FOREACH_BEGIN(sl, pubsub_subscriber_t *, s) {
- tor_free(s);
- } SMARTLIST_FOREACH_END(s);
- smartlist_free(sl);
- topic->subscribers = NULL;
- topic->n_events_fired = 0;
-}
-
diff --git a/src/common/pubsub.h b/src/common/pubsub.h
deleted file mode 100644
index 2bee3af085..0000000000
--- a/src/common/pubsub.h
+++ /dev/null
@@ -1,179 +0,0 @@
-/* Copyright (c) 2016-2017, The Tor Project, Inc. */
-/* See LICENSE for licensing information */
-
-/**
- * \file pubsub.h
- * \brief Macros to implement publish/subscribe abstractions.
- *
- * To use these macros, call DECLARE_PUBSUB_TOPIC() with an identifier to use
- * as your topic. Below, I'm going to assume you say DECLARE_PUBSUB_TOPIC(T).
- *
- * Doing this will declare the following types:
- * typedef struct T_event_data_t T_event_data_t; // you define this struct
- * typedef struct T_subscriber_data_t T_subscriber_data_t; // this one too.
- * typedef struct T_subscriber_t T_subscriber_t; // opaque
- * typedef int (*T_subscriber_fn_t)(T_event_data_t*, T_subscriber_data_t*);
- *
- * and it will declare the following functions:
- * const T_subscriber_t *T_subscribe(T_subscriber_fn_t,
- * T_subscriber_data_t *,
- * unsigned flags,
- * unsigned priority);
- * int T_unsubscribe(const T_subscriber_t *)
- *
- * Elsewhere you can say DECLARE_NOTIFY_PUBSUB_TOPIC(static, T), which
- * declares:
- *
- * static int T_notify(T_event_data_t *, unsigned notify_flags);
- * static void T_clear(void);
- *
- * And in some C file, you would define these functions with:
- * IMPLEMENT_PUBSUB_TOPIC(static, T).
- *
- * The implementations will be small typesafe wrappers over generic versions
- * of the above functions.
- *
- * To use the typesafe functions, you add any number of subscribers with
- * T_subscribe(). Each has an associated function pointer, data pointer,
- * and priority. Later, you can invoke T_notify() to declare that the
- * event has occurred. Each of the subscribers will be invoked once.
- **/
-
-#ifndef TOR_PUBSUB_H
-#define TOR_PUBSUB_H
-
-#include "torint.h"
-
-/**
- * Flag for T_subscribe: die with an assertion failure if the event
- * have ever been published before. Used when a subscriber must absolutely
- * never have missed an event.
- */
-#define SUBSCRIBE_ATSTART (1u<<0)
-
-#define DECLARE_PUBSUB_STRUCT_TYPES(name) \
- /* You define this type. */ \
- typedef struct name ## _event_data_t name ## _event_data_t; \
- /* You define this type. */ \
- typedef struct name ## _subscriber_data_t name ## _subscriber_data_t;
-
-#define DECLARE_PUBSUB_TOPIC(name) \
- /* This type is opaque. */ \
- typedef struct name ## _subscriber_t name ## _subscriber_t; \
- /* You declare functions matching this type. */ \
- typedef int (*name ## _subscriber_fn_t)( \
- name ## _event_data_t *data, \
- name ## _subscriber_data_t *extra); \
- /* Call this function to subscribe to a topic. */ \
- const name ## _subscriber_t *name ## _subscribe( \
- name##_subscriber_fn_t subscriber, \
- name##_subscriber_data_t *extra_data, \
- unsigned flags, \
- unsigned priority); \
- /* Call this function to unsubscribe from a topic. */ \
- int name ## _unsubscribe(const name##_subscriber_t *s);
-
-#define DECLARE_NOTIFY_PUBSUB_TOPIC(linkage, name) \
- /* Call this function to notify all subscribers. Flags not yet used. */ \
- linkage int name ## _notify(name ## _event_data_t *data, unsigned flags); \
- /* Call this function to release storage held by the topic. */ \
- linkage void name ## _clear(void);
-
-/**
- * Type used to hold a generic function for a subscriber.
- *
- * [Yes, it is safe to cast to this, so long as we cast back to the original
- * type before calling. From C99: "A pointer to a function of one type may be
- * converted to a pointer to a function of another type and back again; the
- * result shall compare equal to the original pointer."]
-*/
-typedef int (*pubsub_subscriber_fn_t)(void *, void *);
-
-/**
- * Helper type to implement pubsub abstraction. Don't use this directly.
- * It represents a subscriber.
- */
-typedef struct pubsub_subscriber_t {
- /** Function to invoke when the event triggers. */
- pubsub_subscriber_fn_t fn;
- /** Data associated with this subscriber. */
- void *subscriber_data;
- /** Priority for this subscriber. Low priorities happen first. */
- unsigned priority;
- /** Flags set on this subscriber. Not yet used.*/
- unsigned subscriber_flags;
-} pubsub_subscriber_t;
-
-/**
- * Helper type to implement pubsub abstraction. Don't use this directly.
- * It represents a topic, and keeps a record of subscribers.
- */
-typedef struct pubsub_topic_t {
- /** List of subscribers to this topic. May be NULL. */
- struct smartlist_t *subscribers;
- /** Total number of times that pubsub_notify_() has ever been called on this
- * topic. */
- uint64_t n_events_fired;
- /** True iff we're running 'notify' on this topic, and shouldn't allow
- * any concurrent modifications or events. */
- unsigned locked;
-} pubsub_topic_t;
-
-const pubsub_subscriber_t *pubsub_subscribe_(pubsub_topic_t *topic,
- pubsub_subscriber_fn_t fn,
- void *subscriber_data,
- unsigned subscribe_flags,
- unsigned priority);
-int pubsub_unsubscribe_(pubsub_topic_t *topic, const pubsub_subscriber_t *sub);
-void pubsub_clear_(pubsub_topic_t *topic);
-typedef int (*pubsub_notify_fn_t)(pubsub_subscriber_t *subscriber,
- void *notify_data);
-int pubsub_notify_(pubsub_topic_t *topic, pubsub_notify_fn_t notify_fn,
- void *notify_data, unsigned notify_flags);
-
-#define IMPLEMENT_PUBSUB_TOPIC(notify_linkage, name) \
- static pubsub_topic_t name ## _topic_ = { NULL, 0, 0 }; \
- const name ## _subscriber_t * \
- name ## _subscribe(name##_subscriber_fn_t subscriber, \
- name##_subscriber_data_t *extra_data, \
- unsigned flags, \
- unsigned priority) \
- { \
- const pubsub_subscriber_t *s; \
- s = pubsub_subscribe_(&name##_topic_, \
- (pubsub_subscriber_fn_t)subscriber, \
- extra_data, \
- flags, \
- priority); \
- return (const name##_subscriber_t *)s; \
- } \
- int \
- name ## _unsubscribe(const name##_subscriber_t *subscriber) \
- { \
- return pubsub_unsubscribe_(&name##_topic_, \
- (const pubsub_subscriber_t *)subscriber); \
- } \
- static int \
- name##_call_the_notify_fn_(pubsub_subscriber_t *subscriber, \
- void *notify_data) \
- { \
- name ## _subscriber_fn_t fn; \
- fn = (name ## _subscriber_fn_t) subscriber->fn; \
- return fn(notify_data, subscriber->subscriber_data); \
- } \
- notify_linkage int \
- name ## _notify(name ## _event_data_t *event_data, unsigned flags) \
- { \
- return pubsub_notify_(&name##_topic_, \
- name##_call_the_notify_fn_, \
- event_data, \
- flags); \
- } \
- notify_linkage void \
- name ## _clear(void) \
- { \
- pubsub_clear_(&name##_topic_); \
- }
-
-#endif /* !defined(TOR_PUBSUB_H) */
-
diff --git a/src/common/sandbox.c b/src/common/sandbox.c
deleted file mode 100644
index ca7803ac9c..0000000000
--- a/src/common/sandbox.c
+++ /dev/null
@@ -1,1977 +0,0 @@
- /* Copyright (c) 2001 Matej Pfajfar.
- * Copyright (c) 2001-2004, Roger Dingledine.
- * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2017, The Tor Project, Inc. */
-/* See LICENSE for licensing information */
-
-/**
- * \file sandbox.c
- * \brief Code to enable sandboxing.
- **/
-
-#include "orconfig.h"
-
-#ifndef _LARGEFILE64_SOURCE
-/**
- * Temporarily required for O_LARGEFILE flag. Needs to be removed
- * with the libevent fix.
- */
-#define _LARGEFILE64_SOURCE
-#endif /* !defined(_LARGEFILE64_SOURCE) */
-
-/** Malloc mprotect limit in bytes.
- *
- * 28/06/2017: This value was increased from 16 MB to 20 MB after we introduced
- * LZMA support in Tor (0.3.1.1-alpha). We limit our LZMA coder to 16 MB, but
- * liblzma have a small overhead that we need to compensate for to avoid being
- * killed by the sandbox.
- */
-#define MALLOC_MP_LIM (20*1024*1024)
-
-#include <stdio.h>
-#include <string.h>
-#include <stdlib.h>
-
-#include "sandbox.h"
-#include "container.h"
-#include "torlog.h"
-#include "torint.h"
-#include "util.h"
-#include "tor_queue.h"
-
-#include "ht.h"
-
-#define DEBUGGING_CLOSE
-
-#if defined(USE_LIBSECCOMP)
-
-#include <sys/mman.h>
-#include <sys/syscall.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <sys/epoll.h>
-#include <sys/prctl.h>
-#include <linux/futex.h>
-#include <sys/file.h>
-
-#include <stdarg.h>
-#include <seccomp.h>
-#include <signal.h>
-#include <unistd.h>
-#include <fcntl.h>
-#include <time.h>
-#include <poll.h>
-
-#ifdef HAVE_GNU_LIBC_VERSION_H
-#include <gnu/libc-version.h>
-#endif
-#ifdef HAVE_LINUX_NETFILTER_IPV4_H
-#include <linux/netfilter_ipv4.h>
-#endif
-#ifdef HAVE_LINUX_IF_H
-#include <linux/if.h>
-#endif
-#ifdef HAVE_LINUX_NETFILTER_IPV6_IP6_TABLES_H
-#include <linux/netfilter_ipv6/ip6_tables.h>
-#endif
-
-#if defined(HAVE_EXECINFO_H) && defined(HAVE_BACKTRACE) && \
- defined(HAVE_BACKTRACE_SYMBOLS_FD) && defined(HAVE_SIGACTION)
-#define USE_BACKTRACE
-#define EXPOSE_CLEAN_BACKTRACE
-#include "backtrace.h"
-#endif /* defined(HAVE_EXECINFO_H) && defined(HAVE_BACKTRACE) && ... */
-
-#ifdef USE_BACKTRACE
-#include <execinfo.h>
-#endif
-
-/**
- * Linux 32 bit definitions
- */
-#if defined(__i386__)
-
-#define REG_SYSCALL REG_EAX
-#define M_SYSCALL gregs[REG_SYSCALL]
-
-/**
- * Linux 64 bit definitions
- */
-#elif defined(__x86_64__)
-
-#define REG_SYSCALL REG_RAX
-#define M_SYSCALL gregs[REG_SYSCALL]
-
-#elif defined(__arm__)
-
-#define M_SYSCALL arm_r7
-
-#elif defined(__aarch64__) && defined(__LP64__)
-
-#define REG_SYSCALL 8
-#define M_SYSCALL regs[REG_SYSCALL]
-
-#endif /* defined(__i386__) || ... */
-
-/**Determines if at least one sandbox is active.*/
-static int sandbox_active = 0;
-/** Holds the parameter list configuration for the sandbox.*/
-static sandbox_cfg_t *filter_dynamic = NULL;
-
-#undef SCMP_CMP
-#define SCMP_CMP(a,b,c) ((struct scmp_arg_cmp){(a),(b),(c),0})
-#define SCMP_CMP_STR(a,b,c) \
- ((struct scmp_arg_cmp) {(a),(b),(intptr_t)(void*)(c),0})
-#define SCMP_CMP4(a,b,c,d) ((struct scmp_arg_cmp){(a),(b),(c),(d)})
-/* We use a wrapper here because these masked comparisons seem to be pretty
- * verbose. Also, it's important to cast to scmp_datum_t before negating the
- * mask, since otherwise the negation might get applied to a 32 bit value, and
- * the high bits of the value might get masked out improperly. */
-#define SCMP_CMP_MASKED(a,b,c) \
- SCMP_CMP4((a), SCMP_CMP_MASKED_EQ, ~(scmp_datum_t)(b), (c))
-
-/** Variable used for storing all syscall numbers that will be allowed with the
- * stage 1 general Tor sandbox.
- */
-static int filter_nopar_gen[] = {
- SCMP_SYS(access),
- SCMP_SYS(brk),
- SCMP_SYS(clock_gettime),
- SCMP_SYS(close),
- SCMP_SYS(clone),
- SCMP_SYS(epoll_create),
- SCMP_SYS(epoll_wait),
-#ifdef __NR_epoll_pwait
- SCMP_SYS(epoll_pwait),
-#endif
-#ifdef HAVE_EVENTFD
- SCMP_SYS(eventfd2),
-#endif
-#ifdef HAVE_PIPE2
- SCMP_SYS(pipe2),
-#endif
-#ifdef HAVE_PIPE
- SCMP_SYS(pipe),
-#endif
-#ifdef __NR_fchmod
- SCMP_SYS(fchmod),
-#endif
- SCMP_SYS(fcntl),
- SCMP_SYS(fstat),
-#ifdef __NR_fstat64
- SCMP_SYS(fstat64),
-#endif
- SCMP_SYS(futex),
- SCMP_SYS(getdents),
- SCMP_SYS(getdents64),
- SCMP_SYS(getegid),
-#ifdef __NR_getegid32
- SCMP_SYS(getegid32),
-#endif
- SCMP_SYS(geteuid),
-#ifdef __NR_geteuid32
- SCMP_SYS(geteuid32),
-#endif
- SCMP_SYS(getgid),
-#ifdef __NR_getgid32
- SCMP_SYS(getgid32),
-#endif
- SCMP_SYS(getpid),
-#ifdef __NR_getrlimit
- SCMP_SYS(getrlimit),
-#endif
- SCMP_SYS(gettimeofday),
- SCMP_SYS(gettid),
- SCMP_SYS(getuid),
-#ifdef __NR_getuid32
- SCMP_SYS(getuid32),
-#endif
- SCMP_SYS(lseek),
-#ifdef __NR__llseek
- SCMP_SYS(_llseek),
-#endif
- SCMP_SYS(mkdir),
- SCMP_SYS(mlockall),
-#ifdef __NR_mmap
- /* XXXX restrict this in the same ways as mmap2 */
- SCMP_SYS(mmap),
-#endif
- SCMP_SYS(munmap),
-#ifdef __NR_nanosleep
- SCMP_SYS(nanosleep),
-#endif
-#ifdef __NR_prlimit
- SCMP_SYS(prlimit),
-#endif
-#ifdef __NR_prlimit64
- SCMP_SYS(prlimit64),
-#endif
- SCMP_SYS(read),
- SCMP_SYS(rt_sigreturn),
- SCMP_SYS(sched_getaffinity),
-#ifdef __NR_sched_yield
- SCMP_SYS(sched_yield),
-#endif
- SCMP_SYS(sendmsg),
- SCMP_SYS(set_robust_list),
-#ifdef __NR_setrlimit
- SCMP_SYS(setrlimit),
-#endif
-#ifdef __NR_sigaltstack
- SCMP_SYS(sigaltstack),
-#endif
-#ifdef __NR_sigreturn
- SCMP_SYS(sigreturn),
-#endif
- SCMP_SYS(stat),
- SCMP_SYS(uname),
- SCMP_SYS(wait4),
- SCMP_SYS(write),
- SCMP_SYS(writev),
- SCMP_SYS(exit_group),
- SCMP_SYS(exit),
-
- SCMP_SYS(madvise),
-#ifdef __NR_stat64
- // getaddrinfo uses this..
- SCMP_SYS(stat64),
-#endif
-
-#ifdef __NR_getrandom
- SCMP_SYS(getrandom),
-#endif
-
-#ifdef __NR_sysinfo
- // qsort uses this..
- SCMP_SYS(sysinfo),
-#endif
- /*
- * These socket syscalls are not required on x86_64 and not supported with
- * some libseccomp versions (eg: 1.0.1)
- */
-#if defined(__i386)
- SCMP_SYS(recv),
- SCMP_SYS(send),
-#endif
-
- // socket syscalls
- SCMP_SYS(bind),
- SCMP_SYS(listen),
- SCMP_SYS(connect),
- SCMP_SYS(getsockname),
- SCMP_SYS(recvmsg),
- SCMP_SYS(recvfrom),
- SCMP_SYS(sendto),
- SCMP_SYS(unlink),
- SCMP_SYS(poll)
-};
-
-/* These macros help avoid the error where the number of filters we add on a
- * single rule don't match the arg_cnt param. */
-#define seccomp_rule_add_0(ctx,act,call) \
- seccomp_rule_add((ctx),(act),(call),0)
-#define seccomp_rule_add_1(ctx,act,call,f1) \
- seccomp_rule_add((ctx),(act),(call),1,(f1))
-#define seccomp_rule_add_2(ctx,act,call,f1,f2) \
- seccomp_rule_add((ctx),(act),(call),2,(f1),(f2))
-#define seccomp_rule_add_3(ctx,act,call,f1,f2,f3) \
- seccomp_rule_add((ctx),(act),(call),3,(f1),(f2),(f3))
-#define seccomp_rule_add_4(ctx,act,call,f1,f2,f3,f4) \
- seccomp_rule_add((ctx),(act),(call),4,(f1),(f2),(f3),(f4))
-
-/**
- * Function responsible for setting up the rt_sigaction syscall for
- * the seccomp filter sandbox.
- */
-static int
-sb_rt_sigaction(scmp_filter_ctx ctx, sandbox_cfg_t *filter)
-{
- unsigned i;
- int rc;
- int param[] = { SIGINT, SIGTERM, SIGPIPE, SIGUSR1, SIGUSR2, SIGHUP, SIGCHLD,
-#ifdef SIGXFSZ
- SIGXFSZ
-#endif
- };
- (void) filter;
-
- for (i = 0; i < ARRAY_LENGTH(param); i++) {
- rc = seccomp_rule_add_1(ctx, SCMP_ACT_ALLOW, SCMP_SYS(rt_sigaction),
- SCMP_CMP(0, SCMP_CMP_EQ, param[i]));
- if (rc)
- break;
- }
-
- return rc;
-}
-
-/**
- * Function responsible for setting up the time syscall for
- * the seccomp filter sandbox.
- */
-static int
-sb_time(scmp_filter_ctx ctx, sandbox_cfg_t *filter)
-{
- (void) filter;
-#ifdef __NR_time
- return seccomp_rule_add_1(ctx, SCMP_ACT_ALLOW, SCMP_SYS(time),
- SCMP_CMP(0, SCMP_CMP_EQ, 0));
-#else
- return 0;
-#endif /* defined(__NR_time) */
-}
-
-/**
- * Function responsible for setting up the accept4 syscall for
- * the seccomp filter sandbox.
- */
-static int
-sb_accept4(scmp_filter_ctx ctx, sandbox_cfg_t *filter)
-{
- int rc = 0;
- (void)filter;
-
-#ifdef __i386__
- rc = seccomp_rule_add_1(ctx, SCMP_ACT_ALLOW, SCMP_SYS(socketcall),
- SCMP_CMP(0, SCMP_CMP_EQ, 18));
- if (rc) {
- return rc;
- }
-#endif /* defined(__i386__) */
-
- rc = seccomp_rule_add_1(ctx, SCMP_ACT_ALLOW, SCMP_SYS(accept4),
- SCMP_CMP_MASKED(3, SOCK_CLOEXEC|SOCK_NONBLOCK, 0));
- if (rc) {
- return rc;
- }
-
- return 0;
-}
-
-#ifdef __NR_mmap2
-/**
- * Function responsible for setting up the mmap2 syscall for
- * the seccomp filter sandbox.
- */
-static int
-sb_mmap2(scmp_filter_ctx ctx, sandbox_cfg_t *filter)
-{
- int rc = 0;
- (void)filter;
-
- rc = seccomp_rule_add_2(ctx, SCMP_ACT_ALLOW, SCMP_SYS(mmap2),
- SCMP_CMP(2, SCMP_CMP_EQ, PROT_READ),
- SCMP_CMP(3, SCMP_CMP_EQ, MAP_PRIVATE));
- if (rc) {
- return rc;
- }
-
- rc = seccomp_rule_add_2(ctx, SCMP_ACT_ALLOW, SCMP_SYS(mmap2),
- SCMP_CMP(2, SCMP_CMP_EQ, PROT_NONE),
- SCMP_CMP(3, SCMP_CMP_EQ, MAP_PRIVATE|MAP_ANONYMOUS|MAP_NORESERVE));
- if (rc) {
- return rc;
- }
-
- rc = seccomp_rule_add_2(ctx, SCMP_ACT_ALLOW, SCMP_SYS(mmap2),
- SCMP_CMP(2, SCMP_CMP_EQ, PROT_READ|PROT_WRITE),
- SCMP_CMP(3, SCMP_CMP_EQ, MAP_PRIVATE|MAP_ANONYMOUS));
- if (rc) {
- return rc;
- }
-
- rc = seccomp_rule_add_2(ctx, SCMP_ACT_ALLOW, SCMP_SYS(mmap2),
- SCMP_CMP(2, SCMP_CMP_EQ, PROT_READ|PROT_WRITE),
- SCMP_CMP(3, SCMP_CMP_EQ,MAP_PRIVATE|MAP_ANONYMOUS|MAP_STACK));
- if (rc) {
- return rc;
- }
-
- rc = seccomp_rule_add_2(ctx, SCMP_ACT_ALLOW, SCMP_SYS(mmap2),
- SCMP_CMP(2, SCMP_CMP_EQ, PROT_READ|PROT_WRITE),
- SCMP_CMP(3, SCMP_CMP_EQ, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE));
- if (rc) {
- return rc;
- }
-
- rc = seccomp_rule_add_2(ctx, SCMP_ACT_ALLOW, SCMP_SYS(mmap2),
- SCMP_CMP(2, SCMP_CMP_EQ, PROT_READ|PROT_WRITE),
- SCMP_CMP(3, SCMP_CMP_EQ, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS));
- if (rc) {
- return rc;
- }
-
- rc = seccomp_rule_add_2(ctx, SCMP_ACT_ALLOW, SCMP_SYS(mmap2),
- SCMP_CMP(2, SCMP_CMP_EQ, PROT_READ|PROT_EXEC),
- SCMP_CMP(3, SCMP_CMP_EQ, MAP_PRIVATE|MAP_DENYWRITE));
- if (rc) {
- return rc;
- }
-
- return 0;
-}
-#endif /* defined(__NR_mmap2) */
-
-#ifdef HAVE_GNU_LIBC_VERSION_H
-#ifdef HAVE_GNU_GET_LIBC_VERSION
-#define CHECK_LIBC_VERSION
-#endif
-#endif
-
-/* Return true if we think we're running with a libc that always uses
- * openat on linux. */
-static int
-libc_uses_openat_for_everything(void)
-{
-#ifdef CHECK_LIBC_VERSION
- const char *version = gnu_get_libc_version();
- if (version == NULL)
- return 0;
-
- int major = -1;
- int minor = -1;
-
- tor_sscanf(version, "%d.%d", &major, &minor);
- if (major >= 3)
- return 1;
- else if (major == 2 && minor >= 26)
- return 1;
- else
- return 0;
-#else /* !(defined(CHECK_LIBC_VERSION)) */
- return 0;
-#endif /* defined(CHECK_LIBC_VERSION) */
-}
-
-/** Allow a single file to be opened. If <b>use_openat</b> is true,
- * we're using a libc that remaps all the opens into openats. */
-static int
-allow_file_open(scmp_filter_ctx ctx, int use_openat, const char *file)
-{
- if (use_openat) {
- return seccomp_rule_add_2(ctx, SCMP_ACT_ALLOW, SCMP_SYS(openat),
- SCMP_CMP(0, SCMP_CMP_EQ, (unsigned int)AT_FDCWD),
- SCMP_CMP_STR(1, SCMP_CMP_EQ, file));
- } else {
- return seccomp_rule_add_1(ctx, SCMP_ACT_ALLOW, SCMP_SYS(open),
- SCMP_CMP_STR(0, SCMP_CMP_EQ, file));
- }
-}
-
-/**
- * Function responsible for setting up the open syscall for
- * the seccomp filter sandbox.
- */
-static int
-sb_open(scmp_filter_ctx ctx, sandbox_cfg_t *filter)
-{
- int rc;
- sandbox_cfg_t *elem = NULL;
-
- int use_openat = libc_uses_openat_for_everything();
-
- // for each dynamic parameter filters
- for (elem = filter; elem != NULL; elem = elem->next) {
- smp_param_t *param = elem->param;
-
- if (param != NULL && param->prot == 1 && param->syscall
- == SCMP_SYS(open)) {
- rc = allow_file_open(ctx, use_openat, param->value);
- if (rc != 0) {
- log_err(LD_BUG,"(Sandbox) failed to add open syscall, received "
- "libseccomp error %d", rc);
- return rc;
- }
- }
- }
-
- rc = seccomp_rule_add_1(ctx, SCMP_ACT_ERRNO(EACCES), SCMP_SYS(open),
- SCMP_CMP_MASKED(1, O_CLOEXEC|O_NONBLOCK|O_NOCTTY|O_NOFOLLOW,
- O_RDONLY));
- if (rc != 0) {
- log_err(LD_BUG,"(Sandbox) failed to add open syscall, received libseccomp "
- "error %d", rc);
- return rc;
- }
-
- rc = seccomp_rule_add_1(ctx, SCMP_ACT_ERRNO(EACCES), SCMP_SYS(openat),
- SCMP_CMP_MASKED(2, O_CLOEXEC|O_NONBLOCK|O_NOCTTY|O_NOFOLLOW,
- O_RDONLY));
- if (rc != 0) {
- log_err(LD_BUG,"(Sandbox) failed to add openat syscall, received "
- "libseccomp error %d", rc);
- return rc;
- }
-
- return 0;
-}
-
-static int
-sb_chmod(scmp_filter_ctx ctx, sandbox_cfg_t *filter)
-{
- int rc;
- sandbox_cfg_t *elem = NULL;
-
- // for each dynamic parameter filters
- for (elem = filter; elem != NULL; elem = elem->next) {
- smp_param_t *param = elem->param;
-
- if (param != NULL && param->prot == 1 && param->syscall
- == SCMP_SYS(chmod)) {
- rc = seccomp_rule_add_1(ctx, SCMP_ACT_ALLOW, SCMP_SYS(chmod),
- SCMP_CMP_STR(0, SCMP_CMP_EQ, param->value));
- if (rc != 0) {
- log_err(LD_BUG,"(Sandbox) failed to add chmod syscall, received "
- "libseccomp error %d", rc);
- return rc;
- }
- }
- }
-
- return 0;
-}
-
-static int
-sb_chown(scmp_filter_ctx ctx, sandbox_cfg_t *filter)
-{
- int rc;
- sandbox_cfg_t *elem = NULL;
-
- // for each dynamic parameter filters
- for (elem = filter; elem != NULL; elem = elem->next) {
- smp_param_t *param = elem->param;
-
- if (param != NULL && param->prot == 1 && param->syscall
- == SCMP_SYS(chown)) {
- rc = seccomp_rule_add_1(ctx, SCMP_ACT_ALLOW, SCMP_SYS(chown),
- SCMP_CMP_STR(0, SCMP_CMP_EQ, param->value));
- if (rc != 0) {
- log_err(LD_BUG,"(Sandbox) failed to add chown syscall, received "
- "libseccomp error %d", rc);
- return rc;
- }
- }
- }
-
- return 0;
-}
-
-static int
-sb__sysctl(scmp_filter_ctx ctx, sandbox_cfg_t *filter)
-{
- int rc;
- (void) filter;
- (void) ctx;
-
- rc = seccomp_rule_add_0(ctx, SCMP_ACT_ERRNO(EPERM), SCMP_SYS(_sysctl));
- if (rc != 0) {
- log_err(LD_BUG,"(Sandbox) failed to add _sysctl syscall, "
- "received libseccomp error %d", rc);
- return rc;
- }
-
- return 0;
-}
-
-/**
- * Function responsible for setting up the rename syscall for
- * the seccomp filter sandbox.
- */
-static int
-sb_rename(scmp_filter_ctx ctx, sandbox_cfg_t *filter)
-{
- int rc;
- sandbox_cfg_t *elem = NULL;
-
- // for each dynamic parameter filters
- for (elem = filter; elem != NULL; elem = elem->next) {
- smp_param_t *param = elem->param;
-
- if (param != NULL && param->prot == 1 &&
- param->syscall == SCMP_SYS(rename)) {
-
- rc = seccomp_rule_add_2(ctx, SCMP_ACT_ALLOW, SCMP_SYS(rename),
- SCMP_CMP_STR(0, SCMP_CMP_EQ, param->value),
- SCMP_CMP_STR(1, SCMP_CMP_EQ, param->value2));
- if (rc != 0) {
- log_err(LD_BUG,"(Sandbox) failed to add rename syscall, received "
- "libseccomp error %d", rc);
- return rc;
- }
- }
- }
-
- return 0;
-}
-
-/**
- * Function responsible for setting up the openat syscall for
- * the seccomp filter sandbox.
- */
-static int
-sb_openat(scmp_filter_ctx ctx, sandbox_cfg_t *filter)
-{
- int rc;
- sandbox_cfg_t *elem = NULL;
-
- // for each dynamic parameter filters
- for (elem = filter; elem != NULL; elem = elem->next) {
- smp_param_t *param = elem->param;
-
- if (param != NULL && param->prot == 1 && param->syscall
- == SCMP_SYS(openat)) {
- rc = seccomp_rule_add_3(ctx, SCMP_ACT_ALLOW, SCMP_SYS(openat),
- SCMP_CMP(0, SCMP_CMP_EQ, AT_FDCWD),
- SCMP_CMP_STR(1, SCMP_CMP_EQ, param->value),
- SCMP_CMP(2, SCMP_CMP_EQ, O_RDONLY|O_NONBLOCK|O_LARGEFILE|O_DIRECTORY|
- O_CLOEXEC));
- if (rc != 0) {
- log_err(LD_BUG,"(Sandbox) failed to add openat syscall, received "
- "libseccomp error %d", rc);
- return rc;
- }
- }
- }
-
- return 0;
-}
-
-/**
- * Function responsible for setting up the socket syscall for
- * the seccomp filter sandbox.
- */
-static int
-sb_socket(scmp_filter_ctx ctx, sandbox_cfg_t *filter)
-{
- int rc = 0;
- int i, j;
- (void) filter;
-
-#ifdef __i386__
- rc = seccomp_rule_add_0(ctx, SCMP_ACT_ALLOW, SCMP_SYS(socket));
- if (rc)
- return rc;
-#endif
-
- rc = seccomp_rule_add_2(ctx, SCMP_ACT_ALLOW, SCMP_SYS(socket),
- SCMP_CMP(0, SCMP_CMP_EQ, PF_FILE),
- SCMP_CMP_MASKED(1, SOCK_CLOEXEC|SOCK_NONBLOCK, SOCK_STREAM));
- if (rc)
- return rc;
-
- for (i = 0; i < 2; ++i) {
- const int pf = i ? PF_INET : PF_INET6;
- for (j=0; j < 3; ++j) {
- const int type = (j == 0) ? SOCK_STREAM :
- SOCK_DGRAM;
- const int protocol = (j == 0) ? IPPROTO_TCP :
- (j == 1) ? IPPROTO_IP :
- IPPROTO_UDP;
- rc = seccomp_rule_add_3(ctx, SCMP_ACT_ALLOW, SCMP_SYS(socket),
- SCMP_CMP(0, SCMP_CMP_EQ, pf),
- SCMP_CMP_MASKED(1, SOCK_CLOEXEC|SOCK_NONBLOCK, type),
- SCMP_CMP(2, SCMP_CMP_EQ, protocol));
- if (rc)
- return rc;
- }
- }
-
- rc = seccomp_rule_add_3(ctx, SCMP_ACT_ALLOW, SCMP_SYS(socket),
- SCMP_CMP(0, SCMP_CMP_EQ, PF_UNIX),
- SCMP_CMP_MASKED(1, SOCK_CLOEXEC|SOCK_NONBLOCK, SOCK_STREAM),
- SCMP_CMP(2, SCMP_CMP_EQ, 0));
- if (rc)
- return rc;
-
- rc = seccomp_rule_add_3(ctx, SCMP_ACT_ALLOW, SCMP_SYS(socket),
- SCMP_CMP(0, SCMP_CMP_EQ, PF_UNIX),
- SCMP_CMP_MASKED(1, SOCK_CLOEXEC|SOCK_NONBLOCK, SOCK_DGRAM),
- SCMP_CMP(2, SCMP_CMP_EQ, 0));
- if (rc)
- return rc;
-
- rc = seccomp_rule_add_3(ctx, SCMP_ACT_ALLOW, SCMP_SYS(socket),
- SCMP_CMP(0, SCMP_CMP_EQ, PF_NETLINK),
- SCMP_CMP_MASKED(1, SOCK_CLOEXEC, SOCK_RAW),
- SCMP_CMP(2, SCMP_CMP_EQ, 0));
- if (rc)
- return rc;
-
- return 0;
-}
-
-/**
- * Function responsible for setting up the socketpair syscall for
- * the seccomp filter sandbox.
- */
-static int
-sb_socketpair(scmp_filter_ctx ctx, sandbox_cfg_t *filter)
-{
- int rc = 0;
- (void) filter;
-
-#ifdef __i386__
- rc = seccomp_rule_add_0(ctx, SCMP_ACT_ALLOW, SCMP_SYS(socketpair));
- if (rc)
- return rc;
-#endif
-
- rc = seccomp_rule_add_2(ctx, SCMP_ACT_ALLOW, SCMP_SYS(socketpair),
- SCMP_CMP(0, SCMP_CMP_EQ, PF_FILE),
- SCMP_CMP(1, SCMP_CMP_EQ, SOCK_STREAM|SOCK_CLOEXEC));
- if (rc)
- return rc;
-
- return 0;
-}
-
-#ifdef HAVE_KIST_SUPPORT
-
-#include <linux/sockios.h>
-
-static int
-sb_ioctl(scmp_filter_ctx ctx, sandbox_cfg_t *filter)
-{
- int rc;
- (void) filter;
-
- rc = seccomp_rule_add_1(ctx, SCMP_ACT_ALLOW, SCMP_SYS(ioctl),
- SCMP_CMP(1, SCMP_CMP_EQ, SIOCOUTQNSD));
- if (rc)
- return rc;
- return 0;
-}
-
-#endif /* defined(HAVE_KIST_SUPPORT) */
-
-/**
- * Function responsible for setting up the setsockopt syscall for
- * the seccomp filter sandbox.
- */
-static int
-sb_setsockopt(scmp_filter_ctx ctx, sandbox_cfg_t *filter)
-{
- int rc = 0;
- (void) filter;
-
-#ifdef __i386__
- rc = seccomp_rule_add_0(ctx, SCMP_ACT_ALLOW, SCMP_SYS(setsockopt));
- if (rc)
- return rc;
-#endif
-
- rc = seccomp_rule_add_2(ctx, SCMP_ACT_ALLOW, SCMP_SYS(setsockopt),
- SCMP_CMP(1, SCMP_CMP_EQ, SOL_SOCKET),
- SCMP_CMP(2, SCMP_CMP_EQ, SO_REUSEADDR));
- if (rc)
- return rc;
-
- rc = seccomp_rule_add_2(ctx, SCMP_ACT_ALLOW, SCMP_SYS(setsockopt),
- SCMP_CMP(1, SCMP_CMP_EQ, SOL_SOCKET),
- SCMP_CMP(2, SCMP_CMP_EQ, SO_SNDBUF));
- if (rc)
- return rc;
-
- rc = seccomp_rule_add_2(ctx, SCMP_ACT_ALLOW, SCMP_SYS(setsockopt),
- SCMP_CMP(1, SCMP_CMP_EQ, SOL_SOCKET),
- SCMP_CMP(2, SCMP_CMP_EQ, SO_RCVBUF));
- if (rc)
- return rc;
-
-#ifdef HAVE_SYSTEMD
- rc = seccomp_rule_add_2(ctx, SCMP_ACT_ALLOW, SCMP_SYS(setsockopt),
- SCMP_CMP(1, SCMP_CMP_EQ, SOL_SOCKET),
- SCMP_CMP(2, SCMP_CMP_EQ, SO_SNDBUFFORCE));
- if (rc)
- return rc;
-#endif /* defined(HAVE_SYSTEMD) */
-
-#ifdef IP_TRANSPARENT
- rc = seccomp_rule_add_2(ctx, SCMP_ACT_ALLOW, SCMP_SYS(setsockopt),
- SCMP_CMP(1, SCMP_CMP_EQ, SOL_IP),
- SCMP_CMP(2, SCMP_CMP_EQ, IP_TRANSPARENT));
- if (rc)
- return rc;
-#endif /* defined(IP_TRANSPARENT) */
-
-#ifdef IPV6_V6ONLY
- rc = seccomp_rule_add_2(ctx, SCMP_ACT_ALLOW, SCMP_SYS(setsockopt),
- SCMP_CMP(1, SCMP_CMP_EQ, IPPROTO_IPV6),
- SCMP_CMP(2, SCMP_CMP_EQ, IPV6_V6ONLY));
- if (rc)
- return rc;
-#endif /* defined(IPV6_V6ONLY) */
-
- return 0;
-}
-
-/**
- * Function responsible for setting up the getsockopt syscall for
- * the seccomp filter sandbox.
- */
-static int
-sb_getsockopt(scmp_filter_ctx ctx, sandbox_cfg_t *filter)
-{
- int rc = 0;
- (void) filter;
-
-#ifdef __i386__
- rc = seccomp_rule_add_0(ctx, SCMP_ACT_ALLOW, SCMP_SYS(getsockopt));
- if (rc)
- return rc;
-#endif
-
- rc = seccomp_rule_add_2(ctx, SCMP_ACT_ALLOW, SCMP_SYS(getsockopt),
- SCMP_CMP(1, SCMP_CMP_EQ, SOL_SOCKET),
- SCMP_CMP(2, SCMP_CMP_EQ, SO_ERROR));
- if (rc)
- return rc;
-
-#ifdef HAVE_SYSTEMD
- rc = seccomp_rule_add_2(ctx, SCMP_ACT_ALLOW, SCMP_SYS(getsockopt),
- SCMP_CMP(1, SCMP_CMP_EQ, SOL_SOCKET),
- SCMP_CMP(2, SCMP_CMP_EQ, SO_SNDBUF));
- if (rc)
- return rc;
-#endif /* defined(HAVE_SYSTEMD) */
-
-#ifdef HAVE_LINUX_NETFILTER_IPV4_H
- rc = seccomp_rule_add_2(ctx, SCMP_ACT_ALLOW, SCMP_SYS(getsockopt),
- SCMP_CMP(1, SCMP_CMP_EQ, SOL_IP),
- SCMP_CMP(2, SCMP_CMP_EQ, SO_ORIGINAL_DST));
- if (rc)
- return rc;
-#endif /* defined(HAVE_LINUX_NETFILTER_IPV4_H) */
-
-#ifdef HAVE_LINUX_NETFILTER_IPV6_IP6_TABLES_H
- rc = seccomp_rule_add_2(ctx, SCMP_ACT_ALLOW, SCMP_SYS(getsockopt),
- SCMP_CMP(1, SCMP_CMP_EQ, SOL_IPV6),
- SCMP_CMP(2, SCMP_CMP_EQ, IP6T_SO_ORIGINAL_DST));
- if (rc)
- return rc;
-#endif /* defined(HAVE_LINUX_NETFILTER_IPV6_IP6_TABLES_H) */
-
-#ifdef HAVE_KIST_SUPPORT
-#include <netinet/tcp.h>
- rc = seccomp_rule_add_2(ctx, SCMP_ACT_ALLOW, SCMP_SYS(getsockopt),
- SCMP_CMP(1, SCMP_CMP_EQ, SOL_TCP),
- SCMP_CMP(2, SCMP_CMP_EQ, TCP_INFO));
- if (rc)
- return rc;
-#endif /* defined(HAVE_KIST_SUPPORT) */
-
- return 0;
-}
-
-#ifdef __NR_fcntl64
-/**
- * Function responsible for setting up the fcntl64 syscall for
- * the seccomp filter sandbox.
- */
-static int
-sb_fcntl64(scmp_filter_ctx ctx, sandbox_cfg_t *filter)
-{
- int rc = 0;
- (void) filter;
-
- rc = seccomp_rule_add_1(ctx, SCMP_ACT_ALLOW, SCMP_SYS(fcntl64),
- SCMP_CMP(1, SCMP_CMP_EQ, F_GETFL));
- if (rc)
- return rc;
-
- rc = seccomp_rule_add_2(ctx, SCMP_ACT_ALLOW, SCMP_SYS(fcntl64),
- SCMP_CMP(1, SCMP_CMP_EQ, F_SETFL),
- SCMP_CMP(2, SCMP_CMP_EQ, O_RDWR|O_NONBLOCK));
- if (rc)
- return rc;
-
- rc = seccomp_rule_add_1(ctx, SCMP_ACT_ALLOW, SCMP_SYS(fcntl64),
- SCMP_CMP(1, SCMP_CMP_EQ, F_GETFD));
- if (rc)
- return rc;
-
- rc = seccomp_rule_add_2(ctx, SCMP_ACT_ALLOW, SCMP_SYS(fcntl64),
- SCMP_CMP(1, SCMP_CMP_EQ, F_SETFD),
- SCMP_CMP(2, SCMP_CMP_EQ, FD_CLOEXEC));
- if (rc)
- return rc;
-
- return 0;
-}
-#endif /* defined(__NR_fcntl64) */
-
-/**
- * Function responsible for setting up the epoll_ctl syscall for
- * the seccomp filter sandbox.
- *
- * Note: basically allows everything but will keep for now..
- */
-static int
-sb_epoll_ctl(scmp_filter_ctx ctx, sandbox_cfg_t *filter)
-{
- int rc = 0;
- (void) filter;
-
- rc = seccomp_rule_add_1(ctx, SCMP_ACT_ALLOW, SCMP_SYS(epoll_ctl),
- SCMP_CMP(1, SCMP_CMP_EQ, EPOLL_CTL_ADD));
- if (rc)
- return rc;
-
- rc = seccomp_rule_add_1(ctx, SCMP_ACT_ALLOW, SCMP_SYS(epoll_ctl),
- SCMP_CMP(1, SCMP_CMP_EQ, EPOLL_CTL_MOD));
- if (rc)
- return rc;
-
- rc = seccomp_rule_add_1(ctx, SCMP_ACT_ALLOW, SCMP_SYS(epoll_ctl),
- SCMP_CMP(1, SCMP_CMP_EQ, EPOLL_CTL_DEL));
- if (rc)
- return rc;
-
- return 0;
-}
-
-/**
- * Function responsible for setting up the prctl syscall for
- * the seccomp filter sandbox.
- *
- * NOTE: if multiple filters need to be added, the PR_SECCOMP parameter needs
- * to be whitelisted in this function.
- */
-static int
-sb_prctl(scmp_filter_ctx ctx, sandbox_cfg_t *filter)
-{
- int rc = 0;
- (void) filter;
-
- rc = seccomp_rule_add_1(ctx, SCMP_ACT_ALLOW, SCMP_SYS(prctl),
- SCMP_CMP(0, SCMP_CMP_EQ, PR_SET_DUMPABLE));
- if (rc)
- return rc;
-
- return 0;
-}
-
-/**
- * Function responsible for setting up the mprotect syscall for
- * the seccomp filter sandbox.
- *
- * NOTE: does not NEED to be here.. currently only occurs before filter; will
- * keep just in case for the future.
- */
-static int
-sb_mprotect(scmp_filter_ctx ctx, sandbox_cfg_t *filter)
-{
- int rc = 0;
- (void) filter;
-
- rc = seccomp_rule_add_1(ctx, SCMP_ACT_ALLOW, SCMP_SYS(mprotect),
- SCMP_CMP(2, SCMP_CMP_EQ, PROT_READ));
- if (rc)
- return rc;
-
- rc = seccomp_rule_add_1(ctx, SCMP_ACT_ALLOW, SCMP_SYS(mprotect),
- SCMP_CMP(2, SCMP_CMP_EQ, PROT_NONE));
- if (rc)
- return rc;
-
- return 0;
-}
-
-/**
- * Function responsible for setting up the rt_sigprocmask syscall for
- * the seccomp filter sandbox.
- */
-static int
-sb_rt_sigprocmask(scmp_filter_ctx ctx, sandbox_cfg_t *filter)
-{
- int rc = 0;
- (void) filter;
-
- rc = seccomp_rule_add_1(ctx, SCMP_ACT_ALLOW, SCMP_SYS(rt_sigprocmask),
- SCMP_CMP(0, SCMP_CMP_EQ, SIG_UNBLOCK));
- if (rc)
- return rc;
-
- rc = seccomp_rule_add_1(ctx, SCMP_ACT_ALLOW, SCMP_SYS(rt_sigprocmask),
- SCMP_CMP(0, SCMP_CMP_EQ, SIG_SETMASK));
- if (rc)
- return rc;
-
- return 0;
-}
-
-/**
- * Function responsible for setting up the flock syscall for
- * the seccomp filter sandbox.
- *
- * NOTE: does not need to be here, occurs before filter is applied.
- */
-static int
-sb_flock(scmp_filter_ctx ctx, sandbox_cfg_t *filter)
-{
- int rc = 0;
- (void) filter;
-
- rc = seccomp_rule_add_1(ctx, SCMP_ACT_ALLOW, SCMP_SYS(flock),
- SCMP_CMP(1, SCMP_CMP_EQ, LOCK_EX|LOCK_NB));
- if (rc)
- return rc;
-
- rc = seccomp_rule_add_1(ctx, SCMP_ACT_ALLOW, SCMP_SYS(flock),
- SCMP_CMP(1, SCMP_CMP_EQ, LOCK_UN));
- if (rc)
- return rc;
-
- return 0;
-}
-
-/**
- * Function responsible for setting up the futex syscall for
- * the seccomp filter sandbox.
- */
-static int
-sb_futex(scmp_filter_ctx ctx, sandbox_cfg_t *filter)
-{
- int rc = 0;
- (void) filter;
-
- // can remove
- rc = seccomp_rule_add_1(ctx, SCMP_ACT_ALLOW, SCMP_SYS(futex),
- SCMP_CMP(1, SCMP_CMP_EQ,
- FUTEX_WAIT_BITSET_PRIVATE|FUTEX_CLOCK_REALTIME));
- if (rc)
- return rc;
-
- rc = seccomp_rule_add_1(ctx, SCMP_ACT_ALLOW, SCMP_SYS(futex),
- SCMP_CMP(1, SCMP_CMP_EQ, FUTEX_WAKE_PRIVATE));
- if (rc)
- return rc;
-
- rc = seccomp_rule_add_1(ctx, SCMP_ACT_ALLOW, SCMP_SYS(futex),
- SCMP_CMP(1, SCMP_CMP_EQ, FUTEX_WAIT_PRIVATE));
- if (rc)
- return rc;
-
- return 0;
-}
-
-/**
- * Function responsible for setting up the mremap syscall for
- * the seccomp filter sandbox.
- *
- * NOTE: so far only occurs before filter is applied.
- */
-static int
-sb_mremap(scmp_filter_ctx ctx, sandbox_cfg_t *filter)
-{
- int rc = 0;
- (void) filter;
-
- rc = seccomp_rule_add_1(ctx, SCMP_ACT_ALLOW, SCMP_SYS(mremap),
- SCMP_CMP(3, SCMP_CMP_EQ, MREMAP_MAYMOVE));
- if (rc)
- return rc;
-
- return 0;
-}
-
-#ifdef __NR_stat64
-/**
- * Function responsible for setting up the stat64 syscall for
- * the seccomp filter sandbox.
- */
-static int
-sb_stat64(scmp_filter_ctx ctx, sandbox_cfg_t *filter)
-{
- int rc = 0;
- sandbox_cfg_t *elem = NULL;
-
- // for each dynamic parameter filters
- for (elem = filter; elem != NULL; elem = elem->next) {
- smp_param_t *param = elem->param;
-
- if (param != NULL && param->prot == 1 && (param->syscall == SCMP_SYS(open)
- || param->syscall == SCMP_SYS(stat64))) {
- rc = seccomp_rule_add_1(ctx, SCMP_ACT_ALLOW, SCMP_SYS(stat64),
- SCMP_CMP_STR(0, SCMP_CMP_EQ, param->value));
- if (rc != 0) {
- log_err(LD_BUG,"(Sandbox) failed to add stat64 syscall, received "
- "libseccomp error %d", rc);
- return rc;
- }
- }
- }
-
- return 0;
-}
-#endif /* defined(__NR_stat64) */
-
-static int
-sb_kill(scmp_filter_ctx ctx, sandbox_cfg_t *filter)
-{
- (void) filter;
-#ifdef __NR_kill
- /* Allow killing anything with signal 0 -- it isn't really a kill. */
- return seccomp_rule_add_1(ctx, SCMP_ACT_ALLOW, SCMP_SYS(kill),
- SCMP_CMP(1, SCMP_CMP_EQ, 0));
-#else
- return 0;
-#endif /* defined(__NR_kill) */
-}
-
-/**
- * Array of function pointers responsible for filtering different syscalls at
- * a parameter level.
- */
-static sandbox_filter_func_t filter_func[] = {
- sb_rt_sigaction,
- sb_rt_sigprocmask,
- sb_time,
- sb_accept4,
-#ifdef __NR_mmap2
- sb_mmap2,
-#endif
- sb_chown,
- sb_chmod,
- sb_open,
- sb_openat,
- sb__sysctl,
- sb_rename,
-#ifdef __NR_fcntl64
- sb_fcntl64,
-#endif
- sb_epoll_ctl,
- sb_prctl,
- sb_mprotect,
- sb_flock,
- sb_futex,
- sb_mremap,
-#ifdef __NR_stat64
- sb_stat64,
-#endif
-
- sb_socket,
- sb_setsockopt,
- sb_getsockopt,
- sb_socketpair,
-#ifdef HAVE_KIST_SUPPORT
- sb_ioctl,
-#endif
- sb_kill
-};
-
-const char *
-sandbox_intern_string(const char *str)
-{
- sandbox_cfg_t *elem;
-
- if (str == NULL)
- return NULL;
-
- for (elem = filter_dynamic; elem != NULL; elem = elem->next) {
- smp_param_t *param = elem->param;
-
- if (param->prot) {
- if (!strcmp(str, (char*)(param->value))) {
- return (char*)param->value;
- }
- if (param->value2 && !strcmp(str, (char*)param->value2)) {
- return (char*)param->value2;
- }
- }
- }
-
- if (sandbox_active)
- log_warn(LD_BUG, "No interned sandbox parameter found for %s", str);
- return str;
-}
-
-/* DOCDOC */
-static int
-prot_strings_helper(strmap_t *locations,
- char **pr_mem_next_p,
- size_t *pr_mem_left_p,
- char **value_p)
-{
- char *param_val;
- size_t param_size;
- void *location;
-
- if (*value_p == 0)
- return 0;
-
- param_val = (char*) *value_p;
- param_size = strlen(param_val) + 1;
- location = strmap_get(locations, param_val);
-
- if (location) {
- // We already interned this string.
- tor_free(param_val);
- *value_p = location;
- return 0;
- } else if (*pr_mem_left_p >= param_size) {
- // copy to protected
- location = *pr_mem_next_p;
- memcpy(location, param_val, param_size);
-
- // re-point el parameter to protected
- tor_free(param_val);
- *value_p = location;
-
- strmap_set(locations, location, location); /* good real estate advice */
-
- // move next available protected memory
- *pr_mem_next_p += param_size;
- *pr_mem_left_p -= param_size;
- return 0;
- } else {
- log_err(LD_BUG,"(Sandbox) insufficient protected memory!");
- return -1;
- }
-}
-
-/**
- * Protects all the strings in the sandbox's parameter list configuration. It
- * works by calculating the total amount of memory required by the parameter
- * list, allocating the memory using mmap, and protecting it from writes with
- * mprotect().
- */
-static int
-prot_strings(scmp_filter_ctx ctx, sandbox_cfg_t* cfg)
-{
- int ret = 0;
- size_t pr_mem_size = 0, pr_mem_left = 0;
- char *pr_mem_next = NULL, *pr_mem_base;
- sandbox_cfg_t *el = NULL;
- strmap_t *locations = NULL;
-
- // get total number of bytes required to mmap. (Overestimate.)
- for (el = cfg; el != NULL; el = el->next) {
- pr_mem_size += strlen((char*) el->param->value) + 1;
- if (el->param->value2)
- pr_mem_size += strlen((char*) el->param->value2) + 1;
- }
-
- // allocate protected memory with MALLOC_MP_LIM canary
- pr_mem_base = (char*) mmap(NULL, MALLOC_MP_LIM + pr_mem_size,
- PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANON, -1, 0);
- if (pr_mem_base == MAP_FAILED) {
- log_err(LD_BUG,"(Sandbox) failed allocate protected memory! mmap: %s",
- strerror(errno));
- ret = -1;
- goto out;
- }
-
- pr_mem_next = pr_mem_base + MALLOC_MP_LIM;
- pr_mem_left = pr_mem_size;
-
- locations = strmap_new();
-
- // change el value pointer to protected
- for (el = cfg; el != NULL; el = el->next) {
- if (prot_strings_helper(locations, &pr_mem_next, &pr_mem_left,
- &el->param->value) < 0) {
- ret = -2;
- goto out;
- }
- if (prot_strings_helper(locations, &pr_mem_next, &pr_mem_left,
- &el->param->value2) < 0) {
- ret = -2;
- goto out;
- }
- el->param->prot = 1;
- }
-
- // protecting from writes
- if (mprotect(pr_mem_base, MALLOC_MP_LIM + pr_mem_size, PROT_READ)) {
- log_err(LD_BUG,"(Sandbox) failed to protect memory! mprotect: %s",
- strerror(errno));
- ret = -3;
- goto out;
- }
-
- /*
- * Setting sandbox restrictions so the string memory cannot be tampered with
- */
- // no mremap of the protected base address
- ret = seccomp_rule_add_1(ctx, SCMP_ACT_KILL, SCMP_SYS(mremap),
- SCMP_CMP(0, SCMP_CMP_EQ, (intptr_t) pr_mem_base));
- if (ret) {
- log_err(LD_BUG,"(Sandbox) mremap protected memory filter fail!");
- goto out;
- }
-
- // no munmap of the protected base address
- ret = seccomp_rule_add_1(ctx, SCMP_ACT_KILL, SCMP_SYS(munmap),
- SCMP_CMP(0, SCMP_CMP_EQ, (intptr_t) pr_mem_base));
- if (ret) {
- log_err(LD_BUG,"(Sandbox) munmap protected memory filter fail!");
- goto out;
- }
-
- /*
- * Allow mprotect with PROT_READ|PROT_WRITE because openssl uses it, but
- * never over the memory region used by the protected strings.
- *
- * PROT_READ|PROT_WRITE was originally fully allowed in sb_mprotect(), but
- * had to be removed due to limitation of libseccomp regarding intervals.
- *
- * There is a restriction on how much you can mprotect with R|W up to the
- * size of the canary.
- */
- ret = seccomp_rule_add_3(ctx, SCMP_ACT_ALLOW, SCMP_SYS(mprotect),
- SCMP_CMP(0, SCMP_CMP_LT, (intptr_t) pr_mem_base),
- SCMP_CMP(1, SCMP_CMP_LE, MALLOC_MP_LIM),
- SCMP_CMP(2, SCMP_CMP_EQ, PROT_READ|PROT_WRITE));
- if (ret) {
- log_err(LD_BUG,"(Sandbox) mprotect protected memory filter fail (LT)!");
- goto out;
- }
-
- ret = seccomp_rule_add_3(ctx, SCMP_ACT_ALLOW, SCMP_SYS(mprotect),
- SCMP_CMP(0, SCMP_CMP_GT, (intptr_t) pr_mem_base + pr_mem_size +
- MALLOC_MP_LIM),
- SCMP_CMP(1, SCMP_CMP_LE, MALLOC_MP_LIM),
- SCMP_CMP(2, SCMP_CMP_EQ, PROT_READ|PROT_WRITE));
- if (ret) {
- log_err(LD_BUG,"(Sandbox) mprotect protected memory filter fail (GT)!");
- goto out;
- }
-
- out:
- strmap_free(locations, NULL);
- return ret;
-}
-
-/**
- * Auxiliary function used in order to allocate a sandbox_cfg_t element and set
- * its values according the parameter list. All elements are initialised
- * with the 'prot' field set to false, as the pointer is not protected at this
- * point.
- */
-static sandbox_cfg_t*
-new_element2(int syscall, char *value, char *value2)
-{
- smp_param_t *param = NULL;
-
- sandbox_cfg_t *elem = tor_malloc_zero(sizeof(sandbox_cfg_t));
- param = elem->param = tor_malloc_zero(sizeof(smp_param_t));
-
- param->syscall = syscall;
- param->value = value;
- param->value2 = value2;
- param->prot = 0;
-
- return elem;
-}
-
-static sandbox_cfg_t*
-new_element(int syscall, char *value)
-{
- return new_element2(syscall, value, NULL);
-}
-
-#ifdef __NR_stat64
-#define SCMP_stat SCMP_SYS(stat64)
-#else
-#define SCMP_stat SCMP_SYS(stat)
-#endif
-
-int
-sandbox_cfg_allow_stat_filename(sandbox_cfg_t **cfg, char *file)
-{
- sandbox_cfg_t *elem = NULL;
-
- elem = new_element(SCMP_stat, file);
-
- elem->next = *cfg;
- *cfg = elem;
-
- return 0;
-}
-
-int
-sandbox_cfg_allow_open_filename(sandbox_cfg_t **cfg, char *file)
-{
- sandbox_cfg_t *elem = NULL;
-
- elem = new_element(SCMP_SYS(open), file);
-
- elem->next = *cfg;
- *cfg = elem;
-
- return 0;
-}
-
-int
-sandbox_cfg_allow_chmod_filename(sandbox_cfg_t **cfg, char *file)
-{
- sandbox_cfg_t *elem = NULL;
-
- elem = new_element(SCMP_SYS(chmod), file);
-
- elem->next = *cfg;
- *cfg = elem;
-
- return 0;
-}
-
-int
-sandbox_cfg_allow_chown_filename(sandbox_cfg_t **cfg, char *file)
-{
- sandbox_cfg_t *elem = NULL;
-
- elem = new_element(SCMP_SYS(chown), file);
-
- elem->next = *cfg;
- *cfg = elem;
-
- return 0;
-}
-
-int
-sandbox_cfg_allow_rename(sandbox_cfg_t **cfg, char *file1, char *file2)
-{
- sandbox_cfg_t *elem = NULL;
-
- elem = new_element2(SCMP_SYS(rename), file1, file2);
-
- elem->next = *cfg;
- *cfg = elem;
-
- return 0;
-}
-
-int
-sandbox_cfg_allow_openat_filename(sandbox_cfg_t **cfg, char *file)
-{
- sandbox_cfg_t *elem = NULL;
-
- elem = new_element(SCMP_SYS(openat), file);
-
- elem->next = *cfg;
- *cfg = elem;
-
- return 0;
-}
-
-/** Cache entry for getaddrinfo results; used when sandboxing is implemented
- * so that we can consult the cache when the sandbox prevents us from doing
- * getaddrinfo.
- *
- * We support only a limited range of getaddrinfo calls, where servname is null
- * and hints contains only socktype=SOCK_STREAM, family in INET,INET6,UNSPEC.
- */
-typedef struct cached_getaddrinfo_item_t {
- HT_ENTRY(cached_getaddrinfo_item_t) node;
- char *name;
- int family;
- /** set if no error; otherwise NULL */
- struct addrinfo *res;
- /** 0 for no error; otherwise an EAI_* value */
- int err;
-} cached_getaddrinfo_item_t;
-
-static unsigned
-cached_getaddrinfo_item_hash(const cached_getaddrinfo_item_t *item)
-{
- return (unsigned)siphash24g(item->name, strlen(item->name)) + item->family;
-}
-
-static unsigned
-cached_getaddrinfo_items_eq(const cached_getaddrinfo_item_t *a,
- const cached_getaddrinfo_item_t *b)
-{
- return (a->family == b->family) && 0 == strcmp(a->name, b->name);
-}
-
-#define cached_getaddrinfo_item_free(item) \
- FREE_AND_NULL(cached_getaddrinfo_item_t, \
- cached_getaddrinfo_item_free_, (item))
-
-static void
-cached_getaddrinfo_item_free_(cached_getaddrinfo_item_t *item)
-{
- if (item == NULL)
- return;
-
- tor_free(item->name);
- if (item->res)
- freeaddrinfo(item->res);
- tor_free(item);
-}
-
-static HT_HEAD(getaddrinfo_cache, cached_getaddrinfo_item_t)
- getaddrinfo_cache = HT_INITIALIZER();
-
-HT_PROTOTYPE(getaddrinfo_cache, cached_getaddrinfo_item_t, node,
- cached_getaddrinfo_item_hash,
- cached_getaddrinfo_items_eq)
-HT_GENERATE2(getaddrinfo_cache, cached_getaddrinfo_item_t, node,
- cached_getaddrinfo_item_hash,
- cached_getaddrinfo_items_eq,
- 0.6, tor_reallocarray_, tor_free_)
-
-/** If true, don't try to cache getaddrinfo results. */
-static int sandbox_getaddrinfo_cache_disabled = 0;
-
-/** Tell the sandbox layer not to try to cache getaddrinfo results. Used as in
- * tor-resolve, when we have no intention of initializing crypto or of
- * installing the sandbox.*/
-void
-sandbox_disable_getaddrinfo_cache(void)
-{
- sandbox_getaddrinfo_cache_disabled = 1;
-}
-
-void
-sandbox_freeaddrinfo(struct addrinfo *ai)
-{
- if (sandbox_getaddrinfo_cache_disabled)
- freeaddrinfo(ai);
-}
-
-int
-sandbox_getaddrinfo(const char *name, const char *servname,
- const struct addrinfo *hints,
- struct addrinfo **res)
-{
- int err;
- struct cached_getaddrinfo_item_t search, *item;
-
- if (sandbox_getaddrinfo_cache_disabled) {
- return getaddrinfo(name, NULL, hints, res);
- }
-
- if (servname != NULL) {
- log_warn(LD_BUG, "called with non-NULL servname");
- return EAI_NONAME;
- }
- if (name == NULL) {
- log_warn(LD_BUG, "called with NULL name");
- return EAI_NONAME;
- }
-
- *res = NULL;
-
- memset(&search, 0, sizeof(search));
- search.name = (char *) name;
- search.family = hints ? hints->ai_family : AF_UNSPEC;
- item = HT_FIND(getaddrinfo_cache, &getaddrinfo_cache, &search);
-
- if (! sandbox_is_active()) {
- /* If the sandbox is not turned on yet, then getaddrinfo and store the
- result. */
-
- err = getaddrinfo(name, NULL, hints, res);
- log_info(LD_NET,"(Sandbox) getaddrinfo %s.", err ? "failed" : "succeeded");
-
- if (! item) {
- item = tor_malloc_zero(sizeof(*item));
- item->name = tor_strdup(name);
- item->family = hints ? hints->ai_family : AF_UNSPEC;
- HT_INSERT(getaddrinfo_cache, &getaddrinfo_cache, item);
- }
-
- if (item->res) {
- freeaddrinfo(item->res);
- item->res = NULL;
- }
- item->res = *res;
- item->err = err;
- return err;
- }
-
- /* Otherwise, the sandbox is on. If we have an item, yield its cached
- result. */
- if (item) {
- *res = item->res;
- return item->err;
- }
-
- /* getting here means something went wrong */
- log_err(LD_BUG,"(Sandbox) failed to get address %s!", name);
- return EAI_NONAME;
-}
-
-int
-sandbox_add_addrinfo(const char *name)
-{
- struct addrinfo *res;
- struct addrinfo hints;
- int i;
- static const int families[] = { AF_INET, AF_INET6, AF_UNSPEC };
-
- memset(&hints, 0, sizeof(hints));
- hints.ai_socktype = SOCK_STREAM;
- for (i = 0; i < 3; ++i) {
- hints.ai_family = families[i];
-
- res = NULL;
- (void) sandbox_getaddrinfo(name, NULL, &hints, &res);
- if (res)
- sandbox_freeaddrinfo(res);
- }
-
- return 0;
-}
-
-void
-sandbox_free_getaddrinfo_cache(void)
-{
- cached_getaddrinfo_item_t **next, **item, *this;
-
- for (item = HT_START(getaddrinfo_cache, &getaddrinfo_cache);
- item;
- item = next) {
- this = *item;
- next = HT_NEXT_RMV(getaddrinfo_cache, &getaddrinfo_cache, item);
- cached_getaddrinfo_item_free(this);
- }
-
- HT_CLEAR(getaddrinfo_cache, &getaddrinfo_cache);
-}
-
-/**
- * Function responsible for going through the parameter syscall filters and
- * call each function pointer in the list.
- */
-static int
-add_param_filter(scmp_filter_ctx ctx, sandbox_cfg_t* cfg)
-{
- unsigned i;
- int rc = 0;
-
- // function pointer
- for (i = 0; i < ARRAY_LENGTH(filter_func); i++) {
- rc = filter_func[i](ctx, cfg);
- if (rc) {
- log_err(LD_BUG,"(Sandbox) failed to add syscall %d, received libseccomp "
- "error %d", i, rc);
- return rc;
- }
- }
-
- return 0;
-}
-
-/**
- * Function responsible of loading the libseccomp syscall filters which do not
- * have parameter filtering.
- */
-static int
-add_noparam_filter(scmp_filter_ctx ctx)
-{
- unsigned i;
- int rc = 0;
-
- // add general filters
- for (i = 0; i < ARRAY_LENGTH(filter_nopar_gen); i++) {
- rc = seccomp_rule_add_0(ctx, SCMP_ACT_ALLOW, filter_nopar_gen[i]);
- if (rc != 0) {
- log_err(LD_BUG,"(Sandbox) failed to add syscall index %d (NR=%d), "
- "received libseccomp error %d", i, filter_nopar_gen[i], rc);
- return rc;
- }
- }
-
- return 0;
-}
-
-/**
- * Function responsible for setting up and enabling a global syscall filter.
- * The function is a prototype developed for stage 1 of sandboxing Tor.
- * Returns 0 on success.
- */
-static int
-install_syscall_filter(sandbox_cfg_t* cfg)
-{
- int rc = 0;
- scmp_filter_ctx ctx;
-
- ctx = seccomp_init(SCMP_ACT_TRAP);
- if (ctx == NULL) {
- log_err(LD_BUG,"(Sandbox) failed to initialise libseccomp context");
- rc = -1;
- goto end;
- }
-
- // protectign sandbox parameter strings
- if ((rc = prot_strings(ctx, cfg))) {
- goto end;
- }
-
- // add parameter filters
- if ((rc = add_param_filter(ctx, cfg))) {
- log_err(LD_BUG, "(Sandbox) failed to add param filters!");
- goto end;
- }
-
- // adding filters with no parameters
- if ((rc = add_noparam_filter(ctx))) {
- log_err(LD_BUG, "(Sandbox) failed to add param filters!");
- goto end;
- }
-
- // loading the seccomp2 filter
- if ((rc = seccomp_load(ctx))) {
- log_err(LD_BUG, "(Sandbox) failed to load: %d (%s)! "
- "Are you sure that your kernel has seccomp2 support? The "
- "sandbox won't work without it.", rc,
- strerror(-rc));
- goto end;
- }
-
- // marking the sandbox as active
- sandbox_active = 1;
-
- end:
- seccomp_release(ctx);
- return (rc < 0 ? -rc : rc);
-}
-
-#include "linux_syscalls.inc"
-static const char *
-get_syscall_name(int syscall_num)
-{
- int i;
- for (i = 0; SYSCALLS_BY_NUMBER[i].syscall_name; ++i) {
- if (SYSCALLS_BY_NUMBER[i].syscall_num == syscall_num)
- return SYSCALLS_BY_NUMBER[i].syscall_name;
- }
-
- {
- static char syscall_name_buf[64];
- format_dec_number_sigsafe(syscall_num,
- syscall_name_buf, sizeof(syscall_name_buf));
- return syscall_name_buf;
- }
-}
-
-#ifdef USE_BACKTRACE
-#define MAX_DEPTH 256
-static void *syscall_cb_buf[MAX_DEPTH];
-#endif
-
-/**
- * Function called when a SIGSYS is caught by the application. It notifies the
- * user that an error has occurred and either terminates or allows the
- * application to continue execution, based on the DEBUGGING_CLOSE symbol.
- */
-static void
-sigsys_debugging(int nr, siginfo_t *info, void *void_context)
-{
- ucontext_t *ctx = (ucontext_t *) (void_context);
- const char *syscall_name;
- int syscall;
-#ifdef USE_BACKTRACE
- size_t depth;
- int n_fds, i;
- const int *fds = NULL;
-#endif
-
- (void) nr;
-
- if (info->si_code != SYS_SECCOMP)
- return;
-
- if (!ctx)
- return;
-
- syscall = (int) ctx->uc_mcontext.M_SYSCALL;
-
-#ifdef USE_BACKTRACE
- depth = backtrace(syscall_cb_buf, MAX_DEPTH);
- /* Clean up the top stack frame so we get the real function
- * name for the most recently failing function. */
- clean_backtrace(syscall_cb_buf, depth, ctx);
-#endif /* defined(USE_BACKTRACE) */
-
- syscall_name = get_syscall_name(syscall);
-
- tor_log_err_sigsafe("(Sandbox) Caught a bad syscall attempt (syscall ",
- syscall_name,
- ")\n",
- NULL);
-
-#ifdef USE_BACKTRACE
- n_fds = tor_log_get_sigsafe_err_fds(&fds);
- for (i=0; i < n_fds; ++i)
- backtrace_symbols_fd(syscall_cb_buf, (int)depth, fds[i]);
-#endif
-
-#if defined(DEBUGGING_CLOSE)
- _exit(1); // exit ok: programming error has led to sandbox failure.
-#endif // DEBUGGING_CLOSE
-}
-
-/**
- * Function that adds a handler for SIGSYS, which is the signal thrown
- * when the application is issuing a syscall which is not allowed. The
- * main purpose of this function is to help with debugging by identifying
- * filtered syscalls.
- */
-static int
-install_sigsys_debugging(void)
-{
- struct sigaction act;
- sigset_t mask;
-
- memset(&act, 0, sizeof(act));
- sigemptyset(&mask);
- sigaddset(&mask, SIGSYS);
-
- act.sa_sigaction = &sigsys_debugging;
- act.sa_flags = SA_SIGINFO;
- if (sigaction(SIGSYS, &act, NULL) < 0) {
- log_err(LD_BUG,"(Sandbox) Failed to register SIGSYS signal handler");
- return -1;
- }
-
- if (sigprocmask(SIG_UNBLOCK, &mask, NULL)) {
- log_err(LD_BUG,"(Sandbox) Failed call to sigprocmask()");
- return -2;
- }
-
- return 0;
-}
-
-/**
- * Function responsible of registering the sandbox_cfg_t list of parameter
- * syscall filters to the existing parameter list. This is used for incipient
- * multiple-sandbox support.
- */
-static int
-register_cfg(sandbox_cfg_t* cfg)
-{
- sandbox_cfg_t *elem = NULL;
-
- if (filter_dynamic == NULL) {
- filter_dynamic = cfg;
- return 0;
- }
-
- for (elem = filter_dynamic; elem->next != NULL; elem = elem->next)
- ;
-
- elem->next = cfg;
-
- return 0;
-}
-
-#endif /* defined(USE_LIBSECCOMP) */
-
-#ifdef USE_LIBSECCOMP
-/**
- * Initialises the syscall sandbox filter for any linux architecture, taking
- * into account various available features for different linux flavours.
- */
-static int
-initialise_libseccomp_sandbox(sandbox_cfg_t* cfg)
-{
- /* Prevent glibc from trying to open /dev/tty on fatal error */
- setenv("LIBC_FATAL_STDERR_", "1", 1);
-
- if (install_sigsys_debugging())
- return -1;
-
- if (install_syscall_filter(cfg))
- return -2;
-
- if (register_cfg(cfg))
- return -3;
-
- return 0;
-}
-
-int
-sandbox_is_active(void)
-{
- return sandbox_active != 0;
-}
-#endif /* defined(USE_LIBSECCOMP) */
-
-sandbox_cfg_t*
-sandbox_cfg_new(void)
-{
- return NULL;
-}
-
-int
-sandbox_init(sandbox_cfg_t *cfg)
-{
-#if defined(USE_LIBSECCOMP)
- return initialise_libseccomp_sandbox(cfg);
-
-#elif defined(__linux__)
- (void)cfg;
- log_warn(LD_GENERAL,
- "This version of Tor was built without support for sandboxing. To "
- "build with support for sandboxing on Linux, you must have "
- "libseccomp and its necessary header files (e.g. seccomp.h).");
- return 0;
-
-#else
- (void)cfg;
- log_warn(LD_GENERAL,
- "Currently, sandboxing is only implemented on Linux. The feature "
- "is disabled on your platform.");
- return 0;
-#endif /* defined(USE_LIBSECCOMP) || ... */
-}
-
-#ifndef USE_LIBSECCOMP
-int
-sandbox_cfg_allow_open_filename(sandbox_cfg_t **cfg, char *file)
-{
- (void)cfg; (void)file;
- return 0;
-}
-
-int
-sandbox_cfg_allow_openat_filename(sandbox_cfg_t **cfg, char *file)
-{
- (void)cfg; (void)file;
- return 0;
-}
-
-int
-sandbox_cfg_allow_stat_filename(sandbox_cfg_t **cfg, char *file)
-{
- (void)cfg; (void)file;
- return 0;
-}
-
-int
-sandbox_cfg_allow_chown_filename(sandbox_cfg_t **cfg, char *file)
-{
- (void)cfg; (void)file;
- return 0;
-}
-
-int
-sandbox_cfg_allow_chmod_filename(sandbox_cfg_t **cfg, char *file)
-{
- (void)cfg; (void)file;
- return 0;
-}
-
-int
-sandbox_cfg_allow_rename(sandbox_cfg_t **cfg, char *file1, char *file2)
-{
- (void)cfg; (void)file1; (void)file2;
- return 0;
-}
-
-int
-sandbox_is_active(void)
-{
- return 0;
-}
-
-void
-sandbox_disable_getaddrinfo_cache(void)
-{
-}
-#endif /* !defined(USE_LIBSECCOMP) */
-
diff --git a/src/common/sandbox.h b/src/common/sandbox.h
deleted file mode 100644
index d0f85570f4..0000000000
--- a/src/common/sandbox.h
+++ /dev/null
@@ -1,174 +0,0 @@
-/* Copyright (c) 2001 Matej Pfajfar.
- * Copyright (c) 2001-2004, Roger Dingledine.
- * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2017, The Tor Project, Inc. */
-/* See LICENSE for licensing information */
-
-/**
- * \file sandbox.h
- * \brief Header file for sandbox.c.
- **/
-
-#ifndef SANDBOX_H_
-#define SANDBOX_H_
-
-#include "orconfig.h"
-#include "torint.h"
-
-#ifndef SYS_SECCOMP
-
-/**
- * Used by SIGSYS signal handler to check if the signal was issued due to a
- * seccomp2 filter violation.
- */
-#define SYS_SECCOMP 1
-
-#endif /* !defined(SYS_SECCOMP) */
-
-#if defined(HAVE_SECCOMP_H) && defined(__linux__)
-#define USE_LIBSECCOMP
-#endif
-
-struct sandbox_cfg_elem;
-
-/** Typedef to structure used to manage a sandbox configuration. */
-typedef struct sandbox_cfg_elem sandbox_cfg_t;
-
-/**
- * Linux definitions
- */
-#ifdef USE_LIBSECCOMP
-
-#include <sys/ucontext.h>
-#include <seccomp.h>
-#include <netdb.h>
-
-#define PARAM_PTR 0
-#define PARAM_NUM 1
-
-/**
- * Enum used to manage the type of the implementation for general purpose.
- */
-typedef enum {
- /** Libseccomp implementation based on seccomp2*/
- LIBSECCOMP2 = 0
-} SB_IMPL;
-
-/**
- * Configuration parameter structure associated with the LIBSECCOMP2
- * implementation.
- */
-typedef struct smp_param {
- /** syscall associated with parameter. */
- int syscall;
-
- /** parameter value. */
- char *value;
- /** parameter value, second argument. */
- char *value2;
-
- /** parameter flag (0 = not protected, 1 = protected). */
- int prot;
-} smp_param_t;
-
-/**
- * Structure used to manage a sandbox configuration.
- *
- * It is implemented as a linked list of parameters. Currently only controls
- * parameters for open, openat, execve, stat64.
- */
-struct sandbox_cfg_elem {
- /** Sandbox implementation which dictates the parameter type. */
- SB_IMPL implem;
-
- /** Configuration parameter. */
- smp_param_t *param;
-
- /** Next element of the configuration*/
- struct sandbox_cfg_elem *next;
-};
-
-/** Function pointer defining the prototype of a filter function.*/
-typedef int (*sandbox_filter_func_t)(scmp_filter_ctx ctx,
- sandbox_cfg_t *filter);
-
-/** Type that will be used in step 3 in order to manage multiple sandboxes.*/
-typedef struct {
- /** function pointers associated with the filter */
- sandbox_filter_func_t *filter_func;
-
- /** filter function pointer parameters */
- sandbox_cfg_t *filter_dynamic;
-} sandbox_t;
-
-#endif /* defined(USE_LIBSECCOMP) */
-
-#ifdef USE_LIBSECCOMP
-/** Pre-calls getaddrinfo in order to pre-record result. */
-int sandbox_add_addrinfo(const char *addr);
-
-struct addrinfo;
-/** Replacement for getaddrinfo(), using pre-recorded results. */
-int sandbox_getaddrinfo(const char *name, const char *servname,
- const struct addrinfo *hints,
- struct addrinfo **res);
-void sandbox_freeaddrinfo(struct addrinfo *addrinfo);
-void sandbox_free_getaddrinfo_cache(void);
-#else /* !(defined(USE_LIBSECCOMP)) */
-#define sandbox_getaddrinfo(name, servname, hints, res) \
- getaddrinfo((name),(servname), (hints),(res))
-#define sandbox_add_addrinfo(name) \
- ((void)(name))
-#define sandbox_freeaddrinfo(addrinfo) \
- freeaddrinfo((addrinfo))
-#define sandbox_free_getaddrinfo_cache()
-#endif /* defined(USE_LIBSECCOMP) */
-
-#ifdef USE_LIBSECCOMP
-/** Returns a registered protected string used with the sandbox, given that
- * it matches the parameter.
- */
-const char* sandbox_intern_string(const char *param);
-#else /* !(defined(USE_LIBSECCOMP)) */
-#define sandbox_intern_string(s) (s)
-#endif /* defined(USE_LIBSECCOMP) */
-
-/** Creates an empty sandbox configuration file.*/
-sandbox_cfg_t * sandbox_cfg_new(void);
-
-/**
- * Function used to add a open allowed filename to a supplied configuration.
- * The (char*) specifies the path to the allowed file; we take ownership
- * of the pointer.
- */
-int sandbox_cfg_allow_open_filename(sandbox_cfg_t **cfg, char *file);
-
-int sandbox_cfg_allow_chmod_filename(sandbox_cfg_t **cfg, char *file);
-int sandbox_cfg_allow_chown_filename(sandbox_cfg_t **cfg, char *file);
-
-/* DOCDOC */
-int sandbox_cfg_allow_rename(sandbox_cfg_t **cfg, char *file1, char *file2);
-
-/**
- * Function used to add a openat allowed filename to a supplied configuration.
- * The (char*) specifies the path to the allowed file; we steal the pointer to
- * that file.
- */
-int sandbox_cfg_allow_openat_filename(sandbox_cfg_t **cfg, char *file);
-
-/**
- * Function used to add a stat/stat64 allowed filename to a configuration.
- * The (char*) specifies the path to the allowed file; that pointer is stolen.
- */
-int sandbox_cfg_allow_stat_filename(sandbox_cfg_t **cfg, char *file);
-
-/** Function used to initialise a sandbox configuration.*/
-int sandbox_init(sandbox_cfg_t* cfg);
-
-/** Return true iff the sandbox is turned on. */
-int sandbox_is_active(void);
-
-void sandbox_disable_getaddrinfo_cache(void);
-
-#endif /* !defined(SANDBOX_H_) */
-
diff --git a/src/common/storagedir.c b/src/common/storagedir.c
deleted file mode 100644
index e2c7b4bb87..0000000000
--- a/src/common/storagedir.c
+++ /dev/null
@@ -1,586 +0,0 @@
-/* Copyright (c) 2017, The Tor Project, Inc. */
-/* See LICENSE for licensing information */
-
-#include "container.h"
-#include "compat.h"
-#include "confline.h"
-#include "memarea.h"
-#include "sandbox.h"
-#include "storagedir.h"
-#include "torlog.h"
-#include "util.h"
-
-#ifdef HAVE_SYS_TYPES_H
-#include <sys/types.h>
-#endif
-#ifdef HAVE_SYS_STAT_H
-#include <sys/stat.h>
-#endif
-#ifdef HAVE_UNISTD_H
-#include <unistd.h>
-#endif
-
-#define FNAME_MIN_NUM 1000
-
-/** A storage_dir_t represents a directory full of similar cached
- * files. Filenames are decimal integers. Files can be cleaned as needed
- * to limit total disk usage. */
-struct storage_dir_t {
- /** Directory holding the files for this storagedir. */
- char *directory;
- /** Either NULL, or a directory listing of the directory (as a smartlist
- * of strings */
- smartlist_t *contents;
- /** The largest number of non-temporary files we'll place in the
- * directory. */
- int max_files;
- /** If true, then 'usage' has been computed. */
- int usage_known;
- /** The total number of bytes used in this directory */
- uint64_t usage;
-};
-
-/** Create or open a new storage directory at <b>dirname</b>, with
- * capacity for up to <b>max_files</b> files.
- */
-storage_dir_t *
-storage_dir_new(const char *dirname, int max_files)
-{
- if (check_private_dir(dirname, CPD_CREATE, NULL) < 0)
- return NULL;
-
- storage_dir_t *d = tor_malloc_zero(sizeof(storage_dir_t));
- d->directory = tor_strdup(dirname);
- d->max_files = max_files;
- return d;
-}
-
-/**
- * Drop all in-RAM storage for <b>d</b>. Does not delete any files.
- */
-void
-storage_dir_free_(storage_dir_t *d)
-{
- if (d == NULL)
- return;
- tor_free(d->directory);
- if (d->contents) {
- SMARTLIST_FOREACH(d->contents, char *, cp, tor_free(cp));
- smartlist_free(d->contents);
- }
- tor_free(d);
-}
-
-/**
- * Tell the sandbox (if any) configured by <b>cfg</b> to allow the
- * operations that <b>d</b> will need.
- *
- * The presence of this function is why we need an upper limit on the
- * number of files in a storage_dir_t: we need to approve file operations
- * one by one.
- */
-int
-storage_dir_register_with_sandbox(storage_dir_t *d, sandbox_cfg_t **cfg)
-{
- int problems = 0;
- int idx;
- for (idx = FNAME_MIN_NUM; idx < FNAME_MIN_NUM + d->max_files; ++idx) {
- char *path = NULL, *tmppath = NULL;
- tor_asprintf(&path, "%s/%d", d->directory, idx);
- tor_asprintf(&tmppath, "%s/%d.tmp", d->directory, idx);
-
- problems += sandbox_cfg_allow_open_filename(cfg, tor_strdup(path));
- problems += sandbox_cfg_allow_open_filename(cfg, tor_strdup(tmppath));
- problems += sandbox_cfg_allow_stat_filename(cfg, tor_strdup(path));
- problems += sandbox_cfg_allow_stat_filename(cfg, tor_strdup(tmppath));
- problems += sandbox_cfg_allow_rename(cfg,
- tor_strdup(tmppath), tor_strdup(path));
-
- tor_free(path);
- tor_free(tmppath);
- }
-
- return problems ? -1 : 0;
-}
-
-/**
- * Remove all files in <b>d</b> whose names end with ".tmp".
- *
- * Requires that the contents field of <b>d</b> is set.
- */
-static void
-storage_dir_clean_tmpfiles(storage_dir_t *d)
-{
- if (!d->contents)
- return;
- SMARTLIST_FOREACH_BEGIN(d->contents, char *, fname) {
- if (strcmpend(fname, ".tmp"))
- continue;
- char *path = NULL;
- tor_asprintf(&path, "%s/%s", d->directory, fname);
- if (unlink(sandbox_intern_string(path))) {
- log_warn(LD_FS, "Unable to unlink %s while cleaning "
- "temporary files: %s", escaped(path), strerror(errno));
- tor_free(path);
- continue;
- }
- tor_free(path);
- SMARTLIST_DEL_CURRENT(d->contents, fname);
- tor_free(fname);
- } SMARTLIST_FOREACH_END(fname);
-
- d->usage_known = 0;
-}
-
-/**
- * Re-scan the directory <b>d</b> to learn its contents.
- */
-static int
-storage_dir_rescan(storage_dir_t *d)
-{
- if (d->contents) {
- SMARTLIST_FOREACH(d->contents, char *, cp, tor_free(cp));
- smartlist_free(d->contents);
- }
- d->usage = 0;
- d->usage_known = 0;
- if (NULL == (d->contents = tor_listdir(d->directory))) {
- return -1;
- }
- storage_dir_clean_tmpfiles(d);
- return 0;
-}
-
-/**
- * Return a smartlist containing the filenames within <b>d</b>.
- */
-const smartlist_t *
-storage_dir_list(storage_dir_t *d)
-{
- if (! d->contents)
- storage_dir_rescan(d);
- return d->contents;
-}
-
-/**
- * Return the total number of bytes used for storage in <b>d</b>.
- */
-uint64_t
-storage_dir_get_usage(storage_dir_t *d)
-{
- if (d->usage_known)
- return d->usage;
-
- uint64_t total = 0;
- SMARTLIST_FOREACH_BEGIN(storage_dir_list(d), const char *, cp) {
- char *path = NULL;
- struct stat st;
- tor_asprintf(&path, "%s/%s", d->directory, cp);
- if (stat(sandbox_intern_string(path), &st) == 0) {
- total += st.st_size;
- }
- tor_free(path);
- } SMARTLIST_FOREACH_END(cp);
-
- d->usage = total;
- d->usage_known = 1;
- return d->usage;
-}
-
-/** Mmap a specified file within <b>d</b>.
- *
- * On failure, return NULL and set errno as for tor_mmap_file(). */
-tor_mmap_t *
-storage_dir_map(storage_dir_t *d, const char *fname)
-{
- char *path = NULL;
- tor_asprintf(&path, "%s/%s", d->directory, fname);
- tor_mmap_t *result = tor_mmap_file(path);
- int errval = errno;
- tor_free(path);
- if (result == NULL)
- errno = errval;
- return result;
-}
-
-/** Read a file within <b>d</b> into a newly allocated buffer. Set
- * *<b>sz_out</b> to its size. */
-uint8_t *
-storage_dir_read(storage_dir_t *d, const char *fname, int bin, size_t *sz_out)
-{
- const int flags = bin ? RFTS_BIN : 0;
-
- char *path = NULL;
- tor_asprintf(&path, "%s/%s", d->directory, fname);
- struct stat st;
- char *contents = read_file_to_str(path, flags, &st);
- if (contents && sz_out) {
- // it fits in RAM, so we know its size is less than SIZE_MAX
-#if UINT64_MAX > SIZE_MAX
- tor_assert((uint64_t)st.st_size <= SIZE_MAX);
-#endif
- *sz_out = (size_t) st.st_size;
- }
-
- tor_free(path);
- return (uint8_t *) contents;
-}
-
-/** Helper: Find an unused filename within the directory */
-static char *
-find_unused_fname(storage_dir_t *d)
-{
- if (!d->contents) {
- if (storage_dir_rescan(d) < 0)
- return NULL;
- }
-
- char buf[16];
- int i;
- /* Yuck; this is quadratic. Fortunately, that shouldn't matter much,
- * since disk writes are more expensive by a lot. */
- for (i = FNAME_MIN_NUM; i < FNAME_MIN_NUM + d->max_files; ++i) {
- tor_snprintf(buf, sizeof(buf), "%d", i);
- if (!smartlist_contains_string(d->contents, buf)) {
- return tor_strdup(buf);
- }
- }
- return NULL;
-}
-
-/** Helper: As storage_dir_save_bytes_to_file, but store a smartlist of
- * sized_chunk_t rather than a single byte array. */
-static int
-storage_dir_save_chunks_to_file(storage_dir_t *d,
- const smartlist_t *chunks,
- int binary,
- char **fname_out)
-{
- uint64_t total_length = 0;
- char *fname = find_unused_fname(d);
- if (!fname)
- return -1;
-
- SMARTLIST_FOREACH(chunks, const sized_chunk_t *, ch,
- total_length += ch->len);
-
- char *path = NULL;
- tor_asprintf(&path, "%s/%s", d->directory, fname);
-
- int r = write_chunks_to_file(path, chunks, binary, 0);
- if (r == 0) {
- if (d->usage_known)
- d->usage += total_length;
- if (fname_out) {
- *fname_out = tor_strdup(fname);
- }
- if (d->contents)
- smartlist_add(d->contents, tor_strdup(fname));
- }
- tor_free(fname);
- tor_free(path);
- return r;
-}
-
-/** Try to write the <b>length</b> bytes at <b>data</b> into a new file
- * in <b>d</b>. On success, return 0 and set *<b>fname_out</b> to a
- * newly allocated string containing the filename. On failure, return
- * -1. */
-int
-storage_dir_save_bytes_to_file(storage_dir_t *d,
- const uint8_t *data,
- size_t length,
- int binary,
- char **fname_out)
-{
- smartlist_t *chunks = smartlist_new();
- sized_chunk_t chunk = { (const char *)data, length };
- smartlist_add(chunks, &chunk);
- int r = storage_dir_save_chunks_to_file(d, chunks, binary, fname_out);
- smartlist_free(chunks);
- return r;
-}
-
-/**
- * As storage_dir_save_bytes_to_file, but saves a NUL-terminated string
- * <b>str</b>.
- */
-int
-storage_dir_save_string_to_file(storage_dir_t *d,
- const char *str,
- int binary,
- char **fname_out)
-{
- return storage_dir_save_bytes_to_file(d,
- (const uint8_t*)str, strlen(str), binary, fname_out);
-}
-
-/**
- * As storage_dir_save_bytes_to_file, but associates the data with the
- * key-value pairs in <b>labels</b>. Files stored in this format can be
- * recovered with storage_dir_map_labeled() or storage_dir_read_labeled().
- */
-int
-storage_dir_save_labeled_to_file(storage_dir_t *d,
- const config_line_t *labels,
- const uint8_t *data,
- size_t length,
- char **fname_out)
-{
- /*
- * The storage format is to prefix the data with the key-value pairs in
- * <b>labels</b>, and a single NUL separator. But code outside this module
- * MUST NOT rely on that format.
- */
-
- smartlist_t *chunks = smartlist_new();
- memarea_t *area = memarea_new();
- const config_line_t *line;
- for (line = labels; line; line = line->next) {
- sized_chunk_t *sz = memarea_alloc(area, sizeof(sized_chunk_t));
- sz->len = strlen(line->key) + 1 + strlen(line->value) + 1;
- const size_t allocated = sz->len + 1;
- char *bytes = memarea_alloc(area, allocated);
- tor_snprintf(bytes, allocated, "%s %s\n", line->key, line->value);
- sz->bytes = bytes;
- smartlist_add(chunks, sz);
- }
-
- sized_chunk_t *nul = memarea_alloc(area, sizeof(sized_chunk_t));
- nul->len = 1;
- nul->bytes = "\0";
- smartlist_add(chunks, nul);
-
- sized_chunk_t *datachunk = memarea_alloc(area, sizeof(sized_chunk_t));
- datachunk->bytes = (const char *)data;
- datachunk->len = length;
- smartlist_add(chunks, datachunk);
-
- int r = storage_dir_save_chunks_to_file(d, chunks, 1, fname_out);
- smartlist_free(chunks);
- memarea_drop_all(area);
- return r;
-}
-
-/**
- * Map a file that was created with storage_dir_save_labeled_to_file(). On
- * failure, return NULL. On success, write a set of newly allocated labels
- * into *<b>labels_out</b>, a pointer to the data into *<b>data_out</b>, and
- * the data's size into *<b>sz_out</b>. On success, also return a tor_mmap_t
- * object whose contents should not be used -- it needs to be kept around,
- * though, for as long as <b>data_out</b> is going to be valid.
- *
- * On failure, set errno as for tor_mmap_file() if the file was missing or
- * empty, and set errno to EINVAL if the file was not in the labeled
- * format expected.
- */
-tor_mmap_t *
-storage_dir_map_labeled(storage_dir_t *dir,
- const char *fname,
- config_line_t **labels_out,
- const uint8_t **data_out,
- size_t *sz_out)
-{
- tor_mmap_t *m = storage_dir_map(dir, fname);
- int errval;
- if (! m) {
- errval = errno;
- goto err;
- }
- const char *nulp = memchr(m->data, '\0', m->size);
- if (! nulp) {
- errval = EINVAL;
- goto err;
- }
- if (labels_out && config_get_lines(m->data, labels_out, 0) < 0) {
- errval = EINVAL;
- goto err;
- }
- size_t offset = nulp - m->data + 1;
- tor_assert(offset <= m->size);
- *data_out = (const uint8_t *)(m->data + offset);
- *sz_out = m->size - offset;
-
- return m;
- err:
- tor_munmap_file(m);
- errno = errval;
- return NULL;
-}
-
-/** As storage_dir_map_labeled, but return a new byte array containing the
- * data. */
-uint8_t *
-storage_dir_read_labeled(storage_dir_t *dir,
- const char *fname,
- config_line_t **labels_out,
- size_t *sz_out)
-{
- const uint8_t *data = NULL;
- tor_mmap_t *m = storage_dir_map_labeled(dir, fname, labels_out,
- &data, sz_out);
- if (m == NULL)
- return NULL;
- uint8_t *result = tor_memdup(data, *sz_out);
- tor_munmap_file(m);
- return result;
-}
-
-/* Reduce the cached usage amount in <b>d</b> by <b>removed_file_size</b>.
- * This function is a no-op if <b>d->usage_known</b> is 0. */
-static void
-storage_dir_reduce_usage(storage_dir_t *d, uint64_t removed_file_size)
-{
- if (d->usage_known) {
- if (! BUG(d->usage < removed_file_size)) {
- /* This bug can also be triggered if an external process resized a file
- * between the call to storage_dir_get_usage() that last checked
- * actual usage (rather than relaying on cached usage), and the call to
- * this function. */
- d->usage -= removed_file_size;
- } else {
- /* If we underflowed the cached directory size, re-check the sizes of all
- * the files in the directory. This makes storage_dir_shrink() quadratic,
- * but only if a process is continually changing file sizes in the
- * storage directory (in which case, we have bigger issues).
- *
- * We can't just reset usage_known, because storage_dir_shrink() relies
- * on knowing the usage. */
- storage_dir_rescan(d);
- (void)storage_dir_get_usage(d);
- }
- }
-}
-
-/**
- * Remove the file called <b>fname</b> from <b>d</b>.
- */
-void
-storage_dir_remove_file(storage_dir_t *d,
- const char *fname)
-{
- char *path = NULL;
- tor_asprintf(&path, "%s/%s", d->directory, fname);
- const char *ipath = sandbox_intern_string(path);
-
- uint64_t size = 0;
- if (d->usage_known) {
- struct stat st;
- if (stat(ipath, &st) == 0) {
- size = st.st_size;
- }
- }
- if (unlink(ipath) == 0) {
- storage_dir_reduce_usage(d, size);
- } else {
- log_warn(LD_FS, "Unable to unlink %s while removing file: %s",
- escaped(path), strerror(errno));
- tor_free(path);
- return;
- }
- if (d->contents) {
- smartlist_string_remove(d->contents, fname);
- }
-
- tor_free(path);
-}
-
-/** Helper type: used to sort the members of storage directory by mtime. */
-typedef struct shrinking_dir_entry_t {
- time_t mtime;
- uint64_t size;
- char *path;
-} shrinking_dir_entry_t;
-
-/** Helper: use with qsort to sort shrinking_dir_entry_t structs. */
-static int
-shrinking_dir_entry_compare(const void *a_, const void *b_)
-{
- const shrinking_dir_entry_t *a = a_;
- const shrinking_dir_entry_t *b = b_;
-
- if (a->mtime < b->mtime)
- return -1;
- else if (a->mtime > b->mtime)
- return 1;
- else
- return 0;
-}
-
-/**
- * Try to free space by removing the oldest files in <b>d</b>. Delete
- * until no more than <b>target_size</b> bytes are left, and at least
- * <b>min_to_remove</b> files have been removed... or until there is
- * nothing left to remove.
- *
- * Return 0 on success; -1 on failure.
- */
-int
-storage_dir_shrink(storage_dir_t *d,
- uint64_t target_size,
- int min_to_remove)
-{
- if (d->usage_known && d->usage <= target_size && !min_to_remove) {
- /* Already small enough. */
- return 0;
- }
-
- if (storage_dir_rescan(d) < 0)
- return -1;
-
- const uint64_t orig_usage = storage_dir_get_usage(d);
- if (orig_usage <= target_size && !min_to_remove) {
- /* Okay, small enough after rescan! */
- return 0;
- }
-
- const int n = smartlist_len(d->contents);
- shrinking_dir_entry_t *ents = tor_calloc(n, sizeof(shrinking_dir_entry_t));
- SMARTLIST_FOREACH_BEGIN(d->contents, const char *, fname) {
- shrinking_dir_entry_t *ent = &ents[fname_sl_idx];
- struct stat st;
- tor_asprintf(&ent->path, "%s/%s", d->directory, fname);
- if (stat(sandbox_intern_string(ent->path), &st) == 0) {
- ent->mtime = st.st_mtime;
- ent->size = st.st_size;
- }
- } SMARTLIST_FOREACH_END(fname);
-
- qsort(ents, n, sizeof(shrinking_dir_entry_t), shrinking_dir_entry_compare);
-
- int idx = 0;
- while ((d->usage > target_size || min_to_remove > 0) && idx < n) {
- if (unlink(sandbox_intern_string(ents[idx].path)) == 0) {
- storage_dir_reduce_usage(d, ents[idx].size);
- --min_to_remove;
- }
- ++idx;
- }
-
- for (idx = 0; idx < n; ++idx) {
- tor_free(ents[idx].path);
- }
- tor_free(ents);
-
- storage_dir_rescan(d);
-
- return 0;
-}
-
-/** Remove all files in <b>d</b>. */
-int
-storage_dir_remove_all(storage_dir_t *d)
-{
- return storage_dir_shrink(d, 0, d->max_files);
-}
-
-/**
- * Return the largest number of non-temporary files we're willing to
- * store in <b>d</b>.
- */
-int
-storage_dir_get_max_files(storage_dir_t *d)
-{
- return d->max_files;
-}
-
diff --git a/src/common/storagedir.h b/src/common/storagedir.h
deleted file mode 100644
index d99bd7ec52..0000000000
--- a/src/common/storagedir.h
+++ /dev/null
@@ -1,54 +0,0 @@
-/* Copyright (c) 2017, The Tor Project, Inc. */
-/* See LICENSE for licensing information */
-
-#ifndef TOR_STORAGEDIR_H
-#define TOR_STORAGEDIR_H
-
-typedef struct storage_dir_t storage_dir_t;
-struct config_line_t;
-struct sandbox_cfg_elem;
-
-storage_dir_t * storage_dir_new(const char *dirname, int n_files);
-void storage_dir_free_(storage_dir_t *d);
-#define storage_dir_free(d) \
- FREE_AND_NULL(storage_dir_t, storage_dir_free_, (d))
-
-int storage_dir_register_with_sandbox(storage_dir_t *d,
- struct sandbox_cfg_elem **cfg);
-const smartlist_t *storage_dir_list(storage_dir_t *d);
-uint64_t storage_dir_get_usage(storage_dir_t *d);
-tor_mmap_t *storage_dir_map(storage_dir_t *d, const char *fname);
-uint8_t *storage_dir_read(storage_dir_t *d, const char *fname, int bin,
- size_t *sz_out);
-int storage_dir_save_bytes_to_file(storage_dir_t *d,
- const uint8_t *data,
- size_t length,
- int binary,
- char **fname_out);
-int storage_dir_save_string_to_file(storage_dir_t *d,
- const char *data,
- int binary,
- char **fname_out);
-int storage_dir_save_labeled_to_file(storage_dir_t *d,
- const struct config_line_t *labels,
- const uint8_t *data,
- size_t length,
- char **fname_out);
-tor_mmap_t *storage_dir_map_labeled(storage_dir_t *dir,
- const char *fname,
- struct config_line_t **labels_out,
- const uint8_t **data_out,
- size_t *size_out);
-uint8_t *storage_dir_read_labeled(storage_dir_t *d, const char *fname,
- struct config_line_t **labels_out,
- size_t *sz_out);
-void storage_dir_remove_file(storage_dir_t *d,
- const char *fname);
-int storage_dir_shrink(storage_dir_t *d,
- uint64_t target_size,
- int min_to_remove);
-int storage_dir_remove_all(storage_dir_t *d);
-int storage_dir_get_max_files(storage_dir_t *d);
-
-#endif /* !defined(TOR_STORAGEDIR_H) */
-
diff --git a/src/common/testsupport.h b/src/common/testsupport.h
deleted file mode 100644
index a3f2ff91ed..0000000000
--- a/src/common/testsupport.h
+++ /dev/null
@@ -1,90 +0,0 @@
-/* Copyright (c) 2013-2017, The Tor Project, Inc. */
-/* See LICENSE for licensing information */
-
-#ifndef TOR_TESTSUPPORT_H
-#define TOR_TESTSUPPORT_H
-
-#ifdef TOR_UNIT_TESTS
-#define STATIC
-#define EXTERN(type, name) extern type name;
-#else
-#define STATIC static
-#define EXTERN(type, name)
-#endif /* defined(TOR_UNIT_TESTS) */
-
-/** Quick and dirty macros to implement test mocking.
- *
- * To use them, suppose that you have a function you'd like to mock
- * with the signature "void writebuf(size_t n, char *buf)". You can then
- * declare the function as:
- *
- * MOCK_DECL(void, writebuf, (size_t n, char *buf));
- *
- * and implement it as:
- *
- * MOCK_IMPL(void,
- * writebuf,(size_t n, char *buf))
- * {
- * ...
- * }
- *
- * For the non-testing build, this will expand simply into:
- *
- * void writebuf(size_t n, char *buf);
- * void
- * writebuf(size_t n, char *buf)
- * {
- * ...
- * }
- *
- * But for the testing case, it will expand into:
- *
- * void writebuf__real(size_t n, char *buf);
- * extern void (*writebuf)(size_t n, char *buf);
- *
- * void (*writebuf)(size_t n, char *buf) = writebuf__real;
- * void
- * writebuf__real(size_t n, char *buf)
- * {
- * ...
- * }
- *
- * This is not a great mocking system! It is deliberately "the simplest
- * thing that could work", and pays for its simplicity in its lack of
- * features, and in its uglification of the Tor code. Replacing it with
- * something clever would be a fine thing.
- *
- * @{ */
-#ifdef TOR_UNIT_TESTS
-#define MOCK_DECL(rv, funcname, arglist) \
- rv funcname ##__real arglist; \
- extern rv(*funcname) arglist
-#define MOCK_IMPL(rv, funcname, arglist) \
- rv(*funcname) arglist = funcname ##__real; \
- rv funcname ##__real arglist
-#define MOCK_DECL_ATTR(rv, funcname, arglist, attr) \
- rv funcname ##__real arglist attr; \
- extern rv(*funcname) arglist
-#define MOCK_IMPL(rv, funcname, arglist) \
- rv(*funcname) arglist = funcname ##__real; \
- rv funcname ##__real arglist
-#define MOCK(func, replacement) \
- do { \
- (func) = (replacement); \
- } while (0)
-#define UNMOCK(func) \
- do { \
- func = func ##__real; \
- } while (0)
-#else /* !(defined(TOR_UNIT_TESTS)) */
-#define MOCK_DECL(rv, funcname, arglist) \
- rv funcname arglist
-#define MOCK_DECL_ATTR(rv, funcname, arglist, attr) \
- rv funcname arglist attr
-#define MOCK_IMPL(rv, funcname, arglist) \
- rv funcname arglist
-#endif /* defined(TOR_UNIT_TESTS) */
-/** @} */
-
-#endif /* !defined(TOR_TESTSUPPORT_H) */
-
diff --git a/src/common/timers.c b/src/common/timers.c
deleted file mode 100644
index 6f6236ed3b..0000000000
--- a/src/common/timers.c
+++ /dev/null
@@ -1,318 +0,0 @@
-/* Copyright (c) 2016-2017, The Tor Project, Inc. */
-/* See LICENSE for licensing information */
-
-/**
- * \file timers.c
- * \brief Wrapper around William Ahern's fast hierarchical timer wheel
- * implementation, to tie it in with a libevent backend.
- *
- * Only use these functions from the main thread.
- *
- * The main advantage of tor_timer_t over using libevent's timers is that
- * they're way more efficient if we need to have thousands or millions of
- * them. For more information, see
- * http://www.25thandclement.com/~william/projects/timeout.c.html
- *
- * Periodic timers are available in the backend, but I've turned them off.
- * We can turn them back on if needed.
- */
-
-/* Notes:
- *
- * Having a way to free all timers on shutdown would free people from the
- * need to track them. Not sure if that's clever though.
- *
- * In an ideal world, Libevent would just switch to use this backend, and we
- * could throw this file away. But even if Libevent does switch, we'll be
- * stuck with legacy libevents for some time.
- */
-
-#include "orconfig.h"
-
-#define TOR_TIMERS_PRIVATE
-
-#include "compat.h"
-#include "compat_libevent.h"
-#include "timers.h"
-#include "torlog.h"
-#include "util.h"
-
-struct timeout_cb {
- timer_cb_fn_t cb;
- void *arg;
-};
-
-/*
- * These definitions are for timeouts.c and timeouts.h.
- */
-#ifdef __GNUC__
-/* We're not exposing any of the functions outside this file. */
-#define TIMEOUT_PUBLIC __attribute__((__unused__)) static
-#else
-/* We're not exposing any of the functions outside this file. */
-#define TIMEOUT_PUBLIC static
-#endif /* defined(__GNUC__) */
-/* We're not using periodic events. */
-#define TIMEOUT_DISABLE_INTERVALS
-/* We always know the global_timeouts object, so we don't need each timeout
- * to keep a pointer to it. */
-#define TIMEOUT_DISABLE_RELATIVE_ACCESS
-/* We're providing our own struct timeout_cb. */
-#define TIMEOUT_CB_OVERRIDE
-/* We're going to support timers that are pretty far out in advance. Making
- * this big can be inefficient, but having a significant number of timers
- * above TIMEOUT_MAX can also be super-inefficient. Choosing 5 here sets
- * timeout_max to 2^30 ticks, or 29 hours with our value for USEC_PER_TICK */
-#define WHEEL_NUM 5
-#if SIZEOF_VOID_P == 4
-/* On 32-bit platforms, we want to override wheel_bit, so that timeout.c will
- * use 32-bit math. */
-#define WHEEL_BIT 5
-#endif
-#include "src/ext/timeouts/timeout.c"
-
-static struct timeouts *global_timeouts = NULL;
-static struct mainloop_event_t *global_timer_event = NULL;
-
-static monotime_t start_of_time;
-
-/** We need to choose this value carefully. Because we're using timer wheels,
- * it actually costs us to have extra resolution we don't use. So for now,
- * I'm going to define our resolution as .1 msec, and hope that's good enough.
- *
- * Note that two of the most popular libevent backends (epoll without timerfd,
- * and windows select), simply can't support sub-millisecond resolution,
- * do this is optimistic for a lot of users.
- */
-#define USEC_PER_TICK 100
-
-/** One million microseconds in a second */
-#define USEC_PER_SEC 1000000
-
-/** Check at least once every N seconds. */
-#define MIN_CHECK_SECONDS 3600
-
-/** Check at least once every N ticks. */
-#define MIN_CHECK_TICKS \
- (((timeout_t)MIN_CHECK_SECONDS) * (1000000 / USEC_PER_TICK))
-
-/**
- * Convert the timeval in <b>tv</b> to a timeout_t, and return it.
- *
- * The output resolution is set by USEC_PER_TICK. Only use this to convert
- * delays to number of ticks; the time represented by 0 is undefined.
- */
-static timeout_t
-tv_to_timeout(const struct timeval *tv)
-{
- uint64_t usec = tv->tv_usec;
- usec += ((uint64_t)USEC_PER_SEC) * tv->tv_sec;
- return usec / USEC_PER_TICK;
-}
-
-/**
- * Convert the timeout in <b>t</b> to a timeval in <b>tv_out</b>. Only
- * use this for delays, not absolute times.
- */
-static void
-timeout_to_tv(timeout_t t, struct timeval *tv_out)
-{
- t *= USEC_PER_TICK;
- tv_out->tv_usec = (int)(t % USEC_PER_SEC);
- tv_out->tv_sec = (time_t)(t / USEC_PER_SEC);
-}
-
-/**
- * Update the timer <b>tv</b> to the current time in <b>tv</b>.
- */
-static void
-timer_advance_to_cur_time(const monotime_t *now)
-{
- timeout_t cur_tick = CEIL_DIV(monotime_diff_usec(&start_of_time, now),
- USEC_PER_TICK);
- timeouts_update(global_timeouts, cur_tick);
-}
-
-/**
- * Adjust the time at which the libevent timer should fire based on
- * the next-expiring time in <b>global_timeouts</b>
- */
-static void
-libevent_timer_reschedule(void)
-{
- monotime_t now;
- monotime_get(&now);
- timer_advance_to_cur_time(&now);
-
- timeout_t delay = timeouts_timeout(global_timeouts);
-
- struct timeval d;
- if (delay > MIN_CHECK_TICKS)
- delay = MIN_CHECK_TICKS;
- timeout_to_tv(delay, &d);
- mainloop_event_schedule(global_timer_event, &d);
-}
-
-/** Run the callback of every timer that has expired, based on the current
- * output of monotime_get(). */
-STATIC void
-timers_run_pending(void)
-{
- monotime_t now;
- monotime_get(&now);
- timer_advance_to_cur_time(&now);
-
- tor_timer_t *t;
- while ((t = timeouts_get(global_timeouts))) {
- t->callback.cb(t, t->callback.arg, &now);
- }
-}
-
-/**
- * Invoked when the libevent timer has expired: see which tor_timer_t events
- * have fired, activate their callbacks, and reschedule the libevent timer.
- */
-static void
-libevent_timer_callback(mainloop_event_t *ev, void *arg)
-{
- (void)ev;
- (void)arg;
-
- timers_run_pending();
-
- libevent_timer_reschedule();
-}
-
-/**
- * Initialize the timers subsystem. Requires that libevent has already been
- * initialized.
- */
-void
-timers_initialize(void)
-{
- if (BUG(global_timeouts))
- return; // LCOV_EXCL_LINE
-
- timeout_error_t err = 0;
- global_timeouts = timeouts_open(0, &err);
- if (!global_timeouts) {
- // LCOV_EXCL_START -- this can only fail on malloc failure.
- log_err(LD_BUG, "Unable to open timer backend: %s", strerror(err));
- tor_assert(0);
- // LCOV_EXCL_STOP
- }
-
- monotime_init();
- monotime_get(&start_of_time);
-
- mainloop_event_t *timer_event;
- timer_event = mainloop_event_new(libevent_timer_callback, NULL);
- tor_assert(timer_event);
- global_timer_event = timer_event;
-
- libevent_timer_reschedule();
-}
-
-/**
- * Release all storage held in the timers subsystem. Does not fire timers.
- */
-void
-timers_shutdown(void)
-{
- if (global_timer_event) {
- mainloop_event_free(global_timer_event);
- global_timer_event = NULL;
- }
- if (global_timeouts) {
- timeouts_close(global_timeouts);
- global_timeouts = NULL;
- }
-}
-
-/**
- * Allocate and return a new timer, with given callback and argument.
- */
-tor_timer_t *
-timer_new(timer_cb_fn_t cb, void *arg)
-{
- tor_timer_t *t = tor_malloc(sizeof(tor_timer_t));
- timeout_init(t, 0);
- timer_set_cb(t, cb, arg);
- return t;
-}
-
-/**
- * Release all storage held by <b>t</b>, and unschedule it if was already
- * scheduled.
- */
-void
-timer_free_(tor_timer_t *t)
-{
- if (! t)
- return;
-
- timeouts_del(global_timeouts, t);
- tor_free(t);
-}
-
-/**
- * Change the callback and argument associated with a timer <b>t</b>.
- */
-void
-timer_set_cb(tor_timer_t *t, timer_cb_fn_t cb, void *arg)
-{
- t->callback.cb = cb;
- t->callback.arg = arg;
-}
-
-/**
- * Set *<b>cb_out</b> (if provided) to this timer's callback function,
- * and *<b>arg_out</b> (if provided) to this timer's callback argument.
- */
-void
-timer_get_cb(const tor_timer_t *t,
- timer_cb_fn_t *cb_out, void **arg_out)
-{
- if (cb_out)
- *cb_out = t->callback.cb;
- if (arg_out)
- *arg_out = t->callback.arg;
-}
-
-/**
- * Schedule the timer t to fire at the current time plus a delay of
- * <b>delay</b> microseconds. All times are relative to monotime_get().
- */
-void
-timer_schedule(tor_timer_t *t, const struct timeval *tv)
-{
- const timeout_t delay = tv_to_timeout(tv);
-
- monotime_t now;
- monotime_get(&now);
- timer_advance_to_cur_time(&now);
-
- /* Take the old timeout value. */
- timeout_t to = timeouts_timeout(global_timeouts);
-
- timeouts_add(global_timeouts, t, delay);
-
- /* Should we update the libevent timer? */
- if (to <= delay) {
- return; /* we're already going to fire before this timer would trigger. */
- }
- libevent_timer_reschedule();
-}
-
-/**
- * Cancel the timer <b>t</b> if it is currently scheduled. (It's okay to call
- * this on an unscheduled timer.
- */
-void
-timer_disable(tor_timer_t *t)
-{
- timeouts_del(global_timeouts, t);
- /* We don't reschedule the libevent timer here, since it's okay if it fires
- * early. */
-}
-
diff --git a/src/common/timers.h b/src/common/timers.h
deleted file mode 100644
index 6d27f3e01e..0000000000
--- a/src/common/timers.h
+++ /dev/null
@@ -1,31 +0,0 @@
-/* Copyright (c) 2016-2017, The Tor Project, Inc. */
-/* See LICENSE for licensing information */
-
-#ifndef TOR_TIMERS_H
-#define TOR_TIMERS_H
-
-#include "orconfig.h"
-#include "testsupport.h"
-
-struct monotime_t;
-typedef struct timeout tor_timer_t;
-typedef void (*timer_cb_fn_t)(tor_timer_t *, void *,
- const struct monotime_t *);
-tor_timer_t *timer_new(timer_cb_fn_t cb, void *arg);
-void timer_set_cb(tor_timer_t *t, timer_cb_fn_t cb, void *arg);
-void timer_get_cb(const tor_timer_t *t,
- timer_cb_fn_t *cb_out, void **arg_out);
-void timer_schedule(tor_timer_t *t, const struct timeval *delay);
-void timer_disable(tor_timer_t *t);
-void timer_free_(tor_timer_t *t);
-#define timer_free(t) FREE_AND_NULL(tor_timer_t, timer_free_, (t))
-
-void timers_initialize(void);
-void timers_shutdown(void);
-
-#ifdef TOR_TIMERS_PRIVATE
-STATIC void timers_run_pending(void);
-#endif
-
-#endif /* !defined(TOR_TIMERS_H) */
-
diff --git a/src/common/token_bucket.c b/src/common/token_bucket.c
deleted file mode 100644
index f2396ec58a..0000000000
--- a/src/common/token_bucket.c
+++ /dev/null
@@ -1,255 +0,0 @@
-/* Copyright (c) 2018, The Tor Project, Inc. */
-/* See LICENSE for licensing information */
-
-/**
- * \file token_bucket.c
- * \brief Functions to use and manipulate token buckets, used for
- * rate-limiting on connections and globally.
- *
- * Tor uses these token buckets to keep track of bandwidth usage, and
- * sometimes other things too.
- *
- * There are two layers of abstraction here: "raw" token buckets, in which all
- * the pieces are decoupled, and "read-write" token buckets, which combine all
- * the moving parts into one.
- *
- * Token buckets may become negative.
- **/
-
-#define TOKEN_BUCKET_PRIVATE
-
-#include "token_bucket.h"
-#include "util_bug.h"
-
-/**
- * Set the <b>rate</b> and <b>burst</b> value in a token_bucket_cfg.
- *
- * Note that the <b>rate</b> value is in arbitrary units, but those units will
- * determine the units of token_bucket_raw_dec(), token_bucket_raw_refill, and
- * so on.
- */
-void
-token_bucket_cfg_init(token_bucket_cfg_t *cfg,
- uint32_t rate,
- uint32_t burst)
-{
- tor_assert_nonfatal(rate > 0);
- tor_assert_nonfatal(burst > 0);
- if (burst > TOKEN_BUCKET_MAX_BURST)
- burst = TOKEN_BUCKET_MAX_BURST;
-
- cfg->rate = rate;
- cfg->burst = burst;
-}
-
-/**
- * Initialize a raw token bucket and its associated timestamp to the "full"
- * state, according to <b>cfg</b>.
- */
-void
-token_bucket_raw_reset(token_bucket_raw_t *bucket,
- const token_bucket_cfg_t *cfg)
-{
- bucket->bucket = cfg->burst;
-}
-
-/**
- * Adust a preexisting token bucket to respect the new configuration
- * <b>cfg</b>, by decreasing its current level if needed. */
-void
-token_bucket_raw_adjust(token_bucket_raw_t *bucket,
- const token_bucket_cfg_t *cfg)
-{
- bucket->bucket = MIN(bucket->bucket, cfg->burst);
-}
-
-/**
- * Given an amount of <b>elapsed</b> time units, and a bucket configuration
- * <b>cfg</b>, refill the level of <b>bucket</b> accordingly. Note that the
- * units of time in <b>elapsed</b> must correspond to those used to set the
- * rate in <b>cfg</b>, or the result will be illogical.
- */
-int
-token_bucket_raw_refill_steps(token_bucket_raw_t *bucket,
- const token_bucket_cfg_t *cfg,
- const uint32_t elapsed)
-{
- const int was_empty = (bucket->bucket <= 0);
- /* The casts here prevent an underflow.
- *
- * Note that even if the bucket value is negative, subtracting it from
- * "burst" will still produce a correct result. If this result is
- * ridiculously high, then the "elapsed > gap / rate" check below
- * should catch it. */
- const size_t gap = ((size_t)cfg->burst) - ((size_t)bucket->bucket);
-
- if (elapsed > gap / cfg->rate) {
- bucket->bucket = cfg->burst;
- } else {
- bucket->bucket += cfg->rate * elapsed;
- }
-
- return was_empty && bucket->bucket > 0;
-}
-
-/**
- * Decrement a provided bucket by <b>n</b> units. Note that <b>n</b>
- * must be nonnegative.
- */
-int
-token_bucket_raw_dec(token_bucket_raw_t *bucket,
- ssize_t n)
-{
- if (BUG(n < 0))
- return 0;
- const int becomes_empty = bucket->bucket > 0 && n >= bucket->bucket;
- bucket->bucket -= n;
- return becomes_empty;
-}
-
-/** Convert a rate in bytes per second to a rate in bytes per step */
-STATIC uint32_t
-rate_per_sec_to_rate_per_step(uint32_t rate)
-{
- /*
- The precise calculation we'd want to do is
-
- (rate / 1000) * to_approximate_msec(TICKS_PER_STEP). But to minimize
- rounding error, we do it this way instead, and divide last.
- */
- uint64_t units = (uint64_t) rate * TICKS_PER_STEP;
- uint32_t val = (uint32_t)
- (monotime_coarse_stamp_units_to_approx_msec(units) / 1000);
- return val ? val : 1;
-}
-
-/**
- * Initialize a token bucket in *<b>bucket</b>, set up to allow <b>rate</b>
- * bytes per second, with a maximum burst of <b>burst</b> bytes. The bucket
- * is created such that <b>now_ts</b> is the current timestamp. The bucket
- * starts out full.
- */
-void
-token_bucket_rw_init(token_bucket_rw_t *bucket,
- uint32_t rate,
- uint32_t burst,
- uint32_t now_ts)
-{
- memset(bucket, 0, sizeof(token_bucket_rw_t));
- token_bucket_rw_adjust(bucket, rate, burst);
- token_bucket_rw_reset(bucket, now_ts);
-}
-
-/**
- * Change the configured rate (in bytes per second) and burst (in bytes)
- * for the token bucket in *<b>bucket</b>.
- */
-void
-token_bucket_rw_adjust(token_bucket_rw_t *bucket,
- uint32_t rate,
- uint32_t burst)
-{
- token_bucket_cfg_init(&bucket->cfg,
- rate_per_sec_to_rate_per_step(rate),
- burst);
- token_bucket_raw_adjust(&bucket->read_bucket, &bucket->cfg);
- token_bucket_raw_adjust(&bucket->write_bucket, &bucket->cfg);
-}
-
-/**
- * Reset <b>bucket</b> to be full, as of timestamp <b>now_ts</b>.
- */
-void
-token_bucket_rw_reset(token_bucket_rw_t *bucket,
- uint32_t now_ts)
-{
- token_bucket_raw_reset(&bucket->read_bucket, &bucket->cfg);
- token_bucket_raw_reset(&bucket->write_bucket, &bucket->cfg);
- bucket->last_refilled_at_timestamp = now_ts;
-}
-
-/**
- * Refill <b>bucket</b> as appropriate, given that the current timestamp
- * is <b>now_ts</b>.
- *
- * Return a bitmask containing TB_READ iff read bucket was empty and became
- * nonempty, and TB_WRITE iff the write bucket was empty and became nonempty.
- */
-int
-token_bucket_rw_refill(token_bucket_rw_t *bucket,
- uint32_t now_ts)
-{
- const uint32_t elapsed_ticks =
- (now_ts - bucket->last_refilled_at_timestamp);
- if (elapsed_ticks > UINT32_MAX-(300*1000)) {
- /* Either about 48 days have passed since the last refill, or the
- * monotonic clock has somehow moved backwards. (We're looking at you,
- * Windows.). We accept up to a 5 minute jump backwards as
- * "unremarkable".
- */
- return 0;
- }
- const uint32_t elapsed_steps = elapsed_ticks / TICKS_PER_STEP;
-
- if (!elapsed_steps) {
- /* Note that if less than one whole step elapsed, we don't advance the
- * time in last_refilled_at. That's intentional: we want to make sure
- * that we add some bytes to it eventually. */
- return 0;
- }
-
- int flags = 0;
- if (token_bucket_raw_refill_steps(&bucket->read_bucket,
- &bucket->cfg, elapsed_steps))
- flags |= TB_READ;
- if (token_bucket_raw_refill_steps(&bucket->write_bucket,
- &bucket->cfg, elapsed_steps))
- flags |= TB_WRITE;
-
- bucket->last_refilled_at_timestamp = now_ts;
- return flags;
-}
-
-/**
- * Decrement the read token bucket in <b>bucket</b> by <b>n</b> bytes.
- *
- * Return true if the bucket was nonempty and became empty; return false
- * otherwise.
- */
-int
-token_bucket_rw_dec_read(token_bucket_rw_t *bucket,
- ssize_t n)
-{
- return token_bucket_raw_dec(&bucket->read_bucket, n);
-}
-
-/**
- * Decrement the write token bucket in <b>bucket</b> by <b>n</b> bytes.
- *
- * Return true if the bucket was nonempty and became empty; return false
- * otherwise.
- */
-int
-token_bucket_rw_dec_write(token_bucket_rw_t *bucket,
- ssize_t n)
-{
- return token_bucket_raw_dec(&bucket->write_bucket, n);
-}
-
-/**
- * As token_bucket_rw_dec_read and token_bucket_rw_dec_write, in a single
- * operation. Return a bitmask of TB_READ and TB_WRITE to indicate
- * which buckets became empty.
- */
-int
-token_bucket_rw_dec(token_bucket_rw_t *bucket,
- ssize_t n_read, ssize_t n_written)
-{
- int flags = 0;
- if (token_bucket_rw_dec_read(bucket, n_read))
- flags |= TB_READ;
- if (token_bucket_rw_dec_write(bucket, n_written))
- flags |= TB_WRITE;
- return flags;
-}
-
diff --git a/src/common/token_bucket.h b/src/common/token_bucket.h
deleted file mode 100644
index 0e7832e838..0000000000
--- a/src/common/token_bucket.h
+++ /dev/null
@@ -1,118 +0,0 @@
-/* Copyright (c) 2018, The Tor Project, Inc. */
-/* See LICENSE for licensing information */
-
-/**
- * \file token_bucket_rw.h
- * \brief Headers for token_bucket_rw.c
- **/
-
-#ifndef TOR_TOKEN_BUCKET_H
-#define TOR_TOKEN_BUCKET_H
-
-#include "torint.h"
-#include "testsupport.h"
-
-/** Largest allowable burst value for a token buffer. */
-#define TOKEN_BUCKET_MAX_BURST INT32_MAX
-
-/** A generic token buffer configuration: determines the number of tokens
- * added to the bucket in each time unit (the "rate"), and the maximum number
- * of tokens in the bucket (the "burst") */
-typedef struct token_bucket_cfg_t {
- uint32_t rate;
- int32_t burst;
-} token_bucket_cfg_t;
-
-/** A raw token bucket, decoupled from its configuration and timestamp. */
-typedef struct token_bucket_raw_t {
- int32_t bucket;
-} token_bucket_raw_t;
-
-void token_bucket_cfg_init(token_bucket_cfg_t *cfg,
- uint32_t rate,
- uint32_t burst);
-
-void token_bucket_raw_adjust(token_bucket_raw_t *bucket,
- const token_bucket_cfg_t *cfg);
-
-void token_bucket_raw_reset(token_bucket_raw_t *bucket,
- const token_bucket_cfg_t *cfg);
-
-int token_bucket_raw_dec(token_bucket_raw_t *bucket,
- ssize_t n);
-
-int token_bucket_raw_refill_steps(token_bucket_raw_t *bucket,
- const token_bucket_cfg_t *cfg,
- const uint32_t elapsed_steps);
-
-static inline size_t token_bucket_raw_get(const token_bucket_raw_t *bucket);
-/** Return the current number of bytes set in a token bucket. */
-static inline size_t
-token_bucket_raw_get(const token_bucket_raw_t *bucket)
-{
- return bucket->bucket >= 0 ? bucket->bucket : 0;
-}
-
-/** A convenience type containing all the pieces needed for a coupled
- * read-bucket and write-bucket that have the same rate limit, and which use
- * "timestamp units" (see compat_time.h) for their time. */
-typedef struct token_bucket_rw_t {
- token_bucket_cfg_t cfg;
- token_bucket_raw_t read_bucket;
- token_bucket_raw_t write_bucket;
- uint32_t last_refilled_at_timestamp;
-} token_bucket_rw_t;
-
-void token_bucket_rw_init(token_bucket_rw_t *bucket,
- uint32_t rate,
- uint32_t burst,
- uint32_t now_ts);
-
-void token_bucket_rw_adjust(token_bucket_rw_t *bucket,
- uint32_t rate, uint32_t burst);
-
-void token_bucket_rw_reset(token_bucket_rw_t *bucket,
- uint32_t now_ts);
-
-#define TB_READ 1
-#define TB_WRITE 2
-
-int token_bucket_rw_refill(token_bucket_rw_t *bucket,
- uint32_t now_ts);
-
-int token_bucket_rw_dec_read(token_bucket_rw_t *bucket,
- ssize_t n);
-int token_bucket_rw_dec_write(token_bucket_rw_t *bucket,
- ssize_t n);
-
-int token_bucket_rw_dec(token_bucket_rw_t *bucket,
- ssize_t n_read, ssize_t n_written);
-
-static inline size_t token_bucket_rw_get_read(const token_bucket_rw_t *bucket);
-static inline size_t
-token_bucket_rw_get_read(const token_bucket_rw_t *bucket)
-{
- return token_bucket_raw_get(&bucket->read_bucket);
-}
-
-static inline size_t token_bucket_rw_get_write(
- const token_bucket_rw_t *bucket);
-static inline size_t
-token_bucket_rw_get_write(const token_bucket_rw_t *bucket)
-{
- return token_bucket_raw_get(&bucket->write_bucket);
-}
-
-#ifdef TOKEN_BUCKET_PRIVATE
-
-/* To avoid making the rates too small, we consider units of "steps",
- * where a "step" is defined as this many timestamp ticks. Keep this
- * a power of two if you can. */
-#define TICKS_PER_STEP 16
-
-STATIC uint32_t rate_per_sec_to_rate_per_step(uint32_t rate);
-
-#endif
-
-#endif /* TOR_TOKEN_BUCKET_H */
-
diff --git a/src/common/torint.h b/src/common/torint.h
deleted file mode 100644
index fc7818fe2c..0000000000
--- a/src/common/torint.h
+++ /dev/null
@@ -1,379 +0,0 @@
-/* Copyright (c) 2003, Roger Dingledine
- * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2017, The Tor Project, Inc. */
-/* See LICENSE for licensing information */
-
-/**
- * \file torint.h
- * \brief Header file to define uint32_t and friends
- **/
-
-#ifndef TOR_TORINT_H
-#define TOR_TORINT_H
-
-#include "orconfig.h"
-
-#ifdef HAVE_STDINT_H
-#include <stdint.h>
-#endif
-#ifdef HAVE_SYS_TYPES_H
-#include <sys/types.h>
-#endif
-#ifdef HAVE_LIMITS_H
-#include <limits.h>
-#endif
-#ifdef HAVE_SYS_LIMITS_H
-#include <sys/limits.h>
-#endif
-#ifdef HAVE_MACHINE_LIMITS_H
-#if !defined(__FreeBSD__) && !defined(__FreeBSD_kernel__)
- /* FreeBSD has a bug where it complains that this file is obsolete,
- and I should migrate to using sys/limits. It complains even when
- I include both.
- __FreeBSD_kernel__ is defined by Debian GNU/kFreeBSD which
- does the same thing (but doesn't defined __FreeBSD__).
- */
-#include <machine/limits.h>
-#endif /* !defined(__FreeBSD__) && !defined(__FreeBSD_kernel__) */
-#endif /* defined(HAVE_MACHINE_LIMITS_H) */
-#ifdef HAVE_INTTYPES_H
-#include <inttypes.h>
-#endif
-
-#include <stdbool.h>
-
-#if (SIZEOF_INT8_T != 0)
-#define HAVE_INT8_T
-#endif
-#if (SIZEOF_INT16_T != 0)
-#define HAVE_INT16_T
-#endif
-#if (SIZEOF_INT32_T != 0)
-#define HAVE_INT32_T
-#endif
-#if (SIZEOF_INT64_T != 0)
-#define HAVE_INT64_T
-#endif
-#if (SIZEOF_UINT8_T != 0)
-#define HAVE_UINT8_T
-#endif
-#if (SIZEOF_UINT16_T != 0)
-#define HAVE_UINT16_T
-#endif
-#if (SIZEOF_UINT32_T != 0)
-#define HAVE_UINT32_T
-#endif
-#if (SIZEOF_UINT64_T != 0)
-#define HAVE_UINT64_T
-#endif
-#if (SIZEOF_INTPTR_T != 0)
-#define HAVE_INTPTR_T
-#endif
-#if (SIZEOF_UINTPTR_T != 0)
-#define HAVE_UINTPTR_T
-#endif
-
-#if (SIZEOF_CHAR == 1)
-#ifndef HAVE_INT8_T
-typedef signed char int8_t;
-#define HAVE_INT8_T
-#endif
-#ifndef HAVE_UINT8_T
-typedef unsigned char uint8_t;
-#define HAVE_UINT8_T
-#endif
-#endif /* (SIZEOF_CHAR == 1) */
-
-#if (SIZEOF_SHORT == 2)
-#ifndef HAVE_INT16_T
-typedef signed short int16_t;
-#define HAVE_INT16_T
-#endif
-#ifndef HAVE_UINT16_T
-typedef unsigned short uint16_t;
-#define HAVE_UINT16_T
-#endif
-#endif /* (SIZEOF_SHORT == 2) */
-
-#if (SIZEOF_INT == 2)
-#ifndef HAVE_INT16_T
-typedef signed int int16_t;
-#define HAVE_INT16_T
-#endif
-#ifndef HAVE_UINT16_T
-typedef unsigned int uint16_t;
-#define HAVE_UINT16_T
-#endif
-#elif (SIZEOF_INT == 4)
-#ifndef HAVE_INT32_T
-typedef signed int int32_t;
-#define HAVE_INT32_T
-#endif
-#ifndef HAVE_UINT32_T
-typedef unsigned int uint32_t;
-#define HAVE_UINT32_T
-#endif
-#ifndef UINT16_MAX
-#define UINT16_MAX 0xffffu
-#endif
-#ifndef INT16_MAX
-#define INT16_MAX 0x7fff
-#endif
-#ifndef INT16_MIN
-#define INT16_MIN (-INT16_MAX-1)
-#endif
-#ifndef UINT32_MAX
-#define UINT32_MAX 0xffffffffu
-#endif
-#ifndef INT32_MAX
-#define INT32_MAX 0x7fffffff
-#endif
-#ifndef INT32_MIN
-#define INT32_MIN (-2147483647-1)
-#endif
-#endif /* (SIZEOF_INT == 2) || ... */
-
-#if (SIZEOF_LONG == 4)
-#ifndef HAVE_INT32_T
-typedef signed long int32_t;
-#define HAVE_INT32_T
-#endif
-#ifndef HAVE_UINT32_T
-typedef unsigned long uint32_t;
-#define HAVE_UINT32_T
-#ifndef UINT32_MAX
-#define UINT32_MAX 0xfffffffful
-#endif
-#endif /* !defined(HAVE_UINT32_T) */
-#elif (SIZEOF_LONG == 8)
-#ifndef HAVE_INT64_T
-typedef signed long int64_t;
-#define HAVE_INT64_T
-#endif
-#ifndef HAVE_UINT32_T
-typedef unsigned long uint64_t;
-#define HAVE_UINT32_T
-#endif
-#ifndef UINT64_MAX
-#define UINT64_MAX 0xfffffffffffffffful
-#endif
-#endif /* (SIZEOF_LONG == 4) || ... */
-
-#if (SIZEOF_LONG_LONG == 8)
-#ifndef HAVE_INT64_T
-typedef signed long long int64_t;
-#define HAVE_INT64_T
-#endif
-#ifndef HAVE_UINT64_T
-typedef unsigned long long uint64_t;
-#define HAVE_UINT64_T
-#endif
-#ifndef UINT64_MAX
-#define UINT64_MAX 0xffffffffffffffffull
-#endif
-#ifndef INT64_MAX
-#define INT64_MAX 0x7fffffffffffffffll
-#endif
-#endif /* (SIZEOF_LONG_LONG == 8) */
-
-#if (SIZEOF___INT64 == 8)
-#ifndef HAVE_INT64_T
-typedef signed __int64 int64_t;
-#define HAVE_INT64_T
-#endif
-#ifndef HAVE_UINT64_T
-typedef unsigned __int64 uint64_t;
-#define HAVE_UINT64_T
-#endif
-#ifndef UINT64_MAX
-#define UINT64_MAX 0xffffffffffffffffui64
-#endif
-#ifndef INT64_MAX
-#define INT64_MAX 0x7fffffffffffffffi64
-#endif
-#endif /* (SIZEOF___INT64 == 8) */
-
-#ifndef INT64_MIN
-#define INT64_MIN ((- INT64_MAX) - 1)
-#endif
-
-#ifndef SIZE_MAX
-#if SIZEOF_SIZE_T == 8
-#define SIZE_MAX UINT64_MAX
-#elif SIZEOF_SIZE_T == 4
-#define SIZE_MAX UINT32_MAX
-#else
-#error "Can't define SIZE_MAX"
-#endif /* SIZEOF_SIZE_T == 8 || ... */
-#endif /* !defined(SIZE_MAX) */
-
-#ifndef HAVE_SSIZE_T
-#if SIZEOF_SIZE_T == 8
-typedef int64_t ssize_t;
-#elif SIZEOF_SIZE_T == 4
-typedef int32_t ssize_t;
-#else
-#error "Can't define ssize_t."
-#endif /* SIZEOF_SIZE_T == 8 || ... */
-#endif /* !defined(HAVE_SSIZE_T) */
-
-#if (SIZEOF_VOID_P > 4 && SIZEOF_VOID_P <= 8)
-#ifndef HAVE_INTPTR_T
-typedef int64_t intptr_t;
-#define SIZEOF_INTPTR_T 8
-#endif
-#ifndef HAVE_UINTPTR_T
-typedef uint64_t uintptr_t;
-#define SIZEOF_UINTPTR_T 8
-#endif
-#elif (SIZEOF_VOID_P > 2 && SIZEOF_VOID_P <= 4)
-#ifndef HAVE_INTPTR_T
-typedef int32_t intptr_t;
-#define SIZEOF_INTPTR_T 4
-#endif
-#ifndef HAVE_UINTPTR_T
-typedef uint32_t uintptr_t;
-#define SIZEOF_UINTPTR_T 4
-#endif
-#else
-#error "void * is either >8 bytes or <= 2. In either case, I am confused."
-#endif /* (SIZEOF_VOID_P > 4 && SIZEOF_VOID_P <= 8) || ... */
-
-#ifndef HAVE_INT8_T
-#error "Missing type int8_t"
-#endif
-#ifndef HAVE_UINT8_T
-#error "Missing type uint8_t"
-#endif
-#ifndef HAVE_INT16_T
-#error "Missing type int16_t"
-#endif
-#ifndef HAVE_UINT16_T
-#error "Missing type uint16_t"
-#endif
-#ifndef HAVE_INT32_T
-#error "Missing type int32_t"
-#endif
-#ifndef HAVE_UINT32_T
-#error "Missing type uint32_t"
-#endif
-#ifndef HAVE_INT64_T
-#error "Missing type int64_t"
-#endif
-#ifndef HAVE_UINT64_T
-#error "Missing type uint64_t"
-#endif
-
-/* This assumes a sane (2's-complement) representation. But if you
- * aren't 2's complement, and you don't define LONG_MAX, then you're so
- * bizarre that I want nothing to do with you. */
-#ifndef USING_TWOS_COMPLEMENT
-#error "Seems that your platform doesn't use 2's complement arithmetic. Argh."
-#endif
-#ifndef LONG_MAX
-#if (SIZEOF_LONG == 4)
-#define LONG_MAX 0x7fffffffL
-#elif (SIZEOF_LONG == 8)
-#define LONG_MAX 0x7fffffffffffffffL
-#else
-#error "Can't define LONG_MAX"
-#endif /* (SIZEOF_LONG == 4) || ... */
-#endif /* !defined(LONG_MAX) */
-
-#ifndef INT_MAX
-#if (SIZEOF_INT == 4)
-#define INT_MAX 0x7fffffffL
-#elif (SIZEOF_INT == 8)
-#define INT_MAX 0x7fffffffffffffffL
-#else
-#error "Can't define INT_MAX"
-#endif /* (SIZEOF_INT == 4) || ... */
-#endif /* !defined(INT_MAX) */
-
-#ifndef UINT_MAX
-#if (SIZEOF_INT == 2)
-#define UINT_MAX 0xffffu
-#elif (SIZEOF_INT == 4)
-#define UINT_MAX 0xffffffffu
-#elif (SIZEOF_INT == 8)
-#define UINT_MAX 0xffffffffffffffffu
-#else
-#error "Can't define UINT_MAX"
-#endif /* (SIZEOF_INT == 2) || ... */
-#endif /* !defined(UINT_MAX) */
-
-#ifndef SHORT_MAX
-#if (SIZEOF_SHORT == 2)
-#define SHORT_MAX 0x7fff
-#elif (SIZEOF_SHORT == 4)
-#define SHORT_MAX 0x7fffffff
-#else
-#error "Can't define SHORT_MAX"
-#endif /* (SIZEOF_SHORT == 2) || ... */
-#endif /* !defined(SHORT_MAX) */
-
-#ifndef TIME_MAX
-
-#if (SIZEOF_TIME_T == SIZEOF_INT)
-#define TIME_MAX ((time_t)INT_MAX)
-#elif (SIZEOF_TIME_T == SIZEOF_LONG)
-#define TIME_MAX ((time_t)LONG_MAX)
-#elif (SIZEOF_TIME_T == 8)
-#define TIME_MAX ((time_t)INT64_MAX)
-#else
-#error "Can't define TIME_MAX"
-#endif /* (SIZEOF_TIME_T == SIZEOF_INT) || ... */
-
-#endif /* !defined(TIME_MAX) */
-
-#ifndef TIME_MIN
-
-#if (SIZEOF_TIME_T == SIZEOF_INT)
-#define TIME_MIN ((time_t)INT_MIN)
-#elif (SIZEOF_TIME_T == SIZEOF_LONG)
-#define TIME_MIN ((time_t)LONG_MIN)
-#elif (SIZEOF_TIME_T == 8)
-#define TIME_MIN ((time_t)INT64_MIN)
-#else
-#error "Can't define TIME_MIN"
-#endif /* (SIZEOF_TIME_T == SIZEOF_INT) || ... */
-
-#endif /* !defined(TIME_MIN) */
-
-#ifndef SIZE_MAX
-#if (SIZEOF_SIZE_T == 4)
-#define SIZE_MAX UINT32_MAX
-#elif (SIZEOF_SIZE_T == 8)
-#define SIZE_MAX UINT64_MAX
-#else
-#error "Can't define SIZE_MAX"
-#endif /* (SIZEOF_SIZE_T == 4) || ... */
-#endif /* !defined(SIZE_MAX) */
-
-#ifdef _WIN32
-# ifdef _WIN64
-# define TOR_PRIuSZ PRIu64
-# else
-# define TOR_PRIuSZ PRIu32
-# endif
-#else
-# define TOR_PRIuSZ "zu"
-#endif
-
-#ifndef SSIZE_MAX
-#if (SIZEOF_SIZE_T == 4)
-#define SSIZE_MAX INT32_MAX
-#elif (SIZEOF_SIZE_T == 8)
-#define SSIZE_MAX INT64_MAX
-#else
-#error "Can't define SSIZE_MAX"
-#endif /* (SIZEOF_SIZE_T == 4) || ... */
-#endif /* !defined(SSIZE_MAX) */
-
-/** Any ssize_t larger than this amount is likely to be an underflow. */
-#define SSIZE_T_CEILING ((ssize_t)(SSIZE_MAX-16))
-/** Any size_t larger than this amount is likely to be an underflow. */
-#define SIZE_T_CEILING ((size_t)(SSIZE_MAX-16))
-
-#endif /* !defined(TOR_TORINT_H) */
-
diff --git a/src/common/torlog.h b/src/common/torlog.h
deleted file mode 100644
index de389883c0..0000000000
--- a/src/common/torlog.h
+++ /dev/null
@@ -1,275 +0,0 @@
-/* Copyright (c) 2001, Matej Pfajfar.
- * Copyright (c) 2001-2004, Roger Dingledine.
- * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2017, The Tor Project, Inc. */
-/* See LICENSE for licensing information */
-
-/**
- * \file torlog.h
- *
- * \brief Headers for log.c
- **/
-
-#ifndef TOR_TORLOG_H
-
-#include "compat.h"
-#include "testsupport.h"
-
-#ifdef HAVE_SYSLOG_H
-#include <syslog.h>
-#define LOG_WARN LOG_WARNING
-#if LOG_DEBUG < LOG_ERR
-#error "Your syslog.h thinks high numbers are more important. " \
- "We aren't prepared to deal with that."
-#endif
-#else /* !(defined(HAVE_SYSLOG_H)) */
-/* Note: Syslog's logging code refers to priorities, with 0 being the most
- * important. Thus, all our comparisons needed to be reversed when we added
- * syslog support.
- *
- * The upshot of this is that comments about log levels may be messed up: for
- * "maximum severity" read "most severe" and "numerically *lowest* severity".
- */
-
-/** Debug-level severity: for hyper-verbose messages of no interest to
- * anybody but developers. */
-#define LOG_DEBUG 7
-/** Info-level severity: for messages that appear frequently during normal
- * operation. */
-#define LOG_INFO 6
-/** Notice-level severity: for messages that appear infrequently
- * during normal operation; that the user will probably care about;
- * and that are not errors.
- */
-#define LOG_NOTICE 5
-/** Warn-level severity: for messages that only appear when something has gone
- * wrong. */
-#define LOG_WARN 4
-/** Error-level severity: for messages that only appear when something has gone
- * very wrong, and the Tor process can no longer proceed. */
-#define LOG_ERR 3
-#endif /* defined(HAVE_SYSLOG_H) */
-
-/* Logging domains */
-
-/** Catch-all for miscellaneous events and fatal errors. */
-#define LD_GENERAL (1u<<0)
-/** The cryptography subsystem. */
-#define LD_CRYPTO (1u<<1)
-/** Networking. */
-#define LD_NET (1u<<2)
-/** Parsing and acting on our configuration. */
-#define LD_CONFIG (1u<<3)
-/** Reading and writing from the filesystem. */
-#define LD_FS (1u<<4)
-/** Other servers' (non)compliance with the Tor protocol. */
-#define LD_PROTOCOL (1u<<5)
-/** Memory management. */
-#define LD_MM (1u<<6)
-/** HTTP implementation. */
-#define LD_HTTP (1u<<7)
-/** Application (socks) requests. */
-#define LD_APP (1u<<8)
-/** Communication via the controller protocol. */
-#define LD_CONTROL (1u<<9)
-/** Building, using, and managing circuits. */
-#define LD_CIRC (1u<<10)
-/** Hidden services. */
-#define LD_REND (1u<<11)
-/** Internal errors in this Tor process. */
-#define LD_BUG (1u<<12)
-/** Learning and using information about Tor servers. */
-#define LD_DIR (1u<<13)
-/** Learning and using information about Tor servers. */
-#define LD_DIRSERV (1u<<14)
-/** Onion routing protocol. */
-#define LD_OR (1u<<15)
-/** Generic edge-connection functionality. */
-#define LD_EDGE (1u<<16)
-#define LD_EXIT LD_EDGE
-/** Bandwidth accounting. */
-#define LD_ACCT (1u<<17)
-/** Router history */
-#define LD_HIST (1u<<18)
-/** OR handshaking */
-#define LD_HANDSHAKE (1u<<19)
-/** Heartbeat messages */
-#define LD_HEARTBEAT (1u<<20)
-/** Abstract channel_t code */
-#define LD_CHANNEL (1u<<21)
-/** Scheduler */
-#define LD_SCHED (1u<<22)
-/** Guard nodes */
-#define LD_GUARD (1u<<23)
-/** Generation and application of consensus diffs. */
-#define LD_CONSDIFF (1u<<24)
-/** Denial of Service mitigation. */
-#define LD_DOS (1u<<25)
-/** Number of logging domains in the code. */
-#define N_LOGGING_DOMAINS 26
-
-/** This log message is not safe to send to a callback-based logger
- * immediately. Used as a flag, not a log domain. */
-#define LD_NOCB (1u<<31)
-/** This log message should not include a function name, even if it otherwise
- * would. Used as a flag, not a log domain. */
-#define LD_NOFUNCNAME (1u<<30)
-
-#ifdef TOR_UNIT_TESTS
-/** This log message should not be intercepted by mock_saving_logv */
-#define LD_NO_MOCK (1u<<29)
-#endif
-
-/** Mask of zero or more log domains, OR'd together. */
-typedef uint32_t log_domain_mask_t;
-
-/** Configures which severities are logged for each logging domain for a given
- * log target. */
-typedef struct log_severity_list_t {
- /** For each log severity, a bitmask of which domains a given logger is
- * logging. */
- log_domain_mask_t masks[LOG_DEBUG-LOG_ERR+1];
-} log_severity_list_t;
-
-/** Callback type used for add_callback_log. */
-typedef void (*log_callback)(int severity, uint32_t domain, const char *msg);
-
-void init_logging(int disable_startup_queue);
-int parse_log_level(const char *level);
-const char *log_level_to_string(int level);
-int parse_log_severity_config(const char **cfg,
- log_severity_list_t *severity_out);
-void set_log_severity_config(int minSeverity, int maxSeverity,
- log_severity_list_t *severity_out);
-void add_stream_log(const log_severity_list_t *severity, const char *name,
- int fd);
-int add_file_log(const log_severity_list_t *severity, const char *filename,
- const int truncate);
-#ifdef HAVE_SYSLOG_H
-int add_syslog_log(const log_severity_list_t *severity,
- const char* syslog_identity_tag);
-#endif // HAVE_SYSLOG_H.
-#ifdef HAVE_ANDROID_LOG_H
-int add_android_log(const log_severity_list_t *severity,
- const char *android_identity_tag);
-#endif // HAVE_ANDROID_LOG_H.
-int add_callback_log(const log_severity_list_t *severity, log_callback cb);
-typedef void (*pending_callback_callback)(void);
-void logs_set_pending_callback_callback(pending_callback_callback cb);
-void logs_set_domain_logging(int enabled);
-int get_min_log_level(void);
-void switch_logs_debug(void);
-void logs_free_all(void);
-void add_temp_log(int min_severity);
-void close_temp_logs(void);
-void rollback_log_changes(void);
-void mark_logs_temp(void);
-void change_callback_log_severity(int loglevelMin, int loglevelMax,
- log_callback cb);
-void flush_pending_log_callbacks(void);
-void flush_log_messages_from_startup(void);
-void log_set_application_name(const char *name);
-void set_log_time_granularity(int granularity_msec);
-void truncate_logs(void);
-
-void tor_log(int severity, log_domain_mask_t domain, const char *format, ...)
- CHECK_PRINTF(3,4);
-
-void tor_log_err_sigsafe(const char *m, ...);
-int tor_log_get_sigsafe_err_fds(const int **out);
-void tor_log_update_sigsafe_err_fds(void);
-
-struct smartlist_t;
-void tor_log_get_logfile_names(struct smartlist_t *out);
-
-extern int log_global_min_severity_;
-
-void log_fn_(int severity, log_domain_mask_t domain,
- const char *funcname, const char *format, ...)
- CHECK_PRINTF(4,5);
-struct ratelim_t;
-void log_fn_ratelim_(struct ratelim_t *ratelim, int severity,
- log_domain_mask_t domain, const char *funcname,
- const char *format, ...)
- CHECK_PRINTF(5,6);
-
-int log_message_is_interesting(int severity, log_domain_mask_t domain);
-void tor_log_string(int severity, log_domain_mask_t domain,
- const char *function, const char *string);
-
-#if defined(__GNUC__) && __GNUC__ <= 3
-
-/* These are the GCC varidaic macros, so that older versions of GCC don't
- * break. */
-
-/** 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, __FUNCTION__, args)
-/** As log_fn, but use <b>ratelim</b> (an instance of ratelim_t) to control
- * the frequency at which messages can appear.
- */
-#define log_fn_ratelim(ratelim, severity, domain, args...) \
- log_fn_ratelim_(ratelim, severity, domain, __FUNCTION__, args)
-#define log_debug(domain, args...) \
- STMT_BEGIN \
- if (PREDICT_UNLIKELY(log_global_min_severity_ == LOG_DEBUG)) \
- log_fn_(LOG_DEBUG, domain, __FUNCTION__, args); \
- STMT_END
-#define log_info(domain, args...) \
- log_fn_(LOG_INFO, domain, __FUNCTION__, args)
-#define log_notice(domain, args...) \
- log_fn_(LOG_NOTICE, domain, __FUNCTION__, args)
-#define log_warn(domain, args...) \
- log_fn_(LOG_WARN, domain, __FUNCTION__, args)
-#define log_err(domain, args...) \
- log_fn_(LOG_ERR, domain, __FUNCTION__, args)
-
-#else /* !(defined(__GNUC__) && __GNUC__ <= 3) */
-
-/* Here are the c99 variadic macros, to work with non-GCC compilers */
-
-#define log_debug(domain, args, ...) \
- STMT_BEGIN \
- if (PREDICT_UNLIKELY(log_global_min_severity_ == LOG_DEBUG)) \
- log_fn_(LOG_DEBUG, domain, __FUNCTION__, args, ##__VA_ARGS__); \
- STMT_END
-#define log_info(domain, args,...) \
- log_fn_(LOG_INFO, domain, __FUNCTION__, args, ##__VA_ARGS__)
-#define log_notice(domain, args,...) \
- log_fn_(LOG_NOTICE, domain, __FUNCTION__, args, ##__VA_ARGS__)
-#define log_warn(domain, args,...) \
- log_fn_(LOG_WARN, domain, __FUNCTION__, args, ##__VA_ARGS__)
-#define log_err(domain, args,...) \
- log_fn_(LOG_ERR, domain, __FUNCTION__, args, ##__VA_ARGS__)
-/** 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, __FUNCTION__, args, ##__VA_ARGS__)
-/** As log_fn, but use <b>ratelim</b> (an instance of ratelim_t) to control
- * the frequency at which messages can appear.
- */
-#define log_fn_ratelim(ratelim, severity, domain, args,...) \
- log_fn_ratelim_(ratelim, severity, domain, __FUNCTION__, \
- args, ##__VA_ARGS__)
-#endif /* defined(__GNUC__) && __GNUC__ <= 3 */
-
-/** This defines log levels that are linked in the Rust log module, rather
- * than re-defining these in both Rust and C.
- *
- * C_RUST_COUPLED src/rust/tor_log LogSeverity, LogDomain
- */
-extern const int LOG_WARN_;
-extern const int LOG_NOTICE_;
-extern const log_domain_mask_t LD_NET_;
-extern const log_domain_mask_t LD_GENERAL_;
-
-#ifdef LOG_PRIVATE
-MOCK_DECL(STATIC void, logv, (int severity, log_domain_mask_t domain,
- const char *funcname, const char *suffix, const char *format,
- va_list ap) CHECK_PRINTF(5,0));
-#endif
-
-# define TOR_TORLOG_H
-#endif /* !defined(TOR_TORLOG_H) */
-
diff --git a/src/common/tortls.c b/src/common/tortls.c
deleted file mode 100644
index 08aa35a480..0000000000
--- a/src/common/tortls.c
+++ /dev/null
@@ -1,2670 +0,0 @@
-/* Copyright (c) 2003, Roger Dingledine.
- * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2017, The Tor Project, Inc. */
-/* See LICENSE for licensing information */
-
-/**
- * \file tortls.c
- * \brief Wrapper functions to present a consistent interface to
- * TLS, SSL, and X.509 functions from OpenSSL.
- **/
-
-/* (Unlike other tor functions, these
- * are prefixed with tor_ in order to avoid conflicting with OpenSSL
- * functions and variables.)
- */
-
-#include "orconfig.h"
-
-#define TORTLS_PRIVATE
-#define TORTLS_OPENSSL_PRIVATE
-
-#include <assert.h>
-#ifdef _WIN32 /*wrkard for dtls1.h >= 0.9.8m of "#include <winsock.h>"*/
- #include <winsock2.h>
- #include <ws2tcpip.h>
-#endif
-
-#include "crypto.h"
-#include "crypto_rand.h"
-#include "crypto_util.h"
-#include "compat.h"
-
-/* Some versions of OpenSSL declare SSL_get_selected_srtp_profile twice in
- * srtp.h. Suppress the GCC warning so we can build with -Wredundant-decl. */
-DISABLE_GCC_WARNING(redundant-decls)
-
-#include <openssl/opensslv.h>
-
-#ifdef OPENSSL_NO_EC
-#error "We require OpenSSL with ECC support"
-#endif
-
-#include <openssl/ssl.h>
-#include <openssl/ssl3.h>
-#include <openssl/err.h>
-#include <openssl/tls1.h>
-#include <openssl/asn1.h>
-#include <openssl/bio.h>
-#include <openssl/bn.h>
-#include <openssl/rsa.h>
-
-ENABLE_GCC_WARNING(redundant-decls)
-
-#define TORTLS_PRIVATE
-#include "tortls.h"
-#include "util.h"
-#include "torlog.h"
-#include "container.h"
-#include <string.h>
-
-#ifdef OPENSSL_1_1_API
-#define X509_get_notBefore_const(cert) \
- X509_get0_notBefore(cert)
-#define X509_get_notAfter_const(cert) \
- X509_get0_notAfter(cert)
-#ifndef X509_get_notBefore
-#define X509_get_notBefore(cert) \
- X509_getm_notBefore(cert)
-#endif
-#ifndef X509_get_notAfter
-#define X509_get_notAfter(cert) \
- X509_getm_notAfter(cert)
-#endif
-#else /* ! OPENSSL_VERSION_NUMBER >= OPENSSL_V_SERIES(1,1,0) */
-#define X509_get_notBefore_const(cert) \
- ((const ASN1_TIME*) X509_get_notBefore((X509 *)cert))
-#define X509_get_notAfter_const(cert) \
- ((const ASN1_TIME*) X509_get_notAfter((X509 *)cert))
-#endif
-
-/* Copied from or.h */
-#define LEGAL_NICKNAME_CHARACTERS \
- "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
-
-/** How long do identity certificates live? (sec) */
-#define IDENTITY_CERT_LIFETIME (365*24*60*60)
-
-#define ADDR(tls) (((tls) && (tls)->address) ? tls->address : "peer")
-
-#if OPENSSL_VERSION_NUMBER < OPENSSL_V(1,0,0,'f')
-/* This is a version of OpenSSL before 1.0.0f. It does not have
- * the CVE-2011-4576 fix, and as such it can't use RELEASE_BUFFERS and
- * SSL3 safely at the same time.
- */
-#define DISABLE_SSL3_HANDSHAKE
-#endif /* OPENSSL_VERSION_NUMBER < OPENSSL_V(1,0,0,'f') */
-
-/* We redefine these so that we can run correctly even if the vendor gives us
- * a version of OpenSSL that does not match its header files. (Apple: I am
- * looking at you.)
- */
-#ifndef SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION
-#define SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION 0x00040000L
-#endif
-#ifndef SSL3_FLAGS_ALLOW_UNSAFE_LEGACY_RENEGOTIATION
-#define SSL3_FLAGS_ALLOW_UNSAFE_LEGACY_RENEGOTIATION 0x0010
-#endif
-
-/** Return values for tor_tls_classify_client_ciphers.
- *
- * @{
- */
-/** An error occurred when examining the client ciphers */
-#define CIPHERS_ERR -1
-/** The client cipher list indicates that a v1 handshake was in use. */
-#define CIPHERS_V1 1
-/** The client cipher list indicates that the client is using the v2 or the
- * v3 handshake, but that it is (probably!) lying about what ciphers it
- * supports */
-#define CIPHERS_V2 2
-/** The client cipher list indicates that the client is using the v2 or the
- * v3 handshake, and that it is telling the truth about what ciphers it
- * supports */
-#define CIPHERS_UNRESTRICTED 3
-/** @} */
-
-/** The ex_data index in which we store a pointer to an SSL object's
- * corresponding tor_tls_t object. */
-STATIC int tor_tls_object_ex_data_index = -1;
-
-/** Helper: Allocate tor_tls_object_ex_data_index. */
-STATIC void
-tor_tls_allocate_tor_tls_object_ex_data_index(void)
-{
- if (tor_tls_object_ex_data_index == -1) {
- tor_tls_object_ex_data_index =
- SSL_get_ex_new_index(0, NULL, NULL, NULL, NULL);
- tor_assert(tor_tls_object_ex_data_index != -1);
- }
-}
-
-/** Helper: given a SSL* pointer, return the tor_tls_t object using that
- * pointer. */
-STATIC tor_tls_t *
-tor_tls_get_by_ssl(const SSL *ssl)
-{
- tor_tls_t *result = SSL_get_ex_data(ssl, tor_tls_object_ex_data_index);
- if (result)
- tor_assert(result->magic == TOR_TLS_MAGIC);
- return result;
-}
-
-static void tor_tls_context_decref(tor_tls_context_t *ctx);
-static void tor_tls_context_incref(tor_tls_context_t *ctx);
-
-static int check_cert_lifetime_internal(int severity, const X509 *cert,
- time_t now,
- int past_tolerance, int future_tolerance);
-
-/** Global TLS contexts. We keep them here because nobody else needs
- * to touch them.
- *
- * @{ */
-STATIC tor_tls_context_t *server_tls_context = NULL;
-STATIC tor_tls_context_t *client_tls_context = NULL;
-/**@}*/
-
-/** True iff tor_tls_init() has been called. */
-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)
-
-/** Write a description of the current state of <b>tls</b> into the
- * <b>sz</b>-byte buffer at <b>buf</b>. */
-void
-tor_tls_get_state_description(tor_tls_t *tls, char *buf, size_t sz)
-{
- const char *ssl_state;
- const char *tortls_state;
-
- if (PREDICT_UNLIKELY(!tls || !tls->ssl)) {
- strlcpy(buf, "(No SSL object)", sz);
- return;
- }
-
- ssl_state = SSL_state_string_long(tls->ssl);
- switch (tls->state) {
-#define CASE(st) case TOR_TLS_ST_##st: tortls_state = " in "#st ; break
- CASE(HANDSHAKE);
- CASE(OPEN);
- CASE(GOTCLOSE);
- CASE(SENTCLOSE);
- CASE(CLOSED);
- CASE(RENEGOTIATE);
-#undef CASE
- case TOR_TLS_ST_BUFFEREVENT:
- tortls_state = "";
- break;
- default:
- tortls_state = " in unknown TLS state";
- break;
- }
-
- tor_snprintf(buf, sz, "%s%s", ssl_state, tortls_state);
-}
-
-/** Log a single error <b>err</b> as returned by ERR_get_error(), which was
- * received while performing an operation <b>doing</b> on <b>tls</b>. Log
- * the message at <b>severity</b>, in log domain <b>domain</b>. */
-void
-tor_tls_log_one_error(tor_tls_t *tls, unsigned long err,
- int severity, int domain, const char *doing)
-{
- const char *state = NULL, *addr;
- const char *msg, *lib, *func;
-
- state = (tls && tls->ssl)?SSL_state_string_long(tls->ssl):"---";
-
- addr = tls ? tls->address : NULL;
-
- /* Some errors are known-benign, meaning they are the fault of the other
- * side of the connection. The caller doesn't know this, so override the
- * priority for those cases. */
- switch (ERR_GET_REASON(err)) {
- case SSL_R_HTTP_REQUEST:
- case SSL_R_HTTPS_PROXY_REQUEST:
- case SSL_R_RECORD_LENGTH_MISMATCH:
-#ifndef OPENSSL_1_1_API
- case SSL_R_RECORD_TOO_LARGE:
-#endif
- case SSL_R_UNKNOWN_PROTOCOL:
- case SSL_R_UNSUPPORTED_PROTOCOL:
- severity = LOG_INFO;
- break;
- default:
- break;
- }
-
- msg = (const char*)ERR_reason_error_string(err);
- lib = (const char*)ERR_lib_error_string(err);
- func = (const char*)ERR_func_error_string(err);
- if (!msg) msg = "(null)";
- if (!lib) lib = "(null)";
- if (!func) func = "(null)";
- if (doing) {
- tor_log(severity, domain, "TLS error while %s%s%s: %s (in %s:%s:%s)",
- doing, addr?" with ":"", addr?addr:"",
- msg, lib, func, state);
- } else {
- tor_log(severity, domain, "TLS error%s%s: %s (in %s:%s:%s)",
- addr?" with ":"", addr?addr:"",
- msg, lib, func, state);
- }
-}
-
-/** Log all pending tls errors at level <b>severity</b> in log domain
- * <b>domain</b>. Use <b>doing</b> to describe our current activities.
- */
-STATIC void
-tls_log_errors(tor_tls_t *tls, int severity, int domain, const char *doing)
-{
- unsigned long err;
-
- while ((err = ERR_get_error()) != 0) {
- tor_tls_log_one_error(tls, err, severity, domain, doing);
- }
-}
-
-/** Convert an errno (or a WSAerrno on windows) into a TOR_TLS_* error
- * code. */
-STATIC int
-tor_errno_to_tls_error(int e)
-{
- switch (e) {
- case SOCK_ERRNO(ECONNRESET): // most common
- return TOR_TLS_ERROR_CONNRESET;
- case SOCK_ERRNO(ETIMEDOUT):
- return TOR_TLS_ERROR_TIMEOUT;
- case SOCK_ERRNO(EHOSTUNREACH):
- case SOCK_ERRNO(ENETUNREACH):
- return TOR_TLS_ERROR_NO_ROUTE;
- case SOCK_ERRNO(ECONNREFUSED):
- return TOR_TLS_ERROR_CONNREFUSED; // least common
- default:
- return TOR_TLS_ERROR_MISC;
- }
-}
-
-/** Given a TOR_TLS_* error code, return a string equivalent. */
-const char *
-tor_tls_err_to_string(int err)
-{
- if (err >= 0)
- return "[Not an error.]";
- switch (err) {
- case TOR_TLS_ERROR_MISC: return "misc error";
- case TOR_TLS_ERROR_IO: return "unexpected close";
- case TOR_TLS_ERROR_CONNREFUSED: return "connection refused";
- case TOR_TLS_ERROR_CONNRESET: return "connection reset";
- case TOR_TLS_ERROR_NO_ROUTE: return "host unreachable";
- case TOR_TLS_ERROR_TIMEOUT: return "connection timed out";
- case TOR_TLS_CLOSE: return "closed";
- case TOR_TLS_WANTREAD: return "want to read";
- case TOR_TLS_WANTWRITE: return "want to write";
- default: return "(unknown error code)";
- }
-}
-
-#define CATCH_SYSCALL 1
-#define CATCH_ZERO 2
-
-/** 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
- * reporting syscall errors. If extra&CATCH_ZERO is true, return
- * 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>.
- */
-STATIC int
-tor_tls_get_error(tor_tls_t *tls, int r, int extra,
- const char *doing, int severity, int domain)
-{
- int err = SSL_get_error(tls->ssl, r);
- int tor_error = TOR_TLS_ERROR_MISC;
- switch (err) {
- case SSL_ERROR_NONE:
- return TOR_TLS_DONE;
- case SSL_ERROR_WANT_READ:
- return TOR_TLS_WANTREAD;
- case SSL_ERROR_WANT_WRITE:
- return TOR_TLS_WANTWRITE;
- case SSL_ERROR_SYSCALL:
- if (extra&CATCH_SYSCALL)
- return TOR_TLS_SYSCALL_;
- if (r == 0) {
- tor_log(severity, LD_NET, "TLS error: unexpected close while %s (%s)",
- doing, SSL_state_string_long(tls->ssl));
- tor_error = TOR_TLS_ERROR_IO;
- } else {
- int e = tor_socket_errno(tls->socket);
- tor_log(severity, LD_NET,
- "TLS error: <syscall error while %s> (errno=%d: %s; state=%s)",
- doing, e, tor_socket_strerror(e),
- SSL_state_string_long(tls->ssl));
- tor_error = tor_errno_to_tls_error(e);
- }
- tls_log_errors(tls, severity, domain, doing);
- return tor_error;
- case SSL_ERROR_ZERO_RETURN:
- if (extra&CATCH_ZERO)
- return TOR_TLS_ZERORETURN_;
- tor_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);
- return TOR_TLS_CLOSE;
- default:
- tls_log_errors(tls, severity, domain, doing);
- return TOR_TLS_ERROR_MISC;
- }
-}
-
-/** Initialize OpenSSL, unless it has already been initialized.
- */
-static void
-tor_tls_init(void)
-{
- check_no_tls_errors();
-
- if (!tls_library_is_initialized) {
-#ifdef OPENSSL_1_1_API
- OPENSSL_init_ssl(OPENSSL_INIT_LOAD_SSL_STRINGS, NULL);
-#else
- SSL_library_init();
- SSL_load_error_strings();
-#endif
-
-#if (SIZEOF_VOID_P >= 8 && \
- OPENSSL_VERSION_NUMBER >= OPENSSL_V_SERIES(1,0,1))
- long version = OpenSSL_version_num();
-
- /* LCOV_EXCL_START : we can't test these lines on the same machine */
- if (version >= OPENSSL_V_SERIES(1,0,1)) {
- /* Warn if we could *almost* be running with much faster ECDH.
- If we're built for a 64-bit target, using OpenSSL 1.0.1, but we
- don't have one of the built-in __uint128-based speedups, we are
- just one build operation away from an accelerated handshake.
-
- (We could be looking at OPENSSL_NO_EC_NISTP_64_GCC_128 instead of
- doing this test, but that gives compile-time options, not runtime
- behavior.)
- */
- EC_KEY *key = EC_KEY_new_by_curve_name(NID_X9_62_prime256v1);
- const EC_GROUP *g = key ? EC_KEY_get0_group(key) : NULL;
- const EC_METHOD *m = g ? EC_GROUP_method_of(g) : NULL;
- const int warn = (m == EC_GFp_simple_method() ||
- m == EC_GFp_mont_method() ||
- m == EC_GFp_nist_method());
- EC_KEY_free(key);
-
- if (warn)
- log_notice(LD_GENERAL, "We were built to run on a 64-bit CPU, with "
- "OpenSSL 1.0.1 or later, but with a version of OpenSSL "
- "that apparently lacks accelerated support for the NIST "
- "P-224 and P-256 groups. Building openssl with such "
- "support (using the enable-ec_nistp_64_gcc_128 option "
- "when configuring it) would make ECDH much faster.");
- }
- /* LCOV_EXCL_STOP */
-#endif /* (SIZEOF_VOID_P >= 8 && ... */
-
- tor_tls_allocate_tor_tls_object_ex_data_index();
-
- tls_library_is_initialized = 1;
- }
-}
-
-/** Free all global TLS structures. */
-void
-tor_tls_free_all(void)
-{
- check_no_tls_errors();
-
- if (server_tls_context) {
- tor_tls_context_t *ctx = server_tls_context;
- server_tls_context = NULL;
- tor_tls_context_decref(ctx);
- }
- if (client_tls_context) {
- tor_tls_context_t *ctx = client_tls_context;
- client_tls_context = NULL;
- tor_tls_context_decref(ctx);
- }
-}
-
-/** We need to give OpenSSL a callback to verify certificates. This is
- * it: We always accept peer certs and complete the handshake. We
- * don't validate them until later.
- */
-STATIC int
-always_accept_verify_cb(int preverify_ok,
- X509_STORE_CTX *x509_ctx)
-{
- (void) preverify_ok;
- (void) x509_ctx;
- return 1;
-}
-
-/** Return a newly allocated X509 name with commonName <b>cname</b>. */
-static X509_NAME *
-tor_x509_name_new(const char *cname)
-{
- int nid;
- X509_NAME *name;
- /* LCOV_EXCL_BR_START : these branches will only fail on OOM errors */
- if (!(name = X509_NAME_new()))
- return NULL;
- if ((nid = OBJ_txt2nid("commonName")) == NID_undef) goto error;
- if (!(X509_NAME_add_entry_by_NID(name, nid, MBSTRING_ASC,
- (unsigned char*)cname, -1, -1, 0)))
- goto error;
- /* LCOV_EXCL_BR_STOP */
- return name;
-
- /* LCOV_EXCL_START : these lines will only execute on out of memory errors*/
- error:
- X509_NAME_free(name);
- return NULL;
- /* LCOV_EXCL_STOP */
-}
-
-/** Generate and sign an X509 certificate with the public key <b>rsa</b>,
- * signed by the private key <b>rsa_sign</b>. The commonName of the
- * certificate will be <b>cname</b>; the commonName of the issuer will be
- * <b>cname_sign</b>. The cert will be valid for <b>cert_lifetime</b>
- * seconds, starting from some time in the past.
- *
- * Return a certificate on success, NULL on failure.
- */
-MOCK_IMPL(STATIC X509 *,
-tor_tls_create_certificate,(crypto_pk_t *rsa,
- crypto_pk_t *rsa_sign,
- const char *cname,
- const char *cname_sign,
- unsigned int cert_lifetime))
-{
- /* OpenSSL generates self-signed certificates with random 64-bit serial
- * numbers, so let's do that too. */
-#define SERIAL_NUMBER_SIZE 8
-
- time_t start_time, end_time;
- BIGNUM *serial_number = NULL;
- unsigned char serial_tmp[SERIAL_NUMBER_SIZE];
- EVP_PKEY *sign_pkey = NULL, *pkey=NULL;
- X509 *x509 = NULL;
- X509_NAME *name = NULL, *name_issuer=NULL;
-
- tor_tls_init();
-
- /* Make sure we're part-way through the certificate lifetime, rather
- * than having it start right now. Don't choose quite uniformly, since
- * then we might pick a time where we're about to expire. Lastly, be
- * sure to start on a day boundary. */
- time_t now = time(NULL);
- /* Our certificate lifetime will be cert_lifetime no matter what, but if we
- * start cert_lifetime in the past, we'll have 0 real lifetime. instead we
- * start up to (cert_lifetime - min_real_lifetime - start_granularity) in
- * the past. */
- const time_t min_real_lifetime = 24*3600;
- const time_t start_granularity = 24*3600;
- time_t earliest_start_time;
- /* Don't actually start in the future! */
- if (cert_lifetime <= min_real_lifetime + start_granularity) {
- earliest_start_time = now - 1;
- } else {
- earliest_start_time = now + min_real_lifetime + start_granularity
- - cert_lifetime;
- }
- start_time = crypto_rand_time_range(earliest_start_time, now);
- /* Round the start time back to the start of a day. */
- start_time -= start_time % start_granularity;
-
- end_time = start_time + cert_lifetime;
-
- tor_assert(rsa);
- tor_assert(cname);
- tor_assert(rsa_sign);
- tor_assert(cname_sign);
- if (!(sign_pkey = crypto_pk_get_evp_pkey_(rsa_sign,1)))
- goto error;
- if (!(pkey = crypto_pk_get_evp_pkey_(rsa,0)))
- goto error;
- if (!(x509 = X509_new()))
- goto error;
- if (!(X509_set_version(x509, 2)))
- goto error;
-
- { /* our serial number is 8 random bytes. */
- crypto_rand((char *)serial_tmp, sizeof(serial_tmp));
- if (!(serial_number = BN_bin2bn(serial_tmp, sizeof(serial_tmp), NULL)))
- goto error;
- if (!(BN_to_ASN1_INTEGER(serial_number, X509_get_serialNumber(x509))))
- goto error;
- }
-
- if (!(name = tor_x509_name_new(cname)))
- goto error;
- if (!(X509_set_subject_name(x509, name)))
- goto error;
- if (!(name_issuer = tor_x509_name_new(cname_sign)))
- goto error;
- if (!(X509_set_issuer_name(x509, name_issuer)))
- goto error;
-
- if (!X509_time_adj(X509_get_notBefore(x509),0,&start_time))
- goto error;
- if (!X509_time_adj(X509_get_notAfter(x509),0,&end_time))
- goto error;
- if (!X509_set_pubkey(x509, pkey))
- goto error;
-
- if (!X509_sign(x509, sign_pkey, EVP_sha256()))
- goto error;
-
- goto done;
- error:
- if (x509) {
- X509_free(x509);
- x509 = NULL;
- }
- done:
- tls_log_errors(NULL, LOG_WARN, LD_NET, "generating certificate");
- if (sign_pkey)
- EVP_PKEY_free(sign_pkey);
- if (pkey)
- EVP_PKEY_free(pkey);
- if (serial_number)
- BN_clear_free(serial_number);
- if (name)
- X509_NAME_free(name);
- if (name_issuer)
- X509_NAME_free(name_issuer);
- return x509;
-
-#undef SERIAL_NUMBER_SIZE
-}
-
-/** List of ciphers that servers should select from when the client might be
- * claiming extra unsupported ciphers in order to avoid fingerprinting. */
-static const char SERVER_CIPHER_LIST[] =
-#ifdef TLS1_3_TXT_AES_128_GCM_SHA256
- /* This one can never actually get selected, since if the client lists it,
- * we will assume that the client is honest, and not use this list.
- * Nonetheless we list it if it's available, so that the server doesn't
- * conclude that it has no valid ciphers if it's running with TLS1.3.
- */
- TLS1_3_TXT_AES_128_GCM_SHA256 ":"
-#endif
- TLS1_TXT_DHE_RSA_WITH_AES_256_SHA ":"
- TLS1_TXT_DHE_RSA_WITH_AES_128_SHA;
-
-/** List of ciphers that servers should select from when we actually have
- * our choice of what cipher to use. */
-static const char UNRESTRICTED_SERVER_CIPHER_LIST[] =
- /* Here are the TLS 1.3 ciphers we like, in the order we prefer. */
-#ifdef TLS1_3_TXT_AES_256_GCM_SHA384
- TLS1_3_TXT_AES_256_GCM_SHA384 ":"
-#endif
-#ifdef TLS1_3_TXT_CHACHA20_POLY1305_SHA256
- TLS1_3_TXT_CHACHA20_POLY1305_SHA256 ":"
-#endif
-#ifdef TLS1_3_TXT_AES_128_GCM_SHA256
- TLS1_3_TXT_AES_128_GCM_SHA256 ":"
-#endif
-#ifdef TLS1_3_TXT_AES_128_CCM_SHA256
- TLS1_3_TXT_AES_128_CCM_SHA256 ":"
-#endif
-
- /* This list is autogenerated with the gen_server_ciphers.py script;
- * don't hand-edit it. */
-#ifdef TLS1_TXT_ECDHE_RSA_WITH_AES_256_GCM_SHA384
- TLS1_TXT_ECDHE_RSA_WITH_AES_256_GCM_SHA384 ":"
-#endif
-#ifdef TLS1_TXT_ECDHE_RSA_WITH_AES_128_GCM_SHA256
- TLS1_TXT_ECDHE_RSA_WITH_AES_128_GCM_SHA256 ":"
-#endif
-#ifdef TLS1_TXT_ECDHE_RSA_WITH_AES_256_SHA384
- TLS1_TXT_ECDHE_RSA_WITH_AES_256_SHA384 ":"
-#endif
-#ifdef TLS1_TXT_ECDHE_RSA_WITH_AES_128_SHA256
- TLS1_TXT_ECDHE_RSA_WITH_AES_128_SHA256 ":"
-#endif
-#ifdef TLS1_TXT_ECDHE_RSA_WITH_AES_256_CBC_SHA
- TLS1_TXT_ECDHE_RSA_WITH_AES_256_CBC_SHA ":"
-#endif
-#ifdef TLS1_TXT_ECDHE_RSA_WITH_AES_128_CBC_SHA
- TLS1_TXT_ECDHE_RSA_WITH_AES_128_CBC_SHA ":"
-#endif
-#ifdef TLS1_TXT_DHE_RSA_WITH_AES_256_GCM_SHA384
- TLS1_TXT_DHE_RSA_WITH_AES_256_GCM_SHA384 ":"
-#endif
-#ifdef TLS1_TXT_DHE_RSA_WITH_AES_128_GCM_SHA256
- TLS1_TXT_DHE_RSA_WITH_AES_128_GCM_SHA256 ":"
-#endif
-#ifdef TLS1_TXT_DHE_RSA_WITH_AES_256_CCM
- TLS1_TXT_DHE_RSA_WITH_AES_256_CCM ":"
-#endif
-#ifdef TLS1_TXT_DHE_RSA_WITH_AES_128_CCM
- TLS1_TXT_DHE_RSA_WITH_AES_128_CCM ":"
-#endif
-#ifdef TLS1_TXT_DHE_RSA_WITH_AES_256_SHA256
- TLS1_TXT_DHE_RSA_WITH_AES_256_SHA256 ":"
-#endif
-#ifdef TLS1_TXT_DHE_RSA_WITH_AES_128_SHA256
- TLS1_TXT_DHE_RSA_WITH_AES_128_SHA256 ":"
-#endif
- /* Required */
- TLS1_TXT_DHE_RSA_WITH_AES_256_SHA ":"
- /* Required */
- TLS1_TXT_DHE_RSA_WITH_AES_128_SHA ":"
-#ifdef TLS1_TXT_ECDHE_RSA_WITH_CHACHA20_POLY1305
- TLS1_TXT_ECDHE_RSA_WITH_CHACHA20_POLY1305 ":"
-#endif
-#ifdef TLS1_TXT_DHE_RSA_WITH_CHACHA20_POLY1305
- TLS1_TXT_DHE_RSA_WITH_CHACHA20_POLY1305
-#endif
- ;
-
-/* Note: to set up your own private testing network with link crypto
- * disabled, set your Tors' cipher list to
- * (SSL3_TXT_RSA_NULL_SHA). If you do this, you won't be able to communicate
- * with any of the "real" Tors, though. */
-
-#define CIPHER(id, name) name ":"
-#define XCIPHER(id, name)
-/** List of ciphers that clients should advertise, omitting items that
- * our OpenSSL doesn't know about. */
-static const char CLIENT_CIPHER_LIST[] =
-#include "ciphers.inc"
- /* Tell it not to use SSLv2 ciphers, so that it can select an SSLv3 version
- * of any cipher we say. */
- "!SSLv2"
- ;
-#undef CIPHER
-#undef XCIPHER
-
-/** Free all storage held in <b>cert</b> */
-void
-tor_x509_cert_free_(tor_x509_cert_t *cert)
-{
- if (! cert)
- return;
- if (cert->cert)
- X509_free(cert->cert);
- tor_free(cert->encoded);
- memwipe(cert, 0x03, sizeof(*cert));
- /* LCOV_EXCL_BR_START since cert will never be NULL here */
- tor_free(cert);
- /* LCOV_EXCL_BR_STOP */
-}
-
-/**
- * Allocate a new tor_x509_cert_t to hold the certificate "x509_cert".
- *
- * Steals a reference to x509_cert.
- */
-MOCK_IMPL(STATIC tor_x509_cert_t *,
-tor_x509_cert_new,(X509 *x509_cert))
-{
- tor_x509_cert_t *cert;
- EVP_PKEY *pkey;
- RSA *rsa;
- int length;
- unsigned char *buf = NULL;
-
- if (!x509_cert)
- return NULL;
-
- length = i2d_X509(x509_cert, &buf);
- cert = tor_malloc_zero(sizeof(tor_x509_cert_t));
- if (length <= 0 || buf == NULL) {
- goto err;
- }
- cert->encoded_len = (size_t) length;
- cert->encoded = tor_malloc(length);
- memcpy(cert->encoded, buf, length);
- OPENSSL_free(buf);
-
- cert->cert = x509_cert;
-
- crypto_common_digests(&cert->cert_digests,
- (char*)cert->encoded, cert->encoded_len);
-
- if ((pkey = X509_get_pubkey(x509_cert)) &&
- (rsa = EVP_PKEY_get1_RSA(pkey))) {
- crypto_pk_t *pk = crypto_new_pk_from_rsa_(rsa);
- if (crypto_pk_get_common_digests(pk, &cert->pkey_digests) < 0) {
- crypto_pk_free(pk);
- EVP_PKEY_free(pkey);
- goto err;
- }
-
- cert->pkey_digests_set = 1;
- crypto_pk_free(pk);
- EVP_PKEY_free(pkey);
- }
-
- return cert;
- err:
- /* LCOV_EXCL_START for the same reason as the exclusion above */
- tor_free(cert);
- log_err(LD_CRYPTO, "Couldn't wrap encoded X509 certificate.");
- X509_free(x509_cert);
- return NULL;
- /* LCOV_EXCL_STOP */
-}
-
-/** Return a new copy of <b>cert</b>. */
-tor_x509_cert_t *
-tor_x509_cert_dup(const tor_x509_cert_t *cert)
-{
- tor_assert(cert);
- X509 *x509 = cert->cert;
- return tor_x509_cert_new(X509_dup(x509));
-}
-
-/** Read a DER-encoded X509 cert, of length exactly <b>certificate_len</b>,
- * from a <b>certificate</b>. Return a newly allocated tor_x509_cert_t on
- * success and NULL on failure. */
-tor_x509_cert_t *
-tor_x509_cert_decode(const uint8_t *certificate, size_t certificate_len)
-{
- X509 *x509;
- const unsigned char *cp = (const unsigned char *)certificate;
- tor_x509_cert_t *newcert;
- tor_assert(certificate);
- check_no_tls_errors();
-
- if (certificate_len > INT_MAX)
- goto err;
-
- x509 = d2i_X509(NULL, &cp, (int)certificate_len);
-
- if (!x509)
- goto err; /* Couldn't decode */
- if (cp - certificate != (int)certificate_len) {
- X509_free(x509);
- goto err; /* Didn't use all the bytes */
- }
- newcert = tor_x509_cert_new(x509);
- if (!newcert) {
- goto err;
- }
- if (newcert->encoded_len != certificate_len ||
- fast_memneq(newcert->encoded, certificate, certificate_len)) {
- /* Cert wasn't in DER */
- tor_x509_cert_free(newcert);
- goto err;
- }
- return newcert;
- err:
- tls_log_errors(NULL, LOG_INFO, LD_CRYPTO, "decoding a certificate");
- return NULL;
-}
-
-/** Set *<b>encoded_out</b> and *<b>size_out</b> to <b>cert</b>'s encoded DER
- * representation and length, respectively. */
-void
-tor_x509_cert_get_der(const tor_x509_cert_t *cert,
- const uint8_t **encoded_out, size_t *size_out)
-{
- tor_assert(cert);
- tor_assert(encoded_out);
- tor_assert(size_out);
- *encoded_out = cert->encoded;
- *size_out = cert->encoded_len;
-}
-
-/** Return a set of digests for the public key in <b>cert</b>, or NULL if this
- * cert's public key is not one we know how to take the digest of. */
-const common_digests_t *
-tor_x509_cert_get_id_digests(const tor_x509_cert_t *cert)
-{
- if (cert->pkey_digests_set)
- return &cert->pkey_digests;
- else
- return NULL;
-}
-
-/** Return a set of digests for the public key in <b>cert</b>. */
-const common_digests_t *
-tor_x509_cert_get_cert_digests(const tor_x509_cert_t *cert)
-{
- return &cert->cert_digests;
-}
-
-/** Remove a reference to <b>ctx</b>, and free it if it has no more
- * references. */
-static void
-tor_tls_context_decref(tor_tls_context_t *ctx)
-{
- tor_assert(ctx);
- if (--ctx->refcnt == 0) {
- SSL_CTX_free(ctx->ctx);
- tor_x509_cert_free(ctx->my_link_cert);
- tor_x509_cert_free(ctx->my_id_cert);
- tor_x509_cert_free(ctx->my_auth_cert);
- crypto_pk_free(ctx->link_key);
- crypto_pk_free(ctx->auth_key);
- /* LCOV_EXCL_BR_START since ctx will never be NULL here */
- tor_free(ctx);
- /* LCOV_EXCL_BR_STOP */
- }
-}
-
-/** Set *<b>link_cert_out</b> and *<b>id_cert_out</b> to the link certificate
- * and ID certificate that we're currently using for our V3 in-protocol
- * handshake's certificate chain. If <b>server</b> is true, provide the certs
- * that we use in server mode (auth, ID); otherwise, provide the certs that we
- * use in client mode. (link, ID) */
-int
-tor_tls_get_my_certs(int server,
- const tor_x509_cert_t **link_cert_out,
- const tor_x509_cert_t **id_cert_out)
-{
- tor_tls_context_t *ctx = server ? server_tls_context : client_tls_context;
- if (! ctx)
- return -1;
- if (link_cert_out)
- *link_cert_out = server ? ctx->my_link_cert : ctx->my_auth_cert;
- if (id_cert_out)
- *id_cert_out = ctx->my_id_cert;
- return 0;
-}
-
-/**
- * Return the authentication key that we use to authenticate ourselves as a
- * client in the V3 in-protocol handshake.
- */
-crypto_pk_t *
-tor_tls_get_my_client_auth_key(void)
-{
- if (! client_tls_context)
- return NULL;
- return client_tls_context->auth_key;
-}
-
-/**
- * Return a newly allocated copy of the public key that a certificate
- * certifies. Watch out! This returns NULL if the cert's key is not RSA.
- */
-crypto_pk_t *
-tor_tls_cert_get_key(tor_x509_cert_t *cert)
-{
- crypto_pk_t *result = NULL;
- EVP_PKEY *pkey = X509_get_pubkey(cert->cert);
- RSA *rsa;
- if (!pkey)
- return NULL;
- rsa = EVP_PKEY_get1_RSA(pkey);
- if (!rsa) {
- EVP_PKEY_free(pkey);
- return NULL;
- }
- result = crypto_new_pk_from_rsa_(rsa);
- EVP_PKEY_free(pkey);
- return result;
-}
-
-/** Return true iff the other side of <b>tls</b> has authenticated to us, and
- * the key certified in <b>cert</b> is the same as the key they used to do it.
- */
-MOCK_IMPL(int,
-tor_tls_cert_matches_key,(const tor_tls_t *tls, const tor_x509_cert_t *cert))
-{
- tor_x509_cert_t *peer = tor_tls_get_peer_cert((tor_tls_t *)tls);
- if (!peer)
- return 0;
-
- X509 *peercert = peer->cert;
- EVP_PKEY *link_key = NULL, *cert_key = NULL;
- int result;
-
- link_key = X509_get_pubkey(peercert);
- cert_key = X509_get_pubkey(cert->cert);
-
- result = link_key && cert_key && EVP_PKEY_cmp(cert_key, link_key) == 1;
-
- tor_x509_cert_free(peer);
- if (link_key)
- EVP_PKEY_free(link_key);
- if (cert_key)
- EVP_PKEY_free(cert_key);
-
- return result;
-}
-
-/** Check whether <b>cert</b> is well-formed, currently live, and correctly
- * signed by the public key in <b>signing_cert</b>. If <b>check_rsa_1024</b>,
- * make sure that it has an RSA key with 1024 bits; otherwise, just check that
- * the key is long enough. Return 1 if the cert is good, and 0 if it's bad or
- * we couldn't check it. */
-int
-tor_tls_cert_is_valid(int severity,
- const tor_x509_cert_t *cert,
- const tor_x509_cert_t *signing_cert,
- time_t now,
- int check_rsa_1024)
-{
- check_no_tls_errors();
- EVP_PKEY *cert_key;
- int r, key_ok = 0;
-
- if (!signing_cert || !cert)
- goto bad;
-
- EVP_PKEY *signing_key = X509_get_pubkey(signing_cert->cert);
- if (!signing_key)
- goto bad;
- r = X509_verify(cert->cert, signing_key);
- EVP_PKEY_free(signing_key);
- if (r <= 0)
- goto bad;
-
- /* okay, the signature checked out right. Now let's check the check the
- * lifetime. */
- if (check_cert_lifetime_internal(severity, cert->cert, now,
- 48*60*60, 30*24*60*60) < 0)
- goto bad;
-
- cert_key = X509_get_pubkey(cert->cert);
- if (check_rsa_1024 && cert_key) {
- RSA *rsa = EVP_PKEY_get1_RSA(cert_key);
-#ifdef OPENSSL_1_1_API
- if (rsa && RSA_bits(rsa) == 1024)
-#else
- if (rsa && BN_num_bits(rsa->n) == 1024)
-#endif
- key_ok = 1;
- if (rsa)
- RSA_free(rsa);
- } else if (cert_key) {
- int min_bits = 1024;
-#ifdef EVP_PKEY_EC
- if (EVP_PKEY_base_id(cert_key) == EVP_PKEY_EC)
- min_bits = 128;
-#endif
- if (EVP_PKEY_bits(cert_key) >= min_bits)
- key_ok = 1;
- }
- EVP_PKEY_free(cert_key);
- if (!key_ok)
- goto bad;
-
- /* XXXX compare DNs or anything? */
-
- return 1;
- bad:
- tls_log_errors(NULL, LOG_INFO, LD_CRYPTO, "checking a certificate");
- return 0;
-}
-
-/** Increase the reference count of <b>ctx</b>. */
-static void
-tor_tls_context_incref(tor_tls_context_t *ctx)
-{
- ++ctx->refcnt;
-}
-
-/** Create new global client and server TLS contexts.
- *
- * If <b>server_identity</b> is NULL, this will not generate a server
- * TLS context. If TOR_TLS_CTX_IS_PUBLIC_SERVER is set in <b>flags</b>, use
- * the same TLS context for incoming and outgoing connections, and
- * ignore <b>client_identity</b>. If one of TOR_TLS_CTX_USE_ECDHE_P{224,256}
- * is set in <b>flags</b>, use that ECDHE group if possible; otherwise use
- * the default ECDHE group. */
-int
-tor_tls_context_init(unsigned flags,
- crypto_pk_t *client_identity,
- crypto_pk_t *server_identity,
- unsigned int key_lifetime)
-{
- int rv1 = 0;
- int rv2 = 0;
- const int is_public_server = flags & TOR_TLS_CTX_IS_PUBLIC_SERVER;
- check_no_tls_errors();
-
- if (is_public_server) {
- tor_tls_context_t *new_ctx;
- tor_tls_context_t *old_ctx;
-
- tor_assert(server_identity != NULL);
-
- rv1 = tor_tls_context_init_one(&server_tls_context,
- server_identity,
- key_lifetime, flags, 0);
-
- if (rv1 >= 0) {
- new_ctx = server_tls_context;
- tor_tls_context_incref(new_ctx);
- old_ctx = client_tls_context;
- client_tls_context = new_ctx;
-
- if (old_ctx != NULL) {
- tor_tls_context_decref(old_ctx);
- }
- }
- } else {
- if (server_identity != NULL) {
- rv1 = tor_tls_context_init_one(&server_tls_context,
- server_identity,
- key_lifetime,
- flags,
- 0);
- } else {
- tor_tls_context_t *old_ctx = server_tls_context;
- server_tls_context = NULL;
-
- if (old_ctx != NULL) {
- tor_tls_context_decref(old_ctx);
- }
- }
-
- rv2 = tor_tls_context_init_one(&client_tls_context,
- client_identity,
- key_lifetime,
- flags,
- 1);
- }
-
- tls_log_errors(NULL, LOG_WARN, LD_CRYPTO, "constructing a TLS context");
- return MIN(rv1, rv2);
-}
-
-/** Create a new global TLS context.
- *
- * You can call this function multiple times. Each time you call it,
- * it generates new certificates; all new connections will use
- * the new SSL context.
- */
-STATIC int
-tor_tls_context_init_one(tor_tls_context_t **ppcontext,
- crypto_pk_t *identity,
- unsigned int key_lifetime,
- unsigned int flags,
- int is_client)
-{
- tor_tls_context_t *new_ctx = tor_tls_context_new(identity,
- key_lifetime,
- flags,
- is_client);
- tor_tls_context_t *old_ctx = *ppcontext;
-
- if (new_ctx != NULL) {
- *ppcontext = new_ctx;
-
- /* Free the old context if one existed. */
- if (old_ctx != NULL) {
- /* This is safe even if there are open connections: we reference-
- * count tor_tls_context_t objects. */
- tor_tls_context_decref(old_ctx);
- }
- }
-
- return ((new_ctx != NULL) ? 0 : -1);
-}
-
-/** The group we should use for ecdhe when none was selected. */
-#define NID_tor_default_ecdhe_group NID_X9_62_prime256v1
-
-#define RSA_LINK_KEY_BITS 2048
-
-/** Create a new TLS context for use with Tor TLS handshakes.
- * <b>identity</b> should be set to the identity key used to sign the
- * certificate.
- */
-STATIC tor_tls_context_t *
-tor_tls_context_new(crypto_pk_t *identity, unsigned int key_lifetime,
- unsigned flags, int is_client)
-{
- crypto_pk_t *rsa = NULL, *rsa_auth = NULL;
- EVP_PKEY *pkey = NULL;
- tor_tls_context_t *result = NULL;
- X509 *cert = NULL, *idcert = NULL, *authcert = NULL;
- char *nickname = NULL, *nn2 = NULL;
-
- tor_tls_init();
- nickname = crypto_random_hostname(8, 20, "www.", ".net");
-#ifdef DISABLE_V3_LINKPROTO_SERVERSIDE
- nn2 = crypto_random_hostname(8, 20, "www.", ".net");
-#else
- nn2 = crypto_random_hostname(8, 20, "www.", ".com");
-#endif
-
- /* Generate short-term RSA key for use with TLS. */
- if (!(rsa = crypto_pk_new()))
- goto error;
- if (crypto_pk_generate_key_with_bits(rsa, RSA_LINK_KEY_BITS)<0)
- goto error;
- if (!is_client) {
- /* Generate short-term RSA key for use in the in-protocol ("v3")
- * authentication handshake. */
- if (!(rsa_auth = crypto_pk_new()))
- goto error;
- if (crypto_pk_generate_key(rsa_auth)<0)
- goto error;
- /* Create a link certificate signed by identity key. */
- cert = tor_tls_create_certificate(rsa, identity, nickname, nn2,
- key_lifetime);
- /* Create self-signed certificate for identity key. */
- idcert = tor_tls_create_certificate(identity, identity, nn2, nn2,
- IDENTITY_CERT_LIFETIME);
- /* Create an authentication certificate signed by identity key. */
- authcert = tor_tls_create_certificate(rsa_auth, identity, nickname, nn2,
- key_lifetime);
- if (!cert || !idcert || !authcert) {
- log_warn(LD_CRYPTO, "Error creating certificate");
- goto error;
- }
- }
-
- result = tor_malloc_zero(sizeof(tor_tls_context_t));
- result->refcnt = 1;
- if (!is_client) {
- result->my_link_cert = tor_x509_cert_new(X509_dup(cert));
- result->my_id_cert = tor_x509_cert_new(X509_dup(idcert));
- result->my_auth_cert = tor_x509_cert_new(X509_dup(authcert));
- if (!result->my_link_cert || !result->my_id_cert || !result->my_auth_cert)
- goto error;
- result->link_key = crypto_pk_dup_key(rsa);
- result->auth_key = crypto_pk_dup_key(rsa_auth);
- }
-
-#if 0
- /* Tell OpenSSL to only use TLS1. This may have subtly different results
- * from SSLv23_method() with SSLv2 and SSLv3 disabled, so we need to do some
- * investigation before we consider adjusting it. It should be compatible
- * with existing Tors. */
- if (!(result->ctx = SSL_CTX_new(TLSv1_method())))
- goto error;
-#endif /* 0 */
-
- /* Tell OpenSSL to use TLS 1.0 or later but not SSL2 or SSL3. */
-#ifdef HAVE_TLS_METHOD
- if (!(result->ctx = SSL_CTX_new(TLS_method())))
- goto error;
-#else
- if (!(result->ctx = SSL_CTX_new(SSLv23_method())))
- goto error;
-#endif /* defined(HAVE_TLS_METHOD) */
-
-#ifdef HAVE_SSL_CTX_SET_SECURITY_LEVEL
- /* Level 1 re-enables RSA1024 and DH1024 for compatibility with old tors */
- SSL_CTX_set_security_level(result->ctx, 1);
-#endif
-
- SSL_CTX_set_options(result->ctx, SSL_OP_NO_SSLv2);
- SSL_CTX_set_options(result->ctx, SSL_OP_NO_SSLv3);
-
- /* Prefer the server's ordering of ciphers: the client's ordering has
- * historically been chosen for fingerprinting resistance. */
- SSL_CTX_set_options(result->ctx, SSL_OP_CIPHER_SERVER_PREFERENCE);
-
- /* Disable TLS tickets if they're supported. We never want to use them;
- * using them can make our perfect forward secrecy a little worse, *and*
- * create an opportunity to fingerprint us (since it's unusual to use them
- * with TLS sessions turned off).
- *
- * In 0.2.4, clients advertise support for them though, to avoid a TLS
- * distinguishability vector. This can give us worse PFS, though, if we
- * get a server that doesn't set SSL_OP_NO_TICKET. With luck, there will
- * be few such servers by the time 0.2.4 is more stable.
- */
-#ifdef SSL_OP_NO_TICKET
- if (! is_client) {
- SSL_CTX_set_options(result->ctx, SSL_OP_NO_TICKET);
- }
-#endif
-
- SSL_CTX_set_options(result->ctx, SSL_OP_SINGLE_DH_USE);
- SSL_CTX_set_options(result->ctx, SSL_OP_SINGLE_ECDH_USE);
-
-#ifdef SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION
- SSL_CTX_set_options(result->ctx,
- SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION);
-#endif
- /* Yes, we know what we are doing here. No, we do not treat a renegotiation
- * as authenticating any earlier-received data.
- */
- {
- SSL_CTX_set_options(result->ctx,
- SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION);
- }
-
- /* Don't actually allow compression; it uses RAM and time, it makes TLS
- * vulnerable to CRIME-style attacks, and most of the data we transmit over
- * TLS is encrypted (and therefore uncompressible) anyway. */
-#ifdef SSL_OP_NO_COMPRESSION
- SSL_CTX_set_options(result->ctx, SSL_OP_NO_COMPRESSION);
-#endif
-#if OPENSSL_VERSION_NUMBER < OPENSSL_V_SERIES(1,1,0)
-#ifndef OPENSSL_NO_COMP
- if (result->ctx->comp_methods)
- result->ctx->comp_methods = NULL;
-#endif
-#endif /* OPENSSL_VERSION_NUMBER < OPENSSL_V_SERIES(1,1,0) */
-
-#ifdef SSL_MODE_RELEASE_BUFFERS
- SSL_CTX_set_mode(result->ctx, SSL_MODE_RELEASE_BUFFERS);
-#endif
- if (! is_client) {
- if (cert && !SSL_CTX_use_certificate(result->ctx,cert))
- goto error;
- X509_free(cert); /* We just added a reference to cert. */
- cert=NULL;
- if (idcert) {
- X509_STORE *s = SSL_CTX_get_cert_store(result->ctx);
- tor_assert(s);
- X509_STORE_add_cert(s, idcert);
- X509_free(idcert); /* The context now owns the reference to idcert */
- idcert = NULL;
- }
- }
- 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)))
- goto error;
- if (!SSL_CTX_use_PrivateKey(result->ctx, pkey))
- goto error;
- EVP_PKEY_free(pkey);
- pkey = NULL;
- if (!SSL_CTX_check_private_key(result->ctx))
- goto error;
- }
- {
- 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));
- crypto_dh_free(dh);
- }
- if (! is_client) {
- int nid;
- EC_KEY *ec_key;
- if (flags & TOR_TLS_CTX_USE_ECDHE_P224)
- nid = NID_secp224r1;
- else if (flags & TOR_TLS_CTX_USE_ECDHE_P256)
- nid = NID_X9_62_prime256v1;
- else
- nid = NID_tor_default_ecdhe_group;
- /* Use P-256 for ECDHE. */
- ec_key = EC_KEY_new_by_curve_name(nid);
- if (ec_key != NULL) /*XXXX Handle errors? */
- SSL_CTX_set_tmp_ecdh(result->ctx, ec_key);
- EC_KEY_free(ec_key);
- }
- SSL_CTX_set_verify(result->ctx, SSL_VERIFY_PEER,
- always_accept_verify_cb);
- /* let us realloc bufs that we're writing from */
- SSL_CTX_set_mode(result->ctx, SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER);
-
- if (rsa)
- crypto_pk_free(rsa);
- if (rsa_auth)
- crypto_pk_free(rsa_auth);
- X509_free(authcert);
- tor_free(nickname);
- tor_free(nn2);
- return result;
-
- error:
- tls_log_errors(NULL, LOG_WARN, LD_NET, "creating TLS context");
- tor_free(nickname);
- tor_free(nn2);
- if (pkey)
- EVP_PKEY_free(pkey);
- if (rsa)
- crypto_pk_free(rsa);
- if (rsa_auth)
- crypto_pk_free(rsa_auth);
- if (result)
- tor_tls_context_decref(result);
- if (cert)
- X509_free(cert);
- if (idcert)
- X509_free(idcert);
- if (authcert)
- X509_free(authcert);
- return NULL;
-}
-
-/** Invoked when a TLS state changes: log the change at severity 'debug' */
-STATIC void
-tor_tls_debug_state_callback(const SSL *ssl, int type, int val)
-{
- /* LCOV_EXCL_START since this depends on whether debug is captured or not */
- log_debug(LD_HANDSHAKE, "SSL %p is now in state %s [type=%d,val=%d].",
- ssl, SSL_state_string_long(ssl), type, val);
- /* LCOV_EXCL_STOP */
-}
-
-/* Return the name of the negotiated ciphersuite in use on <b>tls</b> */
-const char *
-tor_tls_get_ciphersuite_name(tor_tls_t *tls)
-{
- return SSL_get_cipher(tls->ssl);
-}
-
-/* Here's the old V2 cipher list we sent from 0.2.1.1-alpha up to
- * 0.2.3.17-beta. If a client is using this list, we can't believe the ciphers
- * that it claims to support. We'll prune this list to remove the ciphers
- * *we* don't recognize. */
-STATIC uint16_t v2_cipher_list[] = {
- 0xc00a, /* TLS1_TXT_ECDHE_ECDSA_WITH_AES_256_CBC_SHA */
- 0xc014, /* TLS1_TXT_ECDHE_RSA_WITH_AES_256_CBC_SHA */
- 0x0039, /* TLS1_TXT_DHE_RSA_WITH_AES_256_SHA */
- 0x0038, /* TLS1_TXT_DHE_DSS_WITH_AES_256_SHA */
- 0xc00f, /* TLS1_TXT_ECDH_RSA_WITH_AES_256_CBC_SHA */
- 0xc005, /* TLS1_TXT_ECDH_ECDSA_WITH_AES_256_CBC_SHA */
- 0x0035, /* TLS1_TXT_RSA_WITH_AES_256_SHA */
- 0xc007, /* TLS1_TXT_ECDHE_ECDSA_WITH_RC4_128_SHA */
- 0xc009, /* TLS1_TXT_ECDHE_ECDSA_WITH_AES_128_CBC_SHA */
- 0xc011, /* TLS1_TXT_ECDHE_RSA_WITH_RC4_128_SHA */
- 0xc013, /* TLS1_TXT_ECDHE_RSA_WITH_AES_128_CBC_SHA */
- 0x0033, /* TLS1_TXT_DHE_RSA_WITH_AES_128_SHA */
- 0x0032, /* TLS1_TXT_DHE_DSS_WITH_AES_128_SHA */
- 0xc00c, /* TLS1_TXT_ECDH_RSA_WITH_RC4_128_SHA */
- 0xc00e, /* TLS1_TXT_ECDH_RSA_WITH_AES_128_CBC_SHA */
- 0xc002, /* TLS1_TXT_ECDH_ECDSA_WITH_RC4_128_SHA */
- 0xc004, /* TLS1_TXT_ECDH_ECDSA_WITH_AES_128_CBC_SHA */
- 0x0004, /* SSL3_TXT_RSA_RC4_128_MD5 */
- 0x0005, /* SSL3_TXT_RSA_RC4_128_SHA */
- 0x002f, /* TLS1_TXT_RSA_WITH_AES_128_SHA */
- 0xc008, /* TLS1_TXT_ECDHE_ECDSA_WITH_DES_192_CBC3_SHA */
- 0xc012, /* TLS1_TXT_ECDHE_RSA_WITH_DES_192_CBC3_SHA */
- 0x0016, /* SSL3_TXT_EDH_RSA_DES_192_CBC3_SHA */
- 0x0013, /* SSL3_TXT_EDH_DSS_DES_192_CBC3_SHA */
- 0xc00d, /* TLS1_TXT_ECDH_RSA_WITH_DES_192_CBC3_SHA */
- 0xc003, /* TLS1_TXT_ECDH_ECDSA_WITH_DES_192_CBC3_SHA */
- 0xfeff, /* SSL3_TXT_RSA_FIPS_WITH_3DES_EDE_CBC_SHA */
- 0x000a, /* SSL3_TXT_RSA_DES_192_CBC3_SHA */
- 0
-};
-/** Have we removed the unrecognized ciphers from v2_cipher_list yet? */
-static int v2_cipher_list_pruned = 0;
-
-/** Return 0 if <b>m</b> does not support the cipher with ID <b>cipher</b>;
- * return 1 if it does support it, or if we have no way to tell. */
-STATIC int
-find_cipher_by_id(const SSL *ssl, const SSL_METHOD *m, uint16_t cipher)
-{
- const SSL_CIPHER *c;
-#ifdef HAVE_SSL_CIPHER_FIND
- (void) m;
- {
- unsigned char cipherid[3];
- tor_assert(ssl);
- set_uint16(cipherid, htons(cipher));
- cipherid[2] = 0; /* If ssl23_get_cipher_by_char finds no cipher starting
- * with a two-byte 'cipherid', it may look for a v2
- * cipher with the appropriate 3 bytes. */
- c = SSL_CIPHER_find((SSL*)ssl, cipherid);
- if (c)
- tor_assert((SSL_CIPHER_get_id(c) & 0xffff) == cipher);
- return c != NULL;
- }
-#else /* !(defined(HAVE_SSL_CIPHER_FIND)) */
-
-# if defined(HAVE_STRUCT_SSL_METHOD_ST_GET_CIPHER_BY_CHAR)
- if (m && m->get_cipher_by_char) {
- unsigned char cipherid[3];
- set_uint16(cipherid, htons(cipher));
- cipherid[2] = 0; /* If ssl23_get_cipher_by_char finds no cipher starting
- * with a two-byte 'cipherid', it may look for a v2
- * cipher with the appropriate 3 bytes. */
- c = m->get_cipher_by_char(cipherid);
- if (c)
- tor_assert((c->id & 0xffff) == cipher);
- return c != NULL;
- }
-#endif /* defined(HAVE_STRUCT_SSL_METHOD_ST_GET_CIPHER_BY_CHAR) */
-# ifndef OPENSSL_1_1_API
- if (m && m->get_cipher && m->num_ciphers) {
- /* It would seem that some of the "let's-clean-up-openssl" forks have
- * removed the get_cipher_by_char function. Okay, so now you get a
- * quadratic search.
- */
- int i;
- for (i = 0; i < m->num_ciphers(); ++i) {
- c = m->get_cipher(i);
- if (c && (c->id & 0xffff) == cipher) {
- return 1;
- }
- }
- return 0;
- }
-#endif /* !defined(OPENSSL_1_1_API) */
- (void) ssl;
- (void) m;
- (void) cipher;
- return 1; /* No way to search */
-#endif /* defined(HAVE_SSL_CIPHER_FIND) */
-}
-
-/** Remove from v2_cipher_list every cipher that we don't support, so that
- * comparing v2_cipher_list to a client's cipher list will give a sensible
- * result. */
-static void
-prune_v2_cipher_list(const SSL *ssl)
-{
- uint16_t *inp, *outp;
-#ifdef HAVE_TLS_METHOD
- const SSL_METHOD *m = TLS_method();
-#else
- const SSL_METHOD *m = SSLv23_method();
-#endif
-
- inp = outp = v2_cipher_list;
- while (*inp) {
- if (find_cipher_by_id(ssl, m, *inp)) {
- *outp++ = *inp++;
- } else {
- inp++;
- }
- }
- *outp = 0;
-
- v2_cipher_list_pruned = 1;
-}
-
-/** Examine the client cipher list in <b>ssl</b>, and determine what kind of
- * client it is. Return one of CIPHERS_ERR, CIPHERS_V1, CIPHERS_V2,
- * CIPHERS_UNRESTRICTED.
- **/
-STATIC int
-tor_tls_classify_client_ciphers(const SSL *ssl,
- STACK_OF(SSL_CIPHER) *peer_ciphers)
-{
- int i, res;
- tor_tls_t *tor_tls;
- if (PREDICT_UNLIKELY(!v2_cipher_list_pruned))
- prune_v2_cipher_list(ssl);
-
- tor_tls = tor_tls_get_by_ssl(ssl);
- if (tor_tls && tor_tls->client_cipher_list_type)
- return tor_tls->client_cipher_list_type;
-
- /* If we reached this point, we just got a client hello. See if there is
- * a cipher list. */
- if (!peer_ciphers) {
- log_info(LD_NET, "No ciphers on session");
- res = CIPHERS_ERR;
- goto done;
- }
- /* Now we need to see if there are any ciphers whose presence means we're
- * dealing with an updated Tor. */
- for (i = 0; i < sk_SSL_CIPHER_num(peer_ciphers); ++i) {
- const SSL_CIPHER *cipher = sk_SSL_CIPHER_value(peer_ciphers, i);
- const char *ciphername = SSL_CIPHER_get_name(cipher);
- if (strcmp(ciphername, TLS1_TXT_DHE_RSA_WITH_AES_128_SHA) &&
- strcmp(ciphername, TLS1_TXT_DHE_RSA_WITH_AES_256_SHA) &&
- strcmp(ciphername, SSL3_TXT_EDH_RSA_DES_192_CBC3_SHA) &&
- strcmp(ciphername, "(NONE)")) {
- log_debug(LD_NET, "Got a non-version-1 cipher called '%s'", ciphername);
- // return 1;
- goto v2_or_higher;
- }
- }
- res = CIPHERS_V1;
- goto done;
- v2_or_higher:
- {
- const uint16_t *v2_cipher = v2_cipher_list;
- for (i = 0; i < sk_SSL_CIPHER_num(peer_ciphers); ++i) {
- const SSL_CIPHER *cipher = sk_SSL_CIPHER_value(peer_ciphers, i);
- uint16_t id = SSL_CIPHER_get_id(cipher) & 0xffff;
- if (id == 0x00ff) /* extended renegotiation indicator. */
- continue;
- if (!id || id != *v2_cipher) {
- res = CIPHERS_UNRESTRICTED;
- goto dump_ciphers;
- }
- ++v2_cipher;
- }
- if (*v2_cipher != 0) {
- res = CIPHERS_UNRESTRICTED;
- goto dump_ciphers;
- }
- res = CIPHERS_V2;
- }
-
- dump_ciphers:
- {
- smartlist_t *elts = smartlist_new();
- char *s;
- for (i = 0; i < sk_SSL_CIPHER_num(peer_ciphers); ++i) {
- const SSL_CIPHER *cipher = sk_SSL_CIPHER_value(peer_ciphers, i);
- const char *ciphername = SSL_CIPHER_get_name(cipher);
- smartlist_add(elts, (char*)ciphername);
- }
- s = smartlist_join_strings(elts, ":", 0, NULL);
- log_debug(LD_NET, "Got a %s V2/V3 cipher list from %s. It is: '%s'",
- (res == CIPHERS_V2) ? "fictitious" : "real", ADDR(tor_tls), s);
- tor_free(s);
- smartlist_free(elts);
- }
- done:
- if (tor_tls)
- return tor_tls->client_cipher_list_type = res;
-
- return res;
-}
-
-/** Return true iff the cipher list suggested by the client for <b>ssl</b> is
- * a list that indicates that the client knows how to do the v2 TLS connection
- * handshake. */
-STATIC int
-tor_tls_client_is_using_v2_ciphers(const SSL *ssl)
-{
- STACK_OF(SSL_CIPHER) *ciphers;
-#ifdef HAVE_SSL_GET_CLIENT_CIPHERS
- ciphers = SSL_get_client_ciphers(ssl);
-#else
- SSL_SESSION *session;
- if (!(session = SSL_get_session((SSL *)ssl))) {
- log_info(LD_NET, "No session on TLS?");
- return CIPHERS_ERR;
- }
- ciphers = session->ciphers;
-#endif /* defined(HAVE_SSL_GET_CLIENT_CIPHERS) */
-
- return tor_tls_classify_client_ciphers(ssl, ciphers) >= CIPHERS_V2;
-}
-
-/** Invoked when we're accepting a connection on <b>ssl</b>, and the connection
- * changes state. We use this:
- * <ul><li>To alter the state of the handshake partway through, so we
- * do not send or request extra certificates in v2 handshakes.</li>
- * <li>To detect renegotiation</li></ul>
- */
-STATIC void
-tor_tls_server_info_callback(const SSL *ssl, int type, int val)
-{
- tor_tls_t *tls;
- (void) val;
-
- IF_BUG_ONCE(ssl == NULL) {
- return; // LCOV_EXCL_LINE
- }
-
- tor_tls_debug_state_callback(ssl, type, val);
-
- if (type != SSL_CB_ACCEPT_LOOP)
- return;
-
- OSSL_HANDSHAKE_STATE ssl_state = SSL_get_state(ssl);
- if (! STATE_IS_SW_SERVER_HELLO(ssl_state))
- return;
- tls = tor_tls_get_by_ssl(ssl);
- if (tls) {
- /* Check whether we're watching for renegotiates. If so, this is one! */
- if (tls->negotiated_callback)
- tls->got_renegotiate = 1;
- if (tls->server_handshake_count < 127) /*avoid any overflow possibility*/
- ++tls->server_handshake_count;
- } else {
- log_warn(LD_BUG, "Couldn't look up the tls for an SSL*. How odd!");
- return;
- }
-
- /* Now check the cipher list. */
- if (tor_tls_client_is_using_v2_ciphers(ssl)) {
- if (tls->wasV2Handshake)
- return; /* We already turned this stuff off for the first handshake;
- * This is a renegotiation. */
-
- /* Yes, we're casting away the const from ssl. This is very naughty of us.
- * Let's hope openssl doesn't notice! */
-
- /* Set SSL_MODE_NO_AUTO_CHAIN to keep from sending back any extra certs. */
- SSL_set_mode((SSL*) ssl, SSL_MODE_NO_AUTO_CHAIN);
- /* Don't send a hello request. */
- SSL_set_verify((SSL*) ssl, SSL_VERIFY_NONE, NULL);
-
- if (tls) {
- tls->wasV2Handshake = 1;
- } else {
- /* LCOV_EXCL_START this line is not reachable */
- log_warn(LD_BUG, "Couldn't look up the tls for an SSL*. How odd!");
- /* LCOV_EXCL_STOP */
- }
- }
-}
-
-/** Callback to get invoked on a server after we've read the list of ciphers
- * the client supports, but before we pick our own ciphersuite.
- *
- * We can't abuse an info_cb for this, since by the time one of the
- * client_hello info_cbs is called, we've already picked which ciphersuite to
- * use.
- *
- * Technically, this function is an abuse of this callback, since the point of
- * a session_secret_cb is to try to set up and/or verify a shared-secret for
- * authentication on the fly. But as long as we return 0, we won't actually be
- * setting up a shared secret, and all will be fine.
- */
-STATIC int
-tor_tls_session_secret_cb(SSL *ssl, void *secret, int *secret_len,
- STACK_OF(SSL_CIPHER) *peer_ciphers,
- CONST_IF_OPENSSL_1_1_API SSL_CIPHER **cipher,
- void *arg)
-{
- (void) secret;
- (void) secret_len;
- (void) peer_ciphers;
- (void) cipher;
- (void) arg;
-
- if (tor_tls_classify_client_ciphers(ssl, peer_ciphers) ==
- CIPHERS_UNRESTRICTED) {
- SSL_set_cipher_list(ssl, UNRESTRICTED_SERVER_CIPHER_LIST);
- }
-
- SSL_set_session_secret_cb(ssl, NULL, NULL);
-
- return 0;
-}
-static void
-tor_tls_setup_session_secret_cb(tor_tls_t *tls)
-{
- SSL_set_session_secret_cb(tls->ssl, tor_tls_session_secret_cb, NULL);
-}
-
-/** Create a new TLS object from a file descriptor, and a flag to
- * determine whether it is functioning as a server.
- */
-tor_tls_t *
-tor_tls_new(int sock, int isServer)
-{
- BIO *bio = NULL;
- tor_tls_t *result = tor_malloc_zero(sizeof(tor_tls_t));
- tor_tls_context_t *context = isServer ? server_tls_context :
- client_tls_context;
- result->magic = TOR_TLS_MAGIC;
-
- check_no_tls_errors();
- tor_assert(context); /* make sure somebody made it first */
- if (!(result->ssl = SSL_new(context->ctx))) {
- tls_log_errors(NULL, LOG_WARN, LD_NET, "creating SSL object");
- tor_free(result);
- goto err;
- }
-
-#ifdef SSL_set_tlsext_host_name
- /* Browsers use the TLS hostname extension, so we should too. */
- if (!isServer) {
- char *fake_hostname = crypto_random_hostname(4,25, "www.",".com");
- SSL_set_tlsext_host_name(result->ssl, fake_hostname);
- tor_free(fake_hostname);
- }
-#endif /* defined(SSL_set_tlsext_host_name) */
-
- if (!SSL_set_cipher_list(result->ssl,
- isServer ? SERVER_CIPHER_LIST : CLIENT_CIPHER_LIST)) {
- tls_log_errors(NULL, LOG_WARN, LD_NET, "setting ciphers");
-#ifdef SSL_set_tlsext_host_name
- SSL_set_tlsext_host_name(result->ssl, NULL);
-#endif
- SSL_free(result->ssl);
- tor_free(result);
- goto err;
- }
- result->socket = sock;
- bio = BIO_new_socket(sock, BIO_NOCLOSE);
- if (! bio) {
- tls_log_errors(NULL, LOG_WARN, LD_NET, "opening BIO");
-#ifdef SSL_set_tlsext_host_name
- SSL_set_tlsext_host_name(result->ssl, NULL);
-#endif
- SSL_free(result->ssl);
- tor_free(result);
- goto err;
- }
- {
- int set_worked =
- SSL_set_ex_data(result->ssl, tor_tls_object_ex_data_index, result);
- if (!set_worked) {
- log_warn(LD_BUG,
- "Couldn't set the tls for an SSL*; connection will fail");
- }
- }
- SSL_set_bio(result->ssl, bio, bio);
- tor_tls_context_incref(context);
- result->context = context;
- result->state = TOR_TLS_ST_HANDSHAKE;
- result->isServer = isServer;
- result->wantwrite_n = 0;
- result->last_write_count = (unsigned long) BIO_number_written(bio);
- result->last_read_count = (unsigned long) BIO_number_read(bio);
- if (result->last_write_count || result->last_read_count) {
- log_warn(LD_NET, "Newly created BIO has read count %lu, write count %lu",
- result->last_read_count, result->last_write_count);
- }
- if (isServer) {
- SSL_set_info_callback(result->ssl, tor_tls_server_info_callback);
- } else {
- SSL_set_info_callback(result->ssl, tor_tls_debug_state_callback);
- }
-
- if (isServer)
- tor_tls_setup_session_secret_cb(result);
-
- goto done;
- err:
- result = NULL;
- done:
- /* Not expected to get called. */
- tls_log_errors(NULL, LOG_WARN, LD_NET, "creating tor_tls_t object");
- return result;
-}
-
-/** Make future log messages about <b>tls</b> display the address
- * <b>address</b>.
- */
-void
-tor_tls_set_logged_address(tor_tls_t *tls, const char *address)
-{
- tor_assert(tls);
- tor_free(tls->address);
- tls->address = tor_strdup(address);
-}
-
-/** Set <b>cb</b> to be called with argument <b>arg</b> whenever <b>tls</b>
- * next gets a client-side renegotiate in the middle of a read. Do not
- * invoke this function until <em>after</em> initial handshaking is done!
- */
-void
-tor_tls_set_renegotiate_callback(tor_tls_t *tls,
- void (*cb)(tor_tls_t *, void *arg),
- void *arg)
-{
- tls->negotiated_callback = cb;
- tls->callback_arg = arg;
- tls->got_renegotiate = 0;
- if (cb) {
- SSL_set_info_callback(tls->ssl, tor_tls_server_info_callback);
- } else {
- SSL_set_info_callback(tls->ssl, tor_tls_debug_state_callback);
- }
-}
-
-/** If this version of openssl requires it, turn on renegotiation on
- * <b>tls</b>.
- */
-void
-tor_tls_unblock_renegotiation(tor_tls_t *tls)
-{
- /* Yes, we know what we are doing here. No, we do not treat a renegotiation
- * as authenticating any earlier-received data. */
- SSL_set_options(tls->ssl,
- SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION);
-}
-
-/** If this version of openssl supports it, turn off renegotiation on
- * <b>tls</b>. (Our protocol never requires this for security, but it's nice
- * to use belt-and-suspenders here.)
- */
-void
-tor_tls_block_renegotiation(tor_tls_t *tls)
-{
-#ifdef SUPPORT_UNSAFE_RENEGOTIATION_FLAG
- tls->ssl->s3->flags &= ~SSL3_FLAGS_ALLOW_UNSAFE_LEGACY_RENEGOTIATION;
-#else
- (void) tls;
-#endif
-}
-
-/** Assert that the flags that allow legacy renegotiation are still set */
-void
-tor_tls_assert_renegotiation_unblocked(tor_tls_t *tls)
-{
-#if defined(SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION) && \
- SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION != 0
- long options = SSL_get_options(tls->ssl);
- tor_assert(0 != (options & SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION));
-#else
- (void) tls;
-#endif /* defined(SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION) && ... */
-}
-
-/** Return whether this tls initiated the connect (client) or
- * received it (server). */
-int
-tor_tls_is_server(tor_tls_t *tls)
-{
- tor_assert(tls);
- return tls->isServer;
-}
-
-/** Release resources associated with a TLS object. Does not close the
- * underlying file descriptor.
- */
-void
-tor_tls_free_(tor_tls_t *tls)
-{
- if (!tls)
- return;
- tor_assert(tls->ssl);
- {
- size_t r,w;
- tor_tls_get_n_raw_bytes(tls,&r,&w); /* ensure written_by_tls is updated */
- }
-#ifdef SSL_set_tlsext_host_name
- SSL_set_tlsext_host_name(tls->ssl, NULL);
-#endif
- SSL_free(tls->ssl);
- tls->ssl = NULL;
- tls->negotiated_callback = NULL;
- if (tls->context)
- tor_tls_context_decref(tls->context);
- tor_free(tls->address);
- tls->magic = 0x99999999;
- tor_free(tls);
-}
-
-/** Underlying function for TLS reading. Reads up to <b>len</b>
- * characters from <b>tls</b> into <b>cp</b>. On success, returns the
- * number of characters read. On failure, returns TOR_TLS_ERROR,
- * TOR_TLS_CLOSE, TOR_TLS_WANTREAD, or TOR_TLS_WANTWRITE.
- */
-MOCK_IMPL(int,
-tor_tls_read,(tor_tls_t *tls, char *cp, size_t len))
-{
- int r, err;
- tor_assert(tls);
- tor_assert(tls->ssl);
- tor_assert(tls->state == TOR_TLS_ST_OPEN);
- tor_assert(len<INT_MAX);
- r = SSL_read(tls->ssl, cp, (int)len);
- if (r > 0) {
- if (tls->got_renegotiate) {
- /* Renegotiation happened! */
- log_info(LD_NET, "Got a TLS renegotiation from %s", ADDR(tls));
- if (tls->negotiated_callback)
- tls->negotiated_callback(tls, tls->callback_arg);
- tls->got_renegotiate = 0;
- }
- 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) {
- log_debug(LD_NET,"read returned r=%d; TLS is closed",r);
- tls->state = TOR_TLS_ST_CLOSED;
- return TOR_TLS_CLOSE;
- } else {
- tor_assert(err != TOR_TLS_DONE);
- log_debug(LD_NET,"read returned r=%d, err=%d",r,err);
- return err;
- }
-}
-
-/** Total number of bytes that we've used TLS to send. Used to track TLS
- * overhead. */
-STATIC uint64_t total_bytes_written_over_tls = 0;
-/** Total number of bytes that TLS has put on the network for us. Used to
- * track TLS overhead. */
-STATIC uint64_t total_bytes_written_by_tls = 0;
-
-/** Underlying function for TLS writing. Write up to <b>n</b>
- * characters from <b>cp</b> onto <b>tls</b>. On success, returns the
- * number of characters written. On failure, returns TOR_TLS_ERROR,
- * TOR_TLS_WANTREAD, or TOR_TLS_WANTWRITE.
- */
-int
-tor_tls_write(tor_tls_t *tls, const char *cp, size_t n)
-{
- int r, err;
- tor_assert(tls);
- tor_assert(tls->ssl);
- tor_assert(tls->state == TOR_TLS_ST_OPEN);
- tor_assert(n < INT_MAX);
- if (n == 0)
- return 0;
- if (tls->wantwrite_n) {
- /* if WANTWRITE last time, we must use the _same_ n as before */
- tor_assert(n >= tls->wantwrite_n);
- log_debug(LD_NET,"resuming pending-write, (%d to flush, reusing %d)",
- (int)n, (int)tls->wantwrite_n);
- n = tls->wantwrite_n;
- tls->wantwrite_n = 0;
- }
- r = SSL_write(tls->ssl, cp, (int)n);
- err = tor_tls_get_error(tls, r, 0, "writing", LOG_INFO, LD_NET);
- if (err == TOR_TLS_DONE) {
- total_bytes_written_over_tls += r;
- return r;
- }
- if (err == TOR_TLS_WANTWRITE || err == TOR_TLS_WANTREAD) {
- tls->wantwrite_n = n;
- }
- return err;
-}
-
-/** Perform initial handshake on <b>tls</b>. When finished, returns
- * TOR_TLS_DONE. On failure, returns TOR_TLS_ERROR, TOR_TLS_WANTREAD,
- * or TOR_TLS_WANTWRITE.
- */
-int
-tor_tls_handshake(tor_tls_t *tls)
-{
- int r;
- tor_assert(tls);
- tor_assert(tls->ssl);
- tor_assert(tls->state == TOR_TLS_ST_HANDSHAKE);
-
- check_no_tls_errors();
-
- OSSL_HANDSHAKE_STATE oldstate = SSL_get_state(tls->ssl);
-
- if (tls->isServer) {
- log_debug(LD_HANDSHAKE, "About to call SSL_accept on %p (%s)", tls,
- SSL_state_string_long(tls->ssl));
- r = SSL_accept(tls->ssl);
- } else {
- log_debug(LD_HANDSHAKE, "About to call SSL_connect on %p (%s)", tls,
- SSL_state_string_long(tls->ssl));
- r = SSL_connect(tls->ssl);
- }
-
- OSSL_HANDSHAKE_STATE newstate = SSL_get_state(tls->ssl);
-
- if (oldstate != newstate)
- log_debug(LD_HANDSHAKE, "After call, %p was in state %s",
- tls, SSL_state_string_long(tls->ssl));
- /* We need to call this here and not earlier, since OpenSSL has a penchant
- * for clearing its flags when you say accept or connect. */
- tor_tls_unblock_renegotiation(tls);
- r = tor_tls_get_error(tls,r,0, "handshaking", LOG_INFO, LD_HANDSHAKE);
- if (ERR_peek_error() != 0) {
- tls_log_errors(tls, tls->isServer ? LOG_INFO : LOG_WARN, LD_HANDSHAKE,
- "handshaking");
- return TOR_TLS_ERROR_MISC;
- }
- if (r == TOR_TLS_DONE) {
- tls->state = TOR_TLS_ST_OPEN;
- return tor_tls_finish_handshake(tls);
- }
- return r;
-}
-
-/** Perform the final part of the initial TLS handshake on <b>tls</b>. This
- * should be called for the first handshake only: it determines whether the v1
- * or the v2 handshake was used, and adjusts things for the renegotiation
- * handshake as appropriate.
- *
- * tor_tls_handshake() calls this on its own; you only need to call this if
- * bufferevent is doing the handshake for you.
- */
-int
-tor_tls_finish_handshake(tor_tls_t *tls)
-{
- int r = TOR_TLS_DONE;
- check_no_tls_errors();
- if (tls->isServer) {
- SSL_set_info_callback(tls->ssl, NULL);
- SSL_set_verify(tls->ssl, SSL_VERIFY_PEER, always_accept_verify_cb);
- SSL_clear_mode(tls->ssl, SSL_MODE_NO_AUTO_CHAIN);
- if (tor_tls_client_is_using_v2_ciphers(tls->ssl)) {
- /* This check is redundant, but back when we did it in the callback,
- * we might have not been able to look up the tor_tls_t if the code
- * was buggy. Fixing that. */
- if (!tls->wasV2Handshake) {
- log_warn(LD_BUG, "For some reason, wasV2Handshake didn't"
- " get set. Fixing that.");
- }
- tls->wasV2Handshake = 1;
- log_debug(LD_HANDSHAKE, "Completed V2 TLS handshake with client; waiting"
- " for renegotiation.");
- } else {
- tls->wasV2Handshake = 0;
- }
- } else {
- /* Client-side */
- tls->wasV2Handshake = 1;
- /* XXXX this can move, probably? -NM */
- if (SSL_set_cipher_list(tls->ssl, SERVER_CIPHER_LIST) == 0) {
- tls_log_errors(NULL, LOG_WARN, LD_HANDSHAKE, "re-setting ciphers");
- r = TOR_TLS_ERROR_MISC;
- }
- }
- tls_log_errors(NULL, LOG_WARN, LD_NET, "finishing the handshake");
- return r;
-}
-
-/** Shut down an open tls connection <b>tls</b>. When finished, returns
- * TOR_TLS_DONE. On failure, returns TOR_TLS_ERROR, TOR_TLS_WANTREAD,
- * or TOR_TLS_WANTWRITE.
- */
-int
-tor_tls_shutdown(tor_tls_t *tls)
-{
- int r, err;
- char buf[128];
- tor_assert(tls);
- tor_assert(tls->ssl);
- check_no_tls_errors();
-
- while (1) {
- if (tls->state == TOR_TLS_ST_SENTCLOSE) {
- /* If we've already called shutdown once to send a close message,
- * we read until the other side has closed too.
- */
- do {
- r = SSL_read(tls->ssl, buf, 128);
- } 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_) {
- tls->state = TOR_TLS_ST_GOTCLOSE;
- /* fall through... */
- } else {
- return err;
- }
- }
-
- r = SSL_shutdown(tls->ssl);
- if (r == 1) {
- /* If shutdown returns 1, the connection is entirely closed. */
- tls->state = TOR_TLS_ST_CLOSED;
- return TOR_TLS_DONE;
- }
- err = tor_tls_get_error(tls, r, CATCH_SYSCALL|CATCH_ZERO, "shutting down",
- LOG_INFO, LD_NET);
- 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_) {
- /* 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
- * and try to read.
- */
- if (tls->state == TOR_TLS_ST_GOTCLOSE ||
- tls->state == TOR_TLS_ST_SENTCLOSE) {
- log_warn(LD_NET,
- "TLS returned \"half-closed\" value while already half-closed");
- return TOR_TLS_ERROR_MISC;
- }
- tls->state = TOR_TLS_ST_SENTCLOSE;
- /* fall through ... */
- } else {
- return err;
- }
- } /* end loop */
-}
-
-/** Return true iff this TLS connection is authenticated.
- */
-int
-tor_tls_peer_has_cert(tor_tls_t *tls)
-{
- X509 *cert;
- cert = SSL_get_peer_certificate(tls->ssl);
- tls_log_errors(tls, LOG_WARN, LD_HANDSHAKE, "getting peer certificate");
- if (!cert)
- return 0;
- X509_free(cert);
- return 1;
-}
-
-/** Return a newly allocated copy of the peer certificate, or NULL if there
- * isn't one. */
-MOCK_IMPL(tor_x509_cert_t *,
-tor_tls_get_peer_cert,(tor_tls_t *tls))
-{
- X509 *cert;
- cert = SSL_get_peer_certificate(tls->ssl);
- tls_log_errors(tls, LOG_WARN, LD_HANDSHAKE, "getting peer certificate");
- if (!cert)
- return NULL;
- return tor_x509_cert_new(cert);
-}
-
-/** Return a newly allocated copy of the cerficate we used on the connection,
- * or NULL if somehow we didn't use one. */
-MOCK_IMPL(tor_x509_cert_t *,
-tor_tls_get_own_cert,(tor_tls_t *tls))
-{
- X509 *cert = SSL_get_certificate(tls->ssl);
- tls_log_errors(tls, LOG_WARN, LD_HANDSHAKE,
- "getting own-connection certificate");
- if (!cert)
- return NULL;
- /* Fun inconsistency: SSL_get_peer_certificate increments the reference
- * count, but SSL_get_certificate does not. */
- X509 *duplicate = X509_dup(cert);
- if (BUG(duplicate == NULL))
- return NULL;
- return tor_x509_cert_new(duplicate);
-}
-
-/** Warn that a certificate lifetime extends through a certain range. */
-static void
-log_cert_lifetime(int severity, const X509 *cert, const char *problem,
- time_t now)
-{
- BIO *bio = NULL;
- BUF_MEM *buf;
- char *s1=NULL, *s2=NULL;
- char mytime[33];
- struct tm tm;
- size_t n;
-
- if (problem)
- tor_log(severity, LD_GENERAL,
- "Certificate %s. Either their clock is set wrong, or your clock "
- "is wrong.",
- problem);
-
- if (!(bio = BIO_new(BIO_s_mem()))) {
- log_warn(LD_GENERAL, "Couldn't allocate BIO!"); goto end;
- }
- if (!(ASN1_TIME_print(bio, X509_get_notBefore_const(cert)))) {
- tls_log_errors(NULL, LOG_WARN, LD_NET, "printing certificate lifetime");
- goto end;
- }
- BIO_get_mem_ptr(bio, &buf);
- s1 = tor_strndup(buf->data, buf->length);
-
- (void)BIO_reset(bio);
- if (!(ASN1_TIME_print(bio, X509_get_notAfter_const(cert)))) {
- tls_log_errors(NULL, LOG_WARN, LD_NET, "printing certificate lifetime");
- goto end;
- }
- BIO_get_mem_ptr(bio, &buf);
- s2 = tor_strndup(buf->data, buf->length);
-
- n = strftime(mytime, 32, "%b %d %H:%M:%S %Y UTC", tor_gmtime_r(&now, &tm));
- if (n > 0) {
- tor_log(severity, LD_GENERAL,
- "(certificate lifetime runs from %s through %s. Your time is %s.)",
- s1,s2,mytime);
- } else {
- tor_log(severity, LD_GENERAL,
- "(certificate lifetime runs from %s through %s. "
- "Couldn't get your time.)",
- s1, s2);
- }
-
- end:
- /* Not expected to get invoked */
- tls_log_errors(NULL, LOG_WARN, LD_NET, "getting certificate lifetime");
- if (bio)
- BIO_free(bio);
- tor_free(s1);
- tor_free(s2);
-}
-
-/** Helper function: try to extract a link certificate and an identity
- * certificate from <b>tls</b>, and store them in *<b>cert_out</b> and
- * *<b>id_cert_out</b> respectively. Log all messages at level
- * <b>severity</b>.
- *
- * Note that a reference is added to cert_out, so it needs to be
- * freed. id_cert_out doesn't. */
-MOCK_IMPL(STATIC void,
-try_to_extract_certs_from_tls,(int severity, tor_tls_t *tls,
- X509 **cert_out, X509 **id_cert_out))
-{
- X509 *cert = NULL, *id_cert = NULL;
- STACK_OF(X509) *chain = NULL;
- int num_in_chain, i;
- *cert_out = *id_cert_out = NULL;
- if (!(cert = SSL_get_peer_certificate(tls->ssl)))
- return;
- *cert_out = cert;
- if (!(chain = SSL_get_peer_cert_chain(tls->ssl)))
- return;
- num_in_chain = sk_X509_num(chain);
- /* 1 means we're receiving (server-side), and it's just the id_cert.
- * 2 means we're connecting (client-side), and it's both the link
- * cert and the id_cert.
- */
- if (num_in_chain < 1) {
- log_fn(severity,LD_PROTOCOL,
- "Unexpected number of certificates in chain (%d)",
- num_in_chain);
- return;
- }
- for (i=0; i<num_in_chain; ++i) {
- id_cert = sk_X509_value(chain, i);
- if (X509_cmp(id_cert, cert) != 0)
- break;
- }
- *id_cert_out = id_cert;
-}
-
-/** If the provided tls connection is authenticated and has a
- * certificate chain that is currently valid and signed, then set
- * *<b>identity_key</b> to the identity certificate's key and return
- * 0. Else, return -1 and log complaints with log-level <b>severity</b>.
- */
-int
-tor_tls_verify(int severity, tor_tls_t *tls, crypto_pk_t **identity_key)
-{
- X509 *cert = NULL, *id_cert = NULL;
- EVP_PKEY *id_pkey = NULL;
- RSA *rsa;
- int r = -1;
-
- check_no_tls_errors();
- *identity_key = NULL;
-
- try_to_extract_certs_from_tls(severity, tls, &cert, &id_cert);
- if (!cert)
- goto done;
- if (!id_cert) {
- log_fn(severity,LD_PROTOCOL,"No distinct identity certificate found");
- goto done;
- }
- tls_log_errors(tls, severity, LD_HANDSHAKE, "before verifying certificate");
-
- if (!(id_pkey = X509_get_pubkey(id_cert)) ||
- X509_verify(cert, id_pkey) <= 0) {
- log_fn(severity,LD_PROTOCOL,"X509_verify on cert and pkey returned <= 0");
- tls_log_errors(tls, severity, LD_HANDSHAKE, "verifying certificate");
- goto done;
- }
-
- rsa = EVP_PKEY_get1_RSA(id_pkey);
- if (!rsa)
- goto done;
- *identity_key = crypto_new_pk_from_rsa_(rsa);
-
- r = 0;
-
- done:
- if (cert)
- X509_free(cert);
- if (id_pkey)
- EVP_PKEY_free(id_pkey);
-
- /* This should never get invoked, but let's make sure in case OpenSSL
- * acts unexpectedly. */
- tls_log_errors(tls, LOG_WARN, LD_HANDSHAKE, "finishing tor_tls_verify");
-
- return r;
-}
-
-/** Check whether the certificate set on the connection <b>tls</b> is expired
- * give or take <b>past_tolerance</b> seconds, or not-yet-valid give or take
- * <b>future_tolerance</b> seconds. Return 0 for valid, -1 for failure.
- *
- * NOTE: you should call tor_tls_verify before tor_tls_check_lifetime.
- */
-int
-tor_tls_check_lifetime(int severity, tor_tls_t *tls,
- time_t now,
- int past_tolerance, int future_tolerance)
-{
- X509 *cert;
- int r = -1;
-
- if (!(cert = SSL_get_peer_certificate(tls->ssl)))
- goto done;
-
- if (check_cert_lifetime_internal(severity, cert, now,
- past_tolerance, future_tolerance) < 0)
- goto done;
-
- r = 0;
- done:
- if (cert)
- X509_free(cert);
- /* Not expected to get invoked */
- tls_log_errors(tls, LOG_WARN, LD_NET, "checking certificate lifetime");
-
- return r;
-}
-
-/** Helper: check whether <b>cert</b> is expired give or take
- * <b>past_tolerance</b> seconds, or not-yet-valid give or take
- * <b>future_tolerance</b> seconds. (Relative to the current time
- * <b>now</b>.) If it is live, return 0. If it is not live, log a message
- * and return -1. */
-static int
-check_cert_lifetime_internal(int severity, const X509 *cert,
- time_t now,
- int past_tolerance, int future_tolerance)
-{
- time_t t;
-
- t = now + future_tolerance;
- if (X509_cmp_time(X509_get_notBefore_const(cert), &t) > 0) {
- log_cert_lifetime(severity, cert, "not yet valid", now);
- return -1;
- }
- t = now - past_tolerance;
- if (X509_cmp_time(X509_get_notAfter_const(cert), &t) < 0) {
- log_cert_lifetime(severity, cert, "already expired", now);
- return -1;
- }
-
- return 0;
-}
-
-#ifdef TOR_UNIT_TESTS
-/* Testing only: return a new x509 cert with the same contents as <b>inp</b>,
- but with the expiration time <b>new_expiration_time</b>, signed with
- <b>signing_key</b>. */
-STATIC tor_x509_cert_t *
-tor_x509_cert_replace_expiration(const tor_x509_cert_t *inp,
- time_t new_expiration_time,
- crypto_pk_t *signing_key)
-{
- X509 *newc = X509_dup(inp->cert);
- X509_time_adj(X509_get_notAfter(newc), 0, &new_expiration_time);
- EVP_PKEY *pk = crypto_pk_get_evp_pkey_(signing_key, 1);
- tor_assert(X509_sign(newc, pk, EVP_sha256()));
- EVP_PKEY_free(pk);
- return tor_x509_cert_new(newc);
-}
-#endif /* defined(TOR_UNIT_TESTS) */
-
-/** Return the number of bytes available for reading from <b>tls</b>.
- */
-int
-tor_tls_get_pending_bytes(tor_tls_t *tls)
-{
- tor_assert(tls);
- return SSL_pending(tls->ssl);
-}
-
-/** If <b>tls</b> requires that the next write be of a particular size,
- * return that size. Otherwise, return 0. */
-size_t
-tor_tls_get_forced_write_size(tor_tls_t *tls)
-{
- return tls->wantwrite_n;
-}
-
-/** Sets n_read and n_written to the number of bytes read and written,
- * respectively, on the raw socket used by <b>tls</b> since the last time this
- * function was called on <b>tls</b>. */
-void
-tor_tls_get_n_raw_bytes(tor_tls_t *tls, size_t *n_read, size_t *n_written)
-{
- BIO *wbio, *tmpbio;
- unsigned long r, w;
- r = (unsigned long) BIO_number_read(SSL_get_rbio(tls->ssl));
- /* We want the number of bytes actually for real written. Unfortunately,
- * sometimes OpenSSL replaces the wbio on tls->ssl with a buffering bio,
- * which makes the answer turn out wrong. Let's cope with that. Note
- * that this approach will fail if we ever replace tls->ssl's BIOs with
- * buffering bios for reasons of our own. As an alternative, we could
- * save the original BIO for tls->ssl in the tor_tls_t structure, but
- * that would be tempting fate. */
- wbio = SSL_get_wbio(tls->ssl);
-#if OPENSSL_VERSION_NUMBER >= OPENSSL_VER(1,1,0,0,5)
- /* BIO structure is opaque as of OpenSSL 1.1.0-pre5-dev. Again, not
- * supposed to use this form of the version macro, but the OpenSSL developers
- * introduced major API changes in the pre-release stage.
- */
- if (BIO_method_type(wbio) == BIO_TYPE_BUFFER &&
- (tmpbio = BIO_next(wbio)) != NULL)
- wbio = tmpbio;
-#else /* !(OPENSSL_VERSION_NUMBER >= OPENSSL_VER(1,1,0,0,5)) */
- if (wbio->method == BIO_f_buffer() && (tmpbio = BIO_next(wbio)) != NULL)
- wbio = tmpbio;
-#endif /* OPENSSL_VERSION_NUMBER >= OPENSSL_VER(1,1,0,0,5) */
- w = (unsigned long) BIO_number_written(wbio);
-
- /* We are ok with letting these unsigned ints go "negative" here:
- * If we wrapped around, this should still give us the right answer, unless
- * we wrapped around by more than ULONG_MAX since the last time we called
- * this function.
- */
- *n_read = (size_t)(r - tls->last_read_count);
- *n_written = (size_t)(w - tls->last_write_count);
- if (*n_read > INT_MAX || *n_written > INT_MAX) {
- log_warn(LD_BUG, "Preposterously large value in tor_tls_get_n_raw_bytes. "
- "r=%lu, last_read=%lu, w=%lu, last_written=%lu",
- r, tls->last_read_count, w, tls->last_write_count);
- }
- total_bytes_written_by_tls += *n_written;
- tls->last_read_count = r;
- tls->last_write_count = w;
-}
-
-/** Return a ratio of the bytes that TLS has sent to the bytes that we've told
- * it to send. Used to track whether our TLS records are getting too tiny. */
-MOCK_IMPL(double,
-tls_get_write_overhead_ratio,(void))
-{
- if (total_bytes_written_over_tls == 0)
- return 1.0;
-
- return U64_TO_DBL(total_bytes_written_by_tls) /
- U64_TO_DBL(total_bytes_written_over_tls);
-}
-
-/** 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)
-{
- if (ERR_peek_error() == 0)
- return;
- log_warn(LD_CRYPTO, "Unhandled OpenSSL errors found at %s:%d: ",
- tor_fix_source_file(fname), line);
- tls_log_errors(NULL, LOG_WARN, LD_NET, NULL);
-}
-
-/** Return true iff the initial TLS connection at <b>tls</b> did not use a v2
- * TLS handshake. Output is undefined if the handshake isn't finished. */
-int
-tor_tls_used_v1_handshake(tor_tls_t *tls)
-{
- return ! tls->wasV2Handshake;
-}
-
-/** Return the number of server handshakes that we've noticed doing on
- * <b>tls</b>. */
-int
-tor_tls_get_num_server_handshakes(tor_tls_t *tls)
-{
- return tls->server_handshake_count;
-}
-
-/** Return true iff the server TLS connection <b>tls</b> got the renegotiation
- * request it was waiting for. */
-int
-tor_tls_server_got_renegotiate(tor_tls_t *tls)
-{
- return tls->got_renegotiate;
-}
-
-#ifndef HAVE_SSL_GET_CLIENT_RANDOM
-static size_t
-SSL_get_client_random(SSL *s, uint8_t *out, size_t len)
-{
- if (len == 0)
- return SSL3_RANDOM_SIZE;
- tor_assert(len == SSL3_RANDOM_SIZE);
- tor_assert(s->s3);
- memcpy(out, s->s3->client_random, len);
- return len;
-}
-#endif /* !defined(HAVE_SSL_GET_CLIENT_RANDOM) */
-
-#ifndef HAVE_SSL_GET_SERVER_RANDOM
-static size_t
-SSL_get_server_random(SSL *s, uint8_t *out, size_t len)
-{
- if (len == 0)
- return SSL3_RANDOM_SIZE;
- tor_assert(len == SSL3_RANDOM_SIZE);
- tor_assert(s->s3);
- memcpy(out, s->s3->server_random, len);
- return len;
-}
-#endif /* !defined(HAVE_SSL_GET_SERVER_RANDOM) */
-
-#ifndef HAVE_SSL_SESSION_GET_MASTER_KEY
-STATIC size_t
-SSL_SESSION_get_master_key(SSL_SESSION *s, uint8_t *out, size_t len)
-{
- tor_assert(s);
- if (len == 0)
- return s->master_key_length;
- tor_assert(len == (size_t)s->master_key_length);
- tor_assert(out);
- memcpy(out, s->master_key, len);
- return len;
-}
-#endif /* !defined(HAVE_SSL_SESSION_GET_MASTER_KEY) */
-
-/** Set the DIGEST256_LEN buffer at <b>secrets_out</b> to the value used in
- * the v3 handshake to prove that the client knows the TLS secrets for the
- * connection <b>tls</b>. Return 0 on success, -1 on failure.
- */
-MOCK_IMPL(int,
-tor_tls_get_tlssecrets,(tor_tls_t *tls, uint8_t *secrets_out))
-{
-#define TLSSECRET_MAGIC "Tor V3 handshake TLS cross-certification"
- uint8_t buf[128];
- size_t len;
- tor_assert(tls);
-
- SSL *const ssl = tls->ssl;
- SSL_SESSION *const session = SSL_get_session(ssl);
-
- tor_assert(ssl);
- tor_assert(session);
-
- const size_t server_random_len = SSL_get_server_random(ssl, NULL, 0);
- const size_t client_random_len = SSL_get_client_random(ssl, NULL, 0);
- const size_t master_key_len = SSL_SESSION_get_master_key(session, NULL, 0);
-
- tor_assert(server_random_len);
- tor_assert(client_random_len);
- tor_assert(master_key_len);
-
- len = client_random_len + server_random_len + strlen(TLSSECRET_MAGIC) + 1;
- tor_assert(len <= sizeof(buf));
-
- {
- size_t r = SSL_get_client_random(ssl, buf, client_random_len);
- tor_assert(r == client_random_len);
- }
-
- {
- size_t r = SSL_get_server_random(ssl,
- buf+client_random_len,
- server_random_len);
- tor_assert(r == server_random_len);
- }
-
- uint8_t *master_key = tor_malloc_zero(master_key_len);
- {
- size_t r = SSL_SESSION_get_master_key(session, master_key, master_key_len);
- tor_assert(r == master_key_len);
- }
-
- uint8_t *nextbuf = buf + client_random_len + server_random_len;
- memcpy(nextbuf, TLSSECRET_MAGIC, strlen(TLSSECRET_MAGIC) + 1);
-
- /*
- The value is an HMAC, using the TLS master key as the HMAC key, of
- client_random | server_random | TLSSECRET_MAGIC
- */
- crypto_hmac_sha256((char*)secrets_out,
- (char*)master_key,
- master_key_len,
- (char*)buf, len);
- memwipe(buf, 0, sizeof(buf));
- memwipe(master_key, 0, master_key_len);
- tor_free(master_key);
-
- return 0;
-}
-
-/** Using the RFC5705 key material exporting construction, and the
- * provided <b>context</b> (<b>context_len</b> bytes long) and
- * <b>label</b> (a NUL-terminated string), compute a 32-byte secret in
- * <b>secrets_out</b> that only the parties to this TLS session can
- * compute. Return 0 on success and -1 on failure.
- */
-MOCK_IMPL(int,
-tor_tls_export_key_material,(tor_tls_t *tls, uint8_t *secrets_out,
- const uint8_t *context,
- size_t context_len,
- const char *label))
-{
- tor_assert(tls);
- tor_assert(tls->ssl);
-
- int r = SSL_export_keying_material(tls->ssl,
- secrets_out, DIGEST256_LEN,
- label, strlen(label),
- context, context_len, 1);
- return (r == 1) ? 0 : -1;
-}
-
-/** Examine the amount of memory used and available for buffers in <b>tls</b>.
- * Set *<b>rbuf_capacity</b> to the amount of storage allocated for the read
- * buffer and *<b>rbuf_bytes</b> to the amount actually used.
- * Set *<b>wbuf_capacity</b> to the amount of storage allocated for the write
- * buffer and *<b>wbuf_bytes</b> to the amount actually used.
- *
- * Return 0 on success, -1 on failure.*/
-int
-tor_tls_get_buffer_sizes(tor_tls_t *tls,
- size_t *rbuf_capacity, size_t *rbuf_bytes,
- size_t *wbuf_capacity, size_t *wbuf_bytes)
-{
-#if OPENSSL_VERSION_NUMBER >= OPENSSL_V_SERIES(1,1,0)
- (void)tls;
- (void)rbuf_capacity;
- (void)rbuf_bytes;
- (void)wbuf_capacity;
- (void)wbuf_bytes;
-
- return -1;
-#else /* !(OPENSSL_VERSION_NUMBER >= OPENSSL_V_SERIES(1,1,0)) */
- if (tls->ssl->s3->rbuf.buf)
- *rbuf_capacity = tls->ssl->s3->rbuf.len;
- else
- *rbuf_capacity = 0;
- if (tls->ssl->s3->wbuf.buf)
- *wbuf_capacity = tls->ssl->s3->wbuf.len;
- else
- *wbuf_capacity = 0;
- *rbuf_bytes = tls->ssl->s3->rbuf.left;
- *wbuf_bytes = tls->ssl->s3->wbuf.left;
- return 0;
-#endif /* OPENSSL_VERSION_NUMBER >= OPENSSL_V_SERIES(1,1,0) */
-}
-
-/** Check whether the ECC group requested is supported by the current OpenSSL
- * library instance. Return 1 if the group is supported, and 0 if not.
- */
-int
-evaluate_ecgroup_for_tls(const char *ecgroup)
-{
- EC_KEY *ec_key;
- int nid;
- int ret;
-
- if (!ecgroup)
- nid = NID_tor_default_ecdhe_group;
- else if (!strcasecmp(ecgroup, "P256"))
- nid = NID_X9_62_prime256v1;
- else if (!strcasecmp(ecgroup, "P224"))
- nid = NID_secp224r1;
- else
- return 0;
-
- ec_key = EC_KEY_new_by_curve_name(nid);
- ret = (ec_key != NULL);
- EC_KEY_free(ec_key);
-
- return ret;
-}
diff --git a/src/common/tortls.h b/src/common/tortls.h
deleted file mode 100644
index 7c867bfff2..0000000000
--- a/src/common/tortls.h
+++ /dev/null
@@ -1,295 +0,0 @@
-/* Copyright (c) 2003, Roger Dingledine
- * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2017, The Tor Project, Inc. */
-/* See LICENSE for licensing information */
-
-#ifndef TOR_TORTLS_H
-#define TOR_TORTLS_H
-
-/**
- * \file tortls.h
- * \brief Headers for tortls.c
- **/
-
-#include "crypto_rsa.h"
-#include "compat_openssl.h"
-#include "compat.h"
-#include "testsupport.h"
-
-/* Opaque structure to hold a TLS connection. */
-typedef struct tor_tls_t tor_tls_t;
-
-/* Opaque structure to hold an X509 certificate. */
-typedef struct tor_x509_cert_t tor_x509_cert_t;
-
-/* Possible return values for most tor_tls_* functions. */
-#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
-#define TOR_TLS_ERROR_CONNREFUSED -7
-#define TOR_TLS_ERROR_CONNRESET -6
-#define TOR_TLS_ERROR_NO_ROUTE -5
-#define TOR_TLS_ERROR_TIMEOUT -4
-#define TOR_TLS_CLOSE -3
-#define TOR_TLS_WANTREAD -2
-#define TOR_TLS_WANTWRITE -1
-#define TOR_TLS_DONE 0
-
-/** Collection of case statements for all TLS errors that are not due to
- * underlying IO failure. */
-#define CASE_TOR_TLS_ERROR_ANY_NONIO \
- case TOR_TLS_ERROR_MISC: \
- case TOR_TLS_ERROR_CONNREFUSED: \
- case TOR_TLS_ERROR_CONNRESET: \
- case TOR_TLS_ERROR_NO_ROUTE: \
- case TOR_TLS_ERROR_TIMEOUT
-
-/** Use this macro in a switch statement to catch _any_ TLS error. That way,
- * if more errors are added, your switches will still work. */
-#define CASE_TOR_TLS_ERROR_ANY \
- CASE_TOR_TLS_ERROR_ANY_NONIO: \
- case TOR_TLS_ERROR_IO
-
-#define TOR_TLS_IS_ERROR(rv) ((rv) < TOR_TLS_CLOSE)
-
-#ifdef TORTLS_PRIVATE
-#define TOR_TLS_MAGIC 0x71571571
-
-typedef enum {
- TOR_TLS_ST_HANDSHAKE, TOR_TLS_ST_OPEN, TOR_TLS_ST_GOTCLOSE,
- TOR_TLS_ST_SENTCLOSE, TOR_TLS_ST_CLOSED, TOR_TLS_ST_RENEGOTIATE,
- TOR_TLS_ST_BUFFEREVENT
-} tor_tls_state_t;
-#define tor_tls_state_bitfield_t ENUM_BF(tor_tls_state_t)
-
-struct x509_st;
-struct ssl_st;
-struct ssl_ctx_st;
-struct ssl_session_st;
-
-/** Holds a SSL_CTX object and related state used to configure TLS
- * connections.
- */
-typedef struct tor_tls_context_t {
- int refcnt;
- struct ssl_ctx_st *ctx;
- tor_x509_cert_t *my_link_cert;
- tor_x509_cert_t *my_id_cert;
- tor_x509_cert_t *my_auth_cert;
- crypto_pk_t *link_key;
- crypto_pk_t *auth_key;
-} tor_tls_context_t;
-
-/** Structure that we use for a single certificate. */
-struct tor_x509_cert_t {
- struct x509_st *cert;
- uint8_t *encoded;
- size_t encoded_len;
- unsigned pkey_digests_set : 1;
- common_digests_t cert_digests;
- common_digests_t pkey_digests;
-};
-
-/** Holds a SSL object and its associated data. Members are only
- * accessed from within tortls.c.
- */
-struct tor_tls_t {
- uint32_t magic;
- tor_tls_context_t *context; /** A link to the context object for this tls. */
- struct ssl_st *ssl; /**< An OpenSSL SSL object. */
- int socket; /**< The underlying file descriptor for this TLS connection. */
- char *address; /**< An address to log when describing this connection. */
- tor_tls_state_bitfield_t state : 3; /**< The current SSL state,
- * depending on which operations
- * have completed successfully. */
- unsigned int isServer:1; /**< True iff this is a server-side connection */
- unsigned int wasV2Handshake:1; /**< True iff the original handshake for
- * this connection used the updated version
- * of the connection protocol (client sends
- * different cipher list, server sends only
- * one certificate). */
- /** True iff we should call negotiated_callback when we're done reading. */
- unsigned int got_renegotiate:1;
- /** Return value from tor_tls_classify_client_ciphers, or 0 if we haven't
- * called that function yet. */
- int8_t client_cipher_list_type;
- /** Incremented every time we start the server side of a handshake. */
- uint8_t server_handshake_count;
- size_t wantwrite_n; /**< 0 normally, >0 if we returned wantwrite last
- * time. */
- /** Last values retrieved from BIO_number_read()/write(); see
- * tor_tls_get_n_raw_bytes() for usage.
- */
- unsigned long last_write_count;
- unsigned long last_read_count;
- /** If set, a callback to invoke whenever the client tries to renegotiate
- * the handshake. */
- void (*negotiated_callback)(tor_tls_t *tls, void *arg);
- /** Argument to pass to negotiated_callback. */
- void *callback_arg;
-};
-
-STATIC int tor_errno_to_tls_error(int e);
-STATIC int tor_tls_get_error(tor_tls_t *tls, int r, int extra,
- const char *doing, int severity, int domain);
-STATIC tor_tls_t *tor_tls_get_by_ssl(const struct ssl_st *ssl);
-STATIC void tor_tls_allocate_tor_tls_object_ex_data_index(void);
-#ifdef TORTLS_OPENSSL_PRIVATE
-STATIC int always_accept_verify_cb(int preverify_ok, X509_STORE_CTX *x509_ctx);
-STATIC int tor_tls_classify_client_ciphers(const struct ssl_st *ssl,
- STACK_OF(SSL_CIPHER) *peer_ciphers);
-#endif
-STATIC int tor_tls_client_is_using_v2_ciphers(const struct ssl_st *ssl);
-MOCK_DECL(STATIC void, try_to_extract_certs_from_tls,
- (int severity, tor_tls_t *tls, struct x509_st **cert_out,
- struct x509_st **id_cert_out));
-#ifndef HAVE_SSL_SESSION_GET_MASTER_KEY
-STATIC size_t SSL_SESSION_get_master_key(struct ssl_session_st *s,
- uint8_t *out,
- size_t len);
-#endif
-STATIC void tor_tls_debug_state_callback(const struct ssl_st *ssl,
- int type, int val);
-STATIC void tor_tls_server_info_callback(const struct ssl_st *ssl,
- int type, int val);
-#ifdef TORTLS_OPENSSL_PRIVATE
-STATIC int tor_tls_session_secret_cb(struct ssl_st *ssl, void *secret,
- int *secret_len,
- STACK_OF(SSL_CIPHER) *peer_ciphers,
- CONST_IF_OPENSSL_1_1_API SSL_CIPHER **cipher,
- void *arg);
-STATIC int find_cipher_by_id(const SSL *ssl, const SSL_METHOD *m,
- uint16_t cipher);
-#endif /* defined(TORTLS_OPENSSL_PRIVATE) */
-MOCK_DECL(STATIC struct x509_st *, tor_tls_create_certificate,
- (crypto_pk_t *rsa,
- crypto_pk_t *rsa_sign,
- const char *cname,
- const char *cname_sign,
- unsigned int cert_lifetime));
-STATIC tor_tls_context_t *tor_tls_context_new(crypto_pk_t *identity,
- unsigned int key_lifetime, unsigned flags, int is_client);
-MOCK_DECL(STATIC tor_x509_cert_t *, tor_x509_cert_new,
- (struct x509_st *x509_cert));
-STATIC int tor_tls_context_init_one(tor_tls_context_t **ppcontext,
- crypto_pk_t *identity,
- unsigned int key_lifetime,
- unsigned int flags,
- int is_client);
-STATIC void tls_log_errors(tor_tls_t *tls, int severity, int domain,
- const char *doing);
-
-#ifdef TOR_UNIT_TESTS
-extern int tor_tls_object_ex_data_index;
-extern tor_tls_context_t *server_tls_context;
-extern tor_tls_context_t *client_tls_context;
-extern uint16_t v2_cipher_list[];
-extern uint64_t total_bytes_written_over_tls;
-extern uint64_t total_bytes_written_by_tls;
-
-STATIC tor_x509_cert_t *tor_x509_cert_replace_expiration(
- const tor_x509_cert_t *inp,
- time_t new_expiration_time,
- crypto_pk_t *signing_key);
-#endif /* defined(TOR_UNIT_TESTS) */
-
-#endif /* defined(TORTLS_PRIVATE) */
-
-tor_x509_cert_t *tor_x509_cert_dup(const tor_x509_cert_t *cert);
-const char *tor_tls_err_to_string(int err);
-void tor_tls_get_state_description(tor_tls_t *tls, char *buf, size_t sz);
-
-void tor_tls_free_all(void);
-
-#define TOR_TLS_CTX_IS_PUBLIC_SERVER (1u<<0)
-#define TOR_TLS_CTX_USE_ECDHE_P256 (1u<<1)
-#define TOR_TLS_CTX_USE_ECDHE_P224 (1u<<2)
-
-int tor_tls_context_init(unsigned flags,
- crypto_pk_t *client_identity,
- crypto_pk_t *server_identity,
- unsigned int key_lifetime);
-tor_tls_t *tor_tls_new(int sock, int is_server);
-void tor_tls_set_logged_address(tor_tls_t *tls, const char *address);
-void tor_tls_set_renegotiate_callback(tor_tls_t *tls,
- void (*cb)(tor_tls_t *, void *arg),
- void *arg);
-int tor_tls_is_server(tor_tls_t *tls);
-void tor_tls_free_(tor_tls_t *tls);
-#define tor_tls_free(tls) FREE_AND_NULL(tor_tls_t, tor_tls_free_, (tls))
-int tor_tls_peer_has_cert(tor_tls_t *tls);
-MOCK_DECL(tor_x509_cert_t *,tor_tls_get_peer_cert,(tor_tls_t *tls));
-MOCK_DECL(tor_x509_cert_t *,tor_tls_get_own_cert,(tor_tls_t *tls));
-int tor_tls_verify(int severity, tor_tls_t *tls, crypto_pk_t **identity);
-int tor_tls_check_lifetime(int severity,
- tor_tls_t *tls, time_t now,
- int past_tolerance,
- int future_tolerance);
-MOCK_DECL(int, tor_tls_read, (tor_tls_t *tls, char *cp, size_t len));
-int tor_tls_write(tor_tls_t *tls, const char *cp, size_t n);
-int tor_tls_handshake(tor_tls_t *tls);
-int tor_tls_finish_handshake(tor_tls_t *tls);
-void tor_tls_unblock_renegotiation(tor_tls_t *tls);
-void tor_tls_block_renegotiation(tor_tls_t *tls);
-void tor_tls_assert_renegotiation_unblocked(tor_tls_t *tls);
-int tor_tls_shutdown(tor_tls_t *tls);
-int tor_tls_get_pending_bytes(tor_tls_t *tls);
-size_t tor_tls_get_forced_write_size(tor_tls_t *tls);
-
-void tor_tls_get_n_raw_bytes(tor_tls_t *tls,
- size_t *n_read, size_t *n_written);
-
-int tor_tls_get_buffer_sizes(tor_tls_t *tls,
- size_t *rbuf_capacity, size_t *rbuf_bytes,
- size_t *wbuf_capacity, size_t *wbuf_bytes);
-
-MOCK_DECL(double, tls_get_write_overhead_ratio, (void));
-
-int tor_tls_used_v1_handshake(tor_tls_t *tls);
-int tor_tls_get_num_server_handshakes(tor_tls_t *tls);
-int tor_tls_server_got_renegotiate(tor_tls_t *tls);
-MOCK_DECL(int,tor_tls_get_tlssecrets,(tor_tls_t *tls, uint8_t *secrets_out));
-MOCK_DECL(int,tor_tls_export_key_material,(
- tor_tls_t *tls, uint8_t *secrets_out,
- const uint8_t *context,
- size_t context_len,
- const char *label));
-
-/* 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__)
-
-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);
-
-void tor_x509_cert_free_(tor_x509_cert_t *cert);
-#define tor_x509_cert_free(c) \
- FREE_AND_NULL(tor_x509_cert_t, tor_x509_cert_free_, (c))
-tor_x509_cert_t *tor_x509_cert_decode(const uint8_t *certificate,
- size_t certificate_len);
-void tor_x509_cert_get_der(const tor_x509_cert_t *cert,
- const uint8_t **encoded_out, size_t *size_out);
-const common_digests_t *tor_x509_cert_get_id_digests(
- const tor_x509_cert_t *cert);
-const common_digests_t *tor_x509_cert_get_cert_digests(
- const tor_x509_cert_t *cert);
-int tor_tls_get_my_certs(int server,
- const tor_x509_cert_t **link_cert_out,
- const tor_x509_cert_t **id_cert_out);
-crypto_pk_t *tor_tls_get_my_client_auth_key(void);
-crypto_pk_t *tor_tls_cert_get_key(tor_x509_cert_t *cert);
-MOCK_DECL(int,tor_tls_cert_matches_key,(const tor_tls_t *tls,
- const tor_x509_cert_t *cert));
-int tor_tls_cert_is_valid(int severity,
- const tor_x509_cert_t *cert,
- const tor_x509_cert_t *signing_cert,
- time_t now,
- int check_rsa_1024);
-const char *tor_tls_get_ciphersuite_name(tor_tls_t *tls);
-
-int evaluate_ecgroup_for_tls(const char *ecgroup);
-
-#endif /* !defined(TOR_TORTLS_H) */
-
diff --git a/src/common/util.c b/src/common/util.c
deleted file mode 100644
index dece5877f1..0000000000
--- a/src/common/util.c
+++ /dev/null
@@ -1,5378 +0,0 @@
-/* Copyright (c) 2003, Roger Dingledine
- * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2017, The Tor Project, Inc. */
-/* See LICENSE for licensing information */
-
-/**
- * \file util.c
- * \brief Common functions for strings, IO, network, data structures,
- * process control.
- **/
-
-#include "orconfig.h"
-#ifdef HAVE_FCNTL_H
-#include <fcntl.h>
-#endif
-#define UTIL_PRIVATE
-#include "util.h"
-#include "torlog.h"
-#include "crypto_digest.h"
-#include "torint.h"
-#include "container.h"
-#include "address.h"
-#include "sandbox.h"
-#include "backtrace.h"
-#include "util_process.h"
-#include "util_format.h"
-
-#ifdef _WIN32
-#include <io.h>
-#include <direct.h>
-#include <process.h>
-#include <tchar.h>
-#include <winbase.h>
-#else /* !(defined(_WIN32)) */
-#include <dirent.h>
-#include <pwd.h>
-#include <grp.h>
-#endif /* defined(_WIN32) */
-
-/* math.h needs this on Linux */
-#ifndef _USE_ISOC99_
-#define _USE_ISOC99_ 1
-#endif
-#include <math.h>
-#include <stdlib.h>
-#include <stdio.h>
-#include <string.h>
-#include <assert.h>
-#include <signal.h>
-
-#ifdef HAVE_NETINET_IN_H
-#include <netinet/in.h>
-#endif
-#ifdef HAVE_ARPA_INET_H
-#include <arpa/inet.h>
-#endif
-#ifdef HAVE_ERRNO_H
-#include <errno.h>
-#endif
-#ifdef HAVE_SYS_SOCKET_H
-#include <sys/socket.h>
-#endif
-#ifdef HAVE_SYS_TIME_H
-#include <sys/time.h>
-#endif
-#ifdef HAVE_UNISTD_H
-#include <unistd.h>
-#endif
-#ifdef HAVE_SYS_STAT_H
-#include <sys/stat.h>
-#endif
-#ifdef HAVE_SYS_FCNTL_H
-#include <sys/fcntl.h>
-#endif
-#ifdef HAVE_TIME_H
-#include <time.h>
-#endif
-#ifdef HAVE_MALLOC_MALLOC_H
-#include <malloc/malloc.h>
-#endif
-#ifdef HAVE_MALLOC_H
-#if !defined(OpenBSD) && !defined(__FreeBSD__)
-/* OpenBSD has a malloc.h, but for our purposes, it only exists in order to
- * scold us for being so stupid as to autodetect its presence. To be fair,
- * they've done this since 1996, when autoconf was only 5 years old. */
-#include <malloc.h>
-#endif /* !defined(OpenBSD) && !defined(__FreeBSD__) */
-#endif /* defined(HAVE_MALLOC_H) */
-#ifdef HAVE_MALLOC_NP_H
-#include <malloc_np.h>
-#endif
-#ifdef HAVE_SYS_WAIT_H
-#include <sys/wait.h>
-#endif
-#if defined(HAVE_SYS_PRCTL_H) && defined(__linux__)
-#include <sys/prctl.h>
-#endif
-
-#ifdef __clang_analyzer__
-#undef MALLOC_ZERO_WORKS
-#endif
-
-/* =====
- * Memory management
- * ===== */
-#ifdef USE_DMALLOC
- #undef strndup
- #include <dmalloc.h>
- /* Macro to pass the extra dmalloc args to another function. */
- #define DMALLOC_FN_ARGS , file, line
-
- #if defined(HAVE_DMALLOC_STRDUP)
- /* the dmalloc_strdup should be fine as defined */
- #elif defined(HAVE_DMALLOC_STRNDUP)
- #define dmalloc_strdup(file, line, string, xalloc_b) \
- dmalloc_strndup(file, line, (string), -1, xalloc_b)
- #else
- #error "No dmalloc_strdup or equivalent"
-#endif /* defined(HAVE_DMALLOC_STRDUP) || ... */
-
-#else /* !(defined(USE_DMALLOC)) */
-
- #define DMALLOC_FN_ARGS
-#endif /* defined(USE_DMALLOC) */
-
-/** Allocate a chunk of <b>size</b> bytes of memory, and return a pointer to
- * result. On error, log and terminate the process. (Same as malloc(size),
- * but never returns NULL.)
- *
- * <b>file</b> and <b>line</b> are used if dmalloc is enabled, and
- * ignored otherwise.
- */
-void *
-tor_malloc_(size_t size DMALLOC_PARAMS)
-{
- void *result;
-
- tor_assert(size < SIZE_T_CEILING);
-
-#ifndef MALLOC_ZERO_WORKS
- /* Some libc mallocs don't work when size==0. Override them. */
- if (size==0) {
- size=1;
- }
-#endif /* !defined(MALLOC_ZERO_WORKS) */
-
-#ifdef USE_DMALLOC
- result = dmalloc_malloc(file, line, size, DMALLOC_FUNC_MALLOC, 0, 0);
-#else
- result = raw_malloc(size);
-#endif
-
- if (PREDICT_UNLIKELY(result == NULL)) {
- /* LCOV_EXCL_START */
- log_err(LD_MM,"Out of memory on malloc(). Dying.");
- /* If these functions die within a worker process, they won't call
- * spawn_exit, but that's ok, since the parent will run out of memory soon
- * anyway. */
- exit(1); // exit ok: alloc failed.
- /* LCOV_EXCL_STOP */
- }
- return result;
-}
-
-/** Allocate a chunk of <b>size</b> bytes of memory, fill the memory with
- * zero bytes, and return a pointer to the result. Log and terminate
- * the process on error. (Same as calloc(size,1), but never returns NULL.)
- */
-void *
-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
- * we don't!" Indeed it does, but its optimizations are only a big win when
- * 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);
- memset(result, 0, size);
- return result;
-}
-
-/* The square root of SIZE_MAX + 1. If a is less than this, and b is less
- * than this, then a*b is less than SIZE_MAX. (For example, if size_t is
- * 32 bits, then SIZE_MAX is 0xffffffff and this value is 0x10000. If a and
- * b are less than this, then their product is at most (65535*65535) ==
- * 0xfffe0001. */
-#define SQRT_SIZE_MAX_P1 (((size_t)1) << (sizeof(size_t)*4))
-
-/** Return non-zero if and only if the product of the arguments is exact,
- * and cannot overflow. */
-int
-size_mul_check(const size_t x, const size_t y)
-{
- /* This first check is equivalent to
- (x < SQRT_SIZE_MAX_P1 && y < SQRT_SIZE_MAX_P1)
-
- Rationale: if either one of x or y is >= SQRT_SIZE_MAX_P1, then it
- will have some bit set in its most significant half.
- */
- return ((x|y) < SQRT_SIZE_MAX_P1 ||
- y == 0 ||
- x <= SIZE_MAX / y);
-}
-
-/** Allocate a chunk of <b>nmemb</b>*<b>size</b> bytes of memory, fill
- * the memory with zero bytes, and return a pointer to the result.
- * Log and terminate the process on error. (Same as
- * calloc(<b>nmemb</b>,<b>size</b>), but never returns NULL.)
- * The second argument (<b>size</b>) should preferably be non-zero
- * and a compile-time constant.
- */
-void *
-tor_calloc_(size_t nmemb, size_t size DMALLOC_PARAMS)
-{
- tor_assert(size_mul_check(nmemb, size));
- return tor_malloc_zero_((nmemb * size) DMALLOC_FN_ARGS);
-}
-
-/** Change the size of the memory block pointed to by <b>ptr</b> to <b>size</b>
- * bytes long; return the new memory block. On error, log and
- * terminate. (Like realloc(ptr,size), but never returns NULL.)
- */
-void *
-tor_realloc_(void *ptr, size_t size DMALLOC_PARAMS)
-{
- void *result;
-
- tor_assert(size < SIZE_T_CEILING);
-
-#ifndef MALLOC_ZERO_WORKS
- /* Some libc mallocs don't work when size==0. Override them. */
- if (size==0) {
- size=1;
- }
-#endif /* !defined(MALLOC_ZERO_WORKS) */
-
-#ifdef USE_DMALLOC
- result = dmalloc_realloc(file, line, ptr, size, DMALLOC_FUNC_REALLOC, 0);
-#else
- result = raw_realloc(ptr, size);
-#endif
-
- if (PREDICT_UNLIKELY(result == NULL)) {
- /* LCOV_EXCL_START */
- log_err(LD_MM,"Out of memory on realloc(). Dying.");
- exit(1); // exit ok: alloc failed.
- /* LCOV_EXCL_STOP */
- }
- return result;
-}
-
-/**
- * Try to realloc <b>ptr</b> so that it takes up sz1 * sz2 bytes. Check for
- * overflow. Unlike other allocation functions, return NULL on overflow.
- */
-void *
-tor_reallocarray_(void *ptr, size_t sz1, size_t sz2 DMALLOC_PARAMS)
-{
- /* XXXX we can make this return 0, but we would need to check all the
- * reallocarray users. */
- tor_assert(size_mul_check(sz1, sz2));
-
- return tor_realloc(ptr, (sz1 * sz2) DMALLOC_FN_ARGS);
-}
-
-/** Return a newly allocated copy of the NUL-terminated string s. On
- * error, log and terminate. (Like strdup(s), but never returns
- * NULL.)
- */
-char *
-tor_strdup_(const char *s DMALLOC_PARAMS)
-{
- char *duplicate;
- tor_assert(s);
-
-#ifdef USE_DMALLOC
- duplicate = dmalloc_strdup(file, line, s, 0);
-#else
- duplicate = raw_strdup(s);
-#endif
- if (PREDICT_UNLIKELY(duplicate == NULL)) {
- /* LCOV_EXCL_START */
- log_err(LD_MM,"Out of memory on strdup(). Dying.");
- exit(1); // exit ok: alloc failed.
- /* LCOV_EXCL_STOP */
- }
- return duplicate;
-}
-
-/** Allocate and return a new string containing the first <b>n</b>
- * characters of <b>s</b>. If <b>s</b> is longer than <b>n</b>
- * characters, only the first <b>n</b> are copied. The result is
- * always NUL-terminated. (Like strndup(s,n), but never returns
- * NULL.)
- */
-char *
-tor_strndup_(const char *s, size_t n DMALLOC_PARAMS)
-{
- char *duplicate;
- tor_assert(s);
- tor_assert(n < SIZE_T_CEILING);
- duplicate = 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.
- */
- strncpy(duplicate, s, n);
- duplicate[n]='\0';
- return duplicate;
-}
-
-/** 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)
-{
- char *duplicate;
- tor_assert(len < SIZE_T_CEILING);
- tor_assert(mem);
- duplicate = tor_malloc_(len DMALLOC_FN_ARGS);
- memcpy(duplicate, mem, len);
- return duplicate;
-}
-
-/** As tor_memdup(), but add an extra 0 byte at the end of the resulting
- * memory. */
-void *
-tor_memdup_nulterm_(const void *mem, size_t len DMALLOC_PARAMS)
-{
- char *duplicate;
- tor_assert(len < SIZE_T_CEILING+1);
- tor_assert(mem);
- duplicate = tor_malloc_(len+1 DMALLOC_FN_ARGS);
- memcpy(duplicate, mem, len);
- duplicate[len] = '\0';
- return duplicate;
-}
-
-/** Helper for places that need to take a function pointer to the right
- * spelling of "free()". */
-void
-tor_free_(void *mem)
-{
- tor_free(mem);
-}
-
-DISABLE_GCC_WARNING(aggregate-return)
-/** 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
-tor_log_mallinfo(int severity)
-{
-#ifdef HAVE_MALLINFO
- struct mallinfo mi;
- memset(&mi, 0, sizeof(mi));
- mi = mallinfo();
- tor_log(severity, LD_MM,
- "mallinfo() said: arena=%d, ordblks=%d, smblks=%d, hblks=%d, "
- "hblkhd=%d, usmblks=%d, fsmblks=%d, uordblks=%d, fordblks=%d, "
- "keepcost=%d",
- mi.arena, mi.ordblks, mi.smblks, mi.hblks,
- mi.hblkhd, mi.usmblks, mi.fsmblks, mi.uordblks, mi.fordblks,
- mi.keepcost);
-#else /* !(defined(HAVE_MALLINFO)) */
- (void)severity;
-#endif /* defined(HAVE_MALLINFO) */
-#ifdef USE_DMALLOC
- dmalloc_log_changed(0, /* Since the program started. */
- 1, /* Log info about non-freed pointers. */
- 0, /* Do not log info about freed pointers. */
- 0 /* Do not log individual pointers. */
- );
-#endif /* defined(USE_DMALLOC) */
-}
-ENABLE_GCC_WARNING(aggregate-return)
-
-/* =====
- * Math
- * ===== */
-
-/**
- * Returns the natural logarithm of d base e. We defined this wrapper here so
- * to avoid conflicts with old versions of tor_log(), which were named log().
- */
-double
-tor_mathlog(double d)
-{
- return log(d);
-}
-
-/** 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)
-{
-#if defined(HAVE_LROUND)
- return lround(d);
-#elif defined(HAVE_RINT)
- return (long)rint(d);
-#else
- return (long)(d > 0 ? d + 0.5 : ceil(d - 0.5));
-#endif /* defined(HAVE_LROUND) || ... */
-}
-
-/** 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 /* defined(HAVE_LLROUND) || ... */
-}
-
-/** Returns floor(log2(u64)). If u64 is 0, (incorrectly) returns 0. */
-int
-tor_log2(uint64_t u64)
-{
- int r = 0;
- if (u64 >= (U64_LITERAL(1)<<32)) {
- u64 >>= 32;
- r = 32;
- }
- if (u64 >= (U64_LITERAL(1)<<16)) {
- u64 >>= 16;
- r += 16;
- }
- if (u64 >= (U64_LITERAL(1)<<8)) {
- u64 >>= 8;
- r += 8;
- }
- if (u64 >= (U64_LITERAL(1)<<4)) {
- u64 >>= 4;
- r += 4;
- }
- if (u64 >= (U64_LITERAL(1)<<2)) {
- u64 >>= 2;
- r += 2;
- }
- if (u64 >= (U64_LITERAL(1)<<1)) {
- // u64 >>= 1; // not using this any more.
- r += 1;
- }
- return r;
-}
-
-/** 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;
- 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
- return low;
-}
-
-/** Return the lowest x such that x is at least <b>number</b>, and x modulo
- * <b>divisor</b> == 0. If no such x can be expressed as an unsigned, return
- * UINT_MAX. Asserts if divisor is zero. */
-unsigned
-round_to_next_multiple_of(unsigned number, unsigned divisor)
-{
- tor_assert(divisor > 0);
- if (UINT_MAX - divisor + 1 < number)
- return UINT_MAX;
- number += divisor - 1;
- number -= number % divisor;
- return number;
-}
-
-/** Return the lowest x such that x is at least <b>number</b>, and x modulo
- * <b>divisor</b> == 0. If no such x can be expressed as a uint32_t, return
- * UINT32_MAX. Asserts if divisor is zero. */
-uint32_t
-round_uint32_to_next_multiple_of(uint32_t number, uint32_t divisor)
-{
- tor_assert(divisor > 0);
- if (UINT32_MAX - divisor + 1 < number)
- return UINT32_MAX;
-
- number += divisor - 1;
- number -= number % divisor;
- return number;
-}
-
-/** Return the lowest x such that x is at least <b>number</b>, and x modulo
- * <b>divisor</b> == 0. If no such x can be expressed as a uint64_t, return
- * UINT64_MAX. Asserts if divisor is zero. */
-uint64_t
-round_uint64_to_next_multiple_of(uint64_t number, uint64_t divisor)
-{
- tor_assert(divisor > 0);
- if (UINT64_MAX - divisor + 1 < number)
- return UINT64_MAX;
- number += divisor - 1;
- number -= number % divisor;
- return number;
-}
-
-/** Transform a random value <b>p</b> from the uniform distribution in
- * [0.0, 1.0[ into a Laplace distributed value with location parameter
- * <b>mu</b> and scale parameter <b>b</b>. Truncate the final result
- * to be an integer in [INT64_MIN, INT64_MAX]. */
-int64_t
-sample_laplace_distribution(double mu, double b, double p)
-{
- double result;
- tor_assert(p >= 0.0 && p < 1.0);
-
- /* This is the "inverse cumulative distribution function" from:
- * http://en.wikipedia.org/wiki/Laplace_distribution */
- if (p <= 0.0) {
- /* Avoid taking log(0.0) == -INFINITY, as some processors or compiler
- * options can cause the program to trap. */
- return INT64_MIN;
- }
-
- result = mu - b * (p > 0.5 ? 1.0 : -1.0)
- * tor_mathlog(1.0 - 2.0 * fabs(p - 0.5));
-
- return clamp_double_to_int64(result);
-}
-
-/** Add random noise between INT64_MIN and INT64_MAX coming from a Laplace
- * distribution with mu = 0 and b = <b>delta_f</b>/<b>epsilon</b> to
- * <b>signal</b> based on the provided <b>random</b> value in [0.0, 1.0[.
- * The epsilon value must be between ]0.0, 1.0]. delta_f must be greater
- * than 0. */
-int64_t
-add_laplace_noise(int64_t signal_, double random_, double delta_f,
- double epsilon)
-{
- int64_t noise;
-
- /* epsilon MUST be between ]0.0, 1.0] */
- tor_assert(epsilon > 0.0 && epsilon <= 1.0);
- /* delta_f MUST be greater than 0. */
- tor_assert(delta_f > 0.0);
-
- /* Just add noise, no further signal */
- noise = sample_laplace_distribution(0.0,
- delta_f / epsilon,
- random_);
-
- /* Clip (signal + noise) to [INT64_MIN, INT64_MAX] */
- if (noise > 0 && INT64_MAX - noise < signal_)
- return INT64_MAX;
- else if (noise < 0 && INT64_MIN - noise > signal_)
- return INT64_MIN;
- else
- return signal_ + noise;
-}
-
-/* Helper: safely add two uint32_t's, capping at UINT32_MAX rather
- * than overflow */
-uint32_t
-tor_add_u32_nowrap(uint32_t a, uint32_t b)
-{
- /* a+b > UINT32_MAX check, without overflow */
- if (PREDICT_UNLIKELY(a > UINT32_MAX - b)) {
- return UINT32_MAX;
- } else {
- return a+b;
- }
-}
-
-/* Helper: return greatest common divisor of a,b */
-static uint64_t
-gcd64(uint64_t a, uint64_t b)
-{
- while (b) {
- uint64_t t = b;
- b = a % b;
- a = t;
- }
- return a;
-}
-
-/* Given a fraction *<b>numer</b> / *<b>denom</b>, simplify it.
- * Requires that the denominator is greater than 0. */
-void
-simplify_fraction64(uint64_t *numer, uint64_t *denom)
-{
- tor_assert(denom);
- uint64_t gcd = gcd64(*numer, *denom);
- *numer /= gcd;
- *denom /= gcd;
-}
-
-/** Return the number of bits set in <b>v</b>. */
-int
-n_bits_set_u8(uint8_t v)
-{
- static const int nybble_table[] = {
- 0, /* 0000 */
- 1, /* 0001 */
- 1, /* 0010 */
- 2, /* 0011 */
- 1, /* 0100 */
- 2, /* 0101 */
- 2, /* 0110 */
- 3, /* 0111 */
- 1, /* 1000 */
- 2, /* 1001 */
- 2, /* 1010 */
- 3, /* 1011 */
- 2, /* 1100 */
- 3, /* 1101 */
- 3, /* 1110 */
- 4, /* 1111 */
- };
-
- return nybble_table[v & 15] + nybble_table[v>>4];
-}
-
-/* =====
- * String manipulation
- * ===== */
-
-/** Remove from the string <b>s</b> every character which appears in
- * <b>strip</b>. */
-void
-tor_strstrip(char *s, const char *strip)
-{
- char *readp = s;
- while (*readp) {
- if (strchr(strip, *readp)) {
- ++readp;
- } else {
- *s++ = *readp++;
- }
- }
- *s = '\0';
-}
-
-/** Return a pointer to a NUL-terminated hexadecimal string encoding
- * the first <b>fromlen</b> bytes of <b>from</b>. (fromlen must be \<= 32.) The
- * result does not need to be deallocated, but repeated calls to
- * hex_str will trash old results.
- */
-const char *
-hex_str(const char *from, size_t fromlen)
-{
- static char buf[65];
- if (fromlen>(sizeof(buf)-1)/2)
- fromlen = (sizeof(buf)-1)/2;
- base16_encode(buf,sizeof(buf),from,fromlen);
- return buf;
-}
-
-/** Convert all alphabetic characters in the nul-terminated string <b>s</b> to
- * lowercase. */
-void
-tor_strlower(char *s)
-{
- while (*s) {
- *s = TOR_TOLOWER(*s);
- ++s;
- }
-}
-
-/** Convert all alphabetic characters in the nul-terminated string <b>s</b> to
- * lowercase. */
-void
-tor_strupper(char *s)
-{
- while (*s) {
- *s = TOR_TOUPPER(*s);
- ++s;
- }
-}
-
-/** Return 1 if every character in <b>s</b> is printable, else return 0.
- */
-int
-tor_strisprint(const char *s)
-{
- while (*s) {
- if (!TOR_ISPRINT(*s))
- return 0;
- s++;
- }
- return 1;
-}
-
-/** Return 1 if no character in <b>s</b> is uppercase, else return 0.
- */
-int
-tor_strisnonupper(const char *s)
-{
- while (*s) {
- if (TOR_ISUPPER(*s))
- return 0;
- s++;
- }
- return 1;
-}
-
-/** Return true iff every character in <b>s</b> is whitespace space; else
- * return false. */
-int
-tor_strisspace(const char *s)
-{
- while (*s) {
- if (!TOR_ISSPACE(*s))
- return 0;
- s++;
- }
- return 1;
-}
-
-/** As strcmp, except that either string may be NULL. The NULL string is
- * considered to be before any non-NULL string. */
-int
-strcmp_opt(const char *s1, const char *s2)
-{
- if (!s1) {
- if (!s2)
- return 0;
- else
- return -1;
- } else if (!s2) {
- return 1;
- } else {
- return strcmp(s1, s2);
- }
-}
-
-/** Compares the first strlen(s2) characters of s1 with s2. Returns as for
- * strcmp.
- */
-int
-strcmpstart(const char *s1, const char *s2)
-{
- size_t n = strlen(s2);
- return strncmp(s1, s2, n);
-}
-
-/** Compare the s1_len-byte string <b>s1</b> with <b>s2</b>,
- * without depending on a terminating nul in s1. Sorting order is first by
- * length, then lexically; return values are as for strcmp.
- */
-int
-strcmp_len(const char *s1, const char *s2, size_t s1_len)
-{
- size_t s2_len = strlen(s2);
- if (s1_len < s2_len)
- return -1;
- if (s1_len > s2_len)
- return 1;
- return fast_memcmp(s1, s2, s2_len);
-}
-
-/** Compares the first strlen(s2) characters of s1 with s2. Returns as for
- * strcasecmp.
- */
-int
-strcasecmpstart(const char *s1, const char *s2)
-{
- size_t n = strlen(s2);
- return strncasecmp(s1, s2, n);
-}
-
-/** Compares the last strlen(s2) characters of s1 with s2. Returns as for
- * strcmp.
- */
-int
-strcmpend(const char *s1, const char *s2)
-{
- size_t n1 = strlen(s1), n2 = strlen(s2);
- if (n2>n1)
- return strcmp(s1,s2);
- else
- return strncmp(s1+(n1-n2), s2, n2);
-}
-
-/** Compares the last strlen(s2) characters of s1 with s2. Returns as for
- * strcasecmp.
- */
-int
-strcasecmpend(const char *s1, const char *s2)
-{
- size_t n1 = strlen(s1), n2 = strlen(s2);
- if (n2>n1) /* then they can't be the same; figure out which is bigger */
- return strcasecmp(s1,s2);
- else
- return strncasecmp(s1+(n1-n2), s2, n2);
-}
-
-/** Compare the value of the string <b>prefix</b> with the start of the
- * <b>memlen</b>-byte memory chunk at <b>mem</b>. Return as for strcmp.
- *
- * [As fast_memcmp(mem, prefix, strlen(prefix)) but returns -1 if memlen is
- * less than strlen(prefix).]
- */
-int
-fast_memcmpstart(const void *mem, size_t memlen,
- const char *prefix)
-{
- size_t plen = strlen(prefix);
- if (memlen < plen)
- return -1;
- return fast_memcmp(mem, prefix, plen);
-}
-
-/** 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.
- */
-const char *
-eat_whitespace(const char *s)
-{
- tor_assert(s);
-
- while (1) {
- switch (*s) {
- case '\0':
- default:
- return s;
- case ' ':
- case '\t':
- case '\n':
- case '\r':
- ++s;
- break;
- case '#':
- ++s;
- while (*s && *s != '\n')
- ++s;
- }
- }
-}
-
-/** 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.
- */
-const char *
-eat_whitespace_eos(const char *s, const char *eos)
-{
- tor_assert(s);
- tor_assert(eos && s <= eos);
-
- while (s < eos) {
- switch (*s) {
- case '\0':
- default:
- return s;
- case ' ':
- case '\t':
- case '\n':
- case '\r':
- ++s;
- break;
- case '#':
- ++s;
- while (s < eos && *s && *s != '\n')
- ++s;
- }
- }
- return s;
-}
-
-/** Return a pointer to the first char of s that is not a space or a tab
- * or a \\r, or to the terminating NUL if no such character exists. */
-const char *
-eat_whitespace_no_nl(const char *s)
-{
- while (*s == ' ' || *s == '\t' || *s == '\r')
- ++s;
- return s;
-}
-
-/** As eat_whitespace_no_nl, but stop at <b>eos</b> whether we have
- * found a non-whitespace character or not. */
-const char *
-eat_whitespace_eos_no_nl(const char *s, const char *eos)
-{
- while (s < eos && (*s == ' ' || *s == '\t' || *s == '\r'))
- ++s;
- return s;
-}
-
-/** Return a pointer to the first char of s that is whitespace or <b>#</b>,
- * or to the terminating NUL if no such character exists.
- */
-const char *
-find_whitespace(const char *s)
-{
- /* tor_assert(s); */
- while (1) {
- switch (*s)
- {
- case '\0':
- case '#':
- case ' ':
- case '\r':
- case '\n':
- case '\t':
- return s;
- default:
- ++s;
- }
- }
-}
-
-/** As find_whitespace, but stop at <b>eos</b> whether we have found a
- * whitespace or not. */
-const char *
-find_whitespace_eos(const char *s, const char *eos)
-{
- /* tor_assert(s); */
- while (s < eos) {
- switch (*s)
- {
- case '\0':
- case '#':
- case ' ':
- case '\r':
- case '\n':
- case '\t':
- return s;
- default:
- ++s;
- }
- }
- return s;
-}
-
-/** Return the first occurrence of <b>needle</b> in <b>haystack</b> that
- * occurs at the start of a line (that is, at the beginning of <b>haystack</b>
- * or immediately after a newline). Return NULL if no such string is found.
- */
-const char *
-find_str_at_start_of_line(const char *haystack, const char *needle)
-{
- size_t needle_len = strlen(needle);
-
- do {
- if (!strncmp(haystack, needle, needle_len))
- return haystack;
-
- haystack = strchr(haystack, '\n');
- if (!haystack)
- return NULL;
- else
- ++haystack;
- } while (*haystack);
-
- return NULL;
-}
-
-/** Returns true if <b>string</b> could be a C identifier.
- A C identifier must begin with a letter or an underscore and the
- rest of its characters can be letters, numbers or underscores. No
- length limit is imposed. */
-int
-string_is_C_identifier(const char *string)
-{
- size_t iter;
- size_t length = strlen(string);
- if (!length)
- return 0;
-
- for (iter = 0; iter < length ; iter++) {
- if (iter == 0) {
- if (!(TOR_ISALPHA(string[iter]) ||
- string[iter] == '_'))
- return 0;
- } else {
- if (!(TOR_ISALPHA(string[iter]) ||
- TOR_ISDIGIT(string[iter]) ||
- string[iter] == '_'))
- return 0;
- }
- }
-
- return 1;
-}
-
-/** Return true iff the 'len' bytes at 'mem' are all zero. */
-int
-tor_mem_is_zero(const char *mem, size_t len)
-{
- static const char ZERO[] = {
- 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0,
- };
- while (len >= sizeof(ZERO)) {
- /* It's safe to use fast_memcmp here, since the very worst thing an
- * attacker could learn is how many initial bytes of a secret were zero */
- if (fast_memcmp(mem, ZERO, sizeof(ZERO)))
- return 0;
- len -= sizeof(ZERO);
- mem += sizeof(ZERO);
- }
- /* Deal with leftover bytes. */
- if (len)
- return fast_memeq(mem, ZERO, len);
-
- return 1;
-}
-
-/** Return true iff the DIGEST_LEN bytes in digest are all zero. */
-int
-tor_digest_is_zero(const char *digest)
-{
- static const uint8_t ZERO_DIGEST[] = {
- 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0
- };
- return tor_memeq(digest, ZERO_DIGEST, DIGEST_LEN);
-}
-
-/** Return true if <b>string</b> is a valid 'key=[value]' string.
- * "value" is optional, to indicate the empty string. Log at logging
- * <b>severity</b> if something ugly happens. */
-int
-string_is_key_value(int severity, const char *string)
-{
- /* position of equal sign in string */
- const char *equal_sign_pos = NULL;
-
- tor_assert(string);
-
- if (strlen(string) < 2) { /* "x=" is shortest args string */
- tor_log(severity, LD_GENERAL, "'%s' is too short to be a k=v value.",
- escaped(string));
- return 0;
- }
-
- equal_sign_pos = strchr(string, '=');
- if (!equal_sign_pos) {
- tor_log(severity, LD_GENERAL, "'%s' is not a k=v value.", escaped(string));
- return 0;
- }
-
- /* validate that the '=' is not in the beginning of the string. */
- if (equal_sign_pos == string) {
- tor_log(severity, LD_GENERAL, "'%s' is not a valid k=v value.",
- escaped(string));
- return 0;
- }
-
- return 1;
-}
-
-/** Return true if <b>string</b> represents a valid IPv4 adddress in
- * 'a.b.c.d' form.
- */
-int
-string_is_valid_ipv4_address(const char *string)
-{
- struct in_addr addr;
-
- return (tor_inet_pton(AF_INET,string,&addr) == 1);
-}
-
-/** Return true if <b>string</b> represents a valid IPv6 address in
- * a form that inet_pton() can parse.
- */
-int
-string_is_valid_ipv6_address(const char *string)
-{
- struct in6_addr addr;
-
- return (tor_inet_pton(AF_INET6,string,&addr) == 1);
-}
-
-/** Return true iff <b>string</b> is a valid destination address,
- * i.e. either a DNS hostname or IPv4/IPv6 address string.
- */
-int
-string_is_valid_dest(const char *string)
-{
- char *tmp = NULL;
- int retval;
- size_t len;
-
- if (string == NULL)
- return 0;
-
- len = strlen(string);
-
- if (len == 0)
- return 0;
-
- if (string[0] == '[' && string[len - 1] == ']')
- string = tmp = tor_strndup(string + 1, len - 2);
-
- retval = string_is_valid_ipv4_address(string) ||
- string_is_valid_ipv6_address(string) ||
- string_is_valid_nonrfc_hostname(string);
-
- tor_free(tmp);
-
- return retval;
-}
-
-/** Return true iff <b>string</b> matches a pattern of DNS names
- * that we allow Tor clients to connect to.
- *
- * Note: This allows certain technically invalid characters ('_') to cope
- * with misconfigured zones that have been encountered in the wild.
- */
-int
-string_is_valid_nonrfc_hostname(const char *string)
-{
- int result = 1;
- int has_trailing_dot;
- char *last_label;
- smartlist_t *components;
-
- if (!string || strlen(string) == 0)
- return 0;
-
- if (string_is_valid_ipv4_address(string))
- return 0;
-
- components = smartlist_new();
-
- smartlist_split_string(components,string,".",0,0);
-
- if (BUG(smartlist_len(components) == 0))
- return 0; // LCOV_EXCL_LINE should be impossible given the earlier checks.
-
- /* Allow a single terminating '.' used rarely to indicate domains
- * are FQDNs rather than relative. */
- last_label = (char *)smartlist_get(components,
- smartlist_len(components) - 1);
- has_trailing_dot = (last_label[0] == '\0');
- if (has_trailing_dot) {
- smartlist_pop_last(components);
- tor_free(last_label);
- last_label = NULL;
- }
-
- SMARTLIST_FOREACH_BEGIN(components, char *, c) {
- if ((c[0] == '-') || (*c == '_')) {
- result = 0;
- break;
- }
-
- do {
- result = (TOR_ISALNUM(*c) || (*c == '-') || (*c == '_'));
- c++;
- } while (result && *c);
-
- if (result == 0) {
- break;
- }
- } SMARTLIST_FOREACH_END(c);
-
- SMARTLIST_FOREACH_BEGIN(components, char *, c) {
- tor_free(c);
- } SMARTLIST_FOREACH_END(c);
-
- smartlist_free(components);
-
- return result;
-}
-
-/** Return true iff the DIGEST256_LEN bytes in digest are all zero. */
-int
-tor_digest256_is_zero(const char *digest)
-{
- return tor_mem_is_zero(digest, DIGEST256_LEN);
-}
-
-/* Helper: common code to check whether the result of a strtol or strtoul or
- * strtoll is correct. */
-#define CHECK_STRTOX_RESULT() \
- /* Did an overflow occur? */ \
- if (errno == ERANGE) \
- goto err; \
- /* Was at least one character converted? */ \
- if (endptr == s) \
- goto err; \
- /* Were there unexpected unconverted characters? */ \
- if (!next && *endptr) \
- goto err; \
- /* Illogical (max, min) inputs? */ \
- if (BUG(max < min)) \
- goto err; \
- /* Is r within limits? */ \
- if (r < min || r > max) \
- goto err; \
- if (ok) *ok = 1; \
- if (next) *next = endptr; \
- return r; \
- err: \
- if (ok) *ok = 0; \
- if (next) *next = endptr; \
- return 0
-
-/** Extract a long from the start of <b>s</b>, in the given numeric
- * <b>base</b>. If <b>base</b> is 0, <b>s</b> is parsed as a decimal,
- * octal, or hex number in the syntax of a C integer literal. If
- * there is unconverted data and <b>next</b> is provided, set
- * *<b>next</b> to the first unconverted character. An error has
- * occurred if no characters are converted; or if there are
- * unconverted characters and <b>next</b> is NULL; or if the parsed
- * value is not between <b>min</b> and <b>max</b>. When no error
- * occurs, return the parsed value and set *<b>ok</b> (if provided) to
- * 1. When an error occurs, return 0 and set *<b>ok</b> (if provided)
- * to 0.
- */
-long
-tor_parse_long(const char *s, int base, long min, long max,
- int *ok, char **next)
-{
- char *endptr;
- long r;
-
- if (BUG(base < 0)) {
- if (ok)
- *ok = 0;
- return 0;
- }
-
- errno = 0;
- r = strtol(s, &endptr, base);
- CHECK_STRTOX_RESULT();
-}
-
-/** As tor_parse_long(), but return an unsigned long. */
-unsigned long
-tor_parse_ulong(const char *s, int base, unsigned long min,
- unsigned long max, int *ok, char **next)
-{
- char *endptr;
- unsigned long r;
-
- if (BUG(base < 0)) {
- if (ok)
- *ok = 0;
- return 0;
- }
-
- errno = 0;
- r = strtoul(s, &endptr, base);
- CHECK_STRTOX_RESULT();
-}
-
-/** As tor_parse_long(), but return a double. */
-double
-tor_parse_double(const char *s, double min, double max, int *ok, char **next)
-{
- char *endptr;
- double r;
-
- errno = 0;
- r = strtod(s, &endptr);
- CHECK_STRTOX_RESULT();
-}
-
-/** As tor_parse_long, but return a uint64_t. Only base 10 is guaranteed to
- * work for now. */
-uint64_t
-tor_parse_uint64(const char *s, int base, uint64_t min,
- uint64_t max, int *ok, char **next)
-{
- char *endptr;
- uint64_t r;
-
- if (BUG(base < 0)) {
- if (ok)
- *ok = 0;
- return 0;
- }
-
- errno = 0;
-#ifdef HAVE_STRTOULL
- r = (uint64_t)strtoull(s, &endptr, base);
-#elif defined(_WIN32)
- r = (uint64_t)_strtoui64(s, &endptr, base);
-#elif SIZEOF_LONG == 8
- r = (uint64_t)strtoul(s, &endptr, base);
-#else
-#error "I don't know how to parse 64-bit numbers."
-#endif /* defined(HAVE_STRTOULL) || ... */
-
- CHECK_STRTOX_RESULT();
-}
-
-/** Allocate and return a new string representing the contents of <b>s</b>,
- * surrounded by quotes and using standard C escapes.
- *
- * Generally, we use this for logging values that come in over the network to
- * keep them from tricking users, and for sending certain values to the
- * controller.
- *
- * We trust values from the resolver, OS, configuration file, and command line
- * to not be maliciously ill-formed. We validate incoming routerdescs and
- * SOCKS requests and addresses from BEGIN cells as they're parsed;
- * afterwards, we trust them as non-malicious.
- */
-char *
-esc_for_log(const char *s)
-{
- const char *cp;
- char *result, *outp;
- size_t len = 3;
- if (!s) {
- return tor_strdup("(null)");
- }
-
- for (cp = s; *cp; ++cp) {
- switch (*cp) {
- case '\\':
- case '\"':
- case '\'':
- case '\r':
- case '\n':
- case '\t':
- len += 2;
- break;
- default:
- if (TOR_ISPRINT(*cp) && ((uint8_t)*cp)<127)
- ++len;
- else
- len += 4;
- break;
- }
- }
-
- tor_assert(len <= SSIZE_MAX);
-
- result = outp = tor_malloc(len);
- *outp++ = '\"';
- for (cp = s; *cp; ++cp) {
- /* This assertion should always succeed, since we will write at least
- * one char here, and two chars for closing quote and nul later */
- tor_assert((outp-result) < (ssize_t)len-2);
- switch (*cp) {
- case '\\':
- case '\"':
- case '\'':
- *outp++ = '\\';
- *outp++ = *cp;
- break;
- case '\n':
- *outp++ = '\\';
- *outp++ = 'n';
- break;
- case '\t':
- *outp++ = '\\';
- *outp++ = 't';
- break;
- case '\r':
- *outp++ = '\\';
- *outp++ = 'r';
- break;
- default:
- if (TOR_ISPRINT(*cp) && ((uint8_t)*cp)<127) {
- *outp++ = *cp;
- } else {
- tor_assert((outp-result) < (ssize_t)len-4);
- tor_snprintf(outp, 5, "\\%03o", (int)(uint8_t) *cp);
- outp += 4;
- }
- break;
- }
- }
-
- tor_assert((outp-result) <= (ssize_t)len-2);
- *outp++ = '\"';
- *outp++ = 0;
-
- return result;
-}
-
-/** Similar to esc_for_log. Allocate and return a new string representing
- * the first n characters in <b>chars</b>, surround by quotes and using
- * standard C escapes. If a NUL character is encountered in <b>chars</b>,
- * the resulting string will be terminated there.
- */
-char *
-esc_for_log_len(const char *chars, size_t n)
-{
- char *string = tor_strndup(chars, n);
- char *string_escaped = esc_for_log(string);
- tor_free(string);
- return string_escaped;
-}
-
-/** Allocate and return a new string representing the contents of <b>s</b>,
- * surrounded by quotes and using standard C escapes.
- *
- * THIS FUNCTION IS NOT REENTRANT. Don't call it from outside the main
- * thread. Also, each call invalidates the last-returned value, so don't
- * try log_warn(LD_GENERAL, "%s %s", escaped(a), escaped(b));
- */
-const char *
-escaped(const char *s)
-{
- static char *escaped_val_ = NULL;
- tor_free(escaped_val_);
-
- if (s)
- escaped_val_ = esc_for_log(s);
- else
- escaped_val_ = NULL;
-
- return escaped_val_;
-}
-
-/** Return a newly allocated string equal to <b>string</b>, except that every
- * character in <b>chars_to_escape</b> is preceded by a backslash. */
-char *
-tor_escape_str_for_pt_args(const char *string, const char *chars_to_escape)
-{
- char *new_string = NULL;
- char *new_cp = NULL;
- size_t length, new_length;
-
- tor_assert(string);
-
- length = strlen(string);
-
- if (!length) /* If we were given the empty string, return the same. */
- return tor_strdup("");
- /* (new_length > SIZE_MAX) => ((length * 2) + 1 > SIZE_MAX) =>
- (length*2 > SIZE_MAX - 1) => (length > (SIZE_MAX - 1)/2) */
- if (length > (SIZE_MAX - 1)/2) /* check for overflow */
- return NULL;
-
- /* this should be enough even if all characters must be escaped */
- new_length = (length * 2) + 1;
-
- new_string = new_cp = tor_malloc(new_length);
-
- while (*string) {
- if (strchr(chars_to_escape, *string))
- *new_cp++ = '\\';
-
- *new_cp++ = *string++;
- }
-
- *new_cp = '\0'; /* NUL-terminate the new string */
-
- return new_string;
-}
-
-/* =====
- * Time
- * ===== */
-
-#define TOR_USEC_PER_SEC 1000000
-
-/** Return the difference between start->tv_sec and end->tv_sec.
- * Returns INT64_MAX on overflow and underflow.
- */
-static int64_t
-tv_secdiff_impl(const struct timeval *start, const struct timeval *end)
-{
- const int64_t s = (int64_t)start->tv_sec;
- const int64_t e = (int64_t)end->tv_sec;
-
- /* This may not be the most efficient way of implemeting this check,
- * but it's easy to see that it's correct and doesn't overflow */
-
- if (s > 0 && e < INT64_MIN + s) {
- /* s is positive: equivalent to e - s < INT64_MIN, but without any
- * overflow */
- return INT64_MAX;
- } else if (s < 0 && e > INT64_MAX + s) {
- /* s is negative: equivalent to e - s > INT64_MAX, but without any
- * overflow */
- return INT64_MAX;
- }
-
- return e - s;
-}
-
-/** Return the number of microseconds elapsed between *start and *end.
- * Returns LONG_MAX on overflow and underflow.
- */
-long
-tv_udiff(const struct timeval *start, const struct timeval *end)
-{
- /* Sanity check tv_usec */
- if (start->tv_usec > TOR_USEC_PER_SEC || start->tv_usec < 0) {
- log_warn(LD_GENERAL, "comparing times on microsecond detail with bad "
- "start tv_usec: " I64_FORMAT " microseconds",
- I64_PRINTF_ARG(start->tv_usec));
- return LONG_MAX;
- }
-
- if (end->tv_usec > TOR_USEC_PER_SEC || end->tv_usec < 0) {
- log_warn(LD_GENERAL, "comparing times on microsecond detail with bad "
- "end tv_usec: " I64_FORMAT " microseconds",
- I64_PRINTF_ARG(end->tv_usec));
- return LONG_MAX;
- }
-
- /* Some BSDs have struct timeval.tv_sec 64-bit, but time_t (and long) 32-bit
- */
- int64_t udiff;
- const int64_t secdiff = tv_secdiff_impl(start, end);
-
- /* end->tv_usec - start->tv_usec can be up to 1 second either way */
- if (secdiff > (int64_t)(LONG_MAX/1000000 - 1) ||
- secdiff < (int64_t)(LONG_MIN/1000000 + 1)) {
- log_warn(LD_GENERAL, "comparing times on microsecond detail too far "
- "apart: " I64_FORMAT " seconds", I64_PRINTF_ARG(secdiff));
- return LONG_MAX;
- }
-
- /* we'll never get an overflow here, because we check that both usecs are
- * between 0 and TV_USEC_PER_SEC. */
- udiff = secdiff*1000000 + ((int64_t)end->tv_usec - (int64_t)start->tv_usec);
-
- /* Some compilers are smart enough to work out this is a no-op on L64 */
-#if SIZEOF_LONG < 8
- if (udiff > (int64_t)LONG_MAX || udiff < (int64_t)LONG_MIN) {
- return LONG_MAX;
- }
-#endif
-
- return (long)udiff;
-}
-
-/** Return the number of milliseconds elapsed between *start and *end.
- * If the tv_usec difference is 500, rounds away from zero.
- * Returns LONG_MAX on overflow and underflow.
- */
-long
-tv_mdiff(const struct timeval *start, const struct timeval *end)
-{
- /* Sanity check tv_usec */
- if (start->tv_usec > TOR_USEC_PER_SEC || start->tv_usec < 0) {
- log_warn(LD_GENERAL, "comparing times on millisecond detail with bad "
- "start tv_usec: " I64_FORMAT " microseconds",
- I64_PRINTF_ARG(start->tv_usec));
- return LONG_MAX;
- }
-
- if (end->tv_usec > TOR_USEC_PER_SEC || end->tv_usec < 0) {
- log_warn(LD_GENERAL, "comparing times on millisecond detail with bad "
- "end tv_usec: " I64_FORMAT " microseconds",
- I64_PRINTF_ARG(end->tv_usec));
- return LONG_MAX;
- }
-
- /* Some BSDs have struct timeval.tv_sec 64-bit, but time_t (and long) 32-bit
- */
- int64_t mdiff;
- const int64_t secdiff = tv_secdiff_impl(start, end);
-
- /* end->tv_usec - start->tv_usec can be up to 1 second either way, but the
- * mdiff calculation may add another temporary second for rounding.
- * Whether this actually causes overflow depends on the compiler's constant
- * folding and order of operations. */
- if (secdiff > (int64_t)(LONG_MAX/1000 - 2) ||
- secdiff < (int64_t)(LONG_MIN/1000 + 1)) {
- log_warn(LD_GENERAL, "comparing times on millisecond detail too far "
- "apart: " I64_FORMAT " seconds", I64_PRINTF_ARG(secdiff));
- return LONG_MAX;
- }
-
- /* Subtract and round */
- mdiff = secdiff*1000 +
- /* We add a million usec here to ensure that the result is positive,
- * so that the round-towards-zero behavior of the division will give
- * the right result for rounding to the nearest msec. Later we subtract
- * 1000 in order to get the correct result.
- * We'll never get an overflow here, because we check that both usecs are
- * between 0 and TV_USEC_PER_SEC. */
- ((int64_t)end->tv_usec - (int64_t)start->tv_usec + 500 + 1000000) / 1000
- - 1000;
-
- /* Some compilers are smart enough to work out this is a no-op on L64 */
-#if SIZEOF_LONG < 8
- if (mdiff > (int64_t)LONG_MAX || mdiff < (int64_t)LONG_MIN) {
- return LONG_MAX;
- }
-#endif
-
- return (long)mdiff;
-}
-
-/**
- * Converts timeval to milliseconds.
- */
-int64_t
-tv_to_msec(const struct timeval *tv)
-{
- int64_t conv = ((int64_t)tv->tv_sec)*1000L;
- /* Round ghetto-style */
- conv += ((int64_t)tv->tv_usec+500)/1000L;
- return conv;
-}
-
-/** Yield true iff <b>y</b> is a leap-year. */
-#define IS_LEAPYEAR(y) (!(y % 4) && ((y % 100) || !(y % 400)))
-/** Helper: Return the number of leap-days between Jan 1, y1 and Jan 1, y2. */
-static int
-n_leapdays(int year1, int year2)
-{
- --year1;
- --year2;
- return (year2/4 - year1/4) - (year2/100 - year1/100)
- + (year2/400 - year1/400);
-}
-/** Number of days per month in non-leap year; used by tor_timegm and
- * parse_rfc1123_time. */
-static const int days_per_month[] =
- { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
-
-/** Compute a time_t given a struct tm. The result is given in UTC, and
- * does not account for leap seconds. Return 0 on success, -1 on failure.
- */
-int
-tor_timegm(const struct tm *tm, time_t *time_out)
-{
- /* This is a pretty ironclad timegm implementation, snarfed from Python2.2.
- * It's way more brute-force than fiddling with tzset().
- *
- * We use int64_t rather than time_t to avoid overflow on multiplication on
- * platforms with 32-bit time_t. Since year is clipped to INT32_MAX, and
- * since 365 * 24 * 60 * 60 is approximately 31 million, it's not possible
- * for INT32_MAX years to overflow int64_t when converted to seconds. */
- int64_t year, days, hours, minutes, seconds;
- int i, invalid_year, dpm;
-
- /* Initialize time_out to 0 for now, to avoid bad usage in case this function
- fails and the caller ignores the return value. */
- tor_assert(time_out);
- *time_out = 0;
-
- /* avoid int overflow on addition */
- if (tm->tm_year < INT32_MAX-1900) {
- year = tm->tm_year + 1900;
- } else {
- /* clamp year */
- year = INT32_MAX;
- }
- invalid_year = (year < 1970 || tm->tm_year >= INT32_MAX-1900);
-
- if (tm->tm_mon >= 0 && tm->tm_mon <= 11) {
- dpm = days_per_month[tm->tm_mon];
- if (tm->tm_mon == 1 && !invalid_year && IS_LEAPYEAR(tm->tm_year)) {
- dpm = 29;
- }
- } else {
- /* invalid month - default to 0 days per month */
- dpm = 0;
- }
-
- if (invalid_year ||
- tm->tm_mon < 0 || tm->tm_mon > 11 ||
- tm->tm_mday < 1 || tm->tm_mday > dpm ||
- tm->tm_hour < 0 || tm->tm_hour > 23 ||
- tm->tm_min < 0 || tm->tm_min > 59 ||
- tm->tm_sec < 0 || tm->tm_sec > 60) {
- log_warn(LD_BUG, "Out-of-range argument to tor_timegm");
- return -1;
- }
- days = 365 * (year-1970) + n_leapdays(1970,(int)year);
- for (i = 0; i < tm->tm_mon; ++i)
- days += days_per_month[i];
- if (tm->tm_mon > 1 && IS_LEAPYEAR(year))
- ++days;
- days += tm->tm_mday - 1;
- hours = days*24 + tm->tm_hour;
-
- minutes = hours*60 + tm->tm_min;
- seconds = minutes*60 + tm->tm_sec;
- /* Check that "seconds" will fit in a time_t. On platforms where time_t is
- * 32-bit, this check will fail for dates in and after 2038.
- *
- * We already know that "seconds" can't be negative because "year" >= 1970 */
-#if SIZEOF_TIME_T < 8
- if (seconds < TIME_MIN || seconds > TIME_MAX) {
- log_warn(LD_BUG, "Result does not fit in tor_timegm");
- return -1;
- }
-#endif /* SIZEOF_TIME_T < 8 */
- *time_out = (time_t)seconds;
- return 0;
-}
-
-/* strftime is locale-specific, so we need to replace those parts */
-
-/** A c-locale array of 3-letter names of weekdays, starting with Sun. */
-static const char *WEEKDAY_NAMES[] =
- { "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" };
-/** A c-locale array of 3-letter names of months, starting with Jan. */
-static const char *MONTH_NAMES[] =
- { "Jan", "Feb", "Mar", "Apr", "May", "Jun",
- "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" };
-
-/** Set <b>buf</b> to the RFC1123 encoding of the UTC value of <b>t</b>.
- * The buffer must be at least RFC1123_TIME_LEN+1 bytes long.
- *
- * (RFC1123 format is "Fri, 29 Sep 2006 15:54:20 GMT". Note the "GMT"
- * rather than "UTC".)
- */
-void
-format_rfc1123_time(char *buf, time_t t)
-{
- struct tm tm;
-
- tor_gmtime_r(&t, &tm);
-
- strftime(buf, RFC1123_TIME_LEN+1, "___, %d ___ %Y %H:%M:%S GMT", &tm);
- tor_assert(tm.tm_wday >= 0);
- tor_assert(tm.tm_wday <= 6);
- memcpy(buf, WEEKDAY_NAMES[tm.tm_wday], 3);
- tor_assert(tm.tm_mon >= 0);
- tor_assert(tm.tm_mon <= 11);
- memcpy(buf+8, MONTH_NAMES[tm.tm_mon], 3);
-}
-
-/** Parse the (a subset of) the RFC1123 encoding of some time (in UTC) from
- * <b>buf</b>, and store the result in *<b>t</b>.
- *
- * Note that we only accept the subset generated by format_rfc1123_time above,
- * not the full range of formats suggested by RFC 1123.
- *
- * Return 0 on success, -1 on failure.
-*/
-int
-parse_rfc1123_time(const char *buf, time_t *t)
-{
- struct tm tm;
- char month[4];
- char weekday[4];
- int i, m, invalid_year;
- unsigned tm_mday, tm_year, tm_hour, tm_min, tm_sec;
- unsigned dpm;
-
- if (strlen(buf) != RFC1123_TIME_LEN)
- return -1;
- memset(&tm, 0, sizeof(tm));
- if (tor_sscanf(buf, "%3s, %2u %3s %u %2u:%2u:%2u GMT", weekday,
- &tm_mday, month, &tm_year, &tm_hour,
- &tm_min, &tm_sec) < 7) {
- char *esc = esc_for_log(buf);
- log_warn(LD_GENERAL, "Got invalid RFC1123 time %s", esc);
- tor_free(esc);
- return -1;
- }
-
- m = -1;
- for (i = 0; i < 12; ++i) {
- if (!strcmp(month, MONTH_NAMES[i])) {
- m = i;
- break;
- }
- }
- if (m<0) {
- char *esc = esc_for_log(buf);
- log_warn(LD_GENERAL, "Got invalid RFC1123 time %s: No such month", esc);
- tor_free(esc);
- return -1;
- }
- tm.tm_mon = m;
-
- invalid_year = (tm_year >= INT32_MAX || tm_year < 1970);
- tor_assert(m >= 0 && m <= 11);
- dpm = days_per_month[m];
- if (m == 1 && !invalid_year && IS_LEAPYEAR(tm_year)) {
- dpm = 29;
- }
-
- if (invalid_year || tm_mday < 1 || tm_mday > dpm ||
- tm_hour > 23 || tm_min > 59 || tm_sec > 60) {
- char *esc = esc_for_log(buf);
- log_warn(LD_GENERAL, "Got invalid RFC1123 time %s", esc);
- tor_free(esc);
- return -1;
- }
- tm.tm_mday = (int)tm_mday;
- tm.tm_year = (int)tm_year;
- tm.tm_hour = (int)tm_hour;
- tm.tm_min = (int)tm_min;
- tm.tm_sec = (int)tm_sec;
-
- if (tm.tm_year < 1970) {
- /* LCOV_EXCL_START
- * XXXX I think this is dead code; we already checked for
- * invalid_year above. */
- tor_assert_nonfatal_unreached();
- char *esc = esc_for_log(buf);
- log_warn(LD_GENERAL,
- "Got invalid RFC1123 time %s. (Before 1970)", esc);
- tor_free(esc);
- return -1;
- /* LCOV_EXCL_STOP */
- }
- tm.tm_year -= 1900;
-
- return tor_timegm(&tm, t);
-}
-
-/** Set <b>buf</b> to the ISO8601 encoding of the local value of <b>t</b>.
- * The buffer must be at least ISO_TIME_LEN+1 bytes long.
- *
- * (ISO8601 format is 2006-10-29 10:57:20)
- */
-void
-format_local_iso_time(char *buf, time_t t)
-{
- struct tm tm;
- strftime(buf, ISO_TIME_LEN+1, "%Y-%m-%d %H:%M:%S", tor_localtime_r(&t, &tm));
-}
-
-/** Set <b>buf</b> to the ISO8601 encoding of the GMT value of <b>t</b>.
- * The buffer must be at least ISO_TIME_LEN+1 bytes long.
- */
-void
-format_iso_time(char *buf, time_t t)
-{
- struct tm tm;
- strftime(buf, ISO_TIME_LEN+1, "%Y-%m-%d %H:%M:%S", tor_gmtime_r(&t, &tm));
-}
-
-/** As format_local_iso_time, but use the yyyy-mm-ddThh:mm:ss format to avoid
- * embedding an internal space. */
-void
-format_local_iso_time_nospace(char *buf, time_t t)
-{
- format_local_iso_time(buf, t);
- buf[10] = 'T';
-}
-
-/** As format_iso_time, but use the yyyy-mm-ddThh:mm:ss format to avoid
- * embedding an internal space. */
-void
-format_iso_time_nospace(char *buf, time_t t)
-{
- format_iso_time(buf, t);
- buf[10] = 'T';
-}
-
-/** As format_iso_time_nospace, but include microseconds in decimal
- * fixed-point format. Requires that buf be at least ISO_TIME_USEC_LEN+1
- * bytes long. */
-void
-format_iso_time_nospace_usec(char *buf, const struct timeval *tv)
-{
- tor_assert(tv);
- format_iso_time_nospace(buf, (time_t)tv->tv_sec);
- tor_snprintf(buf+ISO_TIME_LEN, 8, ".%06d", (int)tv->tv_usec);
-}
-
-/** Given an ISO-formatted UTC time value (after the epoch) in <b>cp</b>,
- * parse it and store its value in *<b>t</b>. Return 0 on success, -1 on
- * failure. Ignore extraneous stuff in <b>cp</b> after the end of the time
- * string, unless <b>strict</b> is set. If <b>nospace</b> is set,
- * expect the YYYY-MM-DDTHH:MM:SS format. */
-int
-parse_iso_time_(const char *cp, time_t *t, int strict, int nospace)
-{
- struct tm st_tm;
- unsigned int year=0, month=0, day=0, hour=0, minute=0, second=0;
- int n_fields;
- char extra_char, separator_char;
- n_fields = tor_sscanf(cp, "%u-%2u-%2u%c%2u:%2u:%2u%c",
- &year, &month, &day,
- &separator_char,
- &hour, &minute, &second, &extra_char);
- if (strict ? (n_fields != 7) : (n_fields < 7)) {
- char *esc = esc_for_log(cp);
- log_warn(LD_GENERAL, "ISO time %s was unparseable", esc);
- tor_free(esc);
- return -1;
- }
- if (separator_char != (nospace ? 'T' : ' ')) {
- char *esc = esc_for_log(cp);
- log_warn(LD_GENERAL, "ISO time %s was unparseable", esc);
- tor_free(esc);
- return -1;
- }
- if (year < 1970 || month < 1 || month > 12 || day < 1 || day > 31 ||
- hour > 23 || minute > 59 || second > 60 || year >= INT32_MAX) {
- char *esc = esc_for_log(cp);
- log_warn(LD_GENERAL, "ISO time %s was nonsensical", esc);
- tor_free(esc);
- return -1;
- }
- st_tm.tm_year = (int)year-1900;
- st_tm.tm_mon = month-1;
- st_tm.tm_mday = day;
- st_tm.tm_hour = hour;
- st_tm.tm_min = minute;
- st_tm.tm_sec = second;
- st_tm.tm_wday = 0; /* Should be ignored. */
-
- if (st_tm.tm_year < 70) {
- /* LCOV_EXCL_START
- * XXXX I think this is dead code; we already checked for
- * year < 1970 above. */
- tor_assert_nonfatal_unreached();
- char *esc = esc_for_log(cp);
- log_warn(LD_GENERAL, "Got invalid ISO time %s. (Before 1970)", esc);
- tor_free(esc);
- return -1;
- /* LCOV_EXCL_STOP */
- }
- return tor_timegm(&st_tm, t);
-}
-
-/** Given an ISO-formatted UTC time value (after the epoch) in <b>cp</b>,
- * parse it and store its value in *<b>t</b>. Return 0 on success, -1 on
- * failure. Reject the string if any characters are present after the time.
- */
-int
-parse_iso_time(const char *cp, time_t *t)
-{
- return parse_iso_time_(cp, t, 1, 0);
-}
-
-/**
- * As parse_iso_time, but parses a time encoded by format_iso_time_nospace().
- */
-int
-parse_iso_time_nospace(const char *cp, time_t *t)
-{
- return parse_iso_time_(cp, t, 1, 1);
-}
-
-/** Given a <b>date</b> in one of the three formats allowed by HTTP (ugh),
- * parse it into <b>tm</b>. Return 0 on success, negative on failure. */
-int
-parse_http_time(const char *date, struct tm *tm)
-{
- const char *cp;
- char month[4];
- char wkday[4];
- int i;
- unsigned tm_mday, tm_year, tm_hour, tm_min, tm_sec;
-
- tor_assert(tm);
- memset(tm, 0, sizeof(*tm));
-
- /* First, try RFC1123 or RFC850 format: skip the weekday. */
- if ((cp = strchr(date, ','))) {
- ++cp;
- if (*cp != ' ')
- return -1;
- ++cp;
- if (tor_sscanf(cp, "%2u %3s %4u %2u:%2u:%2u GMT",
- &tm_mday, month, &tm_year,
- &tm_hour, &tm_min, &tm_sec) == 6) {
- /* rfc1123-date */
- tm_year -= 1900;
- } else if (tor_sscanf(cp, "%2u-%3s-%2u %2u:%2u:%2u GMT",
- &tm_mday, month, &tm_year,
- &tm_hour, &tm_min, &tm_sec) == 6) {
- /* rfc850-date */
- } else {
- return -1;
- }
- } else {
- /* No comma; possibly asctime() format. */
- if (tor_sscanf(date, "%3s %3s %2u %2u:%2u:%2u %4u",
- wkday, month, &tm_mday,
- &tm_hour, &tm_min, &tm_sec, &tm_year) == 7) {
- tm_year -= 1900;
- } else {
- return -1;
- }
- }
- tm->tm_mday = (int)tm_mday;
- tm->tm_year = (int)tm_year;
- tm->tm_hour = (int)tm_hour;
- tm->tm_min = (int)tm_min;
- tm->tm_sec = (int)tm_sec;
- tm->tm_wday = 0; /* Leave this unset. */
-
- month[3] = '\0';
- /* Okay, now decode the month. */
- /* set tm->tm_mon to dummy value so the check below fails. */
- tm->tm_mon = -1;
- for (i = 0; i < 12; ++i) {
- if (!strcasecmp(MONTH_NAMES[i], month)) {
- tm->tm_mon = i;
- }
- }
-
- if (tm->tm_year < 0 ||
- tm->tm_mon < 0 || tm->tm_mon > 11 ||
- tm->tm_mday < 1 || tm->tm_mday > 31 ||
- tm->tm_hour < 0 || tm->tm_hour > 23 ||
- tm->tm_min < 0 || tm->tm_min > 59 ||
- tm->tm_sec < 0 || tm->tm_sec > 60)
- return -1; /* Out of range, or bad month. */
-
- return 0;
-}
-
-/** Given an <b>interval</b> in seconds, try to write it to the
- * <b>out_len</b>-byte buffer in <b>out</b> in a human-readable form.
- * Returns a non-negative integer on success, -1 on failure.
- */
-int
-format_time_interval(char *out, size_t out_len, long interval)
-{
- /* We only report seconds if there's no hours. */
- long sec = 0, min = 0, hour = 0, day = 0;
-
- /* -LONG_MIN is LONG_MAX + 1, which causes signed overflow */
- if (interval < -LONG_MAX)
- interval = LONG_MAX;
- else if (interval < 0)
- interval = -interval;
-
- if (interval >= 86400) {
- day = interval / 86400;
- interval %= 86400;
- }
- if (interval >= 3600) {
- hour = interval / 3600;
- interval %= 3600;
- }
- if (interval >= 60) {
- min = interval / 60;
- interval %= 60;
- }
- sec = interval;
-
- if (day) {
- return tor_snprintf(out, out_len, "%ld days, %ld hours, %ld minutes",
- day, hour, min);
- } else if (hour) {
- return tor_snprintf(out, out_len, "%ld hours, %ld minutes", hour, min);
- } else if (min) {
- return tor_snprintf(out, out_len, "%ld minutes, %ld seconds", min, sec);
- } else {
- return tor_snprintf(out, out_len, "%ld seconds", sec);
- }
-}
-
-/* =====
- * Cached time
- * ===== */
-
-#ifndef TIME_IS_FAST
-/** Cached estimate of the current time. Updated around once per second;
- * may be a few seconds off if we are really busy. This is a hack to avoid
- * calling time(NULL) (which not everybody has optimized) on critical paths.
- */
-static time_t cached_approx_time = 0;
-
-/** Return a cached estimate of the current time from when
- * update_approx_time() was last called. This is a hack to avoid calling
- * time(NULL) on critical paths: please do not even think of calling it
- * anywhere else. */
-time_t
-approx_time(void)
-{
- return cached_approx_time;
-}
-
-/** Update the cached estimate of the current time. This function SHOULD be
- * called once per second, and MUST be called before the first call to
- * get_approx_time. */
-void
-update_approx_time(time_t now)
-{
- cached_approx_time = now;
-}
-#endif /* !defined(TIME_IS_FAST) */
-
-/* =====
- * Rate limiting
- * ===== */
-
-/** If the rate-limiter <b>lim</b> is ready at <b>now</b>, return the number
- * of calls to rate_limit_is_ready (including this one!) since the last time
- * rate_limit_is_ready returned nonzero. Otherwise return 0.
- * If the call number hits <b>RATELIM_TOOMANY</b> limit, drop a warning
- * about this event and stop counting. */
-static int
-rate_limit_is_ready(ratelim_t *lim, time_t now)
-{
- if (lim->rate + lim->last_allowed <= now) {
- int res = lim->n_calls_since_last_time + 1;
- lim->last_allowed = now;
- lim->n_calls_since_last_time = 0;
- return res;
- } else {
- if (lim->n_calls_since_last_time <= RATELIM_TOOMANY) {
- ++lim->n_calls_since_last_time;
- }
-
- return 0;
- }
-}
-
-/** If the rate-limiter <b>lim</b> is ready at <b>now</b>, return a newly
- * allocated string indicating how many messages were suppressed, suitable to
- * append to a log message. Otherwise return NULL. */
-char *
-rate_limit_log(ratelim_t *lim, time_t now)
-{
- int n;
- if ((n = rate_limit_is_ready(lim, now))) {
- if (n == 1) {
- return tor_strdup("");
- } else {
- char *cp=NULL;
- const char *opt_over = (n >= RATELIM_TOOMANY) ? "over " : "";
- /* XXXX this is not exactly correct: the messages could have occurred
- * any time between the old value of lim->allowed and now. */
- tor_asprintf(&cp,
- " [%s%d similar message(s) suppressed in last %d seconds]",
- opt_over, n-1, lim->rate);
- return cp;
- }
- } else {
- return NULL;
- }
-}
-
-/* =====
- * File helpers
- * ===== */
-
-/** Write <b>count</b> bytes from <b>buf</b> to <b>fd</b>. <b>isSocket</b>
- * must be 1 if fd was returned by socket() or accept(), and 0 if fd
- * was returned by open(). Return the number of bytes written, or -1
- * on error. Only use if fd is a blocking fd. */
-ssize_t
-write_all(tor_socket_t fd, const char *buf, size_t count, int isSocket)
-{
- size_t written = 0;
- ssize_t result;
- tor_assert(count < SSIZE_MAX);
-
- while (written != count) {
- if (isSocket)
- result = tor_socket_send(fd, buf+written, count-written, 0);
- else
- result = write((int)fd, buf+written, count-written);
- if (result<0)
- return -1;
- written += result;
- }
- return (ssize_t)count;
-}
-
-/** Read from <b>fd</b> to <b>buf</b>, until we get <b>count</b> bytes
- * or reach the end of the file. <b>isSocket</b> must be 1 if fd
- * was returned by socket() or accept(), and 0 if fd was returned by
- * open(). Return the number of bytes read, or -1 on error. Only use
- * if fd is a blocking fd. */
-ssize_t
-read_all(tor_socket_t fd, char *buf, size_t count, int isSocket)
-{
- size_t numread = 0;
- ssize_t result;
-
- if (count > SIZE_T_CEILING || count > SSIZE_MAX) {
- errno = EINVAL;
- return -1;
- }
-
- while (numread < count) {
- if (isSocket)
- result = tor_socket_recv(fd, buf+numread, count-numread, 0);
- else
- result = read((int)fd, buf+numread, count-numread);
- if (result<0)
- return -1;
- else if (result == 0)
- break;
- numread += result;
- }
- return (ssize_t)numread;
-}
-
-/*
- * Filesystem operations.
- */
-
-/** Clean up <b>name</b> so that we can use it in a call to "stat". On Unix,
- * we do nothing. On Windows, we remove a trailing slash, unless the path is
- * the root of a disk. */
-static void
-clean_name_for_stat(char *name)
-{
-#ifdef _WIN32
- size_t len = strlen(name);
- if (!len)
- return;
- if (name[len-1]=='\\' || name[len-1]=='/') {
- if (len == 1 || (len==3 && name[1]==':'))
- return;
- name[len-1]='\0';
- }
-#else /* !(defined(_WIN32)) */
- (void)name;
-#endif /* defined(_WIN32) */
-}
-
-/** Wrapper for unlink() to make it mockable for the test suite; returns 0
- * if unlinking the file succeeded, -1 and sets errno if unlinking fails.
- */
-
-MOCK_IMPL(int,
-tor_unlink,(const char *pathname))
-{
- return unlink(pathname);
-}
-
-/** Return:
- * FN_ERROR if filename can't be read, is NULL, or is zero-length,
- * FN_NOENT if it doesn't exist,
- * FN_FILE if it is a non-empty regular file, or a FIFO on unix-like systems,
- * FN_EMPTY for zero-byte regular files,
- * FN_DIR if it's a directory, and
- * FN_ERROR for any other file type.
- * On FN_ERROR and FN_NOENT, sets errno. (errno is not set when FN_ERROR
- * is returned due to an unhandled file type.) */
-file_status_t
-file_status(const char *fname)
-{
- struct stat st;
- char *f;
- int r;
- if (!fname || strlen(fname) == 0) {
- return FN_ERROR;
- }
- f = tor_strdup(fname);
- clean_name_for_stat(f);
- log_debug(LD_FS, "stat()ing %s", f);
- r = stat(sandbox_intern_string(f), &st);
- tor_free(f);
- if (r) {
- if (errno == ENOENT) {
- return FN_NOENT;
- }
- return FN_ERROR;
- }
- if (st.st_mode & S_IFDIR) {
- return FN_DIR;
- } else if (st.st_mode & S_IFREG) {
- if (st.st_size > 0) {
- return FN_FILE;
- } else if (st.st_size == 0) {
- return FN_EMPTY;
- } else {
- return FN_ERROR;
- }
-#ifndef _WIN32
- } else if (st.st_mode & S_IFIFO) {
- return FN_FILE;
-#endif
- } else {
- return FN_ERROR;
- }
-}
-
-/** Check whether <b>dirname</b> exists and is private. If yes return 0.
- * If <b>dirname</b> does not exist:
- * - if <b>check</b>&CPD_CREATE, try to create it and return 0 on success.
- * - if <b>check</b>&CPD_CHECK, and we think we can create it, return 0.
- * - if <b>check</b>&CPD_CHECK is false, and the directory exists, return 0.
- * - otherwise, return -1.
- * If CPD_GROUP_OK is set, then it's okay if the directory
- * is group-readable, but in all cases we create the directory mode 0700.
- * If CPD_GROUP_READ is set, existing directory behaves as CPD_GROUP_OK and
- * if the directory is created it will use mode 0750 with group read
- * permission. Group read privileges also assume execute permission
- * as norm for directories. If CPD_CHECK_MODE_ONLY is set, then we don't
- * alter the directory permissions if they are too permissive:
- * we just return -1.
- * When effective_user is not NULL, check permissions against the given user
- * and its primary group.
- */
-MOCK_IMPL(int,
-check_private_dir,(const char *dirname, cpd_check_t check,
- const char *effective_user))
-{
- int r;
- struct stat st;
-
- tor_assert(dirname);
-
-#ifndef _WIN32
- int fd;
- const struct passwd *pw = NULL;
- uid_t running_uid;
- gid_t running_gid;
-
- /*
- * Goal is to harden the implementation by removing any
- * potential for race between stat() and chmod().
- * chmod() accepts filename as argument. If an attacker can move
- * the file between stat() and chmod(), a potential race exists.
- *
- * Several suggestions taken from:
- * https://developer.apple.com/library/mac/documentation/
- * Security/Conceptual/SecureCodingGuide/Articles/RaceConditions.html
- */
-
- /* Open directory.
- * O_NOFOLLOW to ensure that it does not follow symbolic links */
- fd = open(sandbox_intern_string(dirname), O_NOFOLLOW);
-
- /* Was there an error? Maybe the directory does not exist? */
- if (fd == -1) {
-
- if (errno != ENOENT) {
- /* Other directory error */
- log_warn(LD_FS, "Directory %s cannot be read: %s", dirname,
- strerror(errno));
- return -1;
- }
-
- /* Received ENOENT: Directory does not exist */
-
- /* Should we create the directory? */
- if (check & CPD_CREATE) {
- log_info(LD_GENERAL, "Creating directory %s", dirname);
- if (check & CPD_GROUP_READ) {
- r = mkdir(dirname, 0750);
- } else {
- r = mkdir(dirname, 0700);
- }
-
- /* check for mkdir() error */
- if (r) {
- log_warn(LD_FS, "Error creating directory %s: %s", dirname,
- strerror(errno));
- return -1;
- }
-
- /* we just created the directory. try to open it again.
- * permissions on the directory will be checked again below.*/
- fd = open(sandbox_intern_string(dirname), O_NOFOLLOW);
-
- if (fd == -1) {
- log_warn(LD_FS, "Could not reopen recently created directory %s: %s",
- dirname,
- strerror(errno));
- return -1;
- } else {
- close(fd);
- }
-
- } else if (!(check & CPD_CHECK)) {
- log_warn(LD_FS, "Directory %s does not exist.", dirname);
- return -1;
- }
-
- /* XXXX In the case where check==CPD_CHECK, we should look at the
- * parent directory a little harder. */
- return 0;
- }
-
- tor_assert(fd >= 0);
-
- //f = tor_strdup(dirname);
- //clean_name_for_stat(f);
- log_debug(LD_FS, "stat()ing %s", dirname);
- //r = stat(sandbox_intern_string(f), &st);
- r = fstat(fd, &st);
- if (r == -1) {
- log_warn(LD_FS, "fstat() on directory %s failed.", dirname);
- close(fd);
- return -1;
- }
- //tor_free(f);
-
- /* check that dirname is a directory */
- if (!(st.st_mode & S_IFDIR)) {
- log_warn(LD_FS, "%s is not a directory", dirname);
- close(fd);
- return -1;
- }
-
- if (effective_user) {
- /* Look up the user and group information.
- * If we have a problem, bail out. */
- pw = tor_getpwnam(effective_user);
- if (pw == NULL) {
- log_warn(LD_CONFIG, "Error setting configured user: %s not found",
- effective_user);
- close(fd);
- return -1;
- }
- running_uid = pw->pw_uid;
- running_gid = pw->pw_gid;
- } else {
- running_uid = getuid();
- running_gid = getgid();
- }
- if (st.st_uid != running_uid) {
- char *process_ownername = NULL, *file_ownername = NULL;
-
- {
- const struct passwd *pw_running = tor_getpwuid(running_uid);
- process_ownername = pw_running ? tor_strdup(pw_running->pw_name) :
- tor_strdup("<unknown>");
- }
-
- {
- const struct passwd *pw_stat = tor_getpwuid(st.st_uid);
- file_ownername = pw_stat ? tor_strdup(pw_stat->pw_name) :
- tor_strdup("<unknown>");
- }
-
- log_warn(LD_FS, "%s is not owned by this user (%s, %d) but by "
- "%s (%d). Perhaps you are running Tor as the wrong user?",
- dirname, process_ownername, (int)running_uid,
- file_ownername, (int)st.st_uid);
-
- tor_free(process_ownername);
- tor_free(file_ownername);
- close(fd);
- return -1;
- }
- if ( (check & (CPD_GROUP_OK|CPD_GROUP_READ))
- && (st.st_gid != running_gid) && (st.st_gid != 0)) {
- struct group *gr;
- char *process_groupname = NULL;
- gr = getgrgid(running_gid);
- process_groupname = gr ? tor_strdup(gr->gr_name) : tor_strdup("<unknown>");
- gr = getgrgid(st.st_gid);
-
- log_warn(LD_FS, "%s is not owned by this group (%s, %d) but by group "
- "%s (%d). Are you running Tor as the wrong user?",
- dirname, process_groupname, (int)running_gid,
- gr ? gr->gr_name : "<unknown>", (int)st.st_gid);
-
- tor_free(process_groupname);
- close(fd);
- return -1;
- }
- unsigned unwanted_bits = 0;
- if (check & (CPD_GROUP_OK|CPD_GROUP_READ)) {
- unwanted_bits = 0027;
- } else {
- unwanted_bits = 0077;
- }
- unsigned check_bits_filter = ~0;
- if (check & CPD_RELAX_DIRMODE_CHECK) {
- check_bits_filter = 0022;
- }
- if ((st.st_mode & unwanted_bits & check_bits_filter) != 0) {
- unsigned new_mode;
- if (check & CPD_CHECK_MODE_ONLY) {
- log_warn(LD_FS, "Permissions on directory %s are too permissive.",
- dirname);
- close(fd);
- return -1;
- }
- log_warn(LD_FS, "Fixing permissions on directory %s", dirname);
- new_mode = st.st_mode;
- new_mode |= 0700; /* Owner should have rwx */
- if (check & CPD_GROUP_READ) {
- new_mode |= 0050; /* Group should have rx */
- }
- new_mode &= ~unwanted_bits; /* Clear the bits that we didn't want set...*/
- if (fchmod(fd, new_mode)) {
- log_warn(LD_FS, "Could not chmod directory %s: %s", dirname,
- strerror(errno));
- close(fd);
- return -1;
- } else {
- close(fd);
- return 0;
- }
- }
- close(fd);
-#else /* !(!defined(_WIN32)) */
- /* Win32 case: we can't open() a directory. */
- (void)effective_user;
-
- char *f = tor_strdup(dirname);
- clean_name_for_stat(f);
- log_debug(LD_FS, "stat()ing %s", f);
- r = stat(sandbox_intern_string(f), &st);
- tor_free(f);
- if (r) {
- if (errno != ENOENT) {
- log_warn(LD_FS, "Directory %s cannot be read: %s", dirname,
- strerror(errno));
- return -1;
- }
- if (check & CPD_CREATE) {
- log_info(LD_GENERAL, "Creating directory %s", dirname);
- r = mkdir(dirname);
- if (r) {
- log_warn(LD_FS, "Error creating directory %s: %s", dirname,
- strerror(errno));
- return -1;
- }
- } else if (!(check & CPD_CHECK)) {
- log_warn(LD_FS, "Directory %s does not exist.", dirname);
- return -1;
- }
- return 0;
- }
- if (!(st.st_mode & S_IFDIR)) {
- log_warn(LD_FS, "%s is not a directory", dirname);
- return -1;
- }
-
-#endif /* !defined(_WIN32) */
- return 0;
-}
-
-/** Create a file named <b>fname</b> with the contents <b>str</b>. Overwrite
- * the previous <b>fname</b> if possible. Return 0 on success, -1 on failure.
- *
- * This function replaces the old file atomically, if possible. This
- * function, and all other functions in util.c that create files, create them
- * with mode 0600.
- */
-MOCK_IMPL(int,
-write_str_to_file,(const char *fname, const char *str, int bin))
-{
-#ifdef _WIN32
- if (!bin && strchr(str, '\r')) {
- log_warn(LD_BUG,
- "We're writing a text string that already contains a CR to %s",
- escaped(fname));
- }
-#endif /* defined(_WIN32) */
- return write_bytes_to_file(fname, str, strlen(str), bin);
-}
-
-/** Represents a file that we're writing to, with support for atomic commit:
- * we can write into a temporary file, and either remove the file on
- * failure, or replace the original file on success. */
-struct open_file_t {
- char *tempname; /**< Name of the temporary file. */
- char *filename; /**< Name of the original file. */
- unsigned rename_on_close:1; /**< Are we using the temporary file or not? */
- unsigned binary:1; /**< Did we open in binary mode? */
- int fd; /**< fd for the open file. */
- FILE *stdio_file; /**< stdio wrapper for <b>fd</b>. */
-};
-
-/** Try to start writing to the file in <b>fname</b>, passing the flags
- * <b>open_flags</b> to the open() syscall, creating the file (if needed) with
- * access value <b>mode</b>. If the O_APPEND flag is set, we append to the
- * original file. Otherwise, we open a new temporary file in the same
- * directory, and either replace the original or remove the temporary file
- * when we're done.
- *
- * Return the fd for the newly opened file, and store working data in
- * *<b>data_out</b>. The caller should not close the fd manually:
- * instead, call finish_writing_to_file() or abort_writing_to_file().
- * Returns -1 on failure.
- *
- * NOTE: When not appending, the flags O_CREAT and O_TRUNC are treated
- * as true and the flag O_EXCL is treated as false.
- *
- * NOTE: Ordinarily, O_APPEND means "seek to the end of the file before each
- * write()". We don't do that.
- */
-int
-start_writing_to_file(const char *fname, int open_flags, int mode,
- open_file_t **data_out)
-{
- open_file_t *new_file = tor_malloc_zero(sizeof(open_file_t));
- const char *open_name;
- int append = 0;
-
- tor_assert(fname);
- tor_assert(data_out);
-#if (O_BINARY != 0 && O_TEXT != 0)
- tor_assert((open_flags & (O_BINARY|O_TEXT)) != 0);
-#endif
- new_file->fd = -1;
- new_file->filename = tor_strdup(fname);
- if (open_flags & O_APPEND) {
- open_name = fname;
- new_file->rename_on_close = 0;
- append = 1;
- open_flags &= ~O_APPEND;
- } else {
- tor_asprintf(&new_file->tempname, "%s.tmp", fname);
- open_name = new_file->tempname;
- /* We always replace an existing temporary file if there is one. */
- open_flags |= O_CREAT|O_TRUNC;
- open_flags &= ~O_EXCL;
- new_file->rename_on_close = 1;
- }
-#if O_BINARY != 0
- if (open_flags & O_BINARY)
- new_file->binary = 1;
-#endif
-
- new_file->fd = tor_open_cloexec(open_name, open_flags, mode);
- if (new_file->fd < 0) {
- log_warn(LD_FS, "Couldn't open \"%s\" (%s) for writing: %s",
- open_name, fname, strerror(errno));
- goto err;
- }
- if (append) {
- if (tor_fd_seekend(new_file->fd) < 0) {
- log_warn(LD_FS, "Couldn't seek to end of file \"%s\": %s", open_name,
- strerror(errno));
- goto err;
- }
- }
-
- *data_out = new_file;
-
- return new_file->fd;
-
- err:
- if (new_file->fd >= 0)
- close(new_file->fd);
- *data_out = NULL;
- tor_free(new_file->filename);
- tor_free(new_file->tempname);
- tor_free(new_file);
- return -1;
-}
-
-/** Given <b>file_data</b> from start_writing_to_file(), return a stdio FILE*
- * that can be used to write to the same file. The caller should not mix
- * stdio calls with non-stdio calls. */
-FILE *
-fdopen_file(open_file_t *file_data)
-{
- tor_assert(file_data);
- if (file_data->stdio_file)
- return file_data->stdio_file;
- tor_assert(file_data->fd >= 0);
- if (!(file_data->stdio_file = fdopen(file_data->fd,
- file_data->binary?"ab":"a"))) {
- log_warn(LD_FS, "Couldn't fdopen \"%s\" [%d]: %s", file_data->filename,
- file_data->fd, strerror(errno));
- }
- return file_data->stdio_file;
-}
-
-/** Combines start_writing_to_file with fdopen_file(): arguments are as
- * for start_writing_to_file, but */
-FILE *
-start_writing_to_stdio_file(const char *fname, int open_flags, int mode,
- open_file_t **data_out)
-{
- FILE *res;
- if (start_writing_to_file(fname, open_flags, mode, data_out)<0)
- return NULL;
- if (!(res = fdopen_file(*data_out))) {
- abort_writing_to_file(*data_out);
- *data_out = NULL;
- }
- return res;
-}
-
-/** Helper function: close and free the underlying file and memory in
- * <b>file_data</b>. If we were writing into a temporary file, then delete
- * that file (if abort_write is true) or replaces the target file with
- * the temporary file (if abort_write is false). */
-static int
-finish_writing_to_file_impl(open_file_t *file_data, int abort_write)
-{
- int r = 0;
-
- tor_assert(file_data && file_data->filename);
- if (file_data->stdio_file) {
- if (fclose(file_data->stdio_file)) {
- log_warn(LD_FS, "Error closing \"%s\": %s", file_data->filename,
- strerror(errno));
- abort_write = r = -1;
- }
- } else if (file_data->fd >= 0 && close(file_data->fd) < 0) {
- log_warn(LD_FS, "Error flushing \"%s\": %s", file_data->filename,
- strerror(errno));
- abort_write = r = -1;
- }
-
- if (file_data->rename_on_close) {
- tor_assert(file_data->tempname && file_data->filename);
- if (!abort_write) {
- tor_assert(strcmp(file_data->filename, file_data->tempname));
- if (replace_file(file_data->tempname, file_data->filename)) {
- log_warn(LD_FS, "Error replacing \"%s\": %s", file_data->filename,
- strerror(errno));
- abort_write = r = -1;
- }
- }
- if (abort_write) {
- int res = unlink(file_data->tempname);
- if (res != 0) {
- /* We couldn't unlink and we'll leave a mess behind */
- log_warn(LD_FS, "Failed to unlink %s: %s",
- file_data->tempname, strerror(errno));
- r = -1;
- }
- }
- }
-
- tor_free(file_data->filename);
- tor_free(file_data->tempname);
- tor_free(file_data);
-
- return r;
-}
-
-/** Finish writing to <b>file_data</b>: close the file handle, free memory as
- * needed, and if using a temporary file, replace the original file with
- * the temporary file. */
-int
-finish_writing_to_file(open_file_t *file_data)
-{
- return finish_writing_to_file_impl(file_data, 0);
-}
-
-/** Finish writing to <b>file_data</b>: close the file handle, free memory as
- * needed, and if using a temporary file, delete it. */
-int
-abort_writing_to_file(open_file_t *file_data)
-{
- return finish_writing_to_file_impl(file_data, 1);
-}
-
-/** Helper: given a set of flags as passed to open(2), open the file
- * <b>fname</b> and write all the sized_chunk_t structs in <b>chunks</b> to
- * the file. Do so as atomically as possible e.g. by opening temp files and
- * renaming. */
-static int
-write_chunks_to_file_impl(const char *fname, const smartlist_t *chunks,
- int open_flags)
-{
- open_file_t *file = NULL;
- int fd;
- ssize_t result;
- fd = start_writing_to_file(fname, open_flags, 0600, &file);
- if (fd<0)
- return -1;
- SMARTLIST_FOREACH(chunks, sized_chunk_t *, chunk,
- {
- result = write_all(fd, chunk->bytes, chunk->len, 0);
- if (result < 0) {
- log_warn(LD_FS, "Error writing to \"%s\": %s", fname,
- strerror(errno));
- goto err;
- }
- tor_assert((size_t)result == chunk->len);
- });
-
- return finish_writing_to_file(file);
- err:
- abort_writing_to_file(file);
- return -1;
-}
-
-/** Given a smartlist of sized_chunk_t, write them to a file
- * <b>fname</b>, overwriting or creating the file as necessary.
- * If <b>no_tempfile</b> is 0 then the file will be written
- * atomically. */
-int
-write_chunks_to_file(const char *fname, const smartlist_t *chunks, int bin,
- int no_tempfile)
-{
- int flags = OPEN_FLAGS_REPLACE|(bin?O_BINARY:O_TEXT);
-
- if (no_tempfile) {
- /* O_APPEND stops write_chunks_to_file from using tempfiles */
- flags |= O_APPEND;
- }
- return write_chunks_to_file_impl(fname, chunks, flags);
-}
-
-/** Write <b>len</b> bytes, starting at <b>str</b>, to <b>fname</b>
- using the open() flags passed in <b>flags</b>. */
-static int
-write_bytes_to_file_impl(const char *fname, const char *str, size_t len,
- int flags)
-{
- int r;
- sized_chunk_t c = { str, len };
- smartlist_t *chunks = smartlist_new();
- smartlist_add(chunks, &c);
- r = write_chunks_to_file_impl(fname, chunks, flags);
- smartlist_free(chunks);
- return r;
-}
-
-/** As write_str_to_file, but does not assume a NUL-terminated
- * string. Instead, we write <b>len</b> bytes, starting at <b>str</b>. */
-MOCK_IMPL(int,
-write_bytes_to_file,(const char *fname, const char *str, size_t len,
- int bin))
-{
- return write_bytes_to_file_impl(fname, str, len,
- OPEN_FLAGS_REPLACE|(bin?O_BINARY:O_TEXT));
-}
-
-/** As write_bytes_to_file, but if the file already exists, append the bytes
- * to the end of the file instead of overwriting it. */
-int
-append_bytes_to_file(const char *fname, const char *str, size_t len,
- int bin)
-{
- return write_bytes_to_file_impl(fname, str, len,
- OPEN_FLAGS_APPEND|(bin?O_BINARY:O_TEXT));
-}
-
-/** Like write_str_to_file(), but also return -1 if there was a file
- already residing in <b>fname</b>. */
-int
-write_bytes_to_new_file(const char *fname, const char *str, size_t len,
- int bin)
-{
- return write_bytes_to_file_impl(fname, str, len,
- OPEN_FLAGS_DONT_REPLACE|
- (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) {
- errno = EINVAL;
- 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) {
- int save_errno = errno;
- tor_free(string);
- errno = save_errno;
- return NULL;
- }
-
- pos += r;
- } while (r > 0 && pos < max_bytes_to_read);
-
- tor_assert(pos < string_max);
- *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.
- *
- * If <b>stat_out</b> is provided, store the result of stat()ing the
- * file into <b>stat_out</b>.
- *
- * If <b>flags</b> &amp; RFTS_BIN, open the file in binary mode.
- * If <b>flags</b> &amp; RFTS_IGNORE_MISSING, don't warn if the file
- * doesn't exist.
- */
-/*
- * This function <em>may</em> return an erroneous result if the file
- * is modified while it is running, but must not crash or overflow.
- * Right now, the error case occurs when the file length grows between
- * the call to stat and the call to read_all: the resulting string will
- * be truncated.
- */
-MOCK_IMPL(char *,
-read_file_to_str, (const char *filename, int flags, struct stat *stat_out))
-{
- int fd; /* router file */
- struct stat statbuf;
- char *string;
- ssize_t r;
- int bin = flags & RFTS_BIN;
-
- tor_assert(filename);
-
- fd = tor_open_cloexec(filename,O_RDONLY|(bin?O_BINARY:O_TEXT),0);
- if (fd<0) {
- int severity = LOG_WARN;
- int save_errno = errno;
- if (errno == ENOENT && (flags & RFTS_IGNORE_MISSING))
- severity = LOG_INFO;
- log_fn(severity, LD_FS,"Could not open \"%s\": %s",filename,
- strerror(errno));
- errno = save_errno;
- return NULL;
- }
-
- if (fstat(fd, &statbuf)<0) {
- int save_errno = errno;
- close(fd);
- log_warn(LD_FS,"Could not fstat \"%s\".",filename);
- errno = save_errno;
- 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);
- int save_errno = errno;
- if (string && stat_out) {
- statbuf.st_size = sz;
- memcpy(stat_out, &statbuf, sizeof(struct stat));
- }
- close(fd);
- if (!string)
- errno = save_errno;
- return string;
- }
-#endif /* !defined(_WIN32) */
-
- if ((uint64_t)(statbuf.st_size)+1 >= SIZE_T_CEILING) {
- close(fd);
- errno = EINVAL;
- return NULL;
- }
-
- string = tor_malloc((size_t)(statbuf.st_size+1));
-
- r = read_all(fd,string,(size_t)statbuf.st_size,0);
- if (r<0) {
- int save_errno = errno;
- log_warn(LD_FS,"Error reading from file \"%s\": %s", filename,
- strerror(errno));
- tor_free(string);
- close(fd);
- errno = save_errno;
- return NULL;
- }
- string[r] = '\0'; /* NUL-terminate the result. */
-
-#if defined(_WIN32) || defined(__CYGWIN__)
- if (!bin && strchr(string, '\r')) {
- log_debug(LD_FS, "We didn't convert CRLF to LF as well as we hoped "
- "when reading %s. Coping.",
- filename);
- tor_strstrip(string, "\r");
- r = strlen(string);
- }
- if (!bin) {
- statbuf.st_size = (size_t) r;
- } else
-#endif /* defined(_WIN32) || defined(__CYGWIN__) */
- if (r != statbuf.st_size) {
- /* Unless we're using text mode on win32, we'd better have an exact
- * match for size. */
- int save_errno = errno;
- log_warn(LD_FS,"Could read only %d of %ld bytes of file \"%s\".",
- (int)r, (long)statbuf.st_size,filename);
- tor_free(string);
- close(fd);
- errno = save_errno;
- return NULL;
- }
- close(fd);
- if (stat_out) {
- memcpy(stat_out, &statbuf, sizeof(struct stat));
- }
-
- return string;
-}
-
-#define TOR_ISODIGIT(c) ('0' <= (c) && (c) <= '7')
-
-/** Given a c-style double-quoted escaped string in <b>s</b>, extract and
- * decode its contents into a newly allocated string. On success, assign this
- * string to *<b>result</b>, assign its length to <b>size_out</b> (if
- * provided), and return a pointer to the position in <b>s</b> immediately
- * after the string. On failure, return NULL.
- */
-const char *
-unescape_string(const char *s, char **result, size_t *size_out)
-{
- const char *cp;
- char *out;
- if (s[0] != '\"')
- return NULL;
- cp = s+1;
- while (1) {
- switch (*cp) {
- case '\0':
- case '\n':
- return NULL;
- case '\"':
- goto end_of_loop;
- case '\\':
- if (cp[1] == 'x' || cp[1] == 'X') {
- if (!(TOR_ISXDIGIT(cp[2]) && TOR_ISXDIGIT(cp[3])))
- return NULL;
- cp += 4;
- } else if (TOR_ISODIGIT(cp[1])) {
- cp += 2;
- if (TOR_ISODIGIT(*cp)) ++cp;
- if (TOR_ISODIGIT(*cp)) ++cp;
- } else if (cp[1] == 'n' || cp[1] == 'r' || cp[1] == 't' || cp[1] == '"'
- || cp[1] == '\\' || cp[1] == '\'') {
- cp += 2;
- } else {
- return NULL;
- }
- break;
- default:
- ++cp;
- break;
- }
- }
- end_of_loop:
- out = *result = tor_malloc(cp-s + 1);
- cp = s+1;
- while (1) {
- switch (*cp)
- {
- case '\"':
- *out = '\0';
- if (size_out) *size_out = out - *result;
- return cp+1;
-
- /* LCOV_EXCL_START -- we caught this in parse_config_from_line. */
- case '\0':
- tor_fragile_assert();
- tor_free(*result);
- return NULL;
- /* LCOV_EXCL_STOP */
- case '\\':
- switch (cp[1])
- {
- case 'n': *out++ = '\n'; cp += 2; break;
- case 'r': *out++ = '\r'; cp += 2; break;
- case 't': *out++ = '\t'; cp += 2; break;
- case 'x': case 'X':
- {
- int x1, x2;
-
- x1 = hex_decode_digit(cp[2]);
- x2 = hex_decode_digit(cp[3]);
- if (x1 == -1 || x2 == -1) {
- /* LCOV_EXCL_START */
- /* we caught this above in the initial loop. */
- tor_assert_nonfatal_unreached();
- tor_free(*result);
- return NULL;
- /* LCOV_EXCL_STOP */
- }
-
- *out++ = ((x1<<4) + x2);
- cp += 4;
- }
- break;
- case '0': case '1': case '2': case '3': case '4': case '5':
- case '6': case '7':
- {
- int n = cp[1]-'0';
- cp += 2;
- if (TOR_ISODIGIT(*cp)) { n = n*8 + *cp-'0'; cp++; }
- if (TOR_ISODIGIT(*cp)) { n = n*8 + *cp-'0'; cp++; }
- if (n > 255) { tor_free(*result); return NULL; }
- *out++ = (char)n;
- }
- break;
- case '\'':
- case '\"':
- case '\\':
- case '\?':
- *out++ = cp[1];
- cp += 2;
- break;
-
- /* LCOV_EXCL_START */
- default:
- /* we caught this above in the initial loop. */
- tor_assert_nonfatal_unreached();
- tor_free(*result); return NULL;
- /* LCOV_EXCL_STOP */
- }
- break;
- default:
- *out++ = *cp++;
- }
- }
-}
-
-/** Removes enclosing quotes from <b>path</b> and unescapes quotes between the
- * enclosing quotes. Backslashes are not unescaped. Return the unquoted
- * <b>path</b> on success or 0 if <b>path</b> is not quoted correctly. */
-char *
-get_unquoted_path(const char *path)
-{
- size_t len = strlen(path);
-
- if (len == 0) {
- return tor_strdup("");
- }
-
- int has_start_quote = (path[0] == '\"');
- int has_end_quote = (len > 0 && path[len-1] == '\"');
- if (has_start_quote != has_end_quote || (len == 1 && has_start_quote)) {
- return NULL;
- }
-
- char *unquoted_path = tor_malloc(len - has_start_quote - has_end_quote + 1);
- char *s = unquoted_path;
- size_t i;
- for (i = has_start_quote; i < len - has_end_quote; i++) {
- if (path[i] == '\"' && (i > 0 && path[i-1] == '\\')) {
- *(s-1) = path[i];
- } else if (path[i] != '\"') {
- *s++ = path[i];
- } else { /* unescaped quote */
- tor_free(unquoted_path);
- return NULL;
- }
- }
- *s = '\0';
- return unquoted_path;
-}
-
-/** Expand any homedir prefix on <b>filename</b>; return a newly allocated
- * string. */
-char *
-expand_filename(const char *filename)
-{
- tor_assert(filename);
-#ifdef _WIN32
- /* Might consider using GetFullPathName() as described here:
- * http://etutorials.org/Programming/secure+programming/
- * Chapter+3.+Input+Validation/3.7+Validating+Filenames+and+Paths/
- */
- return tor_strdup(filename);
-#else /* !(defined(_WIN32)) */
- if (*filename == '~') {
- char *home, *result=NULL;
- const char *rest;
-
- if (filename[1] == '/' || filename[1] == '\0') {
- home = getenv("HOME");
- if (!home) {
- log_warn(LD_CONFIG, "Couldn't find $HOME environment variable while "
- "expanding \"%s\"; defaulting to \"\".", filename);
- home = tor_strdup("");
- } else {
- home = tor_strdup(home);
- }
- rest = strlen(filename)>=2?(filename+2):"";
- } else {
-#ifdef HAVE_PWD_H
- char *username, *slash;
- slash = strchr(filename, '/');
- if (slash)
- username = tor_strndup(filename+1,slash-filename-1);
- else
- username = tor_strdup(filename+1);
- if (!(home = get_user_homedir(username))) {
- log_warn(LD_CONFIG,"Couldn't get homedir for \"%s\"",username);
- tor_free(username);
- return NULL;
- }
- tor_free(username);
- rest = slash ? (slash+1) : "";
-#else /* !(defined(HAVE_PWD_H)) */
- log_warn(LD_CONFIG, "Couldn't expand homedir on system without pwd.h");
- return tor_strdup(filename);
-#endif /* defined(HAVE_PWD_H) */
- }
- tor_assert(home);
- /* Remove trailing slash. */
- if (strlen(home)>1 && !strcmpend(home,PATH_SEPARATOR)) {
- home[strlen(home)-1] = '\0';
- }
- tor_asprintf(&result,"%s"PATH_SEPARATOR"%s",home,rest);
- tor_free(home);
- return result;
- } else {
- return tor_strdup(filename);
- }
-#endif /* defined(_WIN32) */
-}
-
-#define MAX_SCANF_WIDTH 9999
-
-/** Helper: given an ASCII-encoded decimal digit, return its numeric value.
- * NOTE: requires that its input be in-bounds. */
-static int
-digit_to_num(char d)
-{
- int num = ((int)d) - (int)'0';
- tor_assert(num <= 9 && num >= 0);
- return num;
-}
-
-/** Helper: Read an unsigned 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_unsigned(const char **bufp, unsigned long *out, int width, unsigned base)
-{
- unsigned long result = 0;
- int scanned_so_far = 0;
- const int hex = base==16;
- tor_assert(base == 10 || base == 16);
- if (!bufp || !*bufp || !out)
- return -1;
- if (width<0)
- width=MAX_SCANF_WIDTH;
-
- while (**bufp && (hex?TOR_ISXDIGIT(**bufp):TOR_ISDIGIT(**bufp))
- && scanned_so_far < width) {
- unsigned digit = hex?hex_decode_digit(*(*bufp)++):digit_to_num(*(*bufp)++);
- // Check for overflow beforehand, without actually causing any overflow
- // This preserves functionality on compilers that don't wrap overflow
- // (i.e. that trap or optimise away overflow)
- // result * base + digit > ULONG_MAX
- // result * base > ULONG_MAX - digit
- if (result > (ULONG_MAX - digit)/base)
- return -1; /* Processing this digit would overflow */
- result = result * base + digit;
- ++scanned_so_far;
- }
-
- if (!scanned_so_far) /* No actual digits scanned */
- return -1;
-
- *out = result;
- 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 && result > 0) {
- if (result > ((unsigned long)LONG_MAX) + 1)
- return -1; /* Underflow */
- else if (result == ((unsigned long)LONG_MAX) + 1)
- *out = LONG_MIN;
- else {
- /* We once had a far more clever no-overflow conversion here, but
- * some versions of GCC apparently ran it into the ground. Now
- * we just check for LONG_MIN explicitly.
- */
- *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. */
-static int
-scan_string(const char **bufp, char *out, int width)
-{
- int scanned_so_far = 0;
- if (!bufp || !out || width < 0)
- return -1;
- while (**bufp && ! TOR_ISSPACE(**bufp) && scanned_so_far < width) {
- *out++ = *(*bufp)++;
- ++scanned_so_far;
- }
- *out = '\0';
- return 0;
-}
-
-/** Locale-independent, minimal, no-surprises scanf variant, accepting only a
- * restricted pattern format. For more info on what it supports, see
- * tor_sscanf() documentation. */
-int
-tor_vsscanf(const char *buf, const char *pattern, va_list ap)
-{
- int n_matched = 0;
-
- while (*pattern) {
- if (*pattern != '%') {
- if (*buf == *pattern) {
- ++buf;
- ++pattern;
- continue;
- } else {
- return n_matched;
- }
- } else {
- int width = -1;
- int longmod = 0;
- ++pattern;
- if (TOR_ISDIGIT(*pattern)) {
- width = digit_to_num(*pattern++);
- while (TOR_ISDIGIT(*pattern)) {
- width *= 10;
- width += digit_to_num(*pattern++);
- if (width > MAX_SCANF_WIDTH)
- return -1;
- }
- if (!width) /* No zero-width things. */
- return -1;
- }
- if (*pattern == 'l') {
- longmod = 1;
- ++pattern;
- }
- if (*pattern == 'u' || *pattern == 'x') {
- unsigned long u;
- const int base = (*pattern == 'u') ? 10 : 16;
- if (!*buf)
- return n_matched;
- 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 LONG_MAX > INT_MAX
- if (lng < INT_MIN || lng > INT_MAX)
- return n_matched;
-#endif
- *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)
- return n_matched;
- ++pattern;
- ++n_matched;
- } else if (*pattern == 'c') {
- char *ch = va_arg(ap, char *);
- if (longmod)
- return -1;
- if (width != -1)
- return -1;
- if (!*buf)
- return n_matched;
- *ch = *buf++;
- ++pattern;
- ++n_matched;
- } else if (*pattern == '%') {
- if (*buf != '%')
- return n_matched;
- if (longmod)
- return -1;
- ++buf;
- ++pattern;
- } else {
- return -1; /* Unrecognized pattern component. */
- }
- }
- }
-
- return n_matched;
-}
-
-/** 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:
- * <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
- * miscellaneous characters look like numbers, spaces, and so on.)
- */
-int
-tor_sscanf(const char *buf, const char *pattern, ...)
-{
- int r;
- va_list ap;
- va_start(ap, pattern);
- r = tor_vsscanf(buf, pattern, ap);
- va_end(ap);
- return r;
-}
-
-/** Append the string produced by tor_asprintf(<b>pattern</b>, <b>...</b>)
- * to <b>sl</b>. */
-void
-smartlist_add_asprintf(struct smartlist_t *sl, const char *pattern, ...)
-{
- va_list ap;
- va_start(ap, pattern);
- smartlist_add_vasprintf(sl, pattern, ap);
- va_end(ap);
-}
-
-/** va_list-based backend of smartlist_add_asprintf. */
-void
-smartlist_add_vasprintf(struct smartlist_t *sl, const char *pattern,
- va_list args)
-{
- char *str = NULL;
-
- tor_vasprintf(&str, pattern, args);
- tor_assert(str != NULL);
-
- smartlist_add(sl, str);
-}
-
-/** Append a copy of string to sl */
-void
-smartlist_add_strdup(struct smartlist_t *sl, const char *string)
-{
- char *copy;
-
- copy = tor_strdup(string);
-
- smartlist_add(sl, copy);
-}
-
-/** Return a new list containing the filenames in the directory <b>dirname</b>.
- * Return NULL on error or if <b>dirname</b> is not a directory.
- */
-MOCK_IMPL(smartlist_t *,
-tor_listdir, (const char *dirname))
-{
- smartlist_t *result;
-#ifdef _WIN32
- char *pattern=NULL;
- TCHAR tpattern[MAX_PATH] = {0};
- char name[MAX_PATH*2+1] = {0};
- HANDLE handle;
- WIN32_FIND_DATA findData;
- tor_asprintf(&pattern, "%s\\*", dirname);
-#ifdef UNICODE
- mbstowcs(tpattern,pattern,MAX_PATH);
-#else
- strlcpy(tpattern, pattern, MAX_PATH);
-#endif
- if (INVALID_HANDLE_VALUE == (handle = FindFirstFile(tpattern, &findData))) {
- tor_free(pattern);
- return NULL;
- }
- result = smartlist_new();
- while (1) {
-#ifdef UNICODE
- wcstombs(name,findData.cFileName,MAX_PATH);
- name[sizeof(name)-1] = '\0';
-#else
- strlcpy(name,findData.cFileName,sizeof(name));
-#endif /* defined(UNICODE) */
- if (strcmp(name, ".") &&
- strcmp(name, "..")) {
- smartlist_add_strdup(result, name);
- }
- if (!FindNextFile(handle, &findData)) {
- DWORD err;
- if ((err = GetLastError()) != ERROR_NO_MORE_FILES) {
- char *errstr = format_win32_error(err);
- log_warn(LD_FS, "Error reading directory '%s': %s", dirname, errstr);
- tor_free(errstr);
- }
- break;
- }
- }
- FindClose(handle);
- tor_free(pattern);
-#else /* !(defined(_WIN32)) */
- const char *prot_dname = sandbox_intern_string(dirname);
- DIR *d;
- struct dirent *de;
- if (!(d = opendir(prot_dname)))
- return NULL;
-
- result = smartlist_new();
- while ((de = readdir(d))) {
- if (!strcmp(de->d_name, ".") ||
- !strcmp(de->d_name, ".."))
- continue;
- smartlist_add_strdup(result, de->d_name);
- }
- closedir(d);
-#endif /* defined(_WIN32) */
- return result;
-}
-
-/** Return true iff <b>filename</b> is a relative path. */
-int
-path_is_relative(const char *filename)
-{
- if (filename && filename[0] == '/')
- return 0;
-#ifdef _WIN32
- else if (filename && filename[0] == '\\')
- return 0;
- else if (filename && strlen(filename)>3 && TOR_ISALPHA(filename[0]) &&
- filename[1] == ':' && filename[2] == '\\')
- return 0;
-#endif /* defined(_WIN32) */
- else
- return 1;
-}
-
-/* =====
- * Process helpers
- * ===== */
-
-#ifndef _WIN32
-/* Based on code contributed by christian grothoff */
-/** True iff we've called start_daemon(). */
-static int start_daemon_called = 0;
-/** True iff we've called finish_daemon(). */
-static int finish_daemon_called = 0;
-/** Socketpair used to communicate between parent and child process while
- * daemonizing. */
-static int daemon_filedes[2];
-/** Start putting the process into daemon mode: fork and drop all resources
- * except standard fds. The parent process never returns, but stays around
- * until finish_daemon is called. (Note: it's safe to call this more
- * than once: calls after the first are ignored.)
- */
-void
-start_daemon(void)
-{
- pid_t pid;
-
- if (start_daemon_called)
- return;
- start_daemon_called = 1;
-
- if (pipe(daemon_filedes)) {
- /* LCOV_EXCL_START */
- log_err(LD_GENERAL,"pipe failed; exiting. Error was %s", strerror(errno));
- exit(1); // exit ok: during daemonize, pipe failed.
- /* LCOV_EXCL_STOP */
- }
- pid = fork();
- if (pid < 0) {
- /* LCOV_EXCL_START */
- log_err(LD_GENERAL,"fork failed. Exiting.");
- exit(1); // exit ok: during daemonize, fork failed
- /* LCOV_EXCL_STOP */
- }
- if (pid) { /* Parent */
- int ok;
- char c;
-
- close(daemon_filedes[1]); /* we only read */
- ok = -1;
- while (0 < read(daemon_filedes[0], &c, sizeof(char))) {
- if (c == '.')
- ok = 1;
- }
- fflush(stdout);
- if (ok == 1)
- exit(0); // exit ok: during daemonize, daemonizing.
- else
- exit(1); /* child reported error. exit ok: daemonize failed. */
- } else { /* Child */
- close(daemon_filedes[0]); /* we only write */
-
- (void) setsid(); /* Detach from controlling terminal */
- /*
- * Fork one more time, so the parent (the session group leader) can exit.
- * This means that we, as a non-session group leader, can never regain a
- * controlling terminal. This part is recommended by Stevens's
- * _Advanced Programming in the Unix Environment_.
- */
- if (fork() != 0) {
- exit(0); // exit ok: during daemonize, fork failed (2)
- }
- set_main_thread(); /* We are now the main thread. */
-
- return;
- }
-}
-
-/** Finish putting the process into daemon mode: drop standard fds, and tell
- * the parent process to exit. (Note: it's safe to call this more than once:
- * calls after the first are ignored. Calls start_daemon first if it hasn't
- * been called already.)
- */
-void
-finish_daemon(const char *desired_cwd)
-{
- int nullfd;
- char c = '.';
- if (finish_daemon_called)
- return;
- if (!start_daemon_called)
- start_daemon();
- finish_daemon_called = 1;
-
- if (!desired_cwd)
- desired_cwd = "/";
- /* Don't hold the wrong FS mounted */
- if (chdir(desired_cwd) < 0) {
- log_err(LD_GENERAL,"chdir to \"%s\" failed. Exiting.",desired_cwd);
- exit(1); // exit ok: during daemonize, chdir failed.
- }
-
- nullfd = tor_open_cloexec("/dev/null", O_RDWR, 0);
- if (nullfd < 0) {
- /* LCOV_EXCL_START */
- log_err(LD_GENERAL,"/dev/null can't be opened. Exiting.");
- exit(1); // exit ok: during daemonize, couldn't open /dev/null
- /* LCOV_EXCL_STOP */
- }
- /* close fds linking to invoking terminal, but
- * close usual incoming fds, but redirect them somewhere
- * useful so the fds don't get reallocated elsewhere.
- */
- if (dup2(nullfd,0) < 0 ||
- dup2(nullfd,1) < 0 ||
- dup2(nullfd,2) < 0) {
- /* LCOV_EXCL_START */
- log_err(LD_GENERAL,"dup2 failed. Exiting.");
- exit(1); // exit ok: during daemonize, dup2 failed.
- /* LCOV_EXCL_STOP */
- }
- if (nullfd > 2)
- close(nullfd);
- /* signal success */
- if (write(daemon_filedes[1], &c, sizeof(char)) != sizeof(char)) {
- log_err(LD_GENERAL,"write failed. Exiting.");
- }
- close(daemon_filedes[1]);
-}
-#else /* !(!defined(_WIN32)) */
-/* defined(_WIN32) */
-void
-start_daemon(void)
-{
-}
-void
-finish_daemon(const char *cp)
-{
- (void)cp;
-}
-#endif /* !defined(_WIN32) */
-
-/** Write the current process ID, followed by NL, into <b>filename</b>.
- * Return 0 on success, -1 on failure.
- */
-int
-write_pidfile(const char *filename)
-{
- FILE *pidfile;
-
- if ((pidfile = fopen(filename, "w")) == NULL) {
- log_warn(LD_FS, "Unable to open \"%s\" for writing: %s", filename,
- strerror(errno));
- return -1;
- } else {
-#ifdef _WIN32
- int pid = (int)_getpid();
-#else
- int pid = (int)getpid();
-#endif
- int rv = 0;
- if (fprintf(pidfile, "%d\n", pid) < 0)
- rv = -1;
- if (fclose(pidfile) < 0)
- rv = -1;
- return rv;
- }
-}
-
-#ifdef _WIN32
-HANDLE
-load_windows_system_library(const TCHAR *library_name)
-{
- TCHAR path[MAX_PATH];
- unsigned n;
- n = GetSystemDirectory(path, MAX_PATH);
- if (n == 0 || n + _tcslen(library_name) + 2 >= MAX_PATH)
- return 0;
- _tcscat(path, TEXT("\\"));
- _tcscat(path, library_name);
- return LoadLibrary(path);
-}
-#endif /* defined(_WIN32) */
-
-/** Format a single argument for being put on a Windows command line.
- * Returns a newly allocated string */
-static char *
-format_win_cmdline_argument(const char *arg)
-{
- char *formatted_arg;
- char need_quotes;
- const char *c;
- int i;
- int bs_counter = 0;
- /* Backslash we can point to when one is inserted into the string */
- const char backslash = '\\';
-
- /* Smartlist of *char */
- smartlist_t *arg_chars;
- arg_chars = smartlist_new();
-
- /* Quote string if it contains whitespace or is empty */
- need_quotes = (strchr(arg, ' ') || strchr(arg, '\t') || '\0' == arg[0]);
-
- /* Build up smartlist of *chars */
- for (c=arg; *c != '\0'; c++) {
- if ('"' == *c) {
- /* Double up backslashes preceding a quote */
- for (i=0; i<(bs_counter*2); i++)
- smartlist_add(arg_chars, (void*)&backslash);
- bs_counter = 0;
- /* Escape the quote */
- smartlist_add(arg_chars, (void*)&backslash);
- smartlist_add(arg_chars, (void*)c);
- } else if ('\\' == *c) {
- /* Count backslashes until we know whether to double up */
- bs_counter++;
- } else {
- /* Don't double up slashes preceding a non-quote */
- for (i=0; i<bs_counter; i++)
- smartlist_add(arg_chars, (void*)&backslash);
- bs_counter = 0;
- smartlist_add(arg_chars, (void*)c);
- }
- }
- /* Don't double up trailing backslashes */
- for (i=0; i<bs_counter; i++)
- smartlist_add(arg_chars, (void*)&backslash);
-
- /* Allocate space for argument, quotes (if needed), and terminator */
- const size_t formatted_arg_len = smartlist_len(arg_chars) +
- (need_quotes ? 2 : 0) + 1;
- formatted_arg = tor_malloc_zero(formatted_arg_len);
-
- /* Add leading quote */
- i=0;
- if (need_quotes)
- formatted_arg[i++] = '"';
-
- /* Add characters */
- SMARTLIST_FOREACH(arg_chars, char*, ch,
- {
- formatted_arg[i++] = *ch;
- });
-
- /* Add trailing quote */
- if (need_quotes)
- formatted_arg[i++] = '"';
- formatted_arg[i] = '\0';
-
- smartlist_free(arg_chars);
- return formatted_arg;
-}
-
-/** Format a command line for use on Windows, which takes the command as a
- * string rather than string array. Follows the rules from "Parsing C++
- * Command-Line Arguments" in MSDN. Algorithm based on list2cmdline in the
- * Python subprocess module. Returns a newly allocated string */
-char *
-tor_join_win_cmdline(const char *argv[])
-{
- smartlist_t *argv_list;
- char *joined_argv;
- int i;
-
- /* Format each argument and put the result in a smartlist */
- argv_list = smartlist_new();
- for (i=0; argv[i] != NULL; i++) {
- smartlist_add(argv_list, (void *)format_win_cmdline_argument(argv[i]));
- }
-
- /* Join the arguments with whitespace */
- joined_argv = smartlist_join_strings(argv_list, " ", 0, NULL);
-
- /* Free the newly allocated arguments, and the smartlist */
- SMARTLIST_FOREACH(argv_list, char *, arg,
- {
- tor_free(arg);
- });
- smartlist_free(argv_list);
-
- return joined_argv;
-}
-
-/* As format_{hex,dex}_number_sigsafe, but takes a <b>radix</b> argument
- * in range 2..16 inclusive. */
-static int
-format_number_sigsafe(unsigned long x, char *buf, int buf_len,
- unsigned int radix)
-{
- unsigned long tmp;
- int len;
- char *cp;
-
- /* NOT tor_assert. This needs to be safe to run from within a signal handler,
- * and from within the 'tor_assert() has failed' code. */
- if (radix < 2 || radix > 16)
- return 0;
-
- /* Count how many digits we need. */
- tmp = x;
- len = 1;
- while (tmp >= radix) {
- tmp /= radix;
- ++len;
- }
-
- /* Not long enough */
- if (!buf || len >= buf_len)
- return 0;
-
- cp = buf + len;
- *cp = '\0';
- do {
- unsigned digit = (unsigned) (x % radix);
- tor_assert(cp > buf);
- --cp;
- *cp = "0123456789ABCDEF"[digit];
- x /= radix;
- } while (x);
-
- /* NOT tor_assert; see above. */
- if (cp != buf) {
- abort(); // LCOV_EXCL_LINE
- }
-
- return len;
-}
-
-/**
- * Helper function to output hex numbers from within a signal handler.
- *
- * Writes the nul-terminated hexadecimal digits of <b>x</b> into a buffer
- * <b>buf</b> of size <b>buf_len</b>, and return the actual number of digits
- * written, not counting the terminal NUL.
- *
- * If there is insufficient space, write nothing and return 0.
- *
- * This accepts an unsigned int because format_helper_exit_status() needs to
- * call it with a signed int and an unsigned char, and since the C standard
- * does not guarantee that an int is wider than a char (an int must be at
- * least 16 bits but it is permitted for a char to be that wide as well), we
- * can't assume a signed int is sufficient to accommodate an unsigned char.
- * Thus, format_helper_exit_status() will still need to emit any require '-'
- * on its own.
- *
- * For most purposes, you'd want to use tor_snprintf("%x") instead of this
- * function; it's designed to be used in code paths where you can't call
- * arbitrary C functions.
- */
-int
-format_hex_number_sigsafe(unsigned long x, char *buf, int buf_len)
-{
- return format_number_sigsafe(x, buf, buf_len, 16);
-}
-
-/** As format_hex_number_sigsafe, but format the number in base 10. */
-int
-format_dec_number_sigsafe(unsigned long x, char *buf, int buf_len)
-{
- return format_number_sigsafe(x, buf, buf_len, 10);
-}
-
-#ifndef _WIN32
-/** Format <b>child_state</b> and <b>saved_errno</b> as a hex string placed in
- * <b>hex_errno</b>. Called between fork and _exit, so must be signal-handler
- * safe.
- *
- * <b>hex_errno</b> must have at least HEX_ERRNO_SIZE+1 bytes available.
- *
- * The format of <b>hex_errno</b> is: "CHILD_STATE/ERRNO\n", left-padded
- * with spaces. CHILD_STATE indicates where
- * in the process of starting the child process did the failure occur (see
- * CHILD_STATE_* macros for definition), and SAVED_ERRNO is the value of
- * errno when the failure occurred.
- *
- * On success return the number of characters added to hex_errno, not counting
- * the terminating NUL; return -1 on error.
- */
-STATIC int
-format_helper_exit_status(unsigned char child_state, int saved_errno,
- char *hex_errno)
-{
- unsigned int unsigned_errno;
- int written, left;
- char *cur;
- size_t i;
- int res = -1;
-
- /* Fill hex_errno with spaces, and a trailing newline (memset may
- not be signal handler safe, so we can't use it) */
- for (i = 0; i < (HEX_ERRNO_SIZE - 1); i++)
- hex_errno[i] = ' ';
- hex_errno[HEX_ERRNO_SIZE - 1] = '\n';
-
- /* Convert errno to be unsigned for hex conversion */
- if (saved_errno < 0) {
- // Avoid overflow on the cast to unsigned int when result is INT_MIN
- // by adding 1 to the signed int negative value,
- // then, after it has been negated and cast to unsigned,
- // adding the original 1 back (the double-addition is intentional).
- // Otherwise, the cast to signed could cause a temporary int
- // to equal INT_MAX + 1, which is undefined.
- unsigned_errno = ((unsigned int) -(saved_errno + 1)) + 1;
- } else {
- unsigned_errno = (unsigned int) saved_errno;
- }
-
- /*
- * Count how many chars of space we have left, and keep a pointer into the
- * current point in the buffer.
- */
- left = HEX_ERRNO_SIZE+1;
- cur = hex_errno;
-
- /* Emit child_state */
- written = format_hex_number_sigsafe(child_state, cur, left);
-
- if (written <= 0)
- goto err;
-
- /* Adjust left and cur */
- left -= written;
- cur += written;
- if (left <= 0)
- goto err;
-
- /* Now the '/' */
- *cur = '/';
-
- /* Adjust left and cur */
- ++cur;
- --left;
- if (left <= 0)
- goto err;
-
- /* Need minus? */
- if (saved_errno < 0) {
- *cur = '-';
- ++cur;
- --left;
- if (left <= 0)
- goto err;
- }
-
- /* Emit unsigned_errno */
- written = format_hex_number_sigsafe(unsigned_errno, cur, left);
-
- if (written <= 0)
- goto err;
-
- /* Adjust left and cur */
- left -= written;
- cur += written;
-
- /* Check that we have enough space left for a newline and a NUL */
- if (left <= 1)
- goto err;
-
- /* Emit the newline and NUL */
- *cur++ = '\n';
- *cur++ = '\0';
-
- res = (int)(cur - hex_errno - 1);
-
- goto done;
-
- err:
- /*
- * In error exit, just write a '\0' in the first char so whatever called
- * this at least won't fall off the end.
- */
- *hex_errno = '\0';
-
- done:
- return res;
-}
-#endif /* !defined(_WIN32) */
-
-/* Maximum number of file descriptors, if we cannot get it via sysconf() */
-#define DEFAULT_MAX_FD 256
-
-/** Terminate the process of <b>process_handle</b>, if that process has not
- * already exited.
- *
- * Return 0 if we succeeded in terminating the process (or if the process
- * already exited), and -1 if we tried to kill the process but failed.
- *
- * Based on code originally borrowed from Python's os.kill. */
-int
-tor_terminate_process(process_handle_t *process_handle)
-{
-#ifdef _WIN32
- if (tor_get_exit_code(process_handle, 0, NULL) == PROCESS_EXIT_RUNNING) {
- HANDLE handle = process_handle->pid.hProcess;
-
- if (!TerminateProcess(handle, 0))
- return -1;
- else
- return 0;
- }
-#else /* !(defined(_WIN32)) */
- if (process_handle->waitpid_cb) {
- /* We haven't got a waitpid yet, so we can just kill off the process. */
- return kill(process_handle->pid, SIGTERM);
- }
-#endif /* defined(_WIN32) */
-
- return 0; /* We didn't need to kill the process, so report success */
-}
-
-/** Return the Process ID of <b>process_handle</b>. */
-int
-tor_process_get_pid(process_handle_t *process_handle)
-{
-#ifdef _WIN32
- return (int) process_handle->pid.dwProcessId;
-#else
- return (int) process_handle->pid;
-#endif
-}
-
-#ifdef _WIN32
-HANDLE
-tor_process_get_stdout_pipe(process_handle_t *process_handle)
-{
- return process_handle->stdout_pipe;
-}
-#else /* !(defined(_WIN32)) */
-/* DOCDOC tor_process_get_stdout_pipe */
-int
-tor_process_get_stdout_pipe(process_handle_t *process_handle)
-{
- return process_handle->stdout_pipe;
-}
-#endif /* defined(_WIN32) */
-
-/* DOCDOC process_handle_new */
-static process_handle_t *
-process_handle_new(void)
-{
- process_handle_t *out = tor_malloc_zero(sizeof(process_handle_t));
-
-#ifdef _WIN32
- out->stdin_pipe = INVALID_HANDLE_VALUE;
- out->stdout_pipe = INVALID_HANDLE_VALUE;
- out->stderr_pipe = INVALID_HANDLE_VALUE;
-#else
- out->stdin_pipe = -1;
- out->stdout_pipe = -1;
- out->stderr_pipe = -1;
-#endif /* defined(_WIN32) */
-
- return out;
-}
-
-#ifndef _WIN32
-/** Invoked when a process that we've launched via tor_spawn_background() has
- * been found to have terminated.
- */
-static void
-process_handle_waitpid_cb(int status, void *arg)
-{
- process_handle_t *process_handle = arg;
-
- process_handle->waitpid_exit_status = status;
- clear_waitpid_callback(process_handle->waitpid_cb);
- if (process_handle->status == PROCESS_STATUS_RUNNING)
- process_handle->status = PROCESS_STATUS_NOTRUNNING;
- process_handle->waitpid_cb = 0;
-}
-#endif /* !defined(_WIN32) */
-
-/**
- * @name child-process states
- *
- * Each of these values represents a possible state that a child process can
- * be in. They're used to determine what to say when telling the parent how
- * far along we were before failure.
- *
- * @{
- */
-#define CHILD_STATE_INIT 0
-#define CHILD_STATE_PIPE 1
-#define CHILD_STATE_MAXFD 2
-#define CHILD_STATE_FORK 3
-#define CHILD_STATE_DUPOUT 4
-#define CHILD_STATE_DUPERR 5
-#define CHILD_STATE_DUPIN 6
-#define CHILD_STATE_CLOSEFD 7
-#define CHILD_STATE_EXEC 8
-#define CHILD_STATE_FAILEXEC 9
-/** @} */
-/**
- * Boolean. If true, then Tor may call execve or CreateProcess via
- * tor_spawn_background.
- **/
-static int may_spawn_background_process = 1;
-/**
- * Turn off may_spawn_background_process, so that all future calls to
- * tor_spawn_background are guaranteed to fail.
- **/
-void
-tor_disable_spawning_background_processes(void)
-{
- may_spawn_background_process = 0;
-}
-/** Start a program in the background. If <b>filename</b> contains a '/', then
- * it will be treated as an absolute or relative path. Otherwise, on
- * non-Windows systems, the system path will be searched for <b>filename</b>.
- * On Windows, only the current directory will be searched. Here, to search the
- * system path (as well as the application directory, current working
- * directory, and system directories), set filename to NULL.
- *
- * The strings in <b>argv</b> will be passed as the command line arguments of
- * the child program (following convention, argv[0] should normally be the
- * filename of the executable, and this must be the case if <b>filename</b> is
- * NULL). The last element of argv must be NULL. A handle to the child process
- * will be returned in process_handle (which must be non-NULL). Read
- * process_handle.status to find out if the process was successfully launched.
- * For convenience, process_handle.status is returned by this function.
- *
- * Some parts of this code are based on the POSIX subprocess module from
- * Python, and example code from
- * http://msdn.microsoft.com/en-us/library/ms682499%28v=vs.85%29.aspx.
- */
-int
-tor_spawn_background(const char *const filename, const char **argv,
- process_environment_t *env,
- process_handle_t **process_handle_out)
-{
- if (BUG(may_spawn_background_process == 0)) {
- /* We should never reach this point if we're forbidden to spawn
- * processes. Instead we should have caught the attempt earlier. */
- return PROCESS_STATUS_ERROR;
- }
-
-#ifdef _WIN32
- HANDLE stdout_pipe_read = NULL;
- HANDLE stdout_pipe_write = NULL;
- HANDLE stderr_pipe_read = NULL;
- HANDLE stderr_pipe_write = NULL;
- HANDLE stdin_pipe_read = NULL;
- HANDLE stdin_pipe_write = NULL;
- process_handle_t *process_handle;
- int status;
-
- STARTUPINFOA siStartInfo;
- BOOL retval = FALSE;
-
- SECURITY_ATTRIBUTES saAttr;
- char *joined_argv;
-
- saAttr.nLength = sizeof(SECURITY_ATTRIBUTES);
- saAttr.bInheritHandle = TRUE;
- /* TODO: should we set explicit security attributes? (#2046, comment 5) */
- saAttr.lpSecurityDescriptor = NULL;
-
- /* Assume failure to start process */
- status = PROCESS_STATUS_ERROR;
-
- /* Set up pipe for stdout */
- if (!CreatePipe(&stdout_pipe_read, &stdout_pipe_write, &saAttr, 0)) {
- log_warn(LD_GENERAL,
- "Failed to create pipe for stdout communication with child process: %s",
- format_win32_error(GetLastError()));
- return status;
- }
- if (!SetHandleInformation(stdout_pipe_read, HANDLE_FLAG_INHERIT, 0)) {
- log_warn(LD_GENERAL,
- "Failed to configure pipe for stdout communication with child "
- "process: %s", format_win32_error(GetLastError()));
- return status;
- }
-
- /* Set up pipe for stderr */
- if (!CreatePipe(&stderr_pipe_read, &stderr_pipe_write, &saAttr, 0)) {
- log_warn(LD_GENERAL,
- "Failed to create pipe for stderr communication with child process: %s",
- format_win32_error(GetLastError()));
- return status;
- }
- if (!SetHandleInformation(stderr_pipe_read, HANDLE_FLAG_INHERIT, 0)) {
- log_warn(LD_GENERAL,
- "Failed to configure pipe for stderr communication with child "
- "process: %s", format_win32_error(GetLastError()));
- return status;
- }
-
- /* Set up pipe for stdin */
- if (!CreatePipe(&stdin_pipe_read, &stdin_pipe_write, &saAttr, 0)) {
- log_warn(LD_GENERAL,
- "Failed to create pipe for stdin communication with child process: %s",
- format_win32_error(GetLastError()));
- return status;
- }
- if (!SetHandleInformation(stdin_pipe_write, HANDLE_FLAG_INHERIT, 0)) {
- log_warn(LD_GENERAL,
- "Failed to configure pipe for stdin communication with child "
- "process: %s", format_win32_error(GetLastError()));
- return status;
- }
-
- /* Create the child process */
-
- /* Windows expects argv to be a whitespace delimited string, so join argv up
- */
- joined_argv = tor_join_win_cmdline(argv);
-
- process_handle = process_handle_new();
- process_handle->status = status;
-
- ZeroMemory(&(process_handle->pid), sizeof(PROCESS_INFORMATION));
- ZeroMemory(&siStartInfo, sizeof(STARTUPINFO));
- siStartInfo.cb = sizeof(STARTUPINFO);
- siStartInfo.hStdError = stderr_pipe_write;
- siStartInfo.hStdOutput = stdout_pipe_write;
- siStartInfo.hStdInput = stdin_pipe_read;
- siStartInfo.dwFlags |= STARTF_USESTDHANDLES;
-
- /* Create the child process */
-
- retval = CreateProcessA(filename, // module name
- joined_argv, // command line
- /* TODO: should we set explicit security attributes? (#2046, comment 5) */
- NULL, // process security attributes
- NULL, // primary thread security attributes
- TRUE, // handles are inherited
- /*(TODO: set CREATE_NEW CONSOLE/PROCESS_GROUP to make GetExitCodeProcess()
- * work?) */
- CREATE_NO_WINDOW, // creation flags
- (env==NULL) ? NULL : env->windows_environment_block,
- NULL, // use parent's current directory
- &siStartInfo, // STARTUPINFO pointer
- &(process_handle->pid)); // receives PROCESS_INFORMATION
-
- tor_free(joined_argv);
-
- if (!retval) {
- log_warn(LD_GENERAL,
- "Failed to create child process %s: %s", filename?filename:argv[0],
- format_win32_error(GetLastError()));
- tor_free(process_handle);
- } else {
- /* TODO: Close hProcess and hThread in process_handle->pid? */
- process_handle->stdout_pipe = stdout_pipe_read;
- process_handle->stderr_pipe = stderr_pipe_read;
- process_handle->stdin_pipe = stdin_pipe_write;
- status = process_handle->status = PROCESS_STATUS_RUNNING;
- }
-
- /* TODO: Close pipes on exit */
- *process_handle_out = process_handle;
- return status;
-#else /* !(defined(_WIN32)) */
- pid_t pid;
- int stdout_pipe[2];
- int stderr_pipe[2];
- int stdin_pipe[2];
- int fd, retval;
- process_handle_t *process_handle;
- int status;
-
- const char *error_message = SPAWN_ERROR_MESSAGE;
- size_t error_message_length;
-
- /* Represents where in the process of spawning the program is;
- this is used for printing out the error message */
- unsigned char child_state = CHILD_STATE_INIT;
-
- char hex_errno[HEX_ERRNO_SIZE + 2]; /* + 1 should be sufficient actually */
-
- static int max_fd = -1;
-
- status = PROCESS_STATUS_ERROR;
-
- /* We do the strlen here because strlen() is not signal handler safe,
- and we are not allowed to use unsafe functions between fork and exec */
- error_message_length = strlen(error_message);
-
- // child_state = CHILD_STATE_PIPE;
-
- /* Set up pipe for redirecting stdout, stderr, and stdin of child */
- retval = pipe(stdout_pipe);
- if (-1 == retval) {
- log_warn(LD_GENERAL,
- "Failed to set up pipe for stdout communication with child process: %s",
- strerror(errno));
- return status;
- }
-
- retval = pipe(stderr_pipe);
- if (-1 == retval) {
- log_warn(LD_GENERAL,
- "Failed to set up pipe for stderr communication with child process: %s",
- strerror(errno));
-
- close(stdout_pipe[0]);
- close(stdout_pipe[1]);
-
- return status;
- }
-
- retval = pipe(stdin_pipe);
- if (-1 == retval) {
- log_warn(LD_GENERAL,
- "Failed to set up pipe for stdin communication with child process: %s",
- strerror(errno));
-
- close(stdout_pipe[0]);
- close(stdout_pipe[1]);
- close(stderr_pipe[0]);
- close(stderr_pipe[1]);
-
- return status;
- }
-
- // child_state = CHILD_STATE_MAXFD;
-
-#ifdef _SC_OPEN_MAX
- if (-1 == max_fd) {
- max_fd = (int) sysconf(_SC_OPEN_MAX);
- if (max_fd == -1) {
- max_fd = DEFAULT_MAX_FD;
- log_warn(LD_GENERAL,
- "Cannot find maximum file descriptor, assuming %d", max_fd);
- }
- }
-#else /* !(defined(_SC_OPEN_MAX)) */
- max_fd = DEFAULT_MAX_FD;
-#endif /* defined(_SC_OPEN_MAX) */
-
- // child_state = CHILD_STATE_FORK;
-
- pid = fork();
- if (0 == pid) {
- /* In child */
-
-#if defined(HAVE_SYS_PRCTL_H) && defined(__linux__)
- /* Attempt to have the kernel issue a SIGTERM if the parent
- * goes away. Certain attributes of the binary being execve()ed
- * will clear this during the execve() call, but it's better
- * than nothing.
- */
- prctl(PR_SET_PDEATHSIG, SIGTERM);
-#endif /* defined(HAVE_SYS_PRCTL_H) && defined(__linux__) */
-
- child_state = CHILD_STATE_DUPOUT;
-
- /* Link child stdout to the write end of the pipe */
- retval = dup2(stdout_pipe[1], STDOUT_FILENO);
- if (-1 == retval)
- goto error;
-
- child_state = CHILD_STATE_DUPERR;
-
- /* Link child stderr to the write end of the pipe */
- retval = dup2(stderr_pipe[1], STDERR_FILENO);
- if (-1 == retval)
- goto error;
-
- child_state = CHILD_STATE_DUPIN;
-
- /* Link child stdin to the read end of the pipe */
- retval = dup2(stdin_pipe[0], STDIN_FILENO);
- if (-1 == retval)
- goto error;
-
- // child_state = CHILD_STATE_CLOSEFD;
-
- close(stderr_pipe[0]);
- close(stderr_pipe[1]);
- close(stdout_pipe[0]);
- close(stdout_pipe[1]);
- close(stdin_pipe[0]);
- close(stdin_pipe[1]);
-
- /* Close all other fds, including the read end of the pipe */
- /* XXX: We should now be doing enough FD_CLOEXEC setting to make
- * this needless. */
- for (fd = STDERR_FILENO + 1; fd < max_fd; fd++) {
- close(fd);
- }
-
- // child_state = CHILD_STATE_EXEC;
-
- /* Call the requested program. We need the cast because
- execvp doesn't define argv as const, even though it
- does not modify the arguments */
- if (env)
- execve(filename, (char *const *) argv, env->unixoid_environment_block);
- else {
- static char *new_env[] = { NULL };
- execve(filename, (char *const *) argv, new_env);
- }
-
- /* If we got here, the exec or open(/dev/null) failed */
-
- child_state = CHILD_STATE_FAILEXEC;
-
- error:
- {
- /* XXX: are we leaking fds from the pipe? */
- int n, err=0;
- ssize_t nbytes;
-
- n = format_helper_exit_status(child_state, errno, hex_errno);
-
- if (n >= 0) {
- /* Write the error message. GCC requires that we check the return
- value, but there is nothing we can do if it fails */
- /* TODO: Don't use STDOUT, use a pipe set up just for this purpose */
- nbytes = write(STDOUT_FILENO, error_message, error_message_length);
- err = (nbytes < 0);
- nbytes = write(STDOUT_FILENO, hex_errno, n);
- err += (nbytes < 0);
- }
-
- _exit(err?254:255); // exit ok: in child.
- }
-
- /* Never reached, but avoids compiler warning */
- return status; // LCOV_EXCL_LINE
- }
-
- /* In parent */
-
- if (-1 == pid) {
- log_warn(LD_GENERAL, "Failed to fork child process: %s", strerror(errno));
- close(stdin_pipe[0]);
- close(stdin_pipe[1]);
- close(stdout_pipe[0]);
- close(stdout_pipe[1]);
- close(stderr_pipe[0]);
- close(stderr_pipe[1]);
- return status;
- }
-
- process_handle = process_handle_new();
- process_handle->status = status;
- process_handle->pid = pid;
-
- /* TODO: If the child process forked but failed to exec, waitpid it */
-
- /* Return read end of the pipes to caller, and close write end */
- process_handle->stdout_pipe = stdout_pipe[0];
- retval = close(stdout_pipe[1]);
-
- if (-1 == retval) {
- log_warn(LD_GENERAL,
- "Failed to close write end of stdout pipe in parent process: %s",
- strerror(errno));
- }
-
- process_handle->waitpid_cb = set_waitpid_callback(pid,
- process_handle_waitpid_cb,
- process_handle);
-
- process_handle->stderr_pipe = stderr_pipe[0];
- retval = close(stderr_pipe[1]);
-
- if (-1 == retval) {
- log_warn(LD_GENERAL,
- "Failed to close write end of stderr pipe in parent process: %s",
- strerror(errno));
- }
-
- /* Return write end of the stdin pipe to caller, and close the read end */
- process_handle->stdin_pipe = stdin_pipe[1];
- retval = close(stdin_pipe[0]);
-
- if (-1 == retval) {
- log_warn(LD_GENERAL,
- "Failed to close read end of stdin pipe in parent process: %s",
- strerror(errno));
- }
-
- status = process_handle->status = PROCESS_STATUS_RUNNING;
- /* Set stdin/stdout/stderr pipes to be non-blocking */
- if (fcntl(process_handle->stdout_pipe, F_SETFL, O_NONBLOCK) < 0 ||
- fcntl(process_handle->stderr_pipe, F_SETFL, O_NONBLOCK) < 0 ||
- fcntl(process_handle->stdin_pipe, F_SETFL, O_NONBLOCK) < 0) {
- log_warn(LD_GENERAL, "Failed to set stderror/stdout/stdin pipes "
- "nonblocking in parent process: %s", strerror(errno));
- }
-
- *process_handle_out = process_handle;
- return status;
-#endif /* defined(_WIN32) */
-}
-
-/** Destroy all resources allocated by the process handle in
- * <b>process_handle</b>.
- * If <b>also_terminate_process</b> is true, also terminate the
- * process of the process handle. */
-MOCK_IMPL(void,
-tor_process_handle_destroy,(process_handle_t *process_handle,
- int also_terminate_process))
-{
- if (!process_handle)
- return;
-
- if (also_terminate_process) {
- if (tor_terminate_process(process_handle) < 0) {
- 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'.",
- tor_process_get_pid(process_handle));
- }
- }
-
- process_handle->status = PROCESS_STATUS_NOTRUNNING;
-
-#ifdef _WIN32
- if (process_handle->stdout_pipe)
- CloseHandle(process_handle->stdout_pipe);
-
- if (process_handle->stderr_pipe)
- CloseHandle(process_handle->stderr_pipe);
-
- if (process_handle->stdin_pipe)
- CloseHandle(process_handle->stdin_pipe);
-#else /* !(defined(_WIN32)) */
- close(process_handle->stdout_pipe);
- close(process_handle->stderr_pipe);
- close(process_handle->stdin_pipe);
-
- clear_waitpid_callback(process_handle->waitpid_cb);
-#endif /* defined(_WIN32) */
-
- memset(process_handle, 0x0f, sizeof(process_handle_t));
- tor_free(process_handle);
-}
-
-/** Get the exit code of a process specified by <b>process_handle</b> and store
- * it in <b>exit_code</b>, if set to a non-NULL value. If <b>block</b> is set
- * to true, the call will block until the process has exited. Otherwise if
- * the process is still running, the function will return
- * PROCESS_EXIT_RUNNING, and exit_code will be left unchanged. Returns
- * PROCESS_EXIT_EXITED if the process did exit. If there is a failure,
- * PROCESS_EXIT_ERROR will be returned and the contents of exit_code (if
- * non-NULL) will be undefined. N.B. Under *nix operating systems, this will
- * probably not work in Tor, because waitpid() is called in main.c to reap any
- * terminated child processes.*/
-int
-tor_get_exit_code(process_handle_t *process_handle,
- int block, int *exit_code)
-{
-#ifdef _WIN32
- DWORD retval;
- BOOL success;
-
- if (block) {
- /* Wait for the process to exit */
- retval = WaitForSingleObject(process_handle->pid.hProcess, INFINITE);
- if (retval != WAIT_OBJECT_0) {
- log_warn(LD_GENERAL, "WaitForSingleObject() failed (%d): %s",
- (int)retval, format_win32_error(GetLastError()));
- return PROCESS_EXIT_ERROR;
- }
- } else {
- retval = WaitForSingleObject(process_handle->pid.hProcess, 0);
- if (WAIT_TIMEOUT == retval) {
- /* Process has not exited */
- return PROCESS_EXIT_RUNNING;
- } else if (retval != WAIT_OBJECT_0) {
- log_warn(LD_GENERAL, "WaitForSingleObject() failed (%d): %s",
- (int)retval, format_win32_error(GetLastError()));
- return PROCESS_EXIT_ERROR;
- }
- }
-
- if (exit_code != NULL) {
- success = GetExitCodeProcess(process_handle->pid.hProcess,
- (PDWORD)exit_code);
- if (!success) {
- log_warn(LD_GENERAL, "GetExitCodeProcess() failed: %s",
- format_win32_error(GetLastError()));
- return PROCESS_EXIT_ERROR;
- }
- }
-#else /* !(defined(_WIN32)) */
- int stat_loc;
- int retval;
-
- if (process_handle->waitpid_cb) {
- /* We haven't processed a SIGCHLD yet. */
- retval = waitpid(process_handle->pid, &stat_loc, block?0:WNOHANG);
- if (retval == process_handle->pid) {
- clear_waitpid_callback(process_handle->waitpid_cb);
- process_handle->waitpid_cb = NULL;
- process_handle->waitpid_exit_status = stat_loc;
- }
- } else {
- /* We already got a SIGCHLD for this process, and handled it. */
- retval = process_handle->pid;
- stat_loc = process_handle->waitpid_exit_status;
- }
-
- if (!block && 0 == retval) {
- /* Process has not exited */
- return PROCESS_EXIT_RUNNING;
- } else if (retval != process_handle->pid) {
- log_warn(LD_GENERAL, "waitpid() failed for PID %d: %s",
- (int)process_handle->pid, strerror(errno));
- return PROCESS_EXIT_ERROR;
- }
-
- if (!WIFEXITED(stat_loc)) {
- log_warn(LD_GENERAL, "Process %d did not exit normally",
- (int)process_handle->pid);
- return PROCESS_EXIT_ERROR;
- }
-
- if (exit_code != NULL)
- *exit_code = WEXITSTATUS(stat_loc);
-#endif /* defined(_WIN32) */
-
- return PROCESS_EXIT_EXITED;
-}
-
-/** Helper: return the number of characters in <b>s</b> preceding the first
- * occurrence of <b>ch</b>. If <b>ch</b> does not occur in <b>s</b>, return
- * the length of <b>s</b>. Should be equivalent to strspn(s, "ch"). */
-static inline size_t
-str_num_before(const char *s, char ch)
-{
- const char *cp = strchr(s, ch);
- if (cp)
- return cp - s;
- else
- return strlen(s);
-}
-
-/** Return non-zero iff getenv would consider <b>s1</b> and <b>s2</b>
- * to have the same name as strings in a process's environment. */
-int
-environment_variable_names_equal(const char *s1, const char *s2)
-{
- size_t s1_name_len = str_num_before(s1, '=');
- size_t s2_name_len = str_num_before(s2, '=');
-
- return (s1_name_len == s2_name_len &&
- tor_memeq(s1, s2, s1_name_len));
-}
-
-/** Free <b>env</b> (assuming it was produced by
- * process_environment_make). */
-void
-process_environment_free_(process_environment_t *env)
-{
- if (env == NULL) return;
-
- /* As both an optimization hack to reduce consing on Unixoid systems
- * and a nice way to ensure that some otherwise-Windows-specific
- * code will always get tested before changes to it get merged, the
- * strings which env->unixoid_environment_block points to are packed
- * into env->windows_environment_block. */
- tor_free(env->unixoid_environment_block);
- tor_free(env->windows_environment_block);
-
- tor_free(env);
-}
-
-/** Make a process_environment_t containing the environment variables
- * specified in <b>env_vars</b> (as C strings of the form
- * "NAME=VALUE"). */
-process_environment_t *
-process_environment_make(struct smartlist_t *env_vars)
-{
- process_environment_t *env = tor_malloc_zero(sizeof(process_environment_t));
- int n_env_vars = smartlist_len(env_vars);
- int i;
- size_t total_env_length;
- smartlist_t *env_vars_sorted;
-
- tor_assert(n_env_vars + 1 != 0);
- env->unixoid_environment_block = tor_calloc(n_env_vars + 1, sizeof(char *));
- /* env->unixoid_environment_block is already NULL-terminated,
- * because we assume that NULL == 0 (and check that during compilation). */
-
- total_env_length = 1; /* terminating NUL of terminating empty string */
- for (i = 0; i < n_env_vars; ++i) {
- const char *s = smartlist_get(env_vars, i);
- size_t slen = strlen(s);
-
- tor_assert(slen + 1 != 0);
- tor_assert(slen + 1 < SIZE_MAX - total_env_length);
- total_env_length += slen + 1;
- }
-
- env->windows_environment_block = tor_malloc_zero(total_env_length);
- /* env->windows_environment_block is already
- * (NUL-terminated-empty-string)-terminated. */
-
- /* Some versions of Windows supposedly require that environment
- * blocks be sorted. Or maybe some Windows programs (or their
- * runtime libraries) fail to look up strings in non-sorted
- * environment blocks.
- *
- * Also, sorting strings makes it easy to find duplicate environment
- * variables and environment-variable strings without an '=' on all
- * OSes, and they can cause badness. Let's complain about those. */
- env_vars_sorted = smartlist_new();
- smartlist_add_all(env_vars_sorted, env_vars);
- smartlist_sort_strings(env_vars_sorted);
-
- /* Now copy the strings into the environment blocks. */
- {
- char *cp = env->windows_environment_block;
- const char *prev_env_var = NULL;
-
- for (i = 0; i < n_env_vars; ++i) {
- const char *s = smartlist_get(env_vars_sorted, i);
- size_t slen = strlen(s);
- size_t s_name_len = str_num_before(s, '=');
-
- if (s_name_len == slen) {
- log_warn(LD_GENERAL,
- "Preparing an environment containing a variable "
- "without a value: %s",
- s);
- }
- if (prev_env_var != NULL &&
- environment_variable_names_equal(s, prev_env_var)) {
- log_warn(LD_GENERAL,
- "Preparing an environment containing two variables "
- "with the same name: %s and %s",
- prev_env_var, s);
- }
-
- prev_env_var = s;
-
- /* Actually copy the string into the environment. */
- memcpy(cp, s, slen+1);
- env->unixoid_environment_block[i] = cp;
- cp += slen+1;
- }
-
- tor_assert(cp == env->windows_environment_block + total_env_length - 1);
- }
-
- smartlist_free(env_vars_sorted);
-
- return env;
-}
-
-/** Return a newly allocated smartlist containing every variable in
- * this process's environment, as a NUL-terminated string of the form
- * "NAME=VALUE". Note that on some/many/most/all OSes, the parent
- * process can put strings not of that form in our environment;
- * callers should try to not get crashed by that.
- *
- * The returned strings are heap-allocated, and must be freed by the
- * caller. */
-struct smartlist_t *
-get_current_process_environment_variables(void)
-{
- smartlist_t *sl = smartlist_new();
-
- char **environ_tmp; /* Not const char ** ? Really? */
- for (environ_tmp = get_environment(); *environ_tmp; ++environ_tmp) {
- smartlist_add_strdup(sl, *environ_tmp);
- }
-
- return sl;
-}
-
-/** For each string s in <b>env_vars</b> such that
- * environment_variable_names_equal(s, <b>new_var</b>), remove it; if
- * <b>free_p</b> is non-zero, call <b>free_old</b>(s). If
- * <b>new_var</b> contains '=', insert it into <b>env_vars</b>. */
-void
-set_environment_variable_in_smartlist(struct smartlist_t *env_vars,
- const char *new_var,
- void (*free_old)(void*),
- int free_p)
-{
- SMARTLIST_FOREACH_BEGIN(env_vars, const char *, s) {
- if (environment_variable_names_equal(s, new_var)) {
- SMARTLIST_DEL_CURRENT(env_vars, s);
- if (free_p) {
- free_old((void *)s);
- }
- }
- } SMARTLIST_FOREACH_END(s);
-
- if (strchr(new_var, '=') != NULL) {
- smartlist_add(env_vars, (void *)new_var);
- }
-}
-
-#ifdef _WIN32
-/** Read from a handle <b>h</b> into <b>buf</b>, up to <b>count</b> bytes. If
- * <b>hProcess</b> is NULL, the function will return immediately if there is
- * nothing more to read. Otherwise <b>hProcess</b> should be set to the handle
- * to the process owning the <b>h</b>. In this case, the function will exit
- * only once the process has exited, or <b>count</b> bytes are read. Returns
- * the number of bytes read, or -1 on error. */
-ssize_t
-tor_read_all_handle(HANDLE h, char *buf, size_t count,
- const process_handle_t *process)
-{
- size_t numread = 0;
- BOOL retval;
- DWORD byte_count;
- BOOL process_exited = FALSE;
-
- if (count > SIZE_T_CEILING || count > SSIZE_MAX)
- return -1;
-
- while (numread < count) {
- /* Check if there is anything to read */
- retval = PeekNamedPipe(h, NULL, 0, NULL, &byte_count, NULL);
- if (!retval) {
- log_warn(LD_GENERAL,
- "Failed to peek from handle: %s",
- format_win32_error(GetLastError()));
- return -1;
- } else if (0 == byte_count) {
- /* Nothing available: process exited or it is busy */
-
- /* Exit if we don't know whether the process is running */
- if (NULL == process)
- break;
-
- /* The process exited and there's nothing left to read from it */
- if (process_exited)
- break;
-
- /* If process is not running, check for output one more time in case
- it wrote something after the peek was performed. Otherwise keep on
- waiting for output */
- tor_assert(process != NULL);
- byte_count = WaitForSingleObject(process->pid.hProcess, 0);
- if (WAIT_TIMEOUT != byte_count)
- process_exited = TRUE;
-
- continue;
- }
-
- /* There is data to read; read it */
- retval = ReadFile(h, buf+numread, count-numread, &byte_count, NULL);
- tor_assert(byte_count + numread <= count);
- if (!retval) {
- log_warn(LD_GENERAL, "Failed to read from handle: %s",
- format_win32_error(GetLastError()));
- return -1;
- } else if (0 == byte_count) {
- /* End of file */
- break;
- }
- numread += byte_count;
- }
- return (ssize_t)numread;
-}
-#else /* !(defined(_WIN32)) */
-/** Read from a handle <b>fd</b> into <b>buf</b>, up to <b>count</b> bytes. If
- * <b>process</b> is NULL, the function will return immediately if there is
- * nothing more to read. Otherwise data will be read until end of file, or
- * <b>count</b> bytes are read. Returns the number of bytes read, or -1 on
- * error. Sets <b>eof</b> to true if <b>eof</b> is not NULL and the end of the
- * file has been reached. */
-ssize_t
-tor_read_all_handle(int fd, char *buf, size_t count,
- const process_handle_t *process,
- int *eof)
-{
- size_t numread = 0;
- ssize_t result;
-
- if (eof)
- *eof = 0;
-
- if (count > SIZE_T_CEILING || count > SSIZE_MAX)
- return -1;
-
- while (numread < count) {
- result = read(fd, buf+numread, count-numread);
-
- if (result == 0) {
- log_debug(LD_GENERAL, "read() reached end of file");
- if (eof)
- *eof = 1;
- break;
- } else if (result < 0 && errno == EAGAIN) {
- if (process)
- continue;
- else
- break;
- } else if (result < 0) {
- log_warn(LD_GENERAL, "read() failed: %s", strerror(errno));
- return -1;
- }
-
- numread += result;
- }
-
- log_debug(LD_GENERAL, "read() read %d bytes from handle", (int)numread);
- return (ssize_t)numread;
-}
-#endif /* defined(_WIN32) */
-
-/** Read from stdout of a process until the process exits. */
-ssize_t
-tor_read_all_from_process_stdout(const process_handle_t *process_handle,
- char *buf, size_t count)
-{
-#ifdef _WIN32
- return tor_read_all_handle(process_handle->stdout_pipe, buf, count,
- process_handle);
-#else
- return tor_read_all_handle(process_handle->stdout_pipe, buf, count,
- process_handle, NULL);
-#endif /* defined(_WIN32) */
-}
-
-/** Read from stdout of a process until the process exits. */
-ssize_t
-tor_read_all_from_process_stderr(const process_handle_t *process_handle,
- char *buf, size_t count)
-{
-#ifdef _WIN32
- return tor_read_all_handle(process_handle->stderr_pipe, buf, count,
- process_handle);
-#else
- return tor_read_all_handle(process_handle->stderr_pipe, buf, count,
- process_handle, NULL);
-#endif /* defined(_WIN32) */
-}
-
-/** Split buf into lines, and add to smartlist. The buffer <b>buf</b> will be
- * modified. The resulting smartlist will consist of pointers to buf, so there
- * is no need to free the contents of sl. <b>buf</b> must be a NUL-terminated
- * string. <b>len</b> should be set to the length of the buffer excluding the
- * NUL. Non-printable characters (including NUL) will be replaced with "." */
-int
-tor_split_lines(smartlist_t *sl, char *buf, int len)
-{
- /* Index in buf of the start of the current line */
- int start = 0;
- /* Index in buf of the current character being processed */
- int cur = 0;
- /* Are we currently in a line */
- char in_line = 0;
-
- /* Loop over string */
- while (cur < len) {
- /* Loop until end of line or end of string */
- for (; cur < len; cur++) {
- if (in_line) {
- if ('\r' == buf[cur] || '\n' == buf[cur]) {
- /* End of line */
- buf[cur] = '\0';
- /* Point cur to the next line */
- cur++;
- /* Line starts at start and ends with a nul */
- break;
- } else {
- if (!TOR_ISPRINT(buf[cur]))
- buf[cur] = '.';
- }
- } else {
- if ('\r' == buf[cur] || '\n' == buf[cur]) {
- /* Skip leading vertical space */
- ;
- } else {
- in_line = 1;
- start = cur;
- if (!TOR_ISPRINT(buf[cur]))
- buf[cur] = '.';
- }
- }
- }
- /* We are at the end of the line or end of string. If in_line is true there
- * is a line which starts at buf+start and ends at a NUL. cur points to
- * the character after the NUL. */
- if (in_line)
- smartlist_add(sl, (void *)(buf+start));
- in_line = 0;
- }
- return smartlist_len(sl);
-}
-
-/** Return a string corresponding to <b>stream_status</b>. */
-const char *
-stream_status_to_string(enum stream_status stream_status)
-{
- switch (stream_status) {
- case IO_STREAM_OKAY:
- return "okay";
- case IO_STREAM_EAGAIN:
- return "temporarily unavailable";
- case IO_STREAM_TERM:
- return "terminated";
- case IO_STREAM_CLOSED:
- return "closed";
- default:
- tor_fragile_assert();
- return "unknown";
- }
-}
-
-#ifdef _WIN32
-
-/** Return a smartlist containing lines outputted from
- * <b>handle</b>. Return NULL on error, and set
- * <b>stream_status_out</b> appropriately. */
-MOCK_IMPL(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;
-}
-
-#else /* !(defined(_WIN32)) */
-
-/** Return a smartlist containing lines outputted from
- * <b>fd</b>. Return NULL on error, and set
- * <b>stream_status_out</b> appropriately. */
-MOCK_IMPL(smartlist_t *,
-tor_get_lines_from_handle, (int fd, 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(fd,
- stdout_buf, sizeof(stdout_buf) - 1);
- if (stream_status != IO_STREAM_OKAY)
- goto done;
-
- if (!lines) lines = smartlist_new();
- smartlist_split_string(lines, stdout_buf, "\n", 0, 0);
- }
-
- done:
- *stream_status_out = stream_status;
- return lines;
-}
-
-#endif /* defined(_WIN32) */
-
-/** Reads from <b>fd</b> and stores input in <b>buf_out</b> making
- * sure it's below <b>count</b> bytes.
- * If the string has a trailing newline, we strip it off.
- *
- * This function is specifically created to handle input from managed
- * proxies, according to the pluggable transports spec. Make sure it
- * fits your needs before using it.
- *
- * Returns:
- * IO_STREAM_CLOSED: If the stream is closed.
- * IO_STREAM_EAGAIN: If there is nothing to read and we should check back
- * later.
- * IO_STREAM_TERM: If something is wrong with the stream.
- * IO_STREAM_OKAY: If everything went okay and we got a string
- * in <b>buf_out</b>. */
-enum stream_status
-get_string_from_pipe(int fd, char *buf_out, size_t count)
-{
- ssize_t ret;
-
- tor_assert(count <= INT_MAX);
-
- ret = read(fd, buf_out, count);
-
- if (ret == 0)
- return IO_STREAM_CLOSED;
- else if (ret < 0 && errno == EAGAIN)
- return IO_STREAM_EAGAIN;
- else if (ret < 0)
- return IO_STREAM_TERM;
-
- if (buf_out[ret - 1] == '\n') {
- /* Remove the trailing newline */
- buf_out[ret - 1] = '\0';
- } else
- buf_out[ret] = '\0';
-
- return IO_STREAM_OKAY;
-}
-
-/** Initialize the insecure RNG <b>rng</b> from a seed value <b>seed</b>. */
-void
-tor_init_weak_random(tor_weak_rng_t *rng, unsigned seed)
-{
- rng->state = (uint32_t)(seed & 0x7fffffff);
-}
-
-/** Return a randomly chosen value in the range 0..TOR_WEAK_RANDOM_MAX based
- * on the RNG state of <b>rng</b>. This entropy will not be cryptographically
- * strong; do not rely on it for anything an adversary should not be able to
- * predict. */
-int32_t
-tor_weak_random(tor_weak_rng_t *rng)
-{
- /* Here's a linear congruential generator. OpenBSD and glibc use these
- * parameters; they aren't too bad, and should have maximal period over the
- * range 0..INT32_MAX. We don't want to use the platform rand() or random(),
- * since some platforms have bad weak RNGs that only return values in the
- * range 0..INT16_MAX, which just isn't enough. */
- rng->state = (rng->state * 1103515245 + 12345) & 0x7fffffff;
- return (int32_t) rng->state;
-}
-
-/** Return a random number in the range [0 , <b>top</b>). {That is, the range
- * of integers i such that 0 <= i < top.} Chooses uniformly. Requires that
- * top is greater than 0. This randomness is not cryptographically strong; do
- * not rely on it for anything an adversary should not be able to predict. */
-int32_t
-tor_weak_random_range(tor_weak_rng_t *rng, int32_t top)
-{
- /* We don't want to just do tor_weak_random() % top, since random() is often
- * implemented with an LCG whose modulus is a power of 2, and those are
- * cyclic in their low-order bits. */
- int divisor, result;
- tor_assert(top > 0);
- divisor = TOR_WEAK_RANDOM_MAX / top;
- do {
- result = (int32_t)(tor_weak_random(rng) / divisor);
- } while (result >= top);
- return result;
-}
-
-/** Cast a given double value to a int64_t. Return 0 if number is NaN.
- * Returns either INT64_MIN or INT64_MAX if number is outside of the int64_t
- * range. */
-int64_t
-clamp_double_to_int64(double number)
-{
- int exponent;
-
-#if defined(MINGW_ANY) && GCC_VERSION >= 409
-/*
- Mingw's math.h uses gcc's __builtin_choose_expr() facility to declare
- isnan, isfinite, and signbit. But as implemented in at least some
- versions of gcc, __builtin_choose_expr() can generate type warnings
- even from branches that are not taken. So, suppress those warnings.
-*/
-#define PROBLEMATIC_FLOAT_CONVERSION_WARNING
-DISABLE_GCC_WARNING(float-conversion)
-#endif /* defined(MINGW_ANY) && GCC_VERSION >= 409 */
-
-/*
- With clang 4.0 we apparently run into "double promotion" warnings here,
- since clang thinks we're promoting a double to a long double.
- */
-#if defined(__clang__)
-#if __has_warning("-Wdouble-promotion")
-#define PROBLEMATIC_DOUBLE_PROMOTION_WARNING
-DISABLE_GCC_WARNING(double-promotion)
-#endif
-#endif /* defined(__clang__) */
-
- /* NaN is a special case that can't be used with the logic below. */
- if (isnan(number)) {
- return 0;
- }
-
- /* Time to validate if result can overflows a int64_t value. Fun with
- * float! Find that exponent exp such that
- * number == x * 2^exp
- * for some x with abs(x) in [0.5, 1.0). Note that this implies that the
- * magnitude of number is strictly less than 2^exp.
- *
- * If number is infinite, the call to frexp is legal but the contents of
- * are exponent unspecified. */
- frexp(number, &exponent);
-
- /* If the magnitude of number is strictly less than 2^63, the truncated
- * version of number is guaranteed to be representable. The only
- * representable integer for which this is not the case is INT64_MIN, but
- * it is covered by the logic below. */
- if (isfinite(number) && exponent <= 63) {
- return (int64_t)number;
- }
-
- /* Handle infinities and finite numbers with magnitude >= 2^63. */
- return signbit(number) ? INT64_MIN : INT64_MAX;
-
-#ifdef PROBLEMATIC_DOUBLE_PROMOTION_WARNING
-ENABLE_GCC_WARNING(double-promotion)
-#endif
-#ifdef PROBLEMATIC_FLOAT_CONVERSION_WARNING
-ENABLE_GCC_WARNING(float-conversion)
-#endif
-}
-
-/** Return a uint64_t value from <b>a</b> in network byte order. */
-uint64_t
-tor_htonll(uint64_t a)
-{
-#ifdef WORDS_BIGENDIAN
- /* Big endian. */
- return a;
-#else /* WORDS_BIGENDIAN */
- /* Little endian. The worst... */
- return htonl((uint32_t)(a>>32)) |
- (((uint64_t)htonl((uint32_t)a))<<32);
-#endif /* defined(WORDS_BIGENDIAN) */
-}
-
-/** Return a uint64_t value from <b>a</b> in host byte order. */
-uint64_t
-tor_ntohll(uint64_t a)
-{
- return tor_htonll(a);
-}
-
diff --git a/src/common/util.h b/src/common/util.h
deleted file mode 100644
index 7172b7da08..0000000000
--- a/src/common/util.h
+++ /dev/null
@@ -1,572 +0,0 @@
-/* Copyright (c) 2003-2004, Roger Dingledine
- * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2017, The Tor Project, Inc. */
-/* See LICENSE for licensing information */
-
-/**
- * \file util.h
- * \brief Headers for util.c
- **/
-
-#ifndef TOR_UTIL_H
-#define TOR_UTIL_H
-
-#include "orconfig.h"
-#include "torint.h"
-#include "compat.h"
-#include "di_ops.h"
-#include "testsupport.h"
-#include <stdio.h>
-#include <stdlib.h>
-#ifdef _WIN32
-/* for the correct alias to struct stat */
-#include <sys/stat.h>
-#endif
-#include "util_bug.h"
-
-#ifndef O_BINARY
-#define O_BINARY 0
-#endif
-#ifndef O_TEXT
-#define O_TEXT 0
-#endif
-#ifndef O_NOFOLLOW
-#define O_NOFOLLOW 0
-#endif
-
-/* If we're building with dmalloc, we want all of our memory allocation
- * functions to take an extra file/line pair of arguments. If not, not.
- * We define DMALLOC_PARAMS to the extra parameters to insert in the
- * function prototypes, and DMALLOC_ARGS to the extra arguments to add
- * to calls. */
-#ifdef USE_DMALLOC
-#define DMALLOC_PARAMS , const char *file, const int line
-#define DMALLOC_ARGS , SHORT_FILE__, __LINE__
-#else
-#define DMALLOC_PARAMS
-#define DMALLOC_ARGS
-#endif /* defined(USE_DMALLOC) */
-
-/* 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_calloc_(size_t nmemb, size_t size DMALLOC_PARAMS) ATTR_MALLOC;
-void *tor_realloc_(void *ptr, size_t size DMALLOC_PARAMS);
-void *tor_reallocarray_(void *ptr, size_t size1, size_t size2 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)
- ATTR_MALLOC ATTR_NONNULL((1));
-void *tor_memdup_nulterm_(const void *mem, size_t len DMALLOC_PARAMS)
- ATTR_MALLOC ATTR_NONNULL((1));
-void tor_free_(void *mem);
-uint64_t tor_htonll(uint64_t a);
-uint64_t tor_ntohll(uint64_t a);
-#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); \
- (p)=NULL; \
- } \
- STMT_END
-#else /* !(defined(USE_DMALLOC)) */
-/** Release memory allocated by tor_malloc, tor_realloc, tor_strdup,
- * etc. Unlike the free() function, the tor_free() macro 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_().
- *
- * Note that this macro takes the address of the pointer it is going to
- * free and clear. If that pointer is stored with a nonstandard
- * alignment (eg because of a "packed" pragma) it is not correct to use
- * tor_free().
- */
-#ifdef __GNUC__
-#define tor_free(p) STMT_BEGIN \
- typeof(&(p)) tor_free__tmpvar = &(p); \
- raw_free(*tor_free__tmpvar); \
- *tor_free__tmpvar=NULL; \
- STMT_END
-#else
-#define tor_free(p) STMT_BEGIN \
- raw_free(p); \
- (p)=NULL; \
- STMT_END
-#endif
-#endif /* defined(USE_DMALLOC) */
-
-#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_realloc(ptr, size) tor_realloc_(ptr, size DMALLOC_ARGS)
-#define tor_reallocarray(ptr, sz1, sz2) \
- tor_reallocarray_((ptr), (sz1), (sz2) 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_memdup_nulterm(s, n) tor_memdup_nulterm_(s, n DMALLOC_ARGS)
-
-/* Aliases for the underlying system malloc/realloc/free. Only use
- * them to indicate "I really want the underlying system function, I know
- * what I'm doing." */
-#define raw_malloc malloc
-#define raw_realloc realloc
-#define raw_free free
-#define raw_strdup strdup
-
-void tor_log_mallinfo(int severity);
-
-/* Helper macro: free a variable of type 'typename' using freefn, and
- * set the variable to NULL.
- */
-#define FREE_AND_NULL(typename, freefn, var) \
- do { \
- /* only evaluate (var) once. */ \
- typename **tmp__free__ptr ## freefn = &(var); \
- freefn(*tmp__free__ptr ## freefn); \
- (*tmp__free__ptr ## freefn) = NULL; \
- } while (0)
-
-/** Macro: yield a pointer to the field at position <b>off</b> within the
- * structure <b>st</b>. Example:
- * <pre>
- * struct a { int foo; int bar; } x;
- * off_t bar_offset = offsetof(struct a, bar);
- * int *bar_p = STRUCT_VAR_P(&x, bar_offset);
- * *bar_p = 3;
- * </pre>
- */
-#define STRUCT_VAR_P(st, off) ((void*) ( ((char*)(st)) + (off) ) )
-
-/** Macro: yield a pointer to an enclosing structure given a pointer to
- * a substructure at offset <b>off</b>. Example:
- * <pre>
- * struct base { ... };
- * struct subtype { int x; struct base b; } x;
- * struct base *bp = &x.base;
- * struct *sp = SUBTYPE_P(bp, struct subtype, b);
- * </pre>
- */
-#define SUBTYPE_P(p, subtype, basemember) \
- ((void*) ( ((char*)(p)) - offsetof(subtype, basemember) ))
-
-/* Logic */
-/** Macro: true if two values have the same boolean value. */
-#define bool_eq(a,b) (!(a)==!(b))
-/** Macro: true if two values have different boolean values. */
-#define bool_neq(a,b) (!(a)!=!(b))
-
-/* 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);
-uint32_t round_uint32_to_next_multiple_of(uint32_t number, uint32_t divisor);
-uint64_t round_uint64_to_next_multiple_of(uint64_t number, uint64_t divisor);
-int64_t sample_laplace_distribution(double mu, double b, double p);
-int64_t add_laplace_noise(int64_t signal, double random, double delta_f,
- double epsilon);
-int n_bits_set_u8(uint8_t v);
-int64_t clamp_double_to_int64(double number);
-void simplify_fraction64(uint64_t *numer, uint64_t *denom);
-
-uint32_t tor_add_u32_nowrap(uint32_t a, uint32_t b);
-
-/* Compute the CEIL of <b>a</b> divided by <b>b</b>, for nonnegative <b>a</b>
- * and positive <b>b</b>. Works on integer types only. Not defined if a+(b-1)
- * can overflow. */
-#define CEIL_DIV(a,b) (((a)+((b)-1))/(b))
-
-/* Return <b>v</b> if it's between <b>min</b> and <b>max</b>. Otherwise
- * return <b>min</b> if <b>v</b> is smaller than <b>min</b>, or <b>max</b> if
- * <b>b</b> is larger than <b>max</b>.
- *
- * Requires that <b>min</b> is no more than <b>max</b>. May evaluate any of
- * its arguments more than once! */
-#define CLAMP(min,v,max) \
- ( ((v) < (min)) ? (min) : \
- ((v) > (max)) ? (max) : \
- (v) )
-
-/* String manipulation */
-
-/** Allowable characters in a hexadecimal string. */
-#define HEX_CHARACTERS "0123456789ABCDEFabcdef"
-void tor_strlower(char *s) ATTR_NONNULL((1));
-void tor_strupper(char *s) ATTR_NONNULL((1));
-int tor_strisprint(const char *s) ATTR_NONNULL((1));
-int tor_strisnonupper(const char *s) ATTR_NONNULL((1));
-int tor_strisspace(const char *s);
-int strcmp_opt(const char *s1, const char *s2);
-int strcmpstart(const char *s1, const char *s2) ATTR_NONNULL((1,2));
-int strcmp_len(const char *s1, const char *s2, size_t len) ATTR_NONNULL((1,2));
-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_strstrip(char *s, const char *strip) ATTR_NONNULL((1,2));
-long tor_parse_long(const char *s, int base, long min,
- long max, int *ok, char **next);
-unsigned long tor_parse_ulong(const char *s, int base, unsigned long min,
- unsigned long max, int *ok, char **next);
-double tor_parse_double(const char *s, double min, double max, int *ok,
- char **next);
-uint64_t tor_parse_uint64(const char *s, int base, uint64_t min,
- uint64_t max, int *ok, char **next);
-const char *hex_str(const char *from, size_t fromlen) ATTR_NONNULL((1));
-const char *eat_whitespace(const char *s);
-const char *eat_whitespace_eos(const char *s, const char *eos);
-const char *eat_whitespace_no_nl(const char *s);
-const char *eat_whitespace_eos_no_nl(const char *s, const char *eos);
-const char *find_whitespace(const char *s);
-const char *find_whitespace_eos(const char *s, const char *eos);
-const char *find_str_at_start_of_line(const char *haystack,
- const char *needle);
-int string_is_C_identifier(const char *string);
-int string_is_key_value(int severity, const char *string);
-int string_is_valid_dest(const char *string);
-int string_is_valid_nonrfc_hostname(const char *string);
-int string_is_valid_ipv4_address(const char *string);
-int string_is_valid_ipv6_address(const char *string);
-
-int tor_mem_is_zero(const char *mem, size_t len);
-int tor_digest_is_zero(const char *digest);
-int tor_digest256_is_zero(const char *digest);
-char *esc_for_log(const char *string) ATTR_MALLOC;
-char *esc_for_log_len(const char *chars, size_t n) ATTR_MALLOC;
-const char *escaped(const char *string);
-
-char *tor_escape_str_for_pt_args(const char *string,
- const char *chars_to_escape);
-
-struct smartlist_t;
-int tor_vsscanf(const char *buf, const char *pattern, va_list ap) \
- CHECK_SCANF(2, 0);
-int tor_sscanf(const char *buf, const char *pattern, ...)
- CHECK_SCANF(2, 3);
-
-void smartlist_add_asprintf(struct smartlist_t *sl, const char *pattern, ...)
- CHECK_PRINTF(2, 3);
-void smartlist_add_vasprintf(struct smartlist_t *sl, const char *pattern,
- va_list args)
- CHECK_PRINTF(2, 0);
-void smartlist_add_strdup(struct smartlist_t *sl, const char *string);
-
-/* Time helpers */
-long tv_udiff(const struct timeval *start, const struct timeval *end);
-long tv_mdiff(const struct timeval *start, const struct timeval *end);
-int64_t tv_to_msec(const struct timeval *tv);
-int tor_timegm(const struct tm *tm, time_t *time_out);
-#define RFC1123_TIME_LEN 29
-void format_rfc1123_time(char *buf, time_t t);
-int parse_rfc1123_time(const char *buf, time_t *t);
-#define ISO_TIME_LEN 19
-#define ISO_TIME_USEC_LEN (ISO_TIME_LEN+7)
-void format_local_iso_time(char *buf, time_t t);
-void format_iso_time(char *buf, time_t t);
-void format_local_iso_time_nospace(char *buf, time_t t);
-void format_iso_time_nospace(char *buf, time_t t);
-void format_iso_time_nospace_usec(char *buf, const struct timeval *tv);
-int parse_iso_time_(const char *cp, time_t *t, int strict, int nospace);
-int parse_iso_time(const char *buf, time_t *t);
-int parse_iso_time_nospace(const char *cp, time_t *t);
-int parse_http_time(const char *buf, struct tm *tm);
-int format_time_interval(char *out, size_t out_len, long interval);
-
-/* Cached time */
-#ifdef TIME_IS_FAST
-#define approx_time() time(NULL)
-#define update_approx_time(t) STMT_NIL
-#else
-time_t approx_time(void);
-void update_approx_time(time_t now);
-#endif /* defined(TIME_IS_FAST) */
-
-/* Rate-limiter */
-
-/** A ratelim_t remembers how often an event is occurring, and how often
- * it's allowed to occur. Typical usage is something like:
- *
- <pre>
- if (possibly_very_frequent_event()) {
- const int INTERVAL = 300;
- static ratelim_t warning_limit = RATELIM_INIT(INTERVAL);
- char *m;
- if ((m = rate_limit_log(&warning_limit, approx_time()))) {
- log_warn(LD_GENERAL, "The event occurred!%s", m);
- tor_free(m);
- }
- }
- </pre>
-
- As a convenience wrapper for logging, you can replace the above with:
- <pre>
- if (possibly_very_frequent_event()) {
- static ratelim_t warning_limit = RATELIM_INIT(300);
- log_fn_ratelim(&warning_limit, LOG_WARN, LD_GENERAL,
- "The event occurred!");
- }
- </pre>
- */
-typedef struct ratelim_t {
- int rate;
- time_t last_allowed;
- int n_calls_since_last_time;
-} ratelim_t;
-
-#define RATELIM_INIT(r) { (r), 0, 0 }
-#define RATELIM_TOOMANY (16*1000*1000)
-
-char *rate_limit_log(ratelim_t *lim, time_t now);
-
-/* File helpers */
-ssize_t write_all(tor_socket_t fd, const char *buf, size_t count,int isSocket);
-ssize_t read_all(tor_socket_t fd, char *buf, size_t count, int isSocket);
-
-/** Status of an I/O stream. */
-enum stream_status {
- IO_STREAM_OKAY,
- IO_STREAM_EAGAIN,
- IO_STREAM_TERM,
- IO_STREAM_CLOSED
-};
-
-const char *stream_status_to_string(enum stream_status stream_status);
-
-enum stream_status get_string_from_pipe(int fd, char *buf, size_t count);
-
-MOCK_DECL(int,tor_unlink,(const char *pathname));
-
-/** Return values from file_status(); see that function's documentation
- * for details. */
-typedef enum { FN_ERROR, FN_NOENT, FN_FILE, FN_DIR, FN_EMPTY } file_status_t;
-file_status_t file_status(const char *filename);
-
-/** Possible behaviors for check_private_dir() on encountering a nonexistent
- * directory; see that function's documentation for details. */
-typedef unsigned int cpd_check_t;
-#define CPD_NONE 0
-#define CPD_CREATE (1u << 0)
-#define CPD_CHECK (1u << 1)
-#define CPD_GROUP_OK (1u << 2)
-#define CPD_GROUP_READ (1u << 3)
-#define CPD_CHECK_MODE_ONLY (1u << 4)
-#define CPD_RELAX_DIRMODE_CHECK (1u << 5)
-MOCK_DECL(int, check_private_dir,
- (const char *dirname, cpd_check_t check,
- const char *effective_user));
-
-#define OPEN_FLAGS_REPLACE (O_WRONLY|O_CREAT|O_TRUNC)
-#define OPEN_FLAGS_APPEND (O_WRONLY|O_CREAT|O_APPEND)
-#define OPEN_FLAGS_DONT_REPLACE (O_CREAT|O_EXCL|O_APPEND|O_WRONLY)
-typedef struct open_file_t open_file_t;
-int start_writing_to_file(const char *fname, int open_flags, int mode,
- open_file_t **data_out);
-FILE *start_writing_to_stdio_file(const char *fname, int open_flags, int mode,
- open_file_t **data_out);
-FILE *fdopen_file(open_file_t *file_data);
-int finish_writing_to_file(open_file_t *file_data);
-int abort_writing_to_file(open_file_t *file_data);
-MOCK_DECL(int,
-write_str_to_file,(const char *fname, const char *str, int bin));
-MOCK_DECL(int,
-write_bytes_to_file,(const char *fname, const char *str, size_t len,
- int bin));
-/** An ad-hoc type to hold a string of characters and a count; used by
- * write_chunks_to_file. */
-typedef struct sized_chunk_t {
- const char *bytes;
- size_t len;
-} sized_chunk_t;
-int write_chunks_to_file(const char *fname, const struct smartlist_t *chunks,
- int bin, int no_tempfile);
-int append_bytes_to_file(const char *fname, const char *str, size_t len,
- int bin);
-int write_bytes_to_new_file(const char *fname, const char *str, size_t len,
- int bin);
-
-/** Flag for read_file_to_str: open the file in binary mode. */
-#define RFTS_BIN 1
-/** Flag for read_file_to_str: it's okay if the file doesn't exist. */
-#define RFTS_IGNORE_MISSING 2
-
-#ifndef _WIN32
-struct stat;
-#endif
-MOCK_DECL_ATTR(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 *unescape_string(const char *s, char **result, size_t *size_out);
-char *get_unquoted_path(const char *path);
-char *expand_filename(const char *filename);
-MOCK_DECL(struct smartlist_t *, tor_listdir, (const char *dirname));
-int path_is_relative(const char *filename);
-
-/* Process helpers */
-void start_daemon(void);
-void finish_daemon(const char *desired_cwd);
-int write_pidfile(const char *filename);
-
-void tor_disable_spawning_background_processes(void);
-
-typedef struct process_handle_t process_handle_t;
-typedef struct process_environment_t process_environment_t;
-int tor_spawn_background(const char *const filename, const char **argv,
- process_environment_t *env,
- process_handle_t **process_handle_out);
-
-#define SPAWN_ERROR_MESSAGE "ERR: Failed to spawn background process - code "
-
-#ifdef _WIN32
-HANDLE load_windows_system_library(const TCHAR *library_name);
-#endif
-
-int environment_variable_names_equal(const char *s1, const char *s2);
-
-/* DOCDOC process_environment_t */
-struct process_environment_t {
- /** A pointer to a sorted empty-string-terminated sequence of
- * NUL-terminated strings of the form "NAME=VALUE". */
- char *windows_environment_block;
- /** A pointer to a NULL-terminated array of pointers to
- * NUL-terminated strings of the form "NAME=VALUE". */
- char **unixoid_environment_block;
-};
-
-process_environment_t *process_environment_make(struct smartlist_t *env_vars);
-void process_environment_free_(process_environment_t *env);
-#define process_environment_free(env) \
- FREE_AND_NULL(process_environment_t, process_environment_free_, (env))
-
-struct smartlist_t *get_current_process_environment_variables(void);
-
-void set_environment_variable_in_smartlist(struct smartlist_t *env_vars,
- const char *new_var,
- void (*free_old)(void*),
- int free_p);
-
-/* Values of process_handle_t.status. */
-#define PROCESS_STATUS_NOTRUNNING 0
-#define PROCESS_STATUS_RUNNING 1
-#define PROCESS_STATUS_ERROR -1
-
-#ifdef UTIL_PRIVATE
-struct waitpid_callback_t;
-/** Structure to represent the state of a process with which Tor is
- * communicating. The contents of this structure are private to util.c */
-struct process_handle_t {
- /** One of the PROCESS_STATUS_* values */
- int status;
-#ifdef _WIN32
- HANDLE stdin_pipe;
- HANDLE stdout_pipe;
- HANDLE stderr_pipe;
- PROCESS_INFORMATION pid;
-#else /* !(defined(_WIN32)) */
- int stdin_pipe;
- int stdout_pipe;
- int stderr_pipe;
- pid_t pid;
- /** If the process has not given us a SIGCHLD yet, this has the
- * waitpid_callback_t that gets invoked once it has. Otherwise this
- * contains NULL. */
- struct waitpid_callback_t *waitpid_cb;
- /** The exit status reported by waitpid. */
- int waitpid_exit_status;
-#endif /* defined(_WIN32) */
-};
-#endif /* defined(UTIL_PRIVATE) */
-
-/* Return values of tor_get_exit_code() */
-#define PROCESS_EXIT_RUNNING 1
-#define PROCESS_EXIT_EXITED 0
-#define PROCESS_EXIT_ERROR -1
-int tor_get_exit_code(process_handle_t *process_handle,
- int block, int *exit_code);
-int tor_split_lines(struct smartlist_t *sl, char *buf, int len);
-#ifdef _WIN32
-ssize_t tor_read_all_handle(HANDLE h, char *buf, size_t count,
- const process_handle_t *process);
-#else
-ssize_t tor_read_all_handle(int fd, char *buf, size_t count,
- const process_handle_t *process,
- int *eof);
-#endif /* defined(_WIN32) */
-ssize_t tor_read_all_from_process_stdout(
- const process_handle_t *process_handle, char *buf, size_t count);
-ssize_t tor_read_all_from_process_stderr(
- const process_handle_t *process_handle, char *buf, size_t count);
-char *tor_join_win_cmdline(const char *argv[]);
-
-int tor_process_get_pid(process_handle_t *process_handle);
-#ifdef _WIN32
-HANDLE tor_process_get_stdout_pipe(process_handle_t *process_handle);
-#else
-int tor_process_get_stdout_pipe(process_handle_t *process_handle);
-#endif
-
-#ifdef _WIN32
-MOCK_DECL(struct smartlist_t *,
-tor_get_lines_from_handle,(HANDLE *handle,
- enum stream_status *stream_status));
-#else
-MOCK_DECL(struct smartlist_t *,
-tor_get_lines_from_handle,(int fd,
- enum stream_status *stream_status));
-#endif /* defined(_WIN32) */
-
-int
-tor_terminate_process(process_handle_t *process_handle);
-
-MOCK_DECL(void,
-tor_process_handle_destroy,(process_handle_t *process_handle,
- int also_terminate_process));
-
-/* ===== Insecure rng */
-typedef struct tor_weak_rng_t {
- uint32_t state;
-} tor_weak_rng_t;
-
-#define TOR_WEAK_RNG_INIT {383745623}
-#define TOR_WEAK_RANDOM_MAX (INT_MAX)
-void tor_init_weak_random(tor_weak_rng_t *weak_rng, unsigned seed);
-int32_t tor_weak_random(tor_weak_rng_t *weak_rng);
-int32_t tor_weak_random_range(tor_weak_rng_t *rng, int32_t top);
-/** Randomly return true according to <b>rng</b> with probability 1 in
- * <b>n</b> */
-#define tor_weak_random_one_in_n(rng, n) (0==tor_weak_random_range((rng),(n)))
-
-int format_hex_number_sigsafe(unsigned long x, char *buf, int max_len);
-int format_dec_number_sigsafe(unsigned long x, char *buf, int max_len);
-
-#ifdef UTIL_PRIVATE
-/* Prototypes for private functions only used by util.c (and unit tests) */
-
-#ifndef _WIN32
-STATIC int format_helper_exit_status(unsigned char child_state,
- int saved_errno, char *hex_errno);
-
-/* Space for hex values of child state, a slash, saved_errno (with
- leading minus) and newline (no null) */
-#define HEX_ERRNO_SIZE (sizeof(char) * 2 + 1 + \
- 1 + sizeof(int) * 2 + 1)
-#endif /* !defined(_WIN32) */
-
-#endif /* defined(UTIL_PRIVATE) */
-
-int size_mul_check(const size_t x, const size_t y);
-
-#define ARRAY_LENGTH(x) ((sizeof(x)) / sizeof(x[0]))
-
-#endif /* !defined(TOR_UTIL_H) */
-
diff --git a/src/common/util_bug.c b/src/common/util_bug.c
deleted file mode 100644
index 126e843866..0000000000
--- a/src/common/util_bug.c
+++ /dev/null
@@ -1,119 +0,0 @@
-/* Copyright (c) 2003, Roger Dingledine
- * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2017, The Tor Project, Inc. */
-/* See LICENSE for licensing information */
-
-/**
- * \file util_bug.c
- **/
-
-#include "orconfig.h"
-#include "util_bug.h"
-#include "torlog.h"
-#include "backtrace.h"
-#include "container.h"
-
-#ifdef __COVERITY__
-int bug_macro_deadcode_dummy__ = 0;
-#endif
-
-#ifdef TOR_UNIT_TESTS
-static void (*failed_assertion_cb)(void) = NULL;
-static int n_bugs_to_capture = 0;
-static smartlist_t *bug_messages = NULL;
-#define capturing_bugs() (bug_messages != NULL && n_bugs_to_capture)
-void
-tor_capture_bugs_(int n)
-{
- tor_end_capture_bugs_();
- bug_messages = smartlist_new();
- n_bugs_to_capture = n;
-}
-void
-tor_end_capture_bugs_(void)
-{
- n_bugs_to_capture = 0;
- if (!bug_messages)
- return;
- SMARTLIST_FOREACH(bug_messages, char *, cp, tor_free(cp));
- smartlist_free(bug_messages);
- bug_messages = NULL;
-}
-const smartlist_t *
-tor_get_captured_bug_log_(void)
-{
- return bug_messages;
-}
-static void
-add_captured_bug(const char *s)
-{
- --n_bugs_to_capture;
- smartlist_add_strdup(bug_messages, s);
-}
-/** Set a callback to be invoked when we get any tor_bug_occurred_
- * invocation. We use this in the unit tests so that a nonfatal
- * assertion failure can also count as a test failure.
- */
-void
-tor_set_failed_assertion_callback(void (*fn)(void))
-{
- failed_assertion_cb = fn;
-}
-#else /* !(defined(TOR_UNIT_TESTS)) */
-#define capturing_bugs() (0)
-#define add_captured_bug(s) do { } while (0)
-#endif /* defined(TOR_UNIT_TESTS) */
-
-/** Helper for tor_assert: report the assertion failure. */
-void
-tor_assertion_failed_(const char *fname, unsigned int line,
- const char *func, const char *expr)
-{
- char buf[256];
- log_err(LD_BUG, "%s:%u: %s: Assertion %s failed; aborting.",
- fname, line, func, expr);
- tor_snprintf(buf, sizeof(buf),
- "Assertion %s failed in %s at %s:%u",
- expr, func, fname, line);
- log_backtrace(LOG_ERR, LD_BUG, buf);
-}
-
-/** Helper for tor_assert_nonfatal: report the assertion failure. */
-void
-tor_bug_occurred_(const char *fname, unsigned int line,
- const char *func, const char *expr,
- int once)
-{
- char buf[256];
- const char *once_str = once ?
- " (Future instances of this warning will be silenced.)": "";
- if (! expr) {
- if (capturing_bugs()) {
- add_captured_bug("This line should not have been reached.");
- return;
- }
- log_warn(LD_BUG, "%s:%u: %s: This line should not have been reached.%s",
- fname, line, func, once_str);
- tor_snprintf(buf, sizeof(buf),
- "Line unexpectedly reached at %s at %s:%u",
- func, fname, line);
- } else {
- if (capturing_bugs()) {
- add_captured_bug(expr);
- return;
- }
- log_warn(LD_BUG, "%s:%u: %s: Non-fatal assertion %s failed.%s",
- fname, line, func, expr, once_str);
- tor_snprintf(buf, sizeof(buf),
- "Non-fatal assertion %s failed in %s at %s:%u",
- expr, func, fname, line);
- }
- log_backtrace(LOG_WARN, LD_BUG, buf);
-
-#ifdef TOR_UNIT_TESTS
- if (failed_assertion_cb) {
- failed_assertion_cb();
- }
-#endif
-}
-
diff --git a/src/common/util_bug.h b/src/common/util_bug.h
deleted file mode 100644
index 50becd0c33..0000000000
--- a/src/common/util_bug.h
+++ /dev/null
@@ -1,238 +0,0 @@
-/* Copyright (c) 2003-2004, Roger Dingledine
- * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2017, The Tor Project, Inc. */
-/* See LICENSE for licensing information */
-
-/**
- * \file util_bug.h
- *
- * \brief Macros to manage assertions, fatal and non-fatal.
- *
- * Guidelines: All the different kinds of assertion in this file are for
- * bug-checking only. Don't write code that can assert based on bad inputs.
- *
- * We provide two kinds of assertion here: "fatal" and "nonfatal". Use
- * nonfatal assertions for any bug you can reasonably recover from -- and
- * please, try to recover! Many severe bugs in Tor have been caused by using
- * a regular assertion when a nonfatal assertion would have been better.
- *
- * If you need to check a condition with a nonfatal assertion, AND recover
- * from that same condition, consider using the BUG() macro inside a
- * conditional. For example:
- *
- * <code>
- * // wrong -- use tor_assert_nonfatal() if you just want an assertion.
- * BUG(ptr == NULL);
- *
- * // okay, but needlessly verbose
- * tor_assert_nonfatal(ptr != NULL);
- * if (ptr == NULL) { ... }
- *
- * // this is how we do it:
- * if (BUG(ptr == NULL)) { ... }
- * </code>
- **/
-
-#ifndef TOR_UTIL_BUG_H
-#define TOR_UTIL_BUG_H
-
-#include "orconfig.h"
-#include "compat.h"
-#include "testsupport.h"
-
-/* Replace assert() with a variant that sends failures to the log before
- * calling assert() normally.
- */
-#ifdef NDEBUG
-/* Nobody should ever want to build with NDEBUG set. 99% of our asserts will
- * be outside the critical path anyway, so it's silly to disable bug-checking
- * throughout the entire program just because a few asserts are slowing you
- * down. Profile, optimize the critical path, and keep debugging on.
- *
- * And I'm not just saying that because some of our asserts check
- * security-critical properties.
- */
-#error "Sorry; we don't support building with NDEBUG."
-#endif /* defined(NDEBUG) */
-
-#if defined(TOR_UNIT_TESTS) && defined(__GNUC__)
-/* We define this GCC macro as a replacement for PREDICT_UNLIKELY() in this
- * header, so that in our unit test builds, we'll get compiler warnings about
- * stuff like tor_assert(n = 5).
- *
- * The key here is that (e) is wrapped in exactly one layer of parentheses,
- * and then passed right to a conditional. If you do anything else to the
- * expression here, or introduce any more parentheses, the compiler won't
- * help you.
- *
- * We only do this for the unit-test build case because it interferes with
- * the likely-branch labeling. Note below that in the other case, we define
- * these macros to just be synonyms for PREDICT_(UN)LIKELY.
- */
-#define ASSERT_PREDICT_UNLIKELY_(e) \
- ( { \
- int tor__assert_tmp_value__; \
- if (e) \
- tor__assert_tmp_value__ = 1; \
- else \
- tor__assert_tmp_value__ = 0; \
- tor__assert_tmp_value__; \
- } )
-#define ASSERT_PREDICT_LIKELY_(e) ASSERT_PREDICT_UNLIKELY_(e)
-#else
-#define ASSERT_PREDICT_UNLIKELY_(e) PREDICT_UNLIKELY(e)
-#define ASSERT_PREDICT_LIKELY_(e) PREDICT_LIKELY(e)
-#endif
-
-/* Sometimes we don't want to use assertions during branch coverage tests; it
- * leads to tons of unreached branches which in reality are only assertions we
- * didn't hit. */
-#if defined(TOR_UNIT_TESTS) && defined(DISABLE_ASSERTS_IN_UNIT_TESTS)
-#define tor_assert(a) STMT_BEGIN \
- (void)(a); \
- STMT_END
-#else
-/** Like assert(3), but send assertion failures to the log as well as to
- * stderr. */
-#define tor_assert(expr) STMT_BEGIN \
- if (ASSERT_PREDICT_LIKELY_(expr)) { \
- } else { \
- tor_assertion_failed_(SHORT_FILE__, __LINE__, __func__, #expr); \
- abort(); \
- } STMT_END
-#endif /* defined(TOR_UNIT_TESTS) && defined(DISABLE_ASSERTS_IN_UNIT_TESTS) */
-
-#define tor_assert_unreached() \
- STMT_BEGIN { \
- tor_assertion_failed_(SHORT_FILE__, __LINE__, __func__, \
- "line should be unreached"); \
- abort(); \
- } STMT_END
-
-/* Non-fatal bug assertions. The "unreached" variants mean "this line should
- * never be reached." The "once" variants mean "Don't log a warning more than
- * once".
- *
- * The 'BUG' macro checks a boolean condition and logs an error message if it
- * is true. Example usage:
- * if (BUG(x == NULL))
- * return -1;
- */
-
-#ifdef __COVERITY__
-extern int bug_macro_deadcode_dummy__;
-#undef BUG
-// Coverity defines this in global headers; let's override it. This is a
-// magic coverity-only preprocessor thing.
-// We use this "deadcode_dummy__" trick to prevent coverity from
-// complaining about unreachable bug cases.
-#nodef BUG(x) ((x)?(__coverity_panic__(),1):(0+bug_macro_deadcode_dummy__))
-#endif /* defined(__COVERITY__) */
-
-#if defined(__COVERITY__) || defined(__clang_analyzer__)
-// We're running with a static analysis tool: let's treat even nonfatal
-// assertion failures as something that we need to avoid.
-#define ALL_BUGS_ARE_FATAL
-#endif
-
-#ifdef ALL_BUGS_ARE_FATAL
-#define tor_assert_nonfatal_unreached() tor_assert(0)
-#define tor_assert_nonfatal(cond) tor_assert((cond))
-#define tor_assert_nonfatal_unreached_once() tor_assert(0)
-#define tor_assert_nonfatal_once(cond) tor_assert((cond))
-#define BUG(cond) \
- (ASSERT_PREDICT_UNLIKELY_(cond) ? \
- (tor_assertion_failed_(SHORT_FILE__,__LINE__,__func__,"!("#cond")"), \
- abort(), 1) \
- : 0)
-#elif defined(TOR_UNIT_TESTS) && defined(DISABLE_ASSERTS_IN_UNIT_TESTS)
-#define tor_assert_nonfatal_unreached() STMT_NIL
-#define tor_assert_nonfatal(cond) ((void)(cond))
-#define tor_assert_nonfatal_unreached_once() STMT_NIL
-#define tor_assert_nonfatal_once(cond) ((void)(cond))
-#define BUG(cond) (ASSERT_PREDICT_UNLIKELY_(cond) ? 1 : 0)
-#else /* Normal case, !ALL_BUGS_ARE_FATAL, !DISABLE_ASSERTS_IN_UNIT_TESTS */
-#define tor_assert_nonfatal_unreached() STMT_BEGIN \
- tor_bug_occurred_(SHORT_FILE__, __LINE__, __func__, NULL, 0); \
- STMT_END
-#define tor_assert_nonfatal(cond) STMT_BEGIN \
- if (ASSERT_PREDICT_LIKELY_(cond)) { \
- } else { \
- tor_bug_occurred_(SHORT_FILE__, __LINE__, __func__, #cond, 0); \
- } \
- STMT_END
-#define tor_assert_nonfatal_unreached_once() STMT_BEGIN \
- static int warning_logged__ = 0; \
- if (!warning_logged__) { \
- warning_logged__ = 1; \
- tor_bug_occurred_(SHORT_FILE__, __LINE__, __func__, NULL, 1); \
- } \
- STMT_END
-#define tor_assert_nonfatal_once(cond) STMT_BEGIN \
- static int warning_logged__ = 0; \
- if (ASSERT_PREDICT_LIKELY_(cond)) { \
- } else if (!warning_logged__) { \
- warning_logged__ = 1; \
- tor_bug_occurred_(SHORT_FILE__, __LINE__, __func__, #cond, 1); \
- } \
- STMT_END
-#define BUG(cond) \
- (ASSERT_PREDICT_UNLIKELY_(cond) ? \
- (tor_bug_occurred_(SHORT_FILE__,__LINE__,__func__,"!("#cond")",0), 1) \
- : 0)
-#endif /* defined(ALL_BUGS_ARE_FATAL) || ... */
-
-#ifdef __GNUC__
-#define IF_BUG_ONCE__(cond,var) \
- if (( { \
- static int var = 0; \
- int bool_result = !!(cond); \
- if (bool_result && !var) { \
- var = 1; \
- tor_bug_occurred_(SHORT_FILE__, __LINE__, __func__, \
- "!("#cond")", 1); \
- } \
- bool_result; } ))
-#else /* !(defined(__GNUC__)) */
-#define IF_BUG_ONCE__(cond,var) \
- static int var = 0; \
- if ((cond) ? \
- (var ? 1 : \
- (var=1, \
- tor_bug_occurred_(SHORT_FILE__, __LINE__, __func__, \
- "!("#cond")", 1), \
- 1)) \
- : 0)
-#endif /* defined(__GNUC__) */
-#define IF_BUG_ONCE_VARNAME_(a) \
- warning_logged_on_ ## a ## __
-#define IF_BUG_ONCE_VARNAME__(a) \
- IF_BUG_ONCE_VARNAME_(a)
-
-/** This macro behaves as 'if (bug(x))', except that it only logs its
- * warning once, no matter how many times it triggers.
- */
-
-#define IF_BUG_ONCE(cond) \
- IF_BUG_ONCE__(ASSERT_PREDICT_UNLIKELY_(cond), \
- IF_BUG_ONCE_VARNAME__(__LINE__))
-
-/** Define this if you want Tor to crash when any problem comes up,
- * so you can get a coredump and track things down. */
-// #define tor_fragile_assert() tor_assert_unreached(0)
-#define tor_fragile_assert() tor_assert_nonfatal_unreached_once()
-
-void tor_assertion_failed_(const char *fname, unsigned int line,
- const char *func, const char *expr);
-void tor_bug_occurred_(const char *fname, unsigned int line,
- const char *func, const char *expr,
- int once);
-
-#ifdef TOR_UNIT_TESTS
-void tor_capture_bugs_(int n);
-void tor_end_capture_bugs_(void);
-const struct smartlist_t *tor_get_captured_bug_log_(void);
-void tor_set_failed_assertion_callback(void (*fn)(void));
-#endif /* defined(TOR_UNIT_TESTS) */
-
-#endif /* !defined(TOR_UTIL_BUG_H) */
diff --git a/src/common/util_format.c b/src/common/util_format.c
deleted file mode 100644
index e51757a4e8..0000000000
--- a/src/common/util_format.c
+++ /dev/null
@@ -1,535 +0,0 @@
-/* Copyright (c) 2001, Matej Pfajfar.
- * Copyright (c) 2001-2004, Roger Dingledine.
- * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2017, The Tor Project, Inc. */
-/* See LICENSE for licensing information */
-
-/**
- * \file util_format.c
- *
- * \brief Miscellaneous functions for encoding and decoding various things
- * in base{16,32,64}.
- */
-
-#include "orconfig.h"
-#include "torlog.h"
-#include "util.h"
-#include "util_format.h"
-#include "torint.h"
-
-#include <stddef.h>
-#include <string.h>
-#include <stdlib.h>
-
-/* Return the base32 encoded size in bytes using the source length srclen.
- *
- * (WATCH OUT: This API counts the terminating NUL byte, but
- * base64_encode_size does not.)
- */
-size_t
-base32_encoded_size(size_t srclen)
-{
- size_t enclen;
- tor_assert(srclen < SIZE_T_CEILING / 8);
- enclen = BASE32_NOPAD_BUFSIZE(srclen);
- tor_assert(enclen < INT_MAX && enclen > srclen);
- return enclen;
-}
-
-/** Implements base32 encoding as in RFC 4648. */
-void
-base32_encode(char *dest, size_t destlen, const char *src, size_t srclen)
-{
- unsigned int i, v, u;
- size_t nbits = srclen * 8;
- size_t bit;
-
- /* We need enough space for the encoded data and the extra NUL byte. */
- tor_assert(base32_encoded_size(srclen) <= destlen);
- tor_assert(destlen < SIZE_T_CEILING);
-
- /* Make sure we leave no uninitialized data in the destination buffer. */
- memset(dest, 0, destlen);
-
- for (i=0,bit=0; bit < nbits; ++i, bit+=5) {
- /* set v to the 16-bit value starting at src[bits/8], 0-padded. */
- size_t idx = bit / 8;
- v = ((uint8_t)src[idx]) << 8;
- if (idx+1 < srclen)
- v += (uint8_t)src[idx+1];
- /* set u to the 5-bit value at the bit'th bit of buf. */
- u = (v >> (11-(bit%8))) & 0x1F;
- dest[i] = BASE32_CHARS[u];
- }
- dest[i] = '\0';
-}
-
-/** Implements base32 decoding as in RFC 4648.
- * Returns 0 if successful, -1 otherwise.
- */
-int
-base32_decode(char *dest, size_t destlen, const char *src, size_t srclen)
-{
- /* XXXX we might want to rewrite this along the lines of base64_decode, if
- * it ever shows up in the profile. */
- unsigned int i;
- size_t nbits, j, bit;
- char *tmp;
- nbits = ((srclen * 5) / 8) * 8;
-
- tor_assert(srclen < SIZE_T_CEILING / 5);
- tor_assert((nbits/8) <= destlen); /* We need enough space. */
- tor_assert(destlen < SIZE_T_CEILING);
-
- /* Make sure we leave no uninitialized data in the destination buffer. */
- memset(dest, 0, destlen);
-
- /* Convert base32 encoded chars to the 5-bit values that they represent. */
- tmp = tor_malloc_zero(srclen);
- for (j = 0; j < srclen; ++j) {
- if (src[j] > 0x60 && src[j] < 0x7B) tmp[j] = src[j] - 0x61;
- else if (src[j] > 0x31 && src[j] < 0x38) tmp[j] = src[j] - 0x18;
- else if (src[j] > 0x40 && src[j] < 0x5B) tmp[j] = src[j] - 0x41;
- else {
- log_warn(LD_GENERAL, "illegal character in base32 encoded string");
- tor_free(tmp);
- return -1;
- }
- }
-
- /* Assemble result byte-wise by applying five possible cases. */
- for (i = 0, bit = 0; bit < nbits; ++i, bit += 8) {
- switch (bit % 40) {
- case 0:
- dest[i] = (((uint8_t)tmp[(bit/5)]) << 3) +
- (((uint8_t)tmp[(bit/5)+1]) >> 2);
- break;
- case 8:
- dest[i] = (((uint8_t)tmp[(bit/5)]) << 6) +
- (((uint8_t)tmp[(bit/5)+1]) << 1) +
- (((uint8_t)tmp[(bit/5)+2]) >> 4);
- break;
- case 16:
- dest[i] = (((uint8_t)tmp[(bit/5)]) << 4) +
- (((uint8_t)tmp[(bit/5)+1]) >> 1);
- break;
- case 24:
- dest[i] = (((uint8_t)tmp[(bit/5)]) << 7) +
- (((uint8_t)tmp[(bit/5)+1]) << 2) +
- (((uint8_t)tmp[(bit/5)+2]) >> 3);
- break;
- case 32:
- dest[i] = (((uint8_t)tmp[(bit/5)]) << 5) +
- ((uint8_t)tmp[(bit/5)+1]);
- break;
- }
- }
-
- memset(tmp, 0, srclen); /* on the heap, this should be safe */
- tor_free(tmp);
- tmp = NULL;
- return 0;
-}
-
-#define BASE64_OPENSSL_LINELEN 64
-
-/** Return the Base64 encoded size of <b>srclen</b> bytes of data in
- * bytes.
- *
- * (WATCH OUT: This API <em>does not</em> count the terminating NUL byte,
- * but base32_encoded_size does.)
- *
- * If <b>flags</b>&amp;BASE64_ENCODE_MULTILINE is true, return the size
- * of the encoded output as multiline output (64 character, `\n' terminated
- * lines).
- */
-size_t
-base64_encode_size(size_t srclen, int flags)
-{
- size_t enclen;
-
- /* Use INT_MAX for overflow checking because base64_encode() returns int. */
- tor_assert(srclen < INT_MAX);
- tor_assert(CEIL_DIV(srclen, 3) < INT_MAX / 4);
-
- enclen = BASE64_LEN(srclen);
- if (flags & BASE64_ENCODE_MULTILINE)
- enclen += CEIL_DIV(enclen, BASE64_OPENSSL_LINELEN);
-
- tor_assert(enclen < INT_MAX && (enclen == 0 || enclen > srclen));
- return enclen;
-}
-
-/** Internal table mapping 6 bit values to the Base64 alphabet. */
-static const char base64_encode_table[64] = {
- 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H',
- 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P',
- 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X',
- 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f',
- 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n',
- 'o', 'p', 'q', 'r', 's', 't', 'u', 'v',
- 'w', 'x', 'y', 'z', '0', '1', '2', '3',
- '4', '5', '6', '7', '8', '9', '+', '/'
-};
-
-/** Base64 encode <b>srclen</b> bytes of data from <b>src</b>. Write
- * the result into <b>dest</b>, if it will fit within <b>destlen</b>
- * bytes. Return the number of bytes written on success; -1 if
- * destlen is too short, or other failure.
- *
- * If <b>flags</b>&amp;BASE64_ENCODE_MULTILINE is true, return encoded
- * output in multiline format (64 character, `\n' terminated lines).
- */
-int
-base64_encode(char *dest, size_t destlen, const char *src, size_t srclen,
- int flags)
-{
- const unsigned char *usrc = (unsigned char *)src;
- const unsigned char *eous = usrc + srclen;
- char *d = dest;
- uint32_t n = 0;
- size_t linelen = 0;
- size_t enclen;
- int n_idx = 0;
-
- if (!src || !dest)
- return -1;
-
- /* Ensure that there is sufficient space, including the NUL. */
- enclen = base64_encode_size(srclen, flags);
- if (destlen < enclen + 1)
- return -1;
- if (destlen > SIZE_T_CEILING)
- return -1;
- if (enclen > INT_MAX)
- return -1;
-
- /* Make sure we leave no uninitialized data in the destination buffer. */
- memset(dest, 0, destlen);
-
- /* XXX/Yawning: If this ends up being too slow, this can be sped up
- * by separating the multiline format case and the normal case, and
- * processing 48 bytes of input at a time when newlines are desired.
- */
-#define ENCODE_CHAR(ch) \
- STMT_BEGIN \
- *d++ = ch; \
- if (flags & BASE64_ENCODE_MULTILINE) { \
- if (++linelen % BASE64_OPENSSL_LINELEN == 0) { \
- linelen = 0; \
- *d++ = '\n'; \
- } \
- } \
- STMT_END
-
-#define ENCODE_N(idx) \
- ENCODE_CHAR(base64_encode_table[(n >> ((3 - idx) * 6)) & 0x3f])
-
-#define ENCODE_PAD() ENCODE_CHAR('=')
-
- /* Iterate over all the bytes in src. Each one will add 8 bits to the
- * value we're encoding. Accumulate bits in <b>n</b>, and whenever we
- * have 24 bits, batch them into 4 bytes and flush those bytes to dest.
- */
- for ( ; usrc < eous; ++usrc) {
- n = (n << 8) | *usrc;
- if ((++n_idx) == 3) {
- ENCODE_N(0);
- ENCODE_N(1);
- ENCODE_N(2);
- ENCODE_N(3);
- n_idx = 0;
- n = 0;
- }
- }
- switch (n_idx) {
- case 0:
- /* 0 leftover bits, no pading to add. */
- break;
- case 1:
- /* 8 leftover bits, pad to 12 bits, write the 2 6-bit values followed
- * by 2 padding characters.
- */
- n <<= 4;
- ENCODE_N(2);
- ENCODE_N(3);
- ENCODE_PAD();
- ENCODE_PAD();
- break;
- case 2:
- /* 16 leftover bits, pad to 18 bits, write the 3 6-bit values followed
- * by 1 padding character.
- */
- n <<= 2;
- ENCODE_N(1);
- ENCODE_N(2);
- ENCODE_N(3);
- ENCODE_PAD();
- break;
- // LCOV_EXCL_START -- we can't reach this point, because we enforce
- // 0 <= ncov_idx < 3 in the loop above.
- default:
- /* Something went catastrophically wrong. */
- tor_fragile_assert();
- return -1;
- // LCOV_EXCL_STOP
- }
-
-#undef ENCODE_N
-#undef ENCODE_PAD
-#undef ENCODE_CHAR
-
- /* Multiline output always includes at least one newline. */
- if (flags & BASE64_ENCODE_MULTILINE && linelen != 0)
- *d++ = '\n';
-
- tor_assert(d - dest == (ptrdiff_t)enclen);
-
- *d++ = '\0'; /* NUL terminate the output. */
-
- return (int) enclen;
-}
-
-/** As base64_encode, but do not add any internal spaces or external padding
- * to the output stream. */
-int
-base64_encode_nopad(char *dest, size_t destlen,
- const uint8_t *src, size_t srclen)
-{
- int n = base64_encode(dest, destlen, (const char*) src, srclen, 0);
- if (n <= 0)
- return n;
- tor_assert((size_t)n < destlen && dest[n] == 0);
- char *in, *out;
- in = out = dest;
- while (*in) {
- if (*in == '=' || *in == '\n') {
- ++in;
- } else {
- *out++ = *in++;
- }
- }
- *out = 0;
-
- tor_assert(out - dest <= INT_MAX);
-
- return (int)(out - dest);
-}
-
-#undef BASE64_OPENSSL_LINELEN
-
-/** @{ */
-/** Special values used for the base64_decode_table */
-#define X 255
-#define SP 64
-#define PAD 65
-/** @} */
-/** Internal table mapping byte values to what they represent in base64.
- * Numbers 0..63 are 6-bit integers. SPs are spaces, and should be
- * skipped. Xs are invalid and must not appear in base64. PAD indicates
- * end-of-string. */
-static const uint8_t base64_decode_table[256] = {
- X, X, X, X, X, X, X, X, X, SP, SP, SP, X, SP, X, X, /* */
- X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X,
- SP, X, X, X, X, X, X, X, X, X, X, 62, X, X, X, 63,
- 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, X, X, X, PAD, X, X,
- X, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
- 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, X, X, X, X, X,
- X, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
- 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, X, X, X, X, X,
- X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X,
- X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X,
- X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X,
- X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X,
- X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X,
- X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X,
- X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X,
- X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X,
-};
-
-/** Base64 decode <b>srclen</b> bytes of data from <b>src</b>. Write
- * the result into <b>dest</b>, if it will fit within <b>destlen</b>
- * bytes. Return the number of bytes written on success; -1 if
- * destlen is too short, or other failure.
- *
- * NOTE 1: destlen is checked conservatively, as though srclen contained no
- * spaces or padding.
- *
- * NOTE 2: This implementation does not check for the correct number of
- * padding "=" characters at the end of the string, and does not check
- * for internal padding characters.
- */
-int
-base64_decode(char *dest, size_t destlen, const char *src, size_t srclen)
-{
- const char *eos = src+srclen;
- uint32_t n=0;
- int n_idx=0;
- size_t di = 0;
-
- if (destlen > INT_MAX)
- return -1;
-
- /* Make sure we leave no uninitialized data in the destination buffer. */
- memset(dest, 0, destlen);
-
- /* Iterate over all the bytes in src. Each one will add 0 or 6 bits to the
- * value we're decoding. Accumulate bits in <b>n</b>, and whenever we have
- * 24 bits, batch them into 3 bytes and flush those bytes to dest.
- */
- for ( ; src < eos; ++src) {
- unsigned char c = (unsigned char) *src;
- uint8_t v = base64_decode_table[c];
- switch (v) {
- case X:
- /* This character isn't allowed in base64. */
- return -1;
- case SP:
- /* This character is whitespace, and has no effect. */
- continue;
- case PAD:
- /* We've hit an = character: the data is over. */
- goto end_of_loop;
- default:
- /* We have an actual 6-bit value. Append it to the bits in n. */
- n = (n<<6) | v;
- if ((++n_idx) == 4) {
- /* We've accumulated 24 bits in n. Flush them. */
- if (destlen < 3 || di > destlen - 3)
- return -1;
- dest[di++] = (n>>16);
- dest[di++] = (n>>8) & 0xff;
- dest[di++] = (n) & 0xff;
- n_idx = 0;
- n = 0;
- }
- }
- }
- end_of_loop:
- /* If we have leftover bits, we need to cope. */
- switch (n_idx) {
- case 0:
- default:
- /* No leftover bits. We win. */
- break;
- case 1:
- /* 6 leftover bits. That's invalid; we can't form a byte out of that. */
- return -1;
- case 2:
- /* 12 leftover bits: The last 4 are padding and the first 8 are data. */
- if (destlen < 1 || di > destlen - 1)
- return -1;
- dest[di++] = n >> 4;
- break;
- case 3:
- /* 18 leftover bits: The last 2 are padding and the first 16 are data. */
- if (destlen < 2 || di > destlen - 2)
- return -1;
- dest[di++] = n >> 10;
- dest[di++] = n >> 2;
- }
-
- tor_assert(di <= destlen);
-
- return (int)di;
-}
-#undef X
-#undef SP
-#undef PAD
-
-/** Encode the <b>srclen</b> bytes at <b>src</b> in a NUL-terminated,
- * uppercase hexadecimal string; store it in the <b>destlen</b>-byte buffer
- * <b>dest</b>.
- */
-void
-base16_encode(char *dest, size_t destlen, const char *src, size_t srclen)
-{
- const char *end;
- char *cp;
-
- tor_assert(srclen < SIZE_T_CEILING / 2 - 1);
- tor_assert(destlen >= BASE16_BUFSIZE(srclen));
- tor_assert(destlen < SIZE_T_CEILING);
-
- /* Make sure we leave no uninitialized data in the destination buffer. */
- memset(dest, 0, destlen);
-
- cp = dest;
- end = src+srclen;
- while (src<end) {
- *cp++ = "0123456789ABCDEF"[ (*(const uint8_t*)src) >> 4 ];
- *cp++ = "0123456789ABCDEF"[ (*(const uint8_t*)src) & 0xf ];
- ++src;
- }
- *cp = '\0';
-}
-
-/** Helper: given a hex digit, return its value, or -1 if it isn't hex. */
-static inline int
-hex_decode_digit_(char c)
-{
- switch (c) {
- case '0': return 0;
- case '1': return 1;
- case '2': return 2;
- case '3': return 3;
- case '4': return 4;
- case '5': return 5;
- case '6': return 6;
- case '7': return 7;
- case '8': return 8;
- case '9': return 9;
- case 'A': case 'a': return 10;
- case 'B': case 'b': return 11;
- case 'C': case 'c': return 12;
- case 'D': case 'd': return 13;
- case 'E': case 'e': return 14;
- case 'F': case 'f': return 15;
- default:
- return -1;
- }
-}
-
-/** Helper: given a hex digit, return its value, or -1 if it isn't hex. */
-int
-hex_decode_digit(char c)
-{
- return hex_decode_digit_(c);
-}
-
-/** Given a hexadecimal string of <b>srclen</b> bytes in <b>src</b>, decode
- * it and store the result in the <b>destlen</b>-byte buffer at <b>dest</b>.
- * Return the number of bytes decoded on success, -1 on failure. If
- * <b>destlen</b> is greater than INT_MAX or less than half of
- * <b>srclen</b>, -1 is returned. */
-int
-base16_decode(char *dest, size_t destlen, const char *src, size_t srclen)
-{
- const char *end;
- char *dest_orig = dest;
- int v1,v2;
-
- if ((srclen % 2) != 0)
- return -1;
- if (destlen < srclen/2 || destlen > INT_MAX)
- return -1;
-
- /* Make sure we leave no uninitialized data in the destination buffer. */
- memset(dest, 0, destlen);
-
- end = src+srclen;
- while (src<end) {
- v1 = hex_decode_digit_(*src);
- v2 = hex_decode_digit_(*(src+1));
- if (v1<0||v2<0)
- return -1;
- *(uint8_t*)dest = (v1<<4)|v2;
- ++dest;
- src+=2;
- }
-
- tor_assert((dest-dest_orig) <= (ptrdiff_t) destlen);
-
- return (int) (dest-dest_orig);
-}
-
diff --git a/src/common/util_format.h b/src/common/util_format.h
deleted file mode 100644
index 0aefe3a44e..0000000000
--- a/src/common/util_format.h
+++ /dev/null
@@ -1,52 +0,0 @@
-/* Copyright (c) 2001, Matej Pfajfar.
- * Copyright (c) 2001-2004, Roger Dingledine.
- * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2017, The Tor Project, Inc. */
-/* See LICENSE for licensing information */
-
-#ifndef TOR_UTIL_FORMAT_H
-#define TOR_UTIL_FORMAT_H
-
-#include "testsupport.h"
-#include "torint.h"
-
-/** @{ */
-/** These macros don't check for overflow. Use them only for constant inputs
- * (like array declarations). The *_LEN macros are the raw encoding lengths
- * (without terminating NUL), while the *_BUFSIZE macros count the terminating
- * NUL. */
-#define BASE64_LEN(n) (CEIL_DIV((n), 3) * 4)
-#define BASE32_LEN(n) (CEIL_DIV((n), 5) * 8)
-#define BASE16_LEN(n) ((n) * 2)
-
-#define BASE64_BUFSIZE(n) (BASE64_LEN(n) + 1)
-#define BASE32_BUFSIZE(n) (BASE32_LEN(n) + 1)
-#define BASE16_BUFSIZE(n) (BASE16_LEN(n) + 1)
-
-#define BASE64_NOPAD_LEN(n) (CEIL_DIV((n) * 4, 3))
-#define BASE32_NOPAD_LEN(n) (CEIL_DIV((n) * 8, 5))
-
-#define BASE64_NOPAD_BUFSIZE(n) (BASE64_NOPAD_LEN(n) + 1)
-#define BASE32_NOPAD_BUFSIZE(n) (BASE32_NOPAD_LEN(n) + 1)
-/** @} */
-
-#define BASE64_ENCODE_MULTILINE 1
-size_t base64_encode_size(size_t srclen, int flags);
-int base64_encode(char *dest, size_t destlen, const char *src, size_t srclen,
- int flags);
-int base64_decode(char *dest, size_t destlen, const char *src, size_t srclen);
-int base64_encode_nopad(char *dest, size_t destlen,
- const uint8_t *src, size_t srclen);
-
-/** Characters that can appear (case-insensitively) in a base32 encoding. */
-#define BASE32_CHARS "abcdefghijklmnopqrstuvwxyz234567"
-void base32_encode(char *dest, size_t destlen, const char *src, size_t srclen);
-int base32_decode(char *dest, size_t destlen, const char *src, size_t srclen);
-size_t base32_encoded_size(size_t srclen);
-
-int hex_decode_digit(char c);
-void base16_encode(char *dest, size_t destlen, const char *src, size_t srclen);
-int base16_decode(char *dest, size_t destlen, const char *src, size_t srclen);
-
-#endif /* !defined(TOR_UTIL_FORMAT_H) */
-
diff --git a/src/common/util_process.c b/src/common/util_process.c
deleted file mode 100644
index c2826152e9..0000000000
--- a/src/common/util_process.c
+++ /dev/null
@@ -1,158 +0,0 @@
-/* Copyright (c) 2003-2004, Roger Dingledine
- * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2017, The Tor Project, Inc. */
-/* See LICENSE for licensing information */
-
-/**
- * \file util_process.c
- * \brief utility functions for launching processes and checking their
- * status. These functions are kept separately from procmon so that they
- * won't require linking against libevent.
- **/
-
-#include "orconfig.h"
-
-#ifdef HAVE_SYS_TYPES_H
-#include <sys/types.h>
-#endif
-#ifdef HAVE_SYS_WAIT_H
-#include <sys/wait.h>
-#endif
-
-#include "compat.h"
-#include "util.h"
-#include "torlog.h"
-#include "util_process.h"
-#include "ht.h"
-
-/* ================================================== */
-/* Convenience structures for handlers for waitpid().
- *
- * The tor_process_monitor*() code above doesn't use them, since it is for
- * monitoring a non-child process.
- */
-
-#ifndef _WIN32
-
-/** Mapping from a PID to a userfn/userdata pair. */
-struct waitpid_callback_t {
- HT_ENTRY(waitpid_callback_t) node;
- pid_t pid;
-
- void (*userfn)(int, void *userdata);
- void *userdata;
-
- unsigned running;
-};
-
-static inline unsigned int
-process_map_entry_hash_(const waitpid_callback_t *ent)
-{
- return (unsigned) ent->pid;
-}
-
-static inline unsigned int
-process_map_entries_eq_(const waitpid_callback_t *a,
- const waitpid_callback_t *b)
-{
- return a->pid == b->pid;
-}
-
-static HT_HEAD(process_map, waitpid_callback_t) process_map = HT_INITIALIZER();
-
-HT_PROTOTYPE(process_map, waitpid_callback_t, node, process_map_entry_hash_,
- process_map_entries_eq_)
-HT_GENERATE2(process_map, waitpid_callback_t, node, process_map_entry_hash_,
- process_map_entries_eq_, 0.6, tor_reallocarray_, tor_free_)
-
-/**
- * Begin monitoring the child pid <b>pid</b> to see if we get a SIGCHLD for
- * it. If we eventually do, call <b>fn</b>, passing it the exit status (as
- * yielded by waitpid) and the pointer <b>arg</b>.
- *
- * To cancel this, or clean up after it has triggered, call
- * clear_waitpid_callback().
- */
-waitpid_callback_t *
-set_waitpid_callback(pid_t pid, void (*fn)(int, void *), void *arg)
-{
- waitpid_callback_t *old_ent;
- waitpid_callback_t *ent = tor_malloc_zero(sizeof(waitpid_callback_t));
- ent->pid = pid;
- ent->userfn = fn;
- ent->userdata = arg;
- ent->running = 1;
-
- old_ent = HT_REPLACE(process_map, &process_map, ent);
- if (old_ent) {
- log_warn(LD_BUG, "Replaced a waitpid monitor on pid %u. That should be "
- "impossible.", (unsigned) pid);
- old_ent->running = 0;
- }
-
- return ent;
-}
-
-/**
- * Cancel a waitpid_callback_t, or clean up after one has triggered. Releases
- * all storage held by <b>ent</b>.
- */
-void
-clear_waitpid_callback(waitpid_callback_t *ent)
-{
- waitpid_callback_t *old_ent;
- if (ent == NULL)
- return;
-
- if (ent->running) {
- old_ent = HT_REMOVE(process_map, &process_map, ent);
- if (old_ent != ent) {
- log_warn(LD_BUG, "Couldn't remove waitpid monitor for pid %u.",
- (unsigned) ent->pid);
- return;
- }
- }
-
- tor_free(ent);
-}
-
-/** Helper: find the callack for <b>pid</b>; if there is one, run it,
- * reporting the exit status as <b>status</b>. */
-static void
-notify_waitpid_callback_by_pid(pid_t pid, int status)
-{
- waitpid_callback_t search, *ent;
-
- search.pid = pid;
- ent = HT_REMOVE(process_map, &process_map, &search);
- if (!ent || !ent->running) {
- log_info(LD_GENERAL, "Child process %u has exited; no callback was "
- "registered", (unsigned)pid);
- return;
- }
-
- log_info(LD_GENERAL, "Child process %u has exited; running callback.",
- (unsigned)pid);
-
- ent->running = 0;
- ent->userfn(status, ent->userdata);
-}
-
-/** Use waitpid() to wait for all children that have exited, and invoke any
- * callbacks registered for them. */
-void
-notify_pending_waitpid_callbacks(void)
-{
- /* I was going to call this function reap_zombie_children(), but
- * that makes it sound way more exciting than it really is. */
- pid_t child;
- int status = 0;
-
- while ((child = waitpid(-1, &status, WNOHANG)) > 0) {
- notify_waitpid_callback_by_pid(child, status);
- status = 0; /* should be needless */
- }
-}
-
-#endif /* !defined(_WIN32) */
-
diff --git a/src/common/util_process.h b/src/common/util_process.h
deleted file mode 100644
index c9aa771b77..0000000000
--- a/src/common/util_process.h
+++ /dev/null
@@ -1,26 +0,0 @@
-/* Copyright (c) 2011-2017, The Tor Project, Inc. */
-/* See LICENSE for licensing information */
-
-/**
- * \file util_process.h
- * \brief Headers for util_process.c
- **/
-
-#ifndef TOR_UTIL_PROCESS_H
-#define TOR_UTIL_PROCESS_H
-
-#ifndef _WIN32
-/** A callback structure waiting for us to get a SIGCHLD informing us that a
- * PID has been closed. Created by set_waitpid_callback. Cancelled or cleaned-
- * up from clear_waitpid_callback(). Do not access outside of the main thread;
- * do not access from inside a signal handler. */
-typedef struct waitpid_callback_t waitpid_callback_t;
-
-waitpid_callback_t *set_waitpid_callback(pid_t pid,
- void (*fn)(int, void *), void *arg);
-void clear_waitpid_callback(waitpid_callback_t *ent);
-void notify_pending_waitpid_callbacks(void);
-#endif /* !defined(_WIN32) */
-
-#endif /* !defined(TOR_UTIL_PROCESS_H) */
-
diff --git a/src/common/workqueue.c b/src/common/workqueue.c
deleted file mode 100644
index 563a98af96..0000000000
--- a/src/common/workqueue.c
+++ /dev/null
@@ -1,678 +0,0 @@
-
-/* copyright (c) 2013-2015, The Tor Project, Inc. */
-/* See LICENSE for licensing information */
-
-/**
- * \file workqueue.c
- *
- * \brief Implements worker threads, queues of work for them, and mechanisms
- * for them to send answers back to the main thread.
- *
- * The main structure here is a threadpool_t : it manages a set of worker
- * threads, a queue of pending work, and a reply queue. Every piece of work
- * is a workqueue_entry_t, containing data to process and a function to
- * process it with.
- *
- * The main thread informs the worker threads of pending work by using a
- * condition variable. The workers inform the main process of completed work
- * by using an alert_sockets_t object, as implemented in compat_threads.c.
- *
- * The main thread can also queue an "update" that will be handled by all the
- * workers. This is useful for updating state that all the workers share.
- *
- * In Tor today, there is currently only one thread pool, used in cpuworker.c.
- */
-
-#include "orconfig.h"
-#include "compat.h"
-#include "compat_libevent.h"
-#include "compat_threads.h"
-#include "crypto_rand.h"
-#include "util.h"
-#include "workqueue.h"
-#include "tor_queue.h"
-#include "torlog.h"
-
-#include <event2/event.h>
-
-#define WORKQUEUE_PRIORITY_FIRST WQ_PRI_HIGH
-#define WORKQUEUE_PRIORITY_LAST WQ_PRI_LOW
-#define WORKQUEUE_N_PRIORITIES (((int) WORKQUEUE_PRIORITY_LAST)+1)
-
-TOR_TAILQ_HEAD(work_tailq_t, workqueue_entry_s);
-typedef struct work_tailq_t work_tailq_t;
-
-struct threadpool_s {
- /** An array of pointers to workerthread_t: one for each running worker
- * thread. */
- struct workerthread_s **threads;
-
- /** Condition variable that we wait on when we have no work, and which
- * gets signaled when our queue becomes nonempty. */
- tor_cond_t condition;
- /** Queues of pending work that we have to do. The queue with priority
- * <b>p</b> is work[p]. */
- work_tailq_t work[WORKQUEUE_N_PRIORITIES];
-
- /** Weak RNG, used to decide when to ignore priority. */
- tor_weak_rng_t weak_rng;
-
- /** The current 'update generation' of the threadpool. Any thread that is
- * at an earlier generation needs to run the update function. */
- unsigned generation;
-
- /** Function that should be run for updates on each thread. */
- workqueue_reply_t (*update_fn)(void *, void *);
- /** Function to free update arguments if they can't be run. */
- void (*free_update_arg_fn)(void *);
- /** Array of n_threads update arguments. */
- void **update_args;
- /** Event to notice when another thread has sent a reply. */
- struct event *reply_event;
- void (*reply_cb)(threadpool_t *);
-
- /** Number of elements in threads. */
- int n_threads;
- /** Mutex to protect all the above fields. */
- tor_mutex_t lock;
-
- /** A reply queue to use when constructing new threads. */
- replyqueue_t *reply_queue;
-
- /** Functions used to allocate and free thread state. */
- void *(*new_thread_state_fn)(void*);
- void (*free_thread_state_fn)(void*);
- void *new_thread_state_arg;
-};
-
-/** Used to put a workqueue_priority_t value into a bitfield. */
-#define workqueue_priority_bitfield_t ENUM_BF(workqueue_priority_t)
-/** Number of bits needed to hold all legal values of workqueue_priority_t */
-#define WORKQUEUE_PRIORITY_BITS 2
-
-struct workqueue_entry_s {
- /** The next workqueue_entry_t that's pending on the same thread or
- * reply queue. */
- TOR_TAILQ_ENTRY(workqueue_entry_s) next_work;
- /** The threadpool to which this workqueue_entry_t was assigned. This field
- * is set when the workqueue_entry_t is created, and won't be cleared until
- * after it's handled in the main thread. */
- struct threadpool_s *on_pool;
- /** True iff this entry is waiting for a worker to start processing it. */
- uint8_t pending;
- /** Priority of this entry. */
- workqueue_priority_bitfield_t priority : WORKQUEUE_PRIORITY_BITS;
- /** Function to run in the worker thread. */
- workqueue_reply_t (*fn)(void *state, void *arg);
- /** Function to run while processing the reply queue. */
- void (*reply_fn)(void *arg);
- /** Argument for the above functions. */
- void *arg;
-};
-
-struct replyqueue_s {
- /** Mutex to protect the answers field */
- tor_mutex_t lock;
- /** Doubly-linked list of answers that the reply queue needs to handle. */
- TOR_TAILQ_HEAD(, workqueue_entry_s) answers;
-
- /** Mechanism to wake up the main thread when it is receiving answers. */
- alert_sockets_t alert;
-};
-
-/** A worker thread represents a single thread in a thread pool. */
-typedef struct workerthread_s {
- /** Which thread it this? In range 0..in_pool->n_threads-1 */
- int index;
- /** The pool this thread is a part of. */
- struct threadpool_s *in_pool;
- /** User-supplied state field that we pass to the worker functions of each
- * work item. */
- void *state;
- /** Reply queue to which we pass our results. */
- replyqueue_t *reply_queue;
- /** The current update generation of this thread */
- unsigned generation;
- /** One over the probability of taking work from a lower-priority queue. */
- int32_t lower_priority_chance;
-} workerthread_t;
-
-static void queue_reply(replyqueue_t *queue, workqueue_entry_t *work);
-
-/** Allocate and return a new workqueue_entry_t, set up to run the function
- * <b>fn</b> in the worker thread, and <b>reply_fn</b> in the main
- * thread. See threadpool_queue_work() for full documentation. */
-static workqueue_entry_t *
-workqueue_entry_new(workqueue_reply_t (*fn)(void*, void*),
- void (*reply_fn)(void*),
- void *arg)
-{
- workqueue_entry_t *ent = tor_malloc_zero(sizeof(workqueue_entry_t));
- ent->fn = fn;
- ent->reply_fn = reply_fn;
- ent->arg = arg;
- ent->priority = WQ_PRI_HIGH;
- return ent;
-}
-
-#define workqueue_entry_free(ent) \
- FREE_AND_NULL(workqueue_entry_t, workqueue_entry_free_, (ent))
-
-/**
- * Release all storage held in <b>ent</b>. Call only when <b>ent</b> is not on
- * any queue.
- */
-static void
-workqueue_entry_free_(workqueue_entry_t *ent)
-{
- if (!ent)
- return;
- memset(ent, 0xf0, sizeof(*ent));
- tor_free(ent);
-}
-
-/**
- * Cancel a workqueue_entry_t that has been returned from
- * threadpool_queue_work.
- *
- * You must not call this function on any work whose reply function has been
- * executed in the main thread; that will cause undefined behavior (probably,
- * a crash).
- *
- * If the work is cancelled, this function return the argument passed to the
- * work function. It is the caller's responsibility to free this storage.
- *
- * This function will have no effect if the worker thread has already executed
- * or begun to execute the work item. In that case, it will return NULL.
- */
-void *
-workqueue_entry_cancel(workqueue_entry_t *ent)
-{
- int cancelled = 0;
- void *result = NULL;
- tor_mutex_acquire(&ent->on_pool->lock);
- workqueue_priority_t prio = ent->priority;
- if (ent->pending) {
- TOR_TAILQ_REMOVE(&ent->on_pool->work[prio], ent, next_work);
- cancelled = 1;
- result = ent->arg;
- }
- tor_mutex_release(&ent->on_pool->lock);
-
- if (cancelled) {
- workqueue_entry_free(ent);
- }
- return result;
-}
-
-/**DOCDOC
-
- must hold lock */
-static int
-worker_thread_has_work(workerthread_t *thread)
-{
- unsigned i;
- for (i = WORKQUEUE_PRIORITY_FIRST; i <= WORKQUEUE_PRIORITY_LAST; ++i) {
- if (!TOR_TAILQ_EMPTY(&thread->in_pool->work[i]))
- return 1;
- }
- return thread->generation != thread->in_pool->generation;
-}
-
-/** Extract the next workqueue_entry_t from the the thread's pool, removing
- * it from the relevant queues and marking it as non-pending.
- *
- * The caller must hold the lock. */
-static workqueue_entry_t *
-worker_thread_extract_next_work(workerthread_t *thread)
-{
- threadpool_t *pool = thread->in_pool;
- work_tailq_t *queue = NULL, *this_queue;
- unsigned i;
- for (i = WORKQUEUE_PRIORITY_FIRST; i <= WORKQUEUE_PRIORITY_LAST; ++i) {
- this_queue = &pool->work[i];
- if (!TOR_TAILQ_EMPTY(this_queue)) {
- queue = this_queue;
- if (! tor_weak_random_one_in_n(&pool->weak_rng,
- thread->lower_priority_chance)) {
- /* Usually we'll just break now, so that we can get out of the loop
- * and use the queue where we found work. But with a small
- * probability, we'll keep looking for lower priority work, so that
- * we don't ignore our low-priority queues entirely. */
- break;
- }
- }
- }
-
- if (queue == NULL)
- return NULL;
-
- workqueue_entry_t *work = TOR_TAILQ_FIRST(queue);
- TOR_TAILQ_REMOVE(queue, work, next_work);
- work->pending = 0;
- return work;
-}
-
-/**
- * Main function for the worker thread.
- */
-static void
-worker_thread_main(void *thread_)
-{
- workerthread_t *thread = thread_;
- threadpool_t *pool = thread->in_pool;
- workqueue_entry_t *work;
- workqueue_reply_t result;
-
- tor_mutex_acquire(&pool->lock);
- while (1) {
- /* lock must be held at this point. */
- while (worker_thread_has_work(thread)) {
- /* lock must be held at this point. */
- if (thread->in_pool->generation != thread->generation) {
- void *arg = thread->in_pool->update_args[thread->index];
- thread->in_pool->update_args[thread->index] = NULL;
- workqueue_reply_t (*update_fn)(void*,void*) =
- thread->in_pool->update_fn;
- thread->generation = thread->in_pool->generation;
- tor_mutex_release(&pool->lock);
-
- workqueue_reply_t r = update_fn(thread->state, arg);
-
- if (r != WQ_RPL_REPLY) {
- return;
- }
-
- tor_mutex_acquire(&pool->lock);
- continue;
- }
- work = worker_thread_extract_next_work(thread);
- if (BUG(work == NULL))
- break;
- tor_mutex_release(&pool->lock);
-
- /* We run the work function without holding the thread lock. This
- * is the main thread's first opportunity to give us more work. */
- result = work->fn(thread->state, work->arg);
-
- /* Queue the reply for the main thread. */
- queue_reply(thread->reply_queue, work);
-
- /* We may need to exit the thread. */
- if (result != WQ_RPL_REPLY) {
- return;
- }
- tor_mutex_acquire(&pool->lock);
- }
- /* At this point the lock is held, and there is no work in this thread's
- * queue. */
-
- /* TODO: support an idle-function */
-
- /* Okay. Now, wait till somebody has work for us. */
- if (tor_cond_wait(&pool->condition, &pool->lock, NULL) < 0) {
- log_warn(LD_GENERAL, "Fail tor_cond_wait.");
- }
- }
-}
-
-/** Put a reply on the reply queue. The reply must not currently be on
- * any thread's work queue. */
-static void
-queue_reply(replyqueue_t *queue, workqueue_entry_t *work)
-{
- int was_empty;
- tor_mutex_acquire(&queue->lock);
- was_empty = TOR_TAILQ_EMPTY(&queue->answers);
- TOR_TAILQ_INSERT_TAIL(&queue->answers, work, next_work);
- tor_mutex_release(&queue->lock);
-
- if (was_empty) {
- if (queue->alert.alert_fn(queue->alert.write_fd) < 0) {
- /* XXXX complain! */
- }
- }
-}
-
-/** Allocate and start a new worker thread to use state object <b>state</b>,
- * and send responses to <b>replyqueue</b>. */
-static workerthread_t *
-workerthread_new(int32_t lower_priority_chance,
- void *state, threadpool_t *pool, replyqueue_t *replyqueue)
-{
- workerthread_t *thr = tor_malloc_zero(sizeof(workerthread_t));
- thr->state = state;
- thr->reply_queue = replyqueue;
- thr->in_pool = pool;
- thr->lower_priority_chance = lower_priority_chance;
-
- if (spawn_func(worker_thread_main, thr) < 0) {
- //LCOV_EXCL_START
- tor_assert_nonfatal_unreached();
- log_err(LD_GENERAL, "Can't launch worker thread.");
- tor_free(thr);
- return NULL;
- //LCOV_EXCL_STOP
- }
-
- return thr;
-}
-
-/**
- * Queue an item of work for a thread in a thread pool. The function
- * <b>fn</b> will be run in a worker thread, and will receive as arguments the
- * thread's state object, and the provided object <b>arg</b>. It must return
- * one of WQ_RPL_REPLY, WQ_RPL_ERROR, or WQ_RPL_SHUTDOWN.
- *
- * Regardless of its return value, the function <b>reply_fn</b> will later be
- * run in the main thread when it invokes replyqueue_process(), and will
- * receive as its argument the same <b>arg</b> object. It's the reply
- * function's responsibility to free the work object.
- *
- * On success, return a workqueue_entry_t object that can be passed to
- * workqueue_entry_cancel(). On failure, return NULL. (Failure is not
- * currently possible, but callers should check anyway.)
- *
- * Items are executed in a loose priority order -- each thread will usually
- * take from the queued work with the highest prioirity, but will occasionally
- * visit lower-priority queues to keep them from starving completely.
- *
- * Note that because of priorities and thread behavior, work items may not
- * be executed strictly in order.
- */
-workqueue_entry_t *
-threadpool_queue_work_priority(threadpool_t *pool,
- workqueue_priority_t prio,
- workqueue_reply_t (*fn)(void *, void *),
- void (*reply_fn)(void *),
- void *arg)
-{
- tor_assert(((int)prio) >= WORKQUEUE_PRIORITY_FIRST &&
- ((int)prio) <= WORKQUEUE_PRIORITY_LAST);
-
- workqueue_entry_t *ent = workqueue_entry_new(fn, reply_fn, arg);
- ent->on_pool = pool;
- ent->pending = 1;
- ent->priority = prio;
-
- tor_mutex_acquire(&pool->lock);
-
- TOR_TAILQ_INSERT_TAIL(&pool->work[prio], ent, next_work);
-
- tor_cond_signal_one(&pool->condition);
-
- tor_mutex_release(&pool->lock);
-
- return ent;
-}
-
-/** As threadpool_queue_work_priority(), but assumes WQ_PRI_HIGH */
-workqueue_entry_t *
-threadpool_queue_work(threadpool_t *pool,
- workqueue_reply_t (*fn)(void *, void *),
- void (*reply_fn)(void *),
- void *arg)
-{
- return threadpool_queue_work_priority(pool, WQ_PRI_HIGH, fn, reply_fn, arg);
-}
-
-/**
- * Queue a copy of a work item for every thread in a pool. This can be used,
- * for example, to tell the threads to update some parameter in their states.
- *
- * Arguments are as for <b>threadpool_queue_work</b>, except that the
- * <b>arg</b> value is passed to <b>dup_fn</b> once per each thread to
- * make a copy of it.
- *
- * UPDATE FUNCTIONS MUST BE IDEMPOTENT. We do not guarantee that every update
- * will be run. If a new update is scheduled before the old update finishes
- * running, then the new will replace the old in any threads that haven't run
- * it yet.
- *
- * Return 0 on success, -1 on failure.
- */
-int
-threadpool_queue_update(threadpool_t *pool,
- void *(*dup_fn)(void *),
- workqueue_reply_t (*fn)(void *, void *),
- void (*free_fn)(void *),
- void *arg)
-{
- int i, n_threads;
- void (*old_args_free_fn)(void *arg);
- void **old_args;
- void **new_args;
-
- tor_mutex_acquire(&pool->lock);
- n_threads = pool->n_threads;
- old_args = pool->update_args;
- old_args_free_fn = pool->free_update_arg_fn;
-
- new_args = tor_calloc(n_threads, sizeof(void*));
- for (i = 0; i < n_threads; ++i) {
- if (dup_fn)
- new_args[i] = dup_fn(arg);
- else
- new_args[i] = arg;
- }
-
- pool->update_args = new_args;
- pool->free_update_arg_fn = free_fn;
- pool->update_fn = fn;
- ++pool->generation;
-
- tor_cond_signal_all(&pool->condition);
-
- tor_mutex_release(&pool->lock);
-
- if (old_args) {
- for (i = 0; i < n_threads; ++i) {
- if (old_args[i] && old_args_free_fn)
- old_args_free_fn(old_args[i]);
- }
- tor_free(old_args);
- }
-
- return 0;
-}
-
-/** Don't have more than this many threads per pool. */
-#define MAX_THREADS 1024
-
-/** For half of our threads, choose lower priority queues with probability
- * 1/N for each of these values. Both are chosen somewhat arbitrarily. If
- * CHANCE_PERMISSIVE is too low, then we have a risk of low-priority tasks
- * stalling forever. If it's too high, we have a risk of low-priority tasks
- * grabbing half of the threads. */
-#define CHANCE_PERMISSIVE 37
-#define CHANCE_STRICT INT32_MAX
-
-/** Launch threads until we have <b>n</b>. */
-static int
-threadpool_start_threads(threadpool_t *pool, int n)
-{
- if (BUG(n < 0))
- return -1; // LCOV_EXCL_LINE
- if (n > MAX_THREADS)
- n = MAX_THREADS;
-
- tor_mutex_acquire(&pool->lock);
-
- if (pool->n_threads < n)
- pool->threads = tor_reallocarray(pool->threads,
- sizeof(workerthread_t*), n);
-
- while (pool->n_threads < n) {
- /* For half of our threads, we'll choose lower priorities permissively;
- * for the other half, we'll stick more strictly to higher priorities.
- * This keeps slow low-priority tasks from taking over completely. */
- int32_t chance = (pool->n_threads & 1) ? CHANCE_STRICT : CHANCE_PERMISSIVE;
-
- void *state = pool->new_thread_state_fn(pool->new_thread_state_arg);
- workerthread_t *thr = workerthread_new(chance,
- state, pool, pool->reply_queue);
-
- if (!thr) {
- //LCOV_EXCL_START
- tor_assert_nonfatal_unreached();
- pool->free_thread_state_fn(state);
- tor_mutex_release(&pool->lock);
- return -1;
- //LCOV_EXCL_STOP
- }
- thr->index = pool->n_threads;
- pool->threads[pool->n_threads++] = thr;
- }
- tor_mutex_release(&pool->lock);
-
- return 0;
-}
-
-/**
- * Construct a new thread pool with <b>n</b> worker threads, configured to
- * send their output to <b>replyqueue</b>. The threads' states will be
- * constructed with the <b>new_thread_state_fn</b> call, receiving <b>arg</b>
- * as its argument. When the threads close, they will call
- * <b>free_thread_state_fn</b> on their states.
- */
-threadpool_t *
-threadpool_new(int n_threads,
- replyqueue_t *replyqueue,
- void *(*new_thread_state_fn)(void*),
- void (*free_thread_state_fn)(void*),
- void *arg)
-{
- threadpool_t *pool;
- pool = tor_malloc_zero(sizeof(threadpool_t));
- tor_mutex_init_nonrecursive(&pool->lock);
- tor_cond_init(&pool->condition);
- unsigned i;
- for (i = WORKQUEUE_PRIORITY_FIRST; i <= WORKQUEUE_PRIORITY_LAST; ++i) {
- TOR_TAILQ_INIT(&pool->work[i]);
- }
- {
- unsigned seed;
- crypto_rand((void*)&seed, sizeof(seed));
- tor_init_weak_random(&pool->weak_rng, seed);
- }
-
- pool->new_thread_state_fn = new_thread_state_fn;
- pool->new_thread_state_arg = arg;
- pool->free_thread_state_fn = free_thread_state_fn;
- pool->reply_queue = replyqueue;
-
- if (threadpool_start_threads(pool, n_threads) < 0) {
- //LCOV_EXCL_START
- tor_assert_nonfatal_unreached();
- tor_cond_uninit(&pool->condition);
- tor_mutex_uninit(&pool->lock);
- tor_free(pool);
- return NULL;
- //LCOV_EXCL_STOP
- }
-
- return pool;
-}
-
-/** Return the reply queue associated with a given thread pool. */
-replyqueue_t *
-threadpool_get_replyqueue(threadpool_t *tp)
-{
- return tp->reply_queue;
-}
-
-/** Allocate a new reply queue. Reply queues are used to pass results from
- * worker threads to the main thread. Since the main thread is running an
- * IO-centric event loop, it needs to get woken up with means other than a
- * condition variable. */
-replyqueue_t *
-replyqueue_new(uint32_t alertsocks_flags)
-{
- replyqueue_t *rq;
-
- rq = tor_malloc_zero(sizeof(replyqueue_t));
- if (alert_sockets_create(&rq->alert, alertsocks_flags) < 0) {
- //LCOV_EXCL_START
- tor_free(rq);
- return NULL;
- //LCOV_EXCL_STOP
- }
-
- tor_mutex_init(&rq->lock);
- TOR_TAILQ_INIT(&rq->answers);
-
- return rq;
-}
-
-/** Internal: Run from the libevent mainloop when there is work to handle in
- * the reply queue handler. */
-static void
-reply_event_cb(evutil_socket_t sock, short events, void *arg)
-{
- threadpool_t *tp = arg;
- (void) sock;
- (void) events;
- replyqueue_process(tp->reply_queue);
- if (tp->reply_cb)
- tp->reply_cb(tp);
-}
-
-/** Register the threadpool <b>tp</b>'s reply queue with the libevent
- * mainloop of <b>base</b>. If <b>tp</b> is provided, it is run after
- * each time there is work to process from the reply queue. Return 0 on
- * success, -1 on failure.
- */
-int
-threadpool_register_reply_event(threadpool_t *tp,
- void (*cb)(threadpool_t *tp))
-{
- struct event_base *base = tor_libevent_get_base();
-
- if (tp->reply_event) {
- tor_event_free(tp->reply_event);
- }
- tp->reply_event = tor_event_new(base,
- tp->reply_queue->alert.read_fd,
- EV_READ|EV_PERSIST,
- reply_event_cb,
- tp);
- tor_assert(tp->reply_event);
- tp->reply_cb = cb;
- return event_add(tp->reply_event, NULL);
-}
-
-/**
- * Process all pending replies on a reply queue. The main thread should call
- * this function every time the socket returned by replyqueue_get_socket() is
- * readable.
- */
-void
-replyqueue_process(replyqueue_t *queue)
-{
- int r = queue->alert.drain_fn(queue->alert.read_fd);
- if (r < 0) {
- //LCOV_EXCL_START
- static ratelim_t warn_limit = RATELIM_INIT(7200);
- log_fn_ratelim(&warn_limit, LOG_WARN, LD_GENERAL,
- "Failure from drain_fd: %s",
- tor_socket_strerror(-r));
- //LCOV_EXCL_STOP
- }
-
- tor_mutex_acquire(&queue->lock);
- while (!TOR_TAILQ_EMPTY(&queue->answers)) {
- /* lock must be held at this point.*/
- workqueue_entry_t *work = TOR_TAILQ_FIRST(&queue->answers);
- TOR_TAILQ_REMOVE(&queue->answers, work, next_work);
- tor_mutex_release(&queue->lock);
- work->on_pool = NULL;
-
- work->reply_fn(work->arg);
- workqueue_entry_free(work);
-
- tor_mutex_acquire(&queue->lock);
- }
-
- tor_mutex_release(&queue->lock);
-}
-
diff --git a/src/common/workqueue.h b/src/common/workqueue.h
deleted file mode 100644
index e1fe612e2b..0000000000
--- a/src/common/workqueue.h
+++ /dev/null
@@ -1,66 +0,0 @@
-/* Copyright (c) 2013-2017, The Tor Project, Inc. */
-/* See LICENSE for licensing information */
-
-#ifndef TOR_WORKQUEUE_H
-#define TOR_WORKQUEUE_H
-
-#include "compat.h"
-
-/** A replyqueue is used to tell the main thread about the outcome of
- * work that we queued for the workers. */
-typedef struct replyqueue_s replyqueue_t;
-/** A thread-pool manages starting threads and passing work to them. */
-typedef struct threadpool_s threadpool_t;
-/** A workqueue entry represents a request that has been passed to a thread
- * pool. */
-typedef struct workqueue_entry_s workqueue_entry_t;
-
-/** Possible return value from a work function: */
-typedef enum workqueue_reply_t {
- WQ_RPL_REPLY = 0, /** indicates success */
- WQ_RPL_ERROR = 1, /** indicates fatal error */
- WQ_RPL_SHUTDOWN = 2, /** indicates thread is shutting down */
-} workqueue_reply_t;
-
-/** Possible priorities for work. Lower numeric values are more important. */
-typedef enum workqueue_priority_t {
- WQ_PRI_HIGH = 0,
- WQ_PRI_MED = 1,
- WQ_PRI_LOW = 2,
-} workqueue_priority_t;
-
-workqueue_entry_t *threadpool_queue_work_priority(threadpool_t *pool,
- workqueue_priority_t prio,
- workqueue_reply_t (*fn)(void *,
- void *),
- void (*reply_fn)(void *),
- void *arg);
-
-workqueue_entry_t *threadpool_queue_work(threadpool_t *pool,
- workqueue_reply_t (*fn)(void *,
- void *),
- void (*reply_fn)(void *),
- void *arg);
-
-int threadpool_queue_update(threadpool_t *pool,
- void *(*dup_fn)(void *),
- workqueue_reply_t (*fn)(void *, void *),
- void (*free_fn)(void *),
- void *arg);
-void *workqueue_entry_cancel(workqueue_entry_t *pending_work);
-threadpool_t *threadpool_new(int n_threads,
- replyqueue_t *replyqueue,
- void *(*new_thread_state_fn)(void*),
- void (*free_thread_state_fn)(void*),
- void *arg);
-replyqueue_t *threadpool_get_replyqueue(threadpool_t *tp);
-
-replyqueue_t *replyqueue_new(uint32_t alertsocks_flags);
-void replyqueue_process(replyqueue_t *queue);
-
-struct event_base;
-int threadpool_register_reply_event(threadpool_t *tp,
- void (*cb)(threadpool_t *tp));
-
-#endif /* !defined(TOR_WORKQUEUE_H) */
-