diff options
Diffstat (limited to 'src')
184 files changed, 2374 insertions, 1878 deletions
diff --git a/src/Makefile.am b/src/Makefile.am index eb5b007..c7f6302 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -5,7 +5,7 @@ # packet encryption, packet authentication, and # packet compression. # -# Copyright (C) 2002-2017 OpenVPN Technologies, Inc. <sales@openvpn.net> +# Copyright (C) 2002-2018 OpenVPN Inc <sales@openvpn.net> # Copyright (C) 2006-2012 Alon Bar-Lev <alon.barlev@gmail.com> # diff --git a/src/Makefile.in b/src/Makefile.in index 526d549..4dd5397 100644 --- a/src/Makefile.in +++ b/src/Makefile.in @@ -21,7 +21,7 @@ # packet encryption, packet authentication, and # packet compression. # -# Copyright (C) 2002-2017 OpenVPN Technologies, Inc. <sales@openvpn.net> +# Copyright (C) 2002-2018 OpenVPN Inc <sales@openvpn.net> # Copyright (C) 2006-2012 Alon Bar-Lev <alon.barlev@gmail.com> # VPATH = @srcdir@ @@ -365,6 +365,7 @@ plugindir = @plugindir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ +runstatedir = @runstatedir@ sampledir = @sampledir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ diff --git a/src/compat/Makefile.am b/src/compat/Makefile.am index 444a8f8..b4c3a4a 100644 --- a/src/compat/Makefile.am +++ b/src/compat/Makefile.am @@ -5,7 +5,7 @@ # packet encryption, packet authentication, and # packet compression. # -# Copyright (C) 2002-2017 OpenVPN Technologies, Inc. <sales@openvpn.net> +# Copyright (C) 2002-2018 OpenVPN Inc <sales@openvpn.net> # Copyright (C) 2006-2012 Alon Bar-Lev <alon.barlev@gmail.com> # diff --git a/src/compat/Makefile.in b/src/compat/Makefile.in index b264f40..fd11e4b 100644 --- a/src/compat/Makefile.in +++ b/src/compat/Makefile.in @@ -21,7 +21,7 @@ # packet encryption, packet authentication, and # packet compression. # -# Copyright (C) 2002-2017 OpenVPN Technologies, Inc. <sales@openvpn.net> +# Copyright (C) 2002-2018 OpenVPN Inc <sales@openvpn.net> # Copyright (C) 2006-2012 Alon Bar-Lev <alon.barlev@gmail.com> # @@ -356,6 +356,7 @@ plugindir = @plugindir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ +runstatedir = @runstatedir@ sampledir = @sampledir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ diff --git a/src/compat/compat-gettimeofday.c b/src/compat/compat-gettimeofday.c index fb57f2d..7cae641 100644 --- a/src/compat/compat-gettimeofday.c +++ b/src/compat/compat-gettimeofday.c @@ -5,7 +5,7 @@ * packet encryption, packet authentication, and * packet compression. * - * Copyright (C) 2002-2017 OpenVPN Technologies, Inc. <sales@openvpn.net> + * Copyright (C) 2002-2018 OpenVPN Inc <sales@openvpn.net> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 diff --git a/src/compat/compat-lz4.c b/src/compat/compat-lz4.c index 5855ca1..723157d 100644 --- a/src/compat/compat-lz4.c +++ b/src/compat/compat-lz4.c @@ -1,6 +1,16 @@ +/* This file has been backported by dev-tools/lz4-rebaser.sh + * from upstream lz4 commit 7bb64ff2b69a9f8367de (v1.7.5) + */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#elif defined(_MSC_VER) +#include "config-msvc.h" +#endif + +#ifdef NEED_COMPAT_LZ4 /* LZ4 - Fast LZ compression algorithm - Copyright (C) 2011-2015, Yann Collet. + Copyright (C) 2011-2016, Yann Collet. BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php) @@ -28,19 +38,12 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. You can contact the author at : - - LZ4 source repository : https://github.com/Cyan4973/lz4 - - LZ4 public forum : https://groups.google.com/forum/#!forum/lz4c + - LZ4 homepage : http://www.lz4.org + - LZ4 source repository : https://github.com/lz4/lz4 */ -#ifdef HAVE_CONFIG_H -#include "config.h" -#elif defined(_MSC_VER) -#include "config-msvc.h" -#endif - -#ifdef NEED_COMPAT_LZ4 -/************************************** +/*-************************************ * Tuning parameters **************************************/ /* @@ -48,7 +51,9 @@ * Select how default compression functions will allocate memory for their hash table, * in memory stack (0:default, fastest), or in memory heap (1:requires malloc()). */ -#define HEAPMODE 0 +#ifndef HEAPMODE +# define HEAPMODE 0 +#endif /* * ACCELERATION_DEFAULT : @@ -57,9 +62,31 @@ #define ACCELERATION_DEFAULT 1 -/************************************** +/*-************************************ * CPU Feature Detection **************************************/ +/* LZ4_FORCE_MEMORY_ACCESS + * By default, access to unaligned memory is controlled by `memcpy()`, which is safe and portable. + * Unfortunately, on some target/compiler combinations, the generated assembly is sub-optimal. + * The below switch allow to select different access method for improved performance. + * Method 0 (default) : use `memcpy()`. Safe and portable. + * Method 1 : `__packed` statement. It depends on compiler extension (ie, not portable). + * This method is safe if your compiler supports it, and *generally* as fast or faster than `memcpy`. + * Method 2 : direct access. This method is portable but violate C standard. + * It can generate buggy code on targets which generate assembly depending on alignment. + * But in some circumstances, it's the only known way to get the most performance (ie GCC + ARMv6) + * See https://fastcompression.blogspot.fr/2015/08/accessing-unaligned-memory.html for details. + * Prefer these methods in priority order (0 > 1 > 2) + */ +#ifndef LZ4_FORCE_MEMORY_ACCESS /* can be defined externally, on command line for example */ +# if defined(__GNUC__) && ( defined(__ARM_ARCH_6__) || defined(__ARM_ARCH_6J__) || defined(__ARM_ARCH_6K__) || defined(__ARM_ARCH_6Z__) || defined(__ARM_ARCH_6ZK__) || defined(__ARM_ARCH_6T2__) ) +# define LZ4_FORCE_MEMORY_ACCESS 2 +# elif defined(__INTEL_COMPILER) || \ + (defined(__GNUC__) && ( defined(__ARM_ARCH_7__) || defined(__ARM_ARCH_7A__) || defined(__ARM_ARCH_7R__) || defined(__ARM_ARCH_7M__) || defined(__ARM_ARCH_7S__) )) +# define LZ4_FORCE_MEMORY_ACCESS 1 +# endif +#endif + /* * LZ4_FORCE_SW_BITCOUNT * Define this parameter if your target system or compiler does not support hardware bit count @@ -69,13 +96,14 @@ #endif -/************************************** -* Includes +/*-************************************ +* Dependency **************************************/ #include "compat-lz4.h" +/* see also "memory routines" below */ -/************************************** +/*-************************************ * Compiler Options **************************************/ #ifdef _MSC_VER /* Visual Studio */ @@ -84,19 +112,16 @@ # pragma warning(disable : 4127) /* disable: C4127: conditional expression is constant */ # pragma warning(disable : 4293) /* disable: C4293: too large shift (32-bits) */ #else -# if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) /* C99 */ -# if defined(__GNUC__) || defined(__clang__) -# define FORCE_INLINE static inline __attribute__((always_inline)) -# else -# define FORCE_INLINE static inline -# endif +# if defined(__GNUC__) || defined(__clang__) +# define FORCE_INLINE static inline __attribute__((always_inline)) +# elif defined(__cplusplus) || (defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) /* C99 */) +# define FORCE_INLINE static inline # else # define FORCE_INLINE static -# endif /* __STDC_VERSION__ */ +# endif #endif /* _MSC_VER */ -/* LZ4_GCC_VERSION is defined into lz4.h */ -#if (LZ4_GCC_VERSION >= 302) || (__INTEL_COMPILER >= 800) || defined(__clang__) +#if (defined(__GNUC__) && (__GNUC__ >= 3)) || (defined(__INTEL_COMPILER) && (__INTEL_COMPILER >= 800)) || defined(__clang__) # define expect(expr,value) (__builtin_expect ((expr),(value)) ) #else # define expect(expr,value) (expr) @@ -106,7 +131,7 @@ #define unlikely(expr) expect((expr) != 0, 0) -/************************************** +/*-************************************ * Memory routines **************************************/ #include <stdlib.h> /* malloc, calloc, free */ @@ -116,54 +141,100 @@ #define MEM_INIT memset -/************************************** +/*-************************************ * Basic Types **************************************/ -#if defined (__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) /* C99 */ +#if defined(__cplusplus) || (defined (__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) /* C99 */) # include <stdint.h> typedef uint8_t BYTE; typedef uint16_t U16; typedef uint32_t U32; typedef int32_t S32; typedef uint64_t U64; + typedef uintptr_t uptrval; #else typedef unsigned char BYTE; typedef unsigned short U16; typedef unsigned int U32; typedef signed int S32; typedef unsigned long long U64; + typedef size_t uptrval; /* generally true, except OpenVMS-64 */ #endif +#if defined(__x86_64__) + typedef U64 reg_t; /* 64-bits in x32 mode */ +#else + typedef size_t reg_t; /* 32-bits in x32 mode */ +#endif -/************************************** +/*-************************************ * Reading and writing into memory **************************************/ -#define STEPSIZE sizeof(size_t) - -static unsigned LZ4_64bits(void) { return sizeof(void*)==8; } - static unsigned LZ4_isLittleEndian(void) { - const union { U32 i; BYTE c[4]; } one = { 1 }; /* don't use static : performance detrimental */ + const union { U32 u; BYTE c[4]; } one = { 1 }; /* don't use static : performance detrimental */ return one.c[0]; } +#if defined(LZ4_FORCE_MEMORY_ACCESS) && (LZ4_FORCE_MEMORY_ACCESS==2) +/* lie to the compiler about data alignment; use with caution */ + +static U16 LZ4_read16(const void* memPtr) { return *(const U16*) memPtr; } +static U32 LZ4_read32(const void* memPtr) { return *(const U32*) memPtr; } +static reg_t LZ4_read_ARCH(const void* memPtr) { return *(const reg_t*) memPtr; } + +static void LZ4_write16(void* memPtr, U16 value) { *(U16*)memPtr = value; } +static void LZ4_write32(void* memPtr, U32 value) { *(U32*)memPtr = value; } + +#elif defined(LZ4_FORCE_MEMORY_ACCESS) && (LZ4_FORCE_MEMORY_ACCESS==1) + +/* __pack instructions are safer, but compiler specific, hence potentially problematic for some compilers */ +/* currently only defined for gcc and icc */ +typedef union { U16 u16; U32 u32; reg_t uArch; } __attribute__((packed)) unalign; + +static U16 LZ4_read16(const void* ptr) { return ((const unalign*)ptr)->u16; } +static U32 LZ4_read32(const void* ptr) { return ((const unalign*)ptr)->u32; } +static reg_t LZ4_read_ARCH(const void* ptr) { return ((const unalign*)ptr)->uArch; } + +static void LZ4_write16(void* memPtr, U16 value) { ((unalign*)memPtr)->u16 = value; } +static void LZ4_write32(void* memPtr, U32 value) { ((unalign*)memPtr)->u32 = value; } + +#else /* safe and portable access through memcpy() */ + static U16 LZ4_read16(const void* memPtr) { - U16 val16; - memcpy(&val16, memPtr, 2); - return val16; + U16 val; memcpy(&val, memPtr, sizeof(val)); return val; +} + +static U32 LZ4_read32(const void* memPtr) +{ + U32 val; memcpy(&val, memPtr, sizeof(val)); return val; +} + +static reg_t LZ4_read_ARCH(const void* memPtr) +{ + reg_t val; memcpy(&val, memPtr, sizeof(val)); return val; } +static void LZ4_write16(void* memPtr, U16 value) +{ + memcpy(memPtr, &value, sizeof(value)); +} + +static void LZ4_write32(void* memPtr, U32 value) +{ + memcpy(memPtr, &value, sizeof(value)); +} + +#endif /* LZ4_FORCE_MEMORY_ACCESS */ + + static U16 LZ4_readLE16(const void* memPtr) { - if (LZ4_isLittleEndian()) - { + if (LZ4_isLittleEndian()) { return LZ4_read16(memPtr); - } - else - { + } else { const BYTE* p = (const BYTE*)memPtr; return (U16)((U16)p[0] + (p[1]<<8)); } @@ -171,63 +242,39 @@ static U16 LZ4_readLE16(const void* memPtr) static void LZ4_writeLE16(void* memPtr, U16 value) { - if (LZ4_isLittleEndian()) - { - memcpy(memPtr, &value, 2); - } - else - { + if (LZ4_isLittleEndian()) { + LZ4_write16(memPtr, value); + } else { BYTE* p = (BYTE*)memPtr; p[0] = (BYTE) value; p[1] = (BYTE)(value>>8); } } -static U32 LZ4_read32(const void* memPtr) +static void LZ4_copy8(void* dst, const void* src) { - U32 val32; - memcpy(&val32, memPtr, 4); - return val32; + memcpy(dst,src,8); } -static U64 LZ4_read64(const void* memPtr) -{ - U64 val64; - memcpy(&val64, memPtr, 8); - return val64; -} - -static size_t LZ4_read_ARCH(const void* p) -{ - if (LZ4_64bits()) - return (size_t)LZ4_read64(p); - else - return (size_t)LZ4_read32(p); -} - - -static void LZ4_copy4(void* dstPtr, const void* srcPtr) { memcpy(dstPtr, srcPtr, 4); } - -static void LZ4_copy8(void* dstPtr, const void* srcPtr) { memcpy(dstPtr, srcPtr, 8); } - -/* customized version of memcpy, which may overwrite up to 7 bytes beyond dstEnd */ +/* customized variant of memcpy, which can overwrite up to 8 bytes beyond dstEnd */ static void LZ4_wildCopy(void* dstPtr, const void* srcPtr, void* dstEnd) { BYTE* d = (BYTE*)dstPtr; const BYTE* s = (const BYTE*)srcPtr; - BYTE* e = (BYTE*)dstEnd; + BYTE* const e = (BYTE*)dstEnd; + do { LZ4_copy8(d,s); d+=8; s+=8; } while (d<e); } -/************************************** +/*-************************************ * Common Constants **************************************/ #define MINMATCH 4 -#define COPYLENGTH 8 +#define WILDCOPYLENGTH 8 #define LASTLITERALS 5 -#define MFLIMIT (COPYLENGTH+MINMATCH) +#define MFLIMIT (WILDCOPYLENGTH+MINMATCH) static const int LZ4_minLength = (MFLIMIT+1); #define KB *(1 <<10) @@ -243,55 +290,48 @@ static const int LZ4_minLength = (MFLIMIT+1); #define RUN_MASK ((1U<<RUN_BITS)-1) -/************************************** +/*-************************************ * Common Utils **************************************/ #define LZ4_STATIC_ASSERT(c) { enum { LZ4_static_assert = 1/(int)(!!(c)) }; } /* use only *after* variable declarations */ -/************************************** +/*-************************************ * Common functions **************************************/ -static unsigned LZ4_NbCommonBytes (register size_t val) +static unsigned LZ4_NbCommonBytes (register reg_t val) { - if (LZ4_isLittleEndian()) - { - if (LZ4_64bits()) - { + if (LZ4_isLittleEndian()) { + if (sizeof(val)==8) { # if defined(_MSC_VER) && defined(_WIN64) && !defined(LZ4_FORCE_SW_BITCOUNT) unsigned long r = 0; _BitScanForward64( &r, (U64)val ); return (int)(r>>3); -# elif (defined(__clang__) || (LZ4_GCC_VERSION >= 304)) && !defined(LZ4_FORCE_SW_BITCOUNT) +# elif (defined(__clang__) || (defined(__GNUC__) && (__GNUC__>=3))) && !defined(LZ4_FORCE_SW_BITCOUNT) return (__builtin_ctzll((U64)val) >> 3); # else static const int DeBruijnBytePos[64] = { 0, 0, 0, 0, 0, 1, 1, 2, 0, 3, 1, 3, 1, 4, 2, 7, 0, 2, 3, 6, 1, 5, 3, 5, 1, 3, 4, 4, 2, 5, 6, 7, 7, 0, 1, 2, 3, 3, 4, 6, 2, 6, 5, 5, 3, 4, 5, 6, 7, 1, 2, 4, 6, 4, 4, 5, 7, 2, 6, 5, 7, 6, 7, 7 }; return DeBruijnBytePos[((U64)((val & -(long long)val) * 0x0218A392CDABBD3FULL)) >> 58]; # endif - } - else /* 32 bits */ - { + } else /* 32 bits */ { # if defined(_MSC_VER) && !defined(LZ4_FORCE_SW_BITCOUNT) unsigned long r; _BitScanForward( &r, (U32)val ); return (int)(r>>3); -# elif (defined(__clang__) || (LZ4_GCC_VERSION >= 304)) && !defined(LZ4_FORCE_SW_BITCOUNT) +# elif (defined(__clang__) || (defined(__GNUC__) && (__GNUC__>=3))) && !defined(LZ4_FORCE_SW_BITCOUNT) return (__builtin_ctz((U32)val) >> 3); # else static const int DeBruijnBytePos[32] = { 0, 0, 3, 0, 3, 1, 3, 0, 3, 2, 2, 1, 3, 2, 0, 1, 3, 3, 1, 2, 2, 2, 2, 0, 3, 1, 2, 0, 1, 0, 1, 1 }; return DeBruijnBytePos[((U32)((val & -(S32)val) * 0x077CB531U)) >> 27]; # endif } - } - else /* Big Endian CPU */ - { - if (LZ4_64bits()) - { + } else /* Big Endian CPU */ { + if (sizeof(val)==8) { # if defined(_MSC_VER) && defined(_WIN64) && !defined(LZ4_FORCE_SW_BITCOUNT) unsigned long r = 0; _BitScanReverse64( &r, val ); return (unsigned)(r>>3); -# elif (defined(__clang__) || (LZ4_GCC_VERSION >= 304)) && !defined(LZ4_FORCE_SW_BITCOUNT) +# elif (defined(__clang__) || (defined(__GNUC__) && (__GNUC__>=3))) && !defined(LZ4_FORCE_SW_BITCOUNT) return (__builtin_clzll((U64)val) >> 3); # else unsigned r; @@ -300,14 +340,12 @@ static unsigned LZ4_NbCommonBytes (register size_t val) r += (!val); return r; # endif - } - else /* 32 bits */ - { + } else /* 32 bits */ { # if defined(_MSC_VER) && !defined(LZ4_FORCE_SW_BITCOUNT) unsigned long r = 0; _BitScanReverse( &r, (unsigned long)val ); return (unsigned)(r>>3); -# elif (defined(__clang__) || (LZ4_GCC_VERSION >= 304)) && !defined(LZ4_FORCE_SW_BITCOUNT) +# elif (defined(__clang__) || (defined(__GNUC__) && (__GNUC__>=3))) && !defined(LZ4_FORCE_SW_BITCOUNT) return (__builtin_clz((U32)val) >> 3); # else unsigned r; @@ -319,19 +357,19 @@ static unsigned LZ4_NbCommonBytes (register size_t val) } } +#define STEPSIZE sizeof(reg_t) static unsigned LZ4_count(const BYTE* pIn, const BYTE* pMatch, const BYTE* pInLimit) { const BYTE* const pStart = pIn; - while (likely(pIn<pInLimit-(STEPSIZE-1))) - { - size_t diff = LZ4_read_ARCH(pMatch) ^ LZ4_read_ARCH(pIn); + while (likely(pIn<pInLimit-(STEPSIZE-1))) { + reg_t const diff = LZ4_read_ARCH(pMatch) ^ LZ4_read_ARCH(pIn); if (!diff) { pIn+=STEPSIZE; pMatch+=STEPSIZE; continue; } pIn += LZ4_NbCommonBytes(diff); return (unsigned)(pIn - pStart); } - if (LZ4_64bits()) if ((pIn<(pInLimit-3)) && (LZ4_read32(pMatch) == LZ4_read32(pIn))) { pIn+=4; pMatch+=4; } + if ((STEPSIZE==8) && (pIn<(pInLimit-3)) && (LZ4_read32(pMatch) == LZ4_read32(pIn))) { pIn+=4; pMatch+=4; } if ((pIn<(pInLimit-1)) && (LZ4_read16(pMatch) == LZ4_read16(pIn))) { pIn+=2; pMatch+=2; } if ((pIn<pInLimit) && (*pMatch == *pIn)) pIn++; return (unsigned)(pIn - pStart); @@ -339,29 +377,16 @@ static unsigned LZ4_count(const BYTE* pIn, const BYTE* pMatch, const BYTE* pInLi #ifndef LZ4_COMMONDEFS_ONLY -/************************************** +/*-************************************ * Local Constants **************************************/ -#define LZ4_HASHLOG (LZ4_MEMORY_USAGE-2) -#define HASHTABLESIZE (1 << LZ4_MEMORY_USAGE) -#define HASH_SIZE_U32 (1 << LZ4_HASHLOG) /* required as macro for static allocation */ - static const int LZ4_64Klimit = ((64 KB) + (MFLIMIT-1)); static const U32 LZ4_skipTrigger = 6; /* Increase this value ==> compression run slower on incompressible data */ -/************************************** +/*-************************************ * Local Structures and types **************************************/ -typedef struct { - U32 hashTable[HASH_SIZE_U32]; - U32 currentOffset; - U32 initCheck; - const BYTE* dictionary; - BYTE* bufferStart; /* obsolete, used for slideInputBuffer */ - U32 dictSize; -} LZ4_stream_t_internal; - typedef enum { notLimited = 0, limitedOutput = 1 } limitedOutput_directive; typedef enum { byPtr, byU32, byU16 } tableType_t; @@ -372,44 +397,43 @@ typedef enum { endOnOutputSize = 0, endOnInputSize = 1 } endCondition_directive; typedef enum { full = 0, partial = 1 } earlyEnd_directive; -/************************************** +/*-************************************ * Local Utils **************************************/ int LZ4_versionNumber (void) { return LZ4_VERSION_NUMBER; } +const char* LZ4_versionString(void) { return LZ4_VERSION_STRING; } int LZ4_compressBound(int isize) { return LZ4_COMPRESSBOUND(isize); } int LZ4_sizeofState() { return LZ4_STREAMSIZE; } - -/******************************** +/*-****************************** * Compression functions ********************************/ - -static U32 LZ4_hashSequence(U32 sequence, tableType_t const tableType) +static U32 LZ4_hash4(U32 sequence, tableType_t const tableType) { if (tableType == byU16) - return (((sequence) * 2654435761U) >> ((MINMATCH*8)-(LZ4_HASHLOG+1))); + return ((sequence * 2654435761U) >> ((MINMATCH*8)-(LZ4_HASHLOG+1))); else - return (((sequence) * 2654435761U) >> ((MINMATCH*8)-LZ4_HASHLOG)); + return ((sequence * 2654435761U) >> ((MINMATCH*8)-LZ4_HASHLOG)); } -static const U64 prime5bytes = 889523592379ULL; -static U32 LZ4_hashSequence64(size_t sequence, tableType_t const tableType) +static U32 LZ4_hash5(U64 sequence, tableType_t const tableType) { + static const U64 prime5bytes = 889523592379ULL; + static const U64 prime8bytes = 11400714785074694791ULL; const U32 hashLog = (tableType == byU16) ? LZ4_HASHLOG+1 : LZ4_HASHLOG; - const U32 hashMask = (1<<hashLog) - 1; - return ((sequence * prime5bytes) >> (40 - hashLog)) & hashMask; + if (LZ4_isLittleEndian()) + return (U32)(((sequence << 24) * prime5bytes) >> (64 - hashLog)); + else + return (U32)(((sequence >> 24) * prime8bytes) >> (64 - hashLog)); } -static U32 LZ4_hashSequenceT(size_t sequence, tableType_t const tableType) +FORCE_INLINE U32 LZ4_hashPosition(const void* const p, tableType_t const tableType) { - if (LZ4_64bits()) - return LZ4_hashSequence64(sequence, tableType); - return LZ4_hashSequence((U32)sequence, tableType); + if ((sizeof(reg_t)==8) && (tableType != byU16)) return LZ4_hash5(LZ4_read_ARCH(p), tableType); + return LZ4_hash4(LZ4_read32(p), tableType); } -static U32 LZ4_hashPosition(const void* p, tableType_t tableType) { return LZ4_hashSequenceT(LZ4_read_ARCH(p), tableType); } - static void LZ4_putPositionOnHash(const BYTE* p, U32 h, void* tableBase, tableType_t const tableType, const BYTE* srcBase) { switch (tableType) @@ -420,27 +444,30 @@ static void LZ4_putPositionOnHash(const BYTE* p, U32 h, void* tableBase, tableTy } } -static void LZ4_putPosition(const BYTE* p, void* tableBase, tableType_t tableType, const BYTE* srcBase) +FORCE_INLINE void LZ4_putPosition(const BYTE* p, void* tableBase, tableType_t tableType, const BYTE* srcBase) { - U32 h = LZ4_hashPosition(p, tableType); + U32 const h = LZ4_hashPosition(p, tableType); LZ4_putPositionOnHash(p, h, tableBase, tableType, srcBase); } static const BYTE* LZ4_getPositionOnHash(U32 h, void* tableBase, tableType_t tableType, const BYTE* srcBase) { if (tableType == byPtr) { const BYTE** hashTable = (const BYTE**) tableBase; return hashTable[h]; } - if (tableType == byU32) { U32* hashTable = (U32*) tableBase; return hashTable[h] + srcBase; } - { U16* hashTable = (U16*) tableBase; return hashTable[h] + srcBase; } /* default, to ensure a return */ + if (tableType == byU32) { const U32* const hashTable = (U32*) tableBase; return hashTable[h] + srcBase; } + { const U16* const hashTable = (U16*) tableBase; return hashTable[h] + srcBase; } /* default, to ensure a return */ } -static const BYTE* LZ4_getPosition(const BYTE* p, void* tableBase, tableType_t tableType, const BYTE* srcBase) +FORCE_INLINE const BYTE* LZ4_getPosition(const BYTE* p, void* tableBase, tableType_t tableType, const BYTE* srcBase) { - U32 h = LZ4_hashPosition(p, tableType); + U32 const h = LZ4_hashPosition(p, tableType); return LZ4_getPositionOnHash(h, tableBase, tableType, srcBase); } + +/** LZ4_compress_generic() : + inlined, to ensure branches are decided at compilation time */ FORCE_INLINE int LZ4_compress_generic( - void* const ctx, + LZ4_stream_t_internal* const cctx, const char* const source, char* const dest, const int inputSize, @@ -451,15 +478,13 @@ FORCE_INLINE int LZ4_compress_generic( const dictIssue_directive dictIssue, const U32 acceleration) { - LZ4_stream_t_internal* const dictPtr = (LZ4_stream_t_internal*)ctx; - const BYTE* ip = (const BYTE*) source; const BYTE* base; const BYTE* lowLimit; - const BYTE* const lowRefLimit = ip - dictPtr->dictSize; - const BYTE* const dictionary = dictPtr->dictionary; - const BYTE* const dictEnd = dictionary + dictPtr->dictSize; - const size_t dictDelta = dictEnd - (const BYTE*)source; + const BYTE* const lowRefLimit = ip - cctx->dictSize; + const BYTE* const dictionary = cctx->dictionary; + const BYTE* const dictEnd = dictionary + cctx->dictSize; + const ptrdiff_t dictDelta = dictEnd - (const BYTE*)source; const BYTE* anchor = (const BYTE*) source; const BYTE* const iend = ip + inputSize; const BYTE* const mflimit = iend - MFLIMIT; @@ -469,10 +494,9 @@ FORCE_INLINE int LZ4_compress_generic( BYTE* const olimit = op + maxOutputSize; U32 forwardH; - size_t refDelta=0; /* Init conditions */ - if ((U32)inputSize > (U32)LZ4_MAX_INPUT_SIZE) return 0; /* Unsupported input size, too large (or negative) */ + if ((U32)inputSize > (U32)LZ4_MAX_INPUT_SIZE) return 0; /* Unsupported inputSize, too large (or negative) */ switch(dict) { case noDict: @@ -481,11 +505,11 @@ FORCE_INLINE int LZ4_compress_generic( lowLimit = (const BYTE*)source; break; case withPrefix64k: - base = (const BYTE*)source - dictPtr->currentOffset; - lowLimit = (const BYTE*)source - dictPtr->dictSize; + base = (const BYTE*)source - cctx->currentOffset; + lowLimit = (const BYTE*)source - cctx->dictSize; break; case usingExtDict: - base = (const BYTE*)source - dictPtr->currentOffset; + base = (const BYTE*)source - cctx->currentOffset; lowLimit = (const BYTE*)source; break; } @@ -493,44 +517,38 @@ FORCE_INLINE int LZ4_compress_generic( if (inputSize<LZ4_minLength) goto _last_literals; /* Input too small, no compression (all literals) */ /* First Byte */ - LZ4_putPosition(ip, ctx, tableType, base); + LZ4_putPosition(ip, cctx->hashTable, tableType, base); ip++; forwardH = LZ4_hashPosition(ip, tableType); /* Main Loop */ - for ( ; ; ) - { + for ( ; ; ) { + ptrdiff_t refDelta = 0; const BYTE* match; BYTE* token; - { - const BYTE* forwardIp = ip; + + /* Find a match */ + { const BYTE* forwardIp = ip; unsigned step = 1; unsigned searchMatchNb = acceleration << LZ4_skipTrigger; - - /* Find a match */ do { - U32 h = forwardH; + U32 const h = forwardH; ip = forwardIp; forwardIp += step; step = (searchMatchNb++ >> LZ4_skipTrigger); if (unlikely(forwardIp > mflimit)) goto _last_literals; - match = LZ4_getPositionOnHash(h, ctx, tableType, base); - if (dict==usingExtDict) - { - if (match<(const BYTE*)source) - { + match = LZ4_getPositionOnHash(h, cctx->hashTable, tableType, base); + if (dict==usingExtDict) { + if (match < (const BYTE*)source) { refDelta = dictDelta; lowLimit = dictionary; - } - else - { + } else { refDelta = 0; lowLimit = (const BYTE*)source; - } - } + } } forwardH = LZ4_hashPosition(forwardIp, tableType); - LZ4_putPositionOnHash(ip, h, ctx, tableType, base); + LZ4_putPositionOnHash(ip, h, cctx->hashTable, tableType, base); } while ( ((dictIssue==dictSmall) ? (match < lowRefLimit) : 0) || ((tableType==byU16) ? 0 : (match + MAX_DISTANCE < ip)) @@ -538,18 +556,17 @@ FORCE_INLINE int LZ4_compress_generic( } /* Catch up */ - while ((ip>anchor) && (match+refDelta > lowLimit) && (unlikely(ip[-1]==match[refDelta-1]))) { ip--; match--; } + while (((ip>anchor) & (match+refDelta > lowLimit)) && (unlikely(ip[-1]==match[refDelta-1]))) { ip--; match--; } - { - /* Encode Literal length */ - unsigned litLength = (unsigned)(ip - anchor); + /* Encode Literals */ + { unsigned const litLength = (unsigned)(ip - anchor); token = op++; - if ((outputLimited) && (unlikely(op + litLength + (2 + 1 + LASTLITERALS) + (litLength/255) > olimit))) - return 0; /* Check output limit */ - if (litLength>=RUN_MASK) - { + if ((outputLimited) && /* Check output buffer overflow */ + (unlikely(op + litLength + (2 + 1 + LASTLITERALS) + (litLength/255) > olimit))) + return 0; + if (litLength >= RUN_MASK) { int len = (int)litLength-RUN_MASK; - *token=(RUN_MASK<<ML_BITS); + *token = (RUN_MASK<<ML_BITS); for(; len >= 255 ; len-=255) *op++ = 255; *op++ = (BYTE)len; } @@ -565,41 +582,37 @@ _next_match: LZ4_writeLE16(op, (U16)(ip-match)); op+=2; /* Encode MatchLength */ - { - unsigned matchLength; + { unsigned matchCode; - if ((dict==usingExtDict) && (lowLimit==dictionary)) - { + if ((dict==usingExtDict) && (lowLimit==dictionary)) { const BYTE* limit; match += refDelta; limit = ip + (dictEnd-match); if (limit > matchlimit) limit = matchlimit; - matchLength = LZ4_count(ip+MINMATCH, match+MINMATCH, limit); - ip += MINMATCH + matchLength; - if (ip==limit) - { - unsigned more = LZ4_count(ip, (const BYTE*)source, matchlimit); - matchLength += more; + matchCode = LZ4_count(ip+MINMATCH, match+MINMATCH, limit); + ip += MINMATCH + matchCode; + if (ip==limit) { + unsigned const more = LZ4_count(ip, (const BYTE*)source, matchlimit); + matchCode += more; ip += more; } - } - else - { - matchLength = LZ4_count(ip+MINMATCH, match+MINMATCH, matchlimit); - ip += MINMATCH + matchLength; + } else { + matchCode = LZ4_count(ip+MINMATCH, match+MINMATCH, matchlimit); + ip += MINMATCH + matchCode; } - if ((outputLimited) && (unlikely(op + (1 + LASTLITERALS) + (matchLength>>8) > olimit))) - return 0; /* Check output limit */ - if (matchLength>=ML_MASK) - { + if ( outputLimited && /* Check output buffer overflow */ + (unlikely(op + (1 + LASTLITERALS) + (matchCode>>8) > olimit)) ) + return 0; + if (matchCode >= ML_MASK) { *token += ML_MASK; - matchLength -= ML_MASK; - for (; matchLength >= 510 ; matchLength-=510) { *op++ = 255; *op++ = 255; } - if (matchLength >= 255) { matchLength-=255; *op++ = 255; } - *op++ = (BYTE)matchLength; - } - else *token += (BYTE)(matchLength); + matchCode -= ML_MASK; + LZ4_write32(op, 0xFFFFFFFF); + while (matchCode >= 4*255) op+=4, LZ4_write32(op, 0xFFFFFFFF), matchCode -= 4*255; + op += matchCode / 255; + *op++ = (BYTE)(matchCode % 255); + } else + *token += (BYTE)(matchCode); } anchor = ip; @@ -608,24 +621,19 @@ _next_match: if (ip > mflimit) break; /* Fill table */ - LZ4_putPosition(ip-2, ctx, tableType, base); + LZ4_putPosition(ip-2, cctx->hashTable, tableType, base); /* Test next position */ - match = LZ4_getPosition(ip, ctx, tableType, base); - if (dict==usingExtDict) - { - if (match<(const BYTE*)source) - { + match = LZ4_getPosition(ip, cctx->hashTable, tableType, base); + if (dict==usingExtDict) { + if (match < (const BYTE*)source) { refDelta = dictDelta; lowLimit = dictionary; - } - else - { + } else { refDelta = 0; lowLimit = (const BYTE*)source; - } - } - LZ4_putPosition(ip, ctx, tableType, base); + } } + LZ4_putPosition(ip, cctx->hashTable, tableType, base); if ( ((dictIssue==dictSmall) ? (match>=lowRefLimit) : 1) && (match+MAX_DISTANCE>=ip) && (LZ4_read32(match+refDelta)==LZ4_read32(ip)) ) @@ -637,19 +645,16 @@ _next_match: _last_literals: /* Encode Last Literals */ - { - const size_t lastRun = (size_t)(iend - anchor); - if ((outputLimited) && ((op - (BYTE*)dest) + lastRun + 1 + ((lastRun+255-RUN_MASK)/255) > (U32)maxOutputSize)) - return 0; /* Check output limit */ - if (lastRun >= RUN_MASK) - { + { size_t const lastRun = (size_t)(iend - anchor); + if ( (outputLimited) && /* Check output buffer overflow */ + ((op - (BYTE*)dest) + lastRun + 1 + ((lastRun+255-RUN_MASK)/255) > (U32)maxOutputSize) ) + return 0; + if (lastRun >= RUN_MASK) { size_t accumulator = lastRun - RUN_MASK; *op++ = RUN_MASK << ML_BITS; for(; accumulator >= 255 ; accumulator-=255) *op++ = 255; *op++ = (BYTE) accumulator; - } - else - { + } else { *op++ = (BYTE)(lastRun<<ML_BITS); } memcpy(op, anchor, lastRun); @@ -663,22 +668,20 @@ _last_literals: int LZ4_compress_fast_extState(void* state, const char* source, char* dest, int inputSize, int maxOutputSize, int acceleration) { + LZ4_stream_t_internal* ctx = &((LZ4_stream_t*)state)->internal_donotuse; LZ4_resetStream((LZ4_stream_t*)state); if (acceleration < 1) acceleration = ACCELERATION_DEFAULT; - if (maxOutputSize >= LZ4_compressBound(inputSize)) - { + if (maxOutputSize >= LZ4_compressBound(inputSize)) { if (inputSize < LZ4_64Klimit) - return LZ4_compress_generic(state, source, dest, inputSize, 0, notLimited, byU16, noDict, noDictIssue, acceleration); + return LZ4_compress_generic(ctx, source, dest, inputSize, 0, notLimited, byU16, noDict, noDictIssue, acceleration); else - return LZ4_compress_generic(state, source, dest, inputSize, 0, notLimited, LZ4_64bits() ? byU32 : byPtr, noDict, noDictIssue, acceleration); - } - else - { + return LZ4_compress_generic(ctx, source, dest, inputSize, 0, notLimited, (sizeof(void*)==8) ? byU32 : byPtr, noDict, noDictIssue, acceleration); + } else { if (inputSize < LZ4_64Klimit) - return LZ4_compress_generic(state, source, dest, inputSize, maxOutputSize, limitedOutput, byU16, noDict, noDictIssue, acceleration); + return LZ4_compress_generic(ctx, source, dest, inputSize, maxOutputSize, limitedOutput, byU16, noDict, noDictIssue, acceleration); else - return LZ4_compress_generic(state, source, dest, inputSize, maxOutputSize, limitedOutput, LZ4_64bits() ? byU32 : byPtr, noDict, noDictIssue, acceleration); + return LZ4_compress_generic(ctx, source, dest, inputSize, maxOutputSize, limitedOutput, (sizeof(void*)==8) ? byU32 : byPtr, noDict, noDictIssue, acceleration); } } @@ -689,10 +692,10 @@ int LZ4_compress_fast(const char* source, char* dest, int inputSize, int maxOutp void* ctxPtr = ALLOCATOR(1, sizeof(LZ4_stream_t)); /* malloc-calloc always properly aligned */ #else LZ4_stream_t ctx; - void* ctxPtr = &ctx; + void* const ctxPtr = &ctx; #endif - int result = LZ4_compress_fast_extState(ctxPtr, source, dest, inputSize, maxOutputSize, acceleration); + int const result = LZ4_compress_fast_extState(ctxPtr, source, dest, inputSize, maxOutputSize, acceleration); #if (HEAPMODE) FREEMEM(ctxPtr); @@ -712,22 +715,21 @@ int LZ4_compress_default(const char* source, char* dest, int inputSize, int maxO int LZ4_compress_fast_force(const char* source, char* dest, int inputSize, int maxOutputSize, int acceleration) { LZ4_stream_t ctx; - LZ4_resetStream(&ctx); if (inputSize < LZ4_64Klimit) - return LZ4_compress_generic(&ctx, source, dest, inputSize, maxOutputSize, limitedOutput, byU16, noDict, noDictIssue, acceleration); + return LZ4_compress_generic(&ctx.internal_donotuse, source, dest, inputSize, maxOutputSize, limitedOutput, byU16, noDict, noDictIssue, acceleration); else - return LZ4_compress_generic(&ctx, source, dest, inputSize, maxOutputSize, limitedOutput, LZ4_64bits() ? byU32 : byPtr, noDict, noDictIssue, acceleration); + return LZ4_compress_generic(&ctx.internal_donotuse, source, dest, inputSize, maxOutputSize, limitedOutput, sizeof(void*)==8 ? byU32 : byPtr, noDict, noDictIssue, acceleration); } -/******************************** -* destSize variant +/*-****************************** +* *_destSize() variant ********************************/ static int LZ4_compress_destSize_generic( - void* const ctx, + LZ4_stream_t_internal* const ctx, const char* const src, char* const dst, int* const srcSizePtr, @@ -759,32 +761,30 @@ static int LZ4_compress_destSize_generic( /* First Byte */ *srcSizePtr = 0; - LZ4_putPosition(ip, ctx, tableType, base); + LZ4_putPosition(ip, ctx->hashTable, tableType, base); ip++; forwardH = LZ4_hashPosition(ip, tableType); /* Main Loop */ - for ( ; ; ) - { + for ( ; ; ) { const BYTE* match; BYTE* token; - { - const BYTE* forwardIp = ip; + + /* Find a match */ + { const BYTE* forwardIp = ip; unsigned step = 1; unsigned searchMatchNb = 1 << LZ4_skipTrigger; - /* Find a match */ do { U32 h = forwardH; ip = forwardIp; forwardIp += step; step = (searchMatchNb++ >> LZ4_skipTrigger); - if (unlikely(forwardIp > mflimit)) - goto _last_literals; + if (unlikely(forwardIp > mflimit)) goto _last_literals; - match = LZ4_getPositionOnHash(h, ctx, tableType, base); + match = LZ4_getPositionOnHash(h, ctx->hashTable, tableType, base); forwardH = LZ4_hashPosition(forwardIp, tableType); - LZ4_putPositionOnHash(ip, h, ctx, tableType, base); + LZ4_putPositionOnHash(ip, h, ctx->hashTable, tableType, base); } while ( ((tableType==byU16) ? 0 : (match + MAX_DISTANCE < ip)) || (LZ4_read32(match) != LZ4_read32(ip)) ); @@ -793,18 +793,15 @@ static int LZ4_compress_destSize_generic( /* Catch up */ while ((ip>anchor) && (match > lowLimit) && (unlikely(ip[-1]==match[-1]))) { ip--; match--; } - { - /* Encode Literal length */ - unsigned litLength = (unsigned)(ip - anchor); + /* Encode Literal length */ + { unsigned litLength = (unsigned)(ip - anchor); token = op++; - if (op + ((litLength+240)/255) + litLength > oMaxLit) - { + if (op + ((litLength+240)/255) + litLength > oMaxLit) { /* Not enough space for a last match */ op--; goto _last_literals; } - if (litLength>=RUN_MASK) - { + if (litLength>=RUN_MASK) { unsigned len = litLength - RUN_MASK; *token=(RUN_MASK<<ML_BITS); for(; len >= 255 ; len-=255) *op++ = 255; @@ -822,21 +819,15 @@ _next_match: LZ4_writeLE16(op, (U16)(ip-match)); op+=2; /* Encode MatchLength */ - { - size_t matchLength; + { size_t matchLength = LZ4_count(ip+MINMATCH, match+MINMATCH, matchlimit); - matchLength = LZ4_count(ip+MINMATCH, match+MINMATCH, matchlimit); - - if (op + ((matchLength+240)/255) > oMaxMatch) - { + if (op + ((matchLength+240)/255) > oMaxMatch) { /* Match description too long : reduce it */ matchLength = (15-1) + (oMaxMatch-op) * 255; } - //printf("offset %5i, matchLength%5i \n", (int)(ip-match), matchLength + MINMATCH); ip += MINMATCH + matchLength; - if (matchLength>=ML_MASK) - { + if (matchLength>=ML_MASK) { *token += ML_MASK; matchLength -= ML_MASK; while (matchLength >= 255) { matchLength-=255; *op++ = 255; } @@ -852,11 +843,11 @@ _next_match: if (op > oMaxSeq) break; /* Fill table */ - LZ4_putPosition(ip-2, ctx, tableType, base); + LZ4_putPosition(ip-2, ctx->hashTable, tableType, base); /* Test next position */ - match = LZ4_getPosition(ip, ctx, tableType, base); - LZ4_putPosition(ip, ctx, tableType, base); + match = LZ4_getPosition(ip, ctx->hashTable, tableType, base); + LZ4_putPosition(ip, ctx->hashTable, tableType, base); if ( (match+MAX_DISTANCE>=ip) && (LZ4_read32(match)==LZ4_read32(ip)) ) { token=op++; *token=0; goto _next_match; } @@ -867,25 +858,20 @@ _next_match: _last_literals: /* Encode Last Literals */ - { - size_t lastRunSize = (size_t)(iend - anchor); - if (op + 1 /* token */ + ((lastRunSize+240)/255) /* litLength */ + lastRunSize /* literals */ > oend) - { + { size_t lastRunSize = (size_t)(iend - anchor); + if (op + 1 /* token */ + ((lastRunSize+240)/255) /* litLength */ + lastRunSize /* literals */ > oend) { /* adapt lastRunSize to fill 'dst' */ lastRunSize = (oend-op) - 1; lastRunSize -= (lastRunSize+240)/255; } ip = anchor + lastRunSize; - if (lastRunSize >= RUN_MASK) - { + if (lastRunSize >= RUN_MASK) { size_t accumulator = lastRunSize - RUN_MASK; *op++ = RUN_MASK << ML_BITS; for(; accumulator >= 255 ; accumulator-=255) *op++ = 255; *op++ = (BYTE) accumulator; - } - else - { + } else { *op++ = (BYTE)(lastRunSize<<ML_BITS); } memcpy(op, anchor, lastRunSize); @@ -898,20 +884,17 @@ _last_literals: } -static int LZ4_compress_destSize_extState (void* state, const char* src, char* dst, int* srcSizePtr, int targetDstSize) +static int LZ4_compress_destSize_extState (LZ4_stream_t* state, const char* src, char* dst, int* srcSizePtr, int targetDstSize) { - LZ4_resetStream((LZ4_stream_t*)state); + LZ4_resetStream(state); - if (targetDstSize >= LZ4_compressBound(*srcSizePtr)) /* compression success is guaranteed */ - { + if (targetDstSize >= LZ4_compressBound(*srcSizePtr)) { /* compression success is guaranteed */ return LZ4_compress_fast_extState(state, src, dst, *srcSizePtr, targetDstSize, 1); - } - else - { + } else { if (*srcSizePtr < LZ4_64Klimit) - return LZ4_compress_destSize_generic(state, src, dst, srcSizePtr, targetDstSize, byU16); + return LZ4_compress_destSize_generic(&state->internal_donotuse, src, dst, srcSizePtr, targetDstSize, byU16); else - return LZ4_compress_destSize_generic(state, src, dst, srcSizePtr, targetDstSize, LZ4_64bits() ? byU32 : byPtr); + return LZ4_compress_destSize_generic(&state->internal_donotuse, src, dst, srcSizePtr, targetDstSize, sizeof(void*)==8 ? byU32 : byPtr); } } @@ -919,10 +902,10 @@ static int LZ4_compress_destSize_extState (void* state, const char* src, char* d int LZ4_compress_destSize(const char* src, char* dst, int* srcSizePtr, int targetDstSize) { #if (HEAPMODE) - void* ctx = ALLOCATOR(1, sizeof(LZ4_stream_t)); /* malloc-calloc always properly aligned */ + LZ4_stream_t* ctx = (LZ4_stream_t*)ALLOCATOR(1, sizeof(LZ4_stream_t)); /* malloc-calloc always properly aligned */ #else LZ4_stream_t ctxBody; - void* ctx = &ctxBody; + LZ4_stream_t* ctx = &ctxBody; #endif int result = LZ4_compress_destSize_extState(ctx, src, dst, srcSizePtr, targetDstSize); @@ -935,7 +918,7 @@ int LZ4_compress_destSize(const char* src, char* dst, int* srcSizePtr, int targe -/******************************** +/*-****************************** * Streaming functions ********************************/ @@ -959,10 +942,10 @@ int LZ4_freeStream (LZ4_stream_t* LZ4_stream) } -#define HASH_UNIT sizeof(size_t) +#define HASH_UNIT sizeof(reg_t) int LZ4_loadDict (LZ4_stream_t* LZ4_dict, const char* dictionary, int dictSize) { - LZ4_stream_t_internal* dict = (LZ4_stream_t_internal*) LZ4_dict; + LZ4_stream_t_internal* dict = &LZ4_dict->internal_donotuse; const BYTE* p = (const BYTE*)dictionary; const BYTE* const dictEnd = p + dictSize; const BYTE* base; @@ -970,8 +953,7 @@ int LZ4_loadDict (LZ4_stream_t* LZ4_dict, const char* dictionary, int dictSize) if ((dict->initCheck) || (dict->currentOffset > 1 GB)) /* Uninitialized structure, or reuse overflow */ LZ4_resetStream(LZ4_dict); - if (dictSize < (int)HASH_UNIT) - { + if (dictSize < (int)HASH_UNIT) { dict->dictionary = NULL; dict->dictSize = 0; return 0; @@ -984,8 +966,7 @@ int LZ4_loadDict (LZ4_stream_t* LZ4_dict, const char* dictionary, int dictSize) dict->dictSize = (U32)(dictEnd - p); dict->currentOffset += dict->dictSize; - while (p <= dictEnd-HASH_UNIT) - { + while (p <= dictEnd-HASH_UNIT) { LZ4_putPosition(p, dict->hashTable, byU32, base); p+=3; } @@ -997,14 +978,12 @@ int LZ4_loadDict (LZ4_stream_t* LZ4_dict, const char* dictionary, int dictSize) static void LZ4_renormDictT(LZ4_stream_t_internal* LZ4_dict, const BYTE* src) { if ((LZ4_dict->currentOffset > 0x80000000) || - ((size_t)LZ4_dict->currentOffset > (size_t)src)) /* address space overflow */ - { + ((uptrval)LZ4_dict->currentOffset > (uptrval)src)) { /* address space overflow */ /* rescale hash table */ - U32 delta = LZ4_dict->currentOffset - 64 KB; + U32 const delta = LZ4_dict->currentOffset - 64 KB; const BYTE* dictEnd = LZ4_dict->dictionary + LZ4_dict->dictSize; int i; - for (i=0; i<HASH_SIZE_U32; i++) - { + for (i=0; i<LZ4_HASH_SIZE_U32; i++) { if (LZ4_dict->hashTable[i] < delta) LZ4_dict->hashTable[i]=0; else LZ4_dict->hashTable[i] -= delta; } @@ -1017,7 +996,7 @@ static void LZ4_renormDictT(LZ4_stream_t_internal* LZ4_dict, const BYTE* src) int LZ4_compress_fast_continue (LZ4_stream_t* LZ4_stream, const char* source, char* dest, int inputSize, int maxOutputSize, int acceleration) { - LZ4_stream_t_internal* streamPtr = (LZ4_stream_t_internal*)LZ4_stream; + LZ4_stream_t_internal* streamPtr = &LZ4_stream->internal_donotuse; const BYTE* const dictEnd = streamPtr->dictionary + streamPtr->dictSize; const BYTE* smallest = (const BYTE*) source; @@ -1027,10 +1006,8 @@ int LZ4_compress_fast_continue (LZ4_stream_t* LZ4_stream, const char* source, ch if (acceleration < 1) acceleration = ACCELERATION_DEFAULT; /* Check overlapping input/dictionary space */ - { - const BYTE* sourceEnd = (const BYTE*) source + inputSize; - if ((sourceEnd > streamPtr->dictionary) && (sourceEnd < dictEnd)) - { + { const BYTE* sourceEnd = (const BYTE*) source + inputSize; + if ((sourceEnd > streamPtr->dictionary) && (sourceEnd < dictEnd)) { streamPtr->dictSize = (U32)(dictEnd - sourceEnd); if (streamPtr->dictSize > 64 KB) streamPtr->dictSize = 64 KB; if (streamPtr->dictSize < 4) streamPtr->dictSize = 0; @@ -1039,25 +1016,23 @@ int LZ4_compress_fast_continue (LZ4_stream_t* LZ4_stream, const char* source, ch } /* prefix mode : source data follows dictionary */ - if (dictEnd == (const BYTE*)source) - { + if (dictEnd == (const BYTE*)source) { int result; if ((streamPtr->dictSize < 64 KB) && (streamPtr->dictSize < streamPtr->currentOffset)) - result = LZ4_compress_generic(LZ4_stream, source, dest, inputSize, maxOutputSize, limitedOutput, byU32, withPrefix64k, dictSmall, acceleration); + result = LZ4_compress_generic(streamPtr, source, dest, inputSize, maxOutputSize, limitedOutput, byU32, withPrefix64k, dictSmall, acceleration); else - result = LZ4_compress_generic(LZ4_stream, source, dest, inputSize, maxOutputSize, limitedOutput, byU32, withPrefix64k, noDictIssue, acceleration); + result = LZ4_compress_generic(streamPtr, source, dest, inputSize, maxOutputSize, limitedOutput, byU32, withPrefix64k, noDictIssue, acceleration); streamPtr->dictSize += (U32)inputSize; streamPtr->currentOffset += (U32)inputSize; return result; } /* external dictionary mode */ - { - int result; + { int result; if ((streamPtr->dictSize < 64 KB) && (streamPtr->dictSize < streamPtr->currentOffset)) - result = LZ4_compress_generic(LZ4_stream, source, dest, inputSize, maxOutputSize, limitedOutput, byU32, usingExtDict, dictSmall, acceleration); + result = LZ4_compress_generic(streamPtr, source, dest, inputSize, maxOutputSize, limitedOutput, byU32, usingExtDict, dictSmall, acceleration); else - result = LZ4_compress_generic(LZ4_stream, source, dest, inputSize, maxOutputSize, limitedOutput, byU32, usingExtDict, noDictIssue, acceleration); + result = LZ4_compress_generic(streamPtr, source, dest, inputSize, maxOutputSize, limitedOutput, byU32, usingExtDict, noDictIssue, acceleration); streamPtr->dictionary = (const BYTE*)source; streamPtr->dictSize = (U32)inputSize; streamPtr->currentOffset += (U32)inputSize; @@ -1069,15 +1044,15 @@ int LZ4_compress_fast_continue (LZ4_stream_t* LZ4_stream, const char* source, ch /* Hidden debug function, to force external dictionary mode */ int LZ4_compress_forceExtDict (LZ4_stream_t* LZ4_dict, const char* source, char* dest, int inputSize) { - LZ4_stream_t_internal* streamPtr = (LZ4_stream_t_internal*)LZ4_dict; + LZ4_stream_t_internal* streamPtr = &LZ4_dict->internal_donotuse; int result; const BYTE* const dictEnd = streamPtr->dictionary + streamPtr->dictSize; const BYTE* smallest = dictEnd; if (smallest > (const BYTE*) source) smallest = (const BYTE*) source; - LZ4_renormDictT((LZ4_stream_t_internal*)LZ4_dict, smallest); + LZ4_renormDictT(streamPtr, smallest); - result = LZ4_compress_generic(LZ4_dict, source, dest, inputSize, 0, notLimited, byU32, usingExtDict, noDictIssue, 1); + result = LZ4_compress_generic(streamPtr, source, dest, inputSize, 0, notLimited, byU32, usingExtDict, noDictIssue, 1); streamPtr->dictionary = (const BYTE*)source; streamPtr->dictSize = (U32)inputSize; @@ -1087,10 +1062,17 @@ int LZ4_compress_forceExtDict (LZ4_stream_t* LZ4_dict, const char* source, char* } +/*! LZ4_saveDict() : + * If previously compressed data block is not guaranteed to remain available at its memory location, + * save it into a safer place (char* safeBuffer). + * Note : you don't need to call LZ4_loadDict() afterwards, + * dictionary is immediately usable, you can therefore call LZ4_compress_fast_continue(). + * Return : saved dictionary size in bytes (necessarily <= dictSize), or 0 if error. + */ int LZ4_saveDict (LZ4_stream_t* LZ4_dict, char* safeBuffer, int dictSize) { - LZ4_stream_t_internal* dict = (LZ4_stream_t_internal*) LZ4_dict; - const BYTE* previousDictEnd = dict->dictionary + dict->dictSize; + LZ4_stream_t_internal* const dict = &LZ4_dict->internal_donotuse; + const BYTE* const previousDictEnd = dict->dictionary + dict->dictSize; if ((U32)dictSize > 64 KB) dictSize = 64 KB; /* useless to define a dictionary > 64 KB */ if ((U32)dictSize > dict->dictSize) dictSize = dict->dictSize; @@ -1105,14 +1087,14 @@ int LZ4_saveDict (LZ4_stream_t* LZ4_dict, char* safeBuffer, int dictSize) -/******************************* +/*-***************************** * Decompression functions *******************************/ -/* - * This generic decompression function cover all use cases. - * It shall be instantiated several times, using different sets of directives - * Note that it is essential this generic function is really inlined, - * in order to remove useless branches during compilation optimization. +/*! LZ4_decompress_generic() : + * This generic decompression function cover all use cases. + * It shall be instantiated several times, using different sets of directives + * Note that it is important this generic function is really inlined, + * in order to remove useless branches during compilation optimization. */ FORCE_INLINE int LZ4_decompress_generic( const char* const source, @@ -1124,7 +1106,7 @@ FORCE_INLINE int LZ4_decompress_generic( int partialDecoding, /* full, partial */ int targetOutputSize, /* only used if partialDecoding==partial */ int dict, /* noDict, withPrefix64k, usingExtDict */ - const BYTE* const lowPrefix, /* == dest if dict == noDict */ + const BYTE* const lowPrefix, /* == dest when no prefix */ const BYTE* const dictStart, /* only if dict==usingExtDict */ const size_t dictSize /* note : = 0 if noDict */ ) @@ -1140,53 +1122,45 @@ FORCE_INLINE int LZ4_decompress_generic( const BYTE* const lowLimit = lowPrefix - dictSize; const BYTE* const dictEnd = (const BYTE*)dictStart + dictSize; - const size_t dec32table[] = {4, 1, 2, 1, 4, 4, 4, 4}; - const size_t dec64table[] = {0, 0, 0, (size_t)-1, 0, 1, 2, 3}; + const unsigned dec32table[] = {0, 1, 2, 1, 4, 4, 4, 4}; + const int dec64table[] = {0, 0, 0, -1, 0, 1, 2, 3}; const int safeDecode = (endOnInput==endOnInputSize); const int checkOffset = ((safeDecode) && (dictSize < (int)(64 KB))); /* Special cases */ - if ((partialDecoding) && (oexit> oend-MFLIMIT)) oexit = oend-MFLIMIT; /* targetOutputSize too high => decode everything */ + if ((partialDecoding) && (oexit > oend-MFLIMIT)) oexit = oend-MFLIMIT; /* targetOutputSize too high => decode everything */ if ((endOnInput) && (unlikely(outputSize==0))) return ((inputSize==1) && (*ip==0)) ? 0 : -1; /* Empty output buffer */ if ((!endOnInput) && (unlikely(outputSize==0))) return (*ip==0?1:-1); - - /* Main Loop */ - while (1) - { - unsigned token; + /* Main Loop : decode sequences */ + while (1) { size_t length; const BYTE* match; + size_t offset; /* get literal length */ - token = *ip++; - if ((length=(token>>ML_BITS)) == RUN_MASK) - { + unsigned const token = *ip++; + if ((length=(token>>ML_BITS)) == RUN_MASK) { unsigned s; - do - { + do { s = *ip++; length += s; - } - while (likely((endOnInput)?ip<iend-RUN_MASK:1) && (s==255)); - if ((safeDecode) && unlikely((size_t)(op+length)<(size_t)(op))) goto _output_error; /* overflow detection */ - if ((safeDecode) && unlikely((size_t)(ip+length)<(size_t)(ip))) goto _output_error; /* overflow detection */ + } while ( likely(endOnInput ? ip<iend-RUN_MASK : 1) & (s==255) ); + if ((safeDecode) && unlikely((uptrval)(op)+length<(uptrval)(op))) goto _output_error; /* overflow detection */ + if ((safeDecode) && unlikely((uptrval)(ip)+length<(uptrval)(ip))) goto _output_error; /* overflow detection */ } /* copy literals */ cpy = op+length; - if (((endOnInput) && ((cpy>(partialDecoding?oexit:oend-MFLIMIT)) || (ip+length>iend-(2+1+LASTLITERALS))) ) - || ((!endOnInput) && (cpy>oend-COPYLENGTH))) + if ( ((endOnInput) && ((cpy>(partialDecoding?oexit:oend-MFLIMIT)) || (ip+length>iend-(2+1+LASTLITERALS))) ) + || ((!endOnInput) && (cpy>oend-WILDCOPYLENGTH)) ) { - if (partialDecoding) - { + if (partialDecoding) { if (cpy > oend) goto _output_error; /* Error : write attempt beyond end of output buffer */ if ((endOnInput) && (ip+length > iend)) goto _output_error; /* Error : read attempt beyond end of input buffer */ - } - else - { + } else { if ((!endOnInput) && (cpy != oend)) goto _output_error; /* Error : block decoding must stop exactly there */ if ((endOnInput) && ((ip+length != iend) || (cpy > oend))) goto _output_error; /* Error : input must be consumed */ } @@ -1199,84 +1173,76 @@ FORCE_INLINE int LZ4_decompress_generic( ip += length; op = cpy; /* get offset */ - match = cpy - LZ4_readLE16(ip); ip+=2; - if ((checkOffset) && (unlikely(match < lowLimit))) goto _output_error; /* Error : offset outside destination buffer */ + offset = LZ4_readLE16(ip); ip+=2; + match = op - offset; + if ((checkOffset) && (unlikely(match < lowLimit))) goto _output_error; /* Error : offset outside buffers */ + LZ4_write32(op, (U32)offset); /* costs ~1%; silence an msan warning when offset==0 */ /* get matchlength */ length = token & ML_MASK; - if (length == ML_MASK) - { + if (length == ML_MASK) { unsigned s; - do - { - if ((endOnInput) && (ip > iend-LASTLITERALS)) goto _output_error; + do { s = *ip++; + if ((endOnInput) && (ip > iend-LASTLITERALS)) goto _output_error; length += s; } while (s==255); - if ((safeDecode) && unlikely((size_t)(op+length)<(size_t)op)) goto _output_error; /* overflow detection */ + if ((safeDecode) && unlikely((uptrval)(op)+length<(uptrval)op)) goto _output_error; /* overflow detection */ } length += MINMATCH; /* check external dictionary */ - if ((dict==usingExtDict) && (match < lowPrefix)) - { + if ((dict==usingExtDict) && (match < lowPrefix)) { if (unlikely(op+length > oend-LASTLITERALS)) goto _output_error; /* doesn't respect parsing restriction */ - if (length <= (size_t)(lowPrefix-match)) - { + if (length <= (size_t)(lowPrefix-match)) { /* match can be copied as a single segment from external dictionary */ - match = dictEnd - (lowPrefix-match); - memmove(op, match, length); op += length; - } - else - { - /* match encompass external dictionary and current segment */ - size_t copySize = (size_t)(lowPrefix-match); + memmove(op, dictEnd - (lowPrefix-match), length); + op += length; + } else { + /* match encompass external dictionary and current block */ + size_t const copySize = (size_t)(lowPrefix-match); + size_t const restSize = length - copySize; memcpy(op, dictEnd - copySize, copySize); op += copySize; - copySize = length - copySize; - if (copySize > (size_t)(op-lowPrefix)) /* overlap within current segment */ - { - BYTE* const endOfMatch = op + copySize; + if (restSize > (size_t)(op-lowPrefix)) { /* overlap copy */ + BYTE* const endOfMatch = op + restSize; const BYTE* copyFrom = lowPrefix; while (op < endOfMatch) *op++ = *copyFrom++; - } - else - { - memcpy(op, lowPrefix, copySize); - op += copySize; - } - } + } else { + memcpy(op, lowPrefix, restSize); + op += restSize; + } } continue; } - /* copy repeated sequence */ + /* copy match within block */ cpy = op + length; - if (unlikely((op-match)<8)) - { - const size_t dec64 = dec64table[op-match]; + if (unlikely(offset<8)) { + const int dec64 = dec64table[offset]; op[0] = match[0]; op[1] = match[1]; op[2] = match[2]; op[3] = match[3]; - match += dec32table[op-match]; - LZ4_copy4(op+4, match); - op += 8; match -= dec64; - } else { LZ4_copy8(op, match); op+=8; match+=8; } - - if (unlikely(cpy>oend-12)) - { - if (cpy > oend-LASTLITERALS) goto _output_error; /* Error : last LASTLITERALS bytes must be literals */ - if (op < oend-8) - { - LZ4_wildCopy(op, match, oend-8); - match += (oend-8) - op; - op = oend-8; + match += dec32table[offset]; + memcpy(op+4, match, 4); + match -= dec64; + } else { LZ4_copy8(op, match); match+=8; } + op += 8; + + if (unlikely(cpy>oend-12)) { + BYTE* const oCopyLimit = oend-(WILDCOPYLENGTH-1); + if (cpy > oend-LASTLITERALS) goto _output_error; /* Error : last LASTLITERALS bytes must be literals (uncompressed) */ + if (op < oCopyLimit) { + LZ4_wildCopy(op, match, oCopyLimit); + match += oCopyLimit - op; + op = oCopyLimit; } while (op<cpy) *op++ = *match++; + } else { + LZ4_copy8(op, match); + if (length>16) LZ4_wildCopy(op+8, match+8, cpy); } - else - LZ4_wildCopy(op, match, cpy); op=cpy; /* correction */ } @@ -1308,15 +1274,7 @@ int LZ4_decompress_fast(const char* source, char* dest, int originalSize) } -/* streaming decompression functions */ - -typedef struct -{ - const BYTE* externalDict; - size_t extDictSize; - const BYTE* prefixEnd; - size_t prefixSize; -} LZ4_streamDecode_t_internal; +/*===== streaming decompression functions =====*/ /* * If you prefer dynamic allocation methods, @@ -1335,16 +1293,16 @@ int LZ4_freeStreamDecode (LZ4_streamDecode_t* LZ4_stream) return 0; } -/* - * LZ4_setStreamDecode - * Use this function to instruct where to find the dictionary +/*! + * LZ4_setStreamDecode() : + * Use this function to instruct where to find the dictionary. * This function is not necessary if previous data is still available where it was decoded. * Loading a size of 0 is allowed (same effect as no dictionary). * Return : 1 if OK, 0 if error */ int LZ4_setStreamDecode (LZ4_streamDecode_t* LZ4_streamDecode, const char* dictionary, int dictSize) { - LZ4_streamDecode_t_internal* lz4sd = (LZ4_streamDecode_t_internal*) LZ4_streamDecode; + LZ4_streamDecode_t_internal* lz4sd = &LZ4_streamDecode->internal_donotuse; lz4sd->prefixSize = (size_t) dictSize; lz4sd->prefixEnd = (const BYTE*) dictionary + dictSize; lz4sd->externalDict = NULL; @@ -1361,20 +1319,17 @@ int LZ4_setStreamDecode (LZ4_streamDecode_t* LZ4_streamDecode, const char* dicti */ int LZ4_decompress_safe_continue (LZ4_streamDecode_t* LZ4_streamDecode, const char* source, char* dest, int compressedSize, int maxOutputSize) { - LZ4_streamDecode_t_internal* lz4sd = (LZ4_streamDecode_t_internal*) LZ4_streamDecode; + LZ4_streamDecode_t_internal* lz4sd = &LZ4_streamDecode->internal_donotuse; int result; - if (lz4sd->prefixEnd == (BYTE*)dest) - { + if (lz4sd->prefixEnd == (BYTE*)dest) { result = LZ4_decompress_generic(source, dest, compressedSize, maxOutputSize, endOnInputSize, full, 0, usingExtDict, lz4sd->prefixEnd - lz4sd->prefixSize, lz4sd->externalDict, lz4sd->extDictSize); if (result <= 0) return result; lz4sd->prefixSize += result; lz4sd->prefixEnd += result; - } - else - { + } else { lz4sd->extDictSize = lz4sd->prefixSize; lz4sd->externalDict = lz4sd->prefixEnd - lz4sd->extDictSize; result = LZ4_decompress_generic(source, dest, compressedSize, maxOutputSize, @@ -1390,22 +1345,19 @@ int LZ4_decompress_safe_continue (LZ4_streamDecode_t* LZ4_streamDecode, const ch int LZ4_decompress_fast_continue (LZ4_streamDecode_t* LZ4_streamDecode, const char* source, char* dest, int originalSize) { - LZ4_streamDecode_t_internal* lz4sd = (LZ4_streamDecode_t_internal*) LZ4_streamDecode; + LZ4_streamDecode_t_internal* lz4sd = &LZ4_streamDecode->internal_donotuse; int result; - if (lz4sd->prefixEnd == (BYTE*)dest) - { + if (lz4sd->prefixEnd == (BYTE*)dest) { result = LZ4_decompress_generic(source, dest, 0, originalSize, endOnOutputSize, full, 0, usingExtDict, lz4sd->prefixEnd - lz4sd->prefixSize, lz4sd->externalDict, lz4sd->extDictSize); if (result <= 0) return result; lz4sd->prefixSize += originalSize; lz4sd->prefixEnd += originalSize; - } - else - { + } else { lz4sd->extDictSize = lz4sd->prefixSize; - lz4sd->externalDict = (BYTE*)dest - lz4sd->extDictSize; + lz4sd->externalDict = lz4sd->prefixEnd - lz4sd->extDictSize; result = LZ4_decompress_generic(source, dest, 0, originalSize, endOnOutputSize, full, 0, usingExtDict, (BYTE*)dest, lz4sd->externalDict, lz4sd->extDictSize); @@ -1429,8 +1381,7 @@ FORCE_INLINE int LZ4_decompress_usingDict_generic(const char* source, char* dest { if (dictSize==0) return LZ4_decompress_generic(source, dest, compressedSize, maxOutputSize, safe, full, 0, noDict, (BYTE*)dest, NULL, 0); - if (dictStart+dictSize == dest) - { + if (dictStart+dictSize == dest) { if (dictSize >= (int)(64 KB - 1)) return LZ4_decompress_generic(source, dest, compressedSize, maxOutputSize, safe, full, 0, withPrefix64k, (BYTE*)dest-64 KB, NULL, 0); return LZ4_decompress_generic(source, dest, compressedSize, maxOutputSize, safe, full, 0, noDict, (BYTE*)dest-dictSize, NULL, 0); @@ -1455,7 +1406,7 @@ int LZ4_decompress_safe_forceExtDict(const char* source, char* dest, int compres } -/*************************************************** +/*=************************************************* * Obsolete Functions ***************************************************/ /* obsolete compression functions */ @@ -1480,29 +1431,29 @@ int LZ4_uncompress_unknownOutputSize (const char* source, char* dest, int isize, int LZ4_sizeofStreamState() { return LZ4_STREAMSIZE; } -static void LZ4_init(LZ4_stream_t_internal* lz4ds, BYTE* base) +static void LZ4_init(LZ4_stream_t* lz4ds, BYTE* base) { - MEM_INIT(lz4ds, 0, LZ4_STREAMSIZE); - lz4ds->bufferStart = base; + MEM_INIT(lz4ds, 0, sizeof(LZ4_stream_t)); + lz4ds->internal_donotuse.bufferStart = base; } int LZ4_resetStreamState(void* state, char* inputBuffer) { - if ((((size_t)state) & 3) != 0) return 1; /* Error : pointer is not aligned on 4-bytes boundary */ - LZ4_init((LZ4_stream_t_internal*)state, (BYTE*)inputBuffer); + if ((((uptrval)state) & 3) != 0) return 1; /* Error : pointer is not aligned on 4-bytes boundary */ + LZ4_init((LZ4_stream_t*)state, (BYTE*)inputBuffer); return 0; } void* LZ4_create (char* inputBuffer) { - void* lz4ds = ALLOCATOR(8, LZ4_STREAMSIZE_U64); - LZ4_init ((LZ4_stream_t_internal*)lz4ds, (BYTE*)inputBuffer); + LZ4_stream_t* lz4ds = (LZ4_stream_t*)ALLOCATOR(8, sizeof(LZ4_stream_t)); + LZ4_init (lz4ds, (BYTE*)inputBuffer); return lz4ds; } char* LZ4_slideInputBuffer (void* LZ4_Data) { - LZ4_stream_t_internal* ctx = (LZ4_stream_t_internal*)LZ4_Data; + LZ4_stream_t_internal* ctx = &((LZ4_stream_t*)LZ4_Data)->internal_donotuse; int dictSize = LZ4_saveDict((LZ4_stream_t*)LZ4_Data, (char*)ctx->bufferStart, 64 KB); return (char*)(ctx->bufferStart + dictSize); } @@ -1520,5 +1471,4 @@ int LZ4_decompress_fast_withPrefix64k(const char* source, char* dest, int origin } #endif /* LZ4_COMMONDEFS_ONLY */ - #endif /* NEED_COMPAT_LZ4 */ diff --git a/src/compat/compat-lz4.h b/src/compat/compat-lz4.h index 3e74002..0aae19c 100644 --- a/src/compat/compat-lz4.h +++ b/src/compat/compat-lz4.h @@ -1,7 +1,7 @@ /* - LZ4 - Fast LZ compression algorithm - Header File - Copyright (C) 2011-2015, Yann Collet. + * LZ4 - Fast LZ compression algorithm + * Header File + * Copyright (C) 2011-2016, Yann Collet. BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php) @@ -29,34 +29,79 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. You can contact the author at : - - LZ4 source repository : https://github.com/Cyan4973/lz4 - - LZ4 public forum : https://groups.google.com/forum/#!forum/lz4c + - LZ4 homepage : http://www.lz4.org + - LZ4 source repository : https://github.com/lz4/lz4 */ -#pragma once +#ifndef LZ4_H_2983827168210 +#define LZ4_H_2983827168210 #if defined (__cplusplus) extern "C" { #endif +/* --- Dependency --- */ +#include <stddef.h> /* size_t */ + + +/** + Introduction + + LZ4 is lossless compression algorithm, providing compression speed at 400 MB/s per core, + scalable with multi-cores CPU. It features an extremely fast decoder, with speed in + multiple GB/s per core, typically reaching RAM speed limits on multi-core systems. + + The LZ4 compression library provides in-memory compression and decompression functions. + Compression can be done in: + - a single step (described as Simple Functions) + - a single step, reusing a context (described in Advanced Functions) + - unbounded multiple steps (described as Streaming compression) + + lz4.h provides block compression functions. It gives full buffer control to user. + Decompressing an lz4-compressed block also requires metadata (such as compressed size). + Each application is free to encode such metadata in whichever way it wants. + + An additional format, called LZ4 frame specification (doc/lz4_Frame_format.md), + take care of encoding standard metadata alongside LZ4-compressed blocks. + If your application requires interoperability, it's recommended to use it. + A library is provided to take care of it, see lz4frame.h. +*/ + +/*^*************************************************************** +* Export parameters +*****************************************************************/ /* - * lz4.h provides block compression functions, and gives full buffer control to programmer. - * If you need to generate inter-operable compressed data (respecting LZ4 frame specification), - * and can let the library handle its own memory, please use lz4frame.h instead. +* LZ4_DLL_EXPORT : +* Enable exporting of functions when building a Windows DLL */ +#if defined(LZ4_DLL_EXPORT) && (LZ4_DLL_EXPORT==1) +# define LZ4LIB_API __declspec(dllexport) +#elif defined(LZ4_DLL_IMPORT) && (LZ4_DLL_IMPORT==1) +# define LZ4LIB_API __declspec(dllimport) /* It isn't required but allows to generate better code, saving a function pointer load from the IAT and an indirect jump.*/ +#else +# define LZ4LIB_API +#endif -/************************************** -* Version -**************************************/ + +/*========== Version =========== */ #define LZ4_VERSION_MAJOR 1 /* for breaking interface changes */ #define LZ4_VERSION_MINOR 7 /* for new (non-breaking) interface capabilities */ -#define LZ4_VERSION_RELEASE 1 /* for tweaks, bug-fixes, or development */ +#define LZ4_VERSION_RELEASE 5 /* for tweaks, bug-fixes, or development */ + #define LZ4_VERSION_NUMBER (LZ4_VERSION_MAJOR *100*100 + LZ4_VERSION_MINOR *100 + LZ4_VERSION_RELEASE) -int LZ4_versionNumber (void); -/************************************** +#define LZ4_LIB_VERSION LZ4_VERSION_MAJOR.LZ4_VERSION_MINOR.LZ4_VERSION_RELEASE +#define LZ4_QUOTE(str) #str +#define LZ4_EXPAND_AND_QUOTE(str) LZ4_QUOTE(str) +#define LZ4_VERSION_STRING LZ4_EXPAND_AND_QUOTE(LZ4_LIB_VERSION) + +LZ4LIB_API int LZ4_versionNumber (void); +LZ4LIB_API const char* LZ4_versionString (void); + + +/*-************************************ * Tuning parameter **************************************/ -/* +/*! * LZ4_MEMORY_USAGE : * Memory usage formula : N->2^N Bytes (examples : 10 -> 1KB; 12 -> 4KB ; 16 -> 64KB; 20 -> 1MB; etc.) * Increasing memory usage improves compression ratio @@ -66,15 +111,10 @@ int LZ4_versionNumber (void); #define LZ4_MEMORY_USAGE 14 -/************************************** +/*-************************************ * Simple Functions **************************************/ - -int LZ4_compress_default(const char* source, char* dest, int sourceSize, int maxDestSize); -int LZ4_decompress_safe (const char* source, char* dest, int compressedSize, int maxDecompressedSize); - -/* -LZ4_compress_default() : +/*! LZ4_compress_default() : Compresses 'sourceSize' bytes from buffer 'source' into already allocated 'dest' buffer of size 'maxDestSize'. Compression is guaranteed to succeed if 'maxDestSize' >= LZ4_compressBound(sourceSize). @@ -86,9 +126,10 @@ LZ4_compress_default() : sourceSize : Max supported value is LZ4_MAX_INPUT_VALUE maxDestSize : full or partial size of buffer 'dest' (which must be already allocated) return : the number of bytes written into buffer 'dest' (necessarily <= maxOutputSize) - or 0 if compression fails + or 0 if compression fails */ +LZ4LIB_API int LZ4_compress_default(const char* source, char* dest, int sourceSize, int maxDestSize); -LZ4_decompress_safe() : +/*! LZ4_decompress_safe() : compressedSize : is the precise full size of the compressed block. maxDecompressedSize : is the size of destination buffer, which must be already allocated. return : the number of bytes decompressed into destination buffer (necessarily <= maxDecompressedSize) @@ -97,15 +138,16 @@ LZ4_decompress_safe() : This function is protected against buffer overflow exploits, including malicious data packets. It never writes outside output buffer, nor reads outside input buffer. */ +LZ4LIB_API int LZ4_decompress_safe (const char* source, char* dest, int compressedSize, int maxDecompressedSize); -/************************************** +/*-************************************ * Advanced Functions **************************************/ #define LZ4_MAX_INPUT_SIZE 0x7E000000 /* 2 113 929 216 bytes */ #define LZ4_COMPRESSBOUND(isize) ((unsigned)(isize) > (unsigned)LZ4_MAX_INPUT_SIZE ? 0 : (isize) + ((isize)/255) + 16) -/* +/*! LZ4_compressBound() : Provides the maximum size that LZ4 compression may output in a "worst case" scenario (input data not compressible) This function is primarily useful for memory allocation purposes (destination buffer size). @@ -115,9 +157,9 @@ LZ4_compressBound() : return : maximum output size in a "worst case" scenario or 0, if input size is too large ( > LZ4_MAX_INPUT_SIZE) */ -int LZ4_compressBound(int inputSize); +LZ4LIB_API int LZ4_compressBound(int inputSize); -/* +/*! LZ4_compress_fast() : Same as LZ4_compress_default(), but allows to select an "acceleration" factor. The larger the acceleration value, the faster the algorithm, but also the lesser the compression. @@ -125,21 +167,21 @@ LZ4_compress_fast() : An acceleration value of "1" is the same as regular LZ4_compress_default() Values <= 0 will be replaced by ACCELERATION_DEFAULT (see lz4.c), which is 1. */ -int LZ4_compress_fast (const char* source, char* dest, int sourceSize, int maxDestSize, int acceleration); +LZ4LIB_API int LZ4_compress_fast (const char* source, char* dest, int sourceSize, int maxDestSize, int acceleration); -/* +/*! LZ4_compress_fast_extState() : Same compression function, just using an externally allocated memory space to store compression state. Use LZ4_sizeofState() to know how much memory must be allocated, and allocate it on 8-bytes boundaries (using malloc() typically). Then, provide it as 'void* state' to compression function. */ -int LZ4_sizeofState(void); -int LZ4_compress_fast_extState (void* state, const char* source, char* dest, int inputSize, int maxDestSize, int acceleration); +LZ4LIB_API int LZ4_sizeofState(void); +LZ4LIB_API int LZ4_compress_fast_extState (void* state, const char* source, char* dest, int inputSize, int maxDestSize, int acceleration); -/* +/*! LZ4_compress_destSize() : Reverse the logic, by compressing as much data as possible from 'source' buffer into already allocated buffer 'dest' of size 'targetDestSize'. @@ -150,10 +192,10 @@ LZ4_compress_destSize() : return : Nb bytes written into 'dest' (necessarily <= targetDestSize) or 0 if compression fails */ -int LZ4_compress_destSize (const char* source, char* dest, int* sourceSizePtr, int targetDestSize); +LZ4LIB_API int LZ4_compress_destSize (const char* source, char* dest, int* sourceSizePtr, int targetDestSize); -/* +/*! LZ4_decompress_fast() : originalSize : is the original and therefore uncompressed size return : the number of bytes read from the source buffer (in other words, the compressed size) @@ -164,9 +206,9 @@ LZ4_decompress_fast() : However, it does not provide any protection against intentionally modified data stream (malicious input). Use this function in trusted environment only (data to decode comes from a trusted source). */ -int LZ4_decompress_fast (const char* source, char* dest, int originalSize); +LZ4LIB_API int LZ4_decompress_fast (const char* source, char* dest, int originalSize); -/* +/*! LZ4_decompress_safe_partial() : This function decompress a compressed block of size 'compressedSize' at position 'source' into destination buffer 'dest' of size 'maxDecompressedSize'. @@ -178,98 +220,73 @@ LZ4_decompress_safe_partial() : If the source stream is detected malformed, the function will stop decoding and return a negative result. This function never writes outside of output buffer, and never reads outside of input buffer. It is therefore protected against malicious data packets */ -int LZ4_decompress_safe_partial (const char* source, char* dest, int compressedSize, int targetOutputSize, int maxDecompressedSize); +LZ4LIB_API int LZ4_decompress_safe_partial (const char* source, char* dest, int compressedSize, int targetOutputSize, int maxDecompressedSize); -/*********************************************** +/*-********************************************* * Streaming Compression Functions ***********************************************/ -#define LZ4_STREAMSIZE_U64 ((1 << (LZ4_MEMORY_USAGE-3)) + 4) -#define LZ4_STREAMSIZE (LZ4_STREAMSIZE_U64 * sizeof(long long)) -/* - * LZ4_stream_t - * information structure to track an LZ4 stream. - * important : init this structure content before first use ! - * note : only allocated directly the structure if you are statically linking LZ4 - * If you are using liblz4 as a DLL, please use below construction methods instead. - */ -typedef struct { long long table[LZ4_STREAMSIZE_U64]; } LZ4_stream_t; +typedef union LZ4_stream_u LZ4_stream_t; /* incomplete type (defined later) */ -/* - * LZ4_resetStream - * Use this function to init an allocated LZ4_stream_t structure +/*! LZ4_createStream() and LZ4_freeStream() : + * LZ4_createStream() will allocate and initialize an `LZ4_stream_t` structure. + * LZ4_freeStream() releases its memory. */ -void LZ4_resetStream (LZ4_stream_t* streamPtr); +LZ4LIB_API LZ4_stream_t* LZ4_createStream(void); +LZ4LIB_API int LZ4_freeStream (LZ4_stream_t* streamPtr); -/* - * LZ4_createStream will allocate and initialize an LZ4_stream_t structure - * LZ4_freeStream releases its memory. - * In the context of a DLL (liblz4), please use these methods rather than the static struct. - * They are more future proof, in case of a change of LZ4_stream_t size. +/*! LZ4_resetStream() : + * An LZ4_stream_t structure can be allocated once and re-used multiple times. + * Use this function to init an allocated `LZ4_stream_t` structure and start a new compression. */ -LZ4_stream_t* LZ4_createStream(void); -int LZ4_freeStream (LZ4_stream_t* streamPtr); +LZ4LIB_API void LZ4_resetStream (LZ4_stream_t* streamPtr); -/* - * LZ4_loadDict - * Use this function to load a static dictionary into LZ4_stream. - * Any previous data will be forgotten, only 'dictionary' will remain in memory. - * Loading a size of 0 is allowed. - * Return : dictionary size, in bytes (necessarily <= 64 KB) +/*! LZ4_loadDict() : + * Use this function to load a static dictionary into LZ4_stream. + * Any previous data will be forgotten, only 'dictionary' will remain in memory. + * Loading a size of 0 is allowed. + * Return : dictionary size, in bytes (necessarily <= 64 KB) */ -int LZ4_loadDict (LZ4_stream_t* streamPtr, const char* dictionary, int dictSize); - -/* - * LZ4_compress_fast_continue - * Compress buffer content 'src', using data from previously compressed blocks as dictionary to improve compression ratio. - * Important : Previous data blocks are assumed to still be present and unmodified ! - * 'dst' buffer must be already allocated. - * If maxDstSize >= LZ4_compressBound(srcSize), compression is guaranteed to succeed, and runs faster. - * If not, and if compressed data cannot fit into 'dst' buffer size, compression stops, and function returns a zero. +LZ4LIB_API int LZ4_loadDict (LZ4_stream_t* streamPtr, const char* dictionary, int dictSize); + +/*! LZ4_compress_fast_continue() : + * Compress buffer content 'src', using data from previously compressed blocks as dictionary to improve compression ratio. + * Important : Previous data blocks are assumed to still be present and unmodified ! + * 'dst' buffer must be already allocated. + * If maxDstSize >= LZ4_compressBound(srcSize), compression is guaranteed to succeed, and runs faster. + * If not, and if compressed data cannot fit into 'dst' buffer size, compression stops, and function returns a zero. */ -int LZ4_compress_fast_continue (LZ4_stream_t* streamPtr, const char* src, char* dst, int srcSize, int maxDstSize, int acceleration); - -/* - * LZ4_saveDict - * If previously compressed data block is not guaranteed to remain available at its memory location - * save it into a safer place (char* safeBuffer) - * Note : you don't need to call LZ4_loadDict() afterwards, - * dictionary is immediately usable, you can therefore call LZ4_compress_fast_continue() - * Return : saved dictionary size in bytes (necessarily <= dictSize), or 0 if error +LZ4LIB_API int LZ4_compress_fast_continue (LZ4_stream_t* streamPtr, const char* src, char* dst, int srcSize, int maxDstSize, int acceleration); + +/*! LZ4_saveDict() : + * If previously compressed data block is not guaranteed to remain available at its memory location, + * save it into a safer place (char* safeBuffer). + * Note : you don't need to call LZ4_loadDict() afterwards, + * dictionary is immediately usable, you can therefore call LZ4_compress_fast_continue(). + * Return : saved dictionary size in bytes (necessarily <= dictSize), or 0 if error. */ -int LZ4_saveDict (LZ4_stream_t* streamPtr, char* safeBuffer, int dictSize); +LZ4LIB_API int LZ4_saveDict (LZ4_stream_t* streamPtr, char* safeBuffer, int dictSize); -/************************************************ +/*-********************************************** * Streaming Decompression Functions +* Bufferless synchronous API ************************************************/ +typedef union LZ4_streamDecode_u LZ4_streamDecode_t; /* incomplete type (defined later) */ -#define LZ4_STREAMDECODESIZE_U64 4 -#define LZ4_STREAMDECODESIZE (LZ4_STREAMDECODESIZE_U64 * sizeof(unsigned long long)) -typedef struct { unsigned long long table[LZ4_STREAMDECODESIZE_U64]; } LZ4_streamDecode_t; -/* - * LZ4_streamDecode_t - * information structure to track an LZ4 stream. - * init this structure content using LZ4_setStreamDecode or memset() before first use ! - * - * In the context of a DLL (liblz4) please prefer usage of construction methods below. - * They are more future proof, in case of a change of LZ4_streamDecode_t size in the future. - * LZ4_createStreamDecode will allocate and initialize an LZ4_streamDecode_t structure - * LZ4_freeStreamDecode releases its memory. - */ -LZ4_streamDecode_t* LZ4_createStreamDecode(void); -int LZ4_freeStreamDecode (LZ4_streamDecode_t* LZ4_stream); +/* creation / destruction of streaming decompression tracking structure */ +LZ4LIB_API LZ4_streamDecode_t* LZ4_createStreamDecode(void); +LZ4LIB_API int LZ4_freeStreamDecode (LZ4_streamDecode_t* LZ4_stream); -/* - * LZ4_setStreamDecode - * Use this function to instruct where to find the dictionary. - * Setting a size of 0 is allowed (same effect as reset). - * Return : 1 if OK, 0 if error +/*! LZ4_setStreamDecode() : + * Use this function to instruct where to find the dictionary. + * Setting a size of 0 is allowed (same effect as reset). + * @return : 1 if OK, 0 if error */ -int LZ4_setStreamDecode (LZ4_streamDecode_t* LZ4_streamDecode, const char* dictionary, int dictSize); +LZ4LIB_API int LZ4_setStreamDecode (LZ4_streamDecode_t* LZ4_streamDecode, const char* dictionary, int dictSize); -/* -*_continue() : +/*! +LZ4_decompress_*_continue() : These decoding functions allow decompression of multiple blocks in "streaming" mode. Previously decoded blocks *must* remain available at the memory position where they were decoded (up to 64 KB) In the case of a ring buffers, decoding buffer must be either : @@ -285,35 +302,120 @@ int LZ4_setStreamDecode (LZ4_streamDecode_t* LZ4_streamDecode, const char* dicti Whenever these conditions are not possible, save the last 64KB of decoded data into a safe buffer, and indicate where it is saved using LZ4_setStreamDecode() */ -int LZ4_decompress_safe_continue (LZ4_streamDecode_t* LZ4_streamDecode, const char* source, char* dest, int compressedSize, int maxDecompressedSize); -int LZ4_decompress_fast_continue (LZ4_streamDecode_t* LZ4_streamDecode, const char* source, char* dest, int originalSize); +LZ4LIB_API int LZ4_decompress_safe_continue (LZ4_streamDecode_t* LZ4_streamDecode, const char* source, char* dest, int compressedSize, int maxDecompressedSize); +LZ4LIB_API int LZ4_decompress_fast_continue (LZ4_streamDecode_t* LZ4_streamDecode, const char* source, char* dest, int originalSize); -/* -Advanced decoding functions : -*_usingDict() : - These decoding functions work the same as - a combination of LZ4_setStreamDecode() followed by LZ4_decompress_x_continue() - They are stand-alone. They don't need nor update an LZ4_streamDecode_t structure. -*/ -int LZ4_decompress_safe_usingDict (const char* source, char* dest, int compressedSize, int maxDecompressedSize, const char* dictStart, int dictSize); -int LZ4_decompress_fast_usingDict (const char* source, char* dest, int originalSize, const char* dictStart, int dictSize); +/*! LZ4_decompress_*_usingDict() : + * These decoding functions work the same as + * a combination of LZ4_setStreamDecode() followed by LZ4_decompress_*_continue() + * They are stand-alone, and don't need an LZ4_streamDecode_t structure. + */ +LZ4LIB_API int LZ4_decompress_safe_usingDict (const char* source, char* dest, int compressedSize, int maxDecompressedSize, const char* dictStart, int dictSize); +LZ4LIB_API int LZ4_decompress_fast_usingDict (const char* source, char* dest, int originalSize, const char* dictStart, int dictSize); + + +/*^********************************************** + * !!!!!! STATIC LINKING ONLY !!!!!! + ***********************************************/ +/*-************************************ + * Private definitions + ************************************** + * Do not use these definitions. + * They are exposed to allow static allocation of `LZ4_stream_t` and `LZ4_streamDecode_t`. + * Using these definitions will expose code to API and/or ABI break in future versions of the library. + **************************************/ +#define LZ4_HASHLOG (LZ4_MEMORY_USAGE-2) +#define LZ4_HASHTABLESIZE (1 << LZ4_MEMORY_USAGE) +#define LZ4_HASH_SIZE_U32 (1 << LZ4_HASHLOG) /* required as macro for static allocation */ + +#if defined(__cplusplus) || (defined (__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) /* C99 */) +#include <stdint.h> + +typedef struct { + uint32_t hashTable[LZ4_HASH_SIZE_U32]; + uint32_t currentOffset; + uint32_t initCheck; + const uint8_t* dictionary; + uint8_t* bufferStart; /* obsolete, used for slideInputBuffer */ + uint32_t dictSize; +} LZ4_stream_t_internal; + +typedef struct { + const uint8_t* externalDict; + size_t extDictSize; + const uint8_t* prefixEnd; + size_t prefixSize; +} LZ4_streamDecode_t_internal; + +#else + +typedef struct { + unsigned int hashTable[LZ4_HASH_SIZE_U32]; + unsigned int currentOffset; + unsigned int initCheck; + const unsigned char* dictionary; + unsigned char* bufferStart; /* obsolete, used for slideInputBuffer */ + unsigned int dictSize; +} LZ4_stream_t_internal; + +typedef struct { + const unsigned char* externalDict; + size_t extDictSize; + const unsigned char* prefixEnd; + size_t prefixSize; +} LZ4_streamDecode_t_internal; + +#endif +/*! + * LZ4_stream_t : + * information structure to track an LZ4 stream. + * init this structure before first use. + * note : only use in association with static linking ! + * this definition is not API/ABI safe, + * and may change in a future version ! + */ +#define LZ4_STREAMSIZE_U64 ((1 << (LZ4_MEMORY_USAGE-3)) + 4) +#define LZ4_STREAMSIZE (LZ4_STREAMSIZE_U64 * sizeof(unsigned long long)) +union LZ4_stream_u { + unsigned long long table[LZ4_STREAMSIZE_U64]; + LZ4_stream_t_internal internal_donotuse; +} ; /* previously typedef'd to LZ4_stream_t */ + + +/*! + * LZ4_streamDecode_t : + * information structure to track an LZ4 stream during decompression. + * init this structure using LZ4_setStreamDecode (or memset()) before first use + * note : only use in association with static linking ! + * this definition is not API/ABI safe, + * and may change in a future version ! + */ +#define LZ4_STREAMDECODESIZE_U64 4 +#define LZ4_STREAMDECODESIZE (LZ4_STREAMDECODESIZE_U64 * sizeof(unsigned long long)) +union LZ4_streamDecode_u { + unsigned long long table[LZ4_STREAMDECODESIZE_U64]; + LZ4_streamDecode_t_internal internal_donotuse; +} ; /* previously typedef'd to LZ4_streamDecode_t */ -/************************************** +/*=************************************ * Obsolete Functions **************************************/ -/* Deprecate Warnings */ -/* Should these warnings messages be a problem, +/* Deprecation warnings */ +/* Should these warnings be a problem, it is generally possible to disable them, - with -Wno-deprecated-declarations for gcc - or _CRT_SECURE_NO_WARNINGS in Visual for example. - You can also define LZ4_DEPRECATE_WARNING_DEFBLOCK. */ -#ifndef LZ4_DEPRECATE_WARNING_DEFBLOCK -# define LZ4_DEPRECATE_WARNING_DEFBLOCK + typically with -Wno-deprecated-declarations for gcc + or _CRT_SECURE_NO_WARNINGS in Visual. + Otherwise, it's also possible to define LZ4_DISABLE_DEPRECATE_WARNINGS */ +#ifdef LZ4_DISABLE_DEPRECATE_WARNINGS +# define LZ4_DEPRECATED(message) /* disable deprecation warnings */ +#else # define LZ4_GCC_VERSION (__GNUC__ * 100 + __GNUC_MINOR__) -# if (LZ4_GCC_VERSION >= 405) || defined(__clang__) +# if defined (__cplusplus) && (__cplusplus >= 201402) /* C++14 or greater */ +# define LZ4_DEPRECATED(message) [[deprecated(message)]] +# elif (LZ4_GCC_VERSION >= 405) || defined(__clang__) # define LZ4_DEPRECATED(message) __attribute__((deprecated(message))) # elif (LZ4_GCC_VERSION >= 301) # define LZ4_DEPRECATED(message) __attribute__((deprecated)) @@ -323,20 +425,19 @@ int LZ4_decompress_fast_usingDict (const char* source, char* dest, int originalS # pragma message("WARNING: You need to implement LZ4_DEPRECATED for this compiler") # define LZ4_DEPRECATED(message) # endif -#endif /* LZ4_DEPRECATE_WARNING_DEFBLOCK */ +#endif /* LZ4_DISABLE_DEPRECATE_WARNINGS */ /* Obsolete compression functions */ -/* These functions are planned to start generate warnings by r131 approximately */ -int LZ4_compress (const char* source, char* dest, int sourceSize); -int LZ4_compress_limitedOutput (const char* source, char* dest, int sourceSize, int maxOutputSize); -int LZ4_compress_withState (void* state, const char* source, char* dest, int inputSize); -int LZ4_compress_limitedOutput_withState (void* state, const char* source, char* dest, int inputSize, int maxOutputSize); -int LZ4_compress_continue (LZ4_stream_t* LZ4_streamPtr, const char* source, char* dest, int inputSize); -int LZ4_compress_limitedOutput_continue (LZ4_stream_t* LZ4_streamPtr, const char* source, char* dest, int inputSize, int maxOutputSize); +LZ4_DEPRECATED("use LZ4_compress_default() instead") int LZ4_compress (const char* source, char* dest, int sourceSize); +LZ4_DEPRECATED("use LZ4_compress_default() instead") int LZ4_compress_limitedOutput (const char* source, char* dest, int sourceSize, int maxOutputSize); +LZ4_DEPRECATED("use LZ4_compress_fast_extState() instead") int LZ4_compress_withState (void* state, const char* source, char* dest, int inputSize); +LZ4_DEPRECATED("use LZ4_compress_fast_extState() instead") int LZ4_compress_limitedOutput_withState (void* state, const char* source, char* dest, int inputSize, int maxOutputSize); +LZ4_DEPRECATED("use LZ4_compress_fast_continue() instead") int LZ4_compress_continue (LZ4_stream_t* LZ4_streamPtr, const char* source, char* dest, int inputSize); +LZ4_DEPRECATED("use LZ4_compress_fast_continue() instead") int LZ4_compress_limitedOutput_continue (LZ4_stream_t* LZ4_streamPtr, const char* source, char* dest, int inputSize, int maxOutputSize); /* Obsolete decompression functions */ /* These function names are completely deprecated and must no longer be used. - They are only provided here for compatibility with older programs. + They are only provided in lz4.c for compatibility with older programs. - LZ4_uncompress is the same as LZ4_decompress_fast - LZ4_uncompress_unknownOutputSize is the same as LZ4_decompress_safe These function prototypes are now disabled; uncomment them only if you really need them. @@ -358,3 +459,5 @@ LZ4_DEPRECATED("use LZ4_decompress_fast_usingDict() instead") int LZ4_decompress #if defined (__cplusplus) } #endif + +#endif /* LZ4_H_2983827168210 */ diff --git a/src/openvpn/Makefile.am b/src/openvpn/Makefile.am index fcc22d6..f3bf52f 100644 --- a/src/openvpn/Makefile.am +++ b/src/openvpn/Makefile.am @@ -5,7 +5,7 @@ # packet encryption, packet authentication, and # packet compression. # -# Copyright (C) 2002-2017 OpenVPN Technologies, Inc. <sales@openvpn.net> +# Copyright (C) 2002-2018 OpenVPN Inc <sales@openvpn.net> # Copyright (C) 2006-2012 Alon Bar-Lev <alon.barlev@gmail.com> # @@ -132,5 +132,5 @@ openvpn_LDADD = \ $(OPTIONAL_DL_LIBS) if WIN32 openvpn_SOURCES += openvpn_win32_resources.rc block_dns.c block_dns.h -openvpn_LDADD += -lgdi32 -lws2_32 -lwininet -lcrypt32 -liphlpapi -lwinmm -lfwpuclnt -lrpcrt4 +openvpn_LDADD += -lgdi32 -lws2_32 -lwininet -lcrypt32 -liphlpapi -lwinmm -lfwpuclnt -lrpcrt4 -lncrypt endif diff --git a/src/openvpn/Makefile.in b/src/openvpn/Makefile.in index ca4635b..69fa9c8 100644 --- a/src/openvpn/Makefile.in +++ b/src/openvpn/Makefile.in @@ -21,7 +21,7 @@ # packet encryption, packet authentication, and # packet compression. # -# Copyright (C) 2002-2017 OpenVPN Technologies, Inc. <sales@openvpn.net> +# Copyright (C) 2002-2018 OpenVPN Inc <sales@openvpn.net> # Copyright (C) 2006-2012 Alon Bar-Lev <alon.barlev@gmail.com> # @@ -115,7 +115,7 @@ host_triplet = @host@ @WIN32_TRUE@am__append_1 = -municode -UUNICODE sbin_PROGRAMS = openvpn$(EXEEXT) @WIN32_TRUE@am__append_2 = openvpn_win32_resources.rc block_dns.c block_dns.h -@WIN32_TRUE@am__append_3 = -lgdi32 -lws2_32 -lwininet -lcrypt32 -liphlpapi -lwinmm -lfwpuclnt -lrpcrt4 +@WIN32_TRUE@am__append_3 = -lgdi32 -lws2_32 -lwininet -lcrypt32 -liphlpapi -lwinmm -lfwpuclnt -lrpcrt4 -lncrypt subdir = src/openvpn ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/m4/ax_emptyarray.m4 \ @@ -434,6 +434,7 @@ plugindir = @plugindir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ +runstatedir = @runstatedir@ sampledir = @sampledir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ diff --git a/src/openvpn/argv.c b/src/openvpn/argv.c index a71d261..124e1c4 100644 --- a/src/openvpn/argv.c +++ b/src/openvpn/argv.c @@ -5,7 +5,7 @@ * packet encryption, packet authentication, and * packet compression. * - * Copyright (C) 2002-2017 OpenVPN Technologies, Inc. <sales@openvpn.net> + * Copyright (C) 2002-2018 OpenVPN Inc <sales@openvpn.net> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 @@ -36,6 +36,7 @@ #include "syshead.h" #include "argv.h" +#include "integer.h" #include "options.h" static void diff --git a/src/openvpn/argv.h b/src/openvpn/argv.h index 7d0754c..9d9f387 100644 --- a/src/openvpn/argv.h +++ b/src/openvpn/argv.h @@ -5,7 +5,7 @@ * packet encryption, packet authentication, and * packet compression. * - * Copyright (C) 2002-2017 OpenVPN Technologies, Inc. <sales@openvpn.net> + * Copyright (C) 2002-2018 OpenVPN Inc <sales@openvpn.net> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 diff --git a/src/openvpn/basic.h b/src/openvpn/basic.h index 3aa69ca..eb9f211 100644 --- a/src/openvpn/basic.h +++ b/src/openvpn/basic.h @@ -5,7 +5,7 @@ * packet encryption, packet authentication, and * packet compression. * - * Copyright (C) 2002-2017 OpenVPN Technologies, Inc. <sales@openvpn.net> + * Copyright (C) 2002-2018 OpenVPN Inc <sales@openvpn.net> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 diff --git a/src/openvpn/block_dns.c b/src/openvpn/block_dns.c index d43cbcf..889d6bb 100644 --- a/src/openvpn/block_dns.c +++ b/src/openvpn/block_dns.c @@ -5,7 +5,7 @@ * packet encryption, packet authentication, and * packet compression. * - * Copyright (C) 2002-2017 OpenVPN Technologies, Inc. <sales@openvpn.net> + * Copyright (C) 2002-2018 OpenVPN Inc <sales@openvpn.net> * 2015-2016 <iam@valdikss.org.ru> * 2016 Selva Nair <selva.nair@gmail.com> * @@ -344,33 +344,43 @@ delete_block_dns_filters(HANDLE engine_handle) } /* - * Returns interface metric value for specified interface index. + * Return interface metric value for the specified interface index. * * Arguments: * index : The index of TAP adapter. * family : Address family (AF_INET for IPv4 and AF_INET6 for IPv6). - * Returns positive metric value or zero for automatic metric on success, - * a less then zero error code on failure. + * is_auto : On return set to true if automatic metric is in use. + * Unused if NULL. + * + * Returns positive metric value or -1 on error. */ - int -get_interface_metric(const NET_IFINDEX index, const ADDRESS_FAMILY family) +get_interface_metric(const NET_IFINDEX index, const ADDRESS_FAMILY family, int *is_auto) { DWORD err = 0; MIB_IPINTERFACE_ROW ipiface; InitializeIpInterfaceEntry(&ipiface); ipiface.Family = family; ipiface.InterfaceIndex = index; + + if (is_auto) + { + *is_auto = 0; + } err = GetIpInterfaceEntry(&ipiface); - if (err == NO_ERROR) + + /* On Windows metric is never > INT_MAX so return value of int is ok. + * But we check for overflow nevertheless. + */ + if (err == NO_ERROR && ipiface.Metric <= INT_MAX) { - if (ipiface.UseAutomaticMetric) + if (is_auto) { - return 0; + *is_auto = ipiface.UseAutomaticMetric; } - return ipiface.Metric; + return (int)ipiface.Metric; } - return -err; + return -1; } /* diff --git a/src/openvpn/block_dns.h b/src/openvpn/block_dns.h index c4b6693..50b383f 100644 --- a/src/openvpn/block_dns.h +++ b/src/openvpn/block_dns.h @@ -26,7 +26,7 @@ #ifndef OPENVPN_BLOCK_DNS_H #define OPENVPN_BLOCK_DNS_H -/* Any value less than 5 should work fine. 3 is choosen without any real reason. */ +/* Any value less than 5 should work fine. 3 is chosen without any real reason. */ #define BLOCK_DNS_IFACE_METRIC 3 typedef void (*block_dns_msg_handler_t) (DWORD err, const char *msg); @@ -39,17 +39,17 @@ add_block_dns_filters(HANDLE *engine, int iface_index, const WCHAR *exe_path, block_dns_msg_handler_t msg_handler_callback); /** - * Returns interface metric value for specified interface index. + * Return interface metric value for the specified interface index. * - * @param index The index of TAP adapter - * @param family Address family (AF_INET for IPv4 and AF_INET6 for IPv6) + * @param index The index of TAP adapter. + * @param family Address family (AF_INET for IPv4 and AF_INET6 for IPv6). + * @param is_auto On return set to true if automatic metric is in use. + * Unused if NULL. * - * @return positive metric value or zero for automatic metric on success, - * a less then zero error code on failure. + * @return positive interface metric on success or -1 on error */ - int -get_interface_metric(const NET_IFINDEX index, const ADDRESS_FAMILY family); +get_interface_metric(const NET_IFINDEX index, const ADDRESS_FAMILY family, int *is_auto); /** * Sets interface metric value for specified interface index. diff --git a/src/openvpn/buffer.c b/src/openvpn/buffer.c index 87e27ec..f2ab066 100644 --- a/src/openvpn/buffer.c +++ b/src/openvpn/buffer.c @@ -5,7 +5,7 @@ * packet encryption, packet authentication, and * packet compression. * - * Copyright (C) 2002-2017 OpenVPN Technologies, Inc. <sales@openvpn.net> + * Copyright (C) 2002-2018 OpenVPN Inc <sales@openvpn.net> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 @@ -180,7 +180,7 @@ buf_assign(struct buffer *dest, const struct buffer *src) } struct buffer -clear_buf() +clear_buf(void) { struct buffer buf; CLEAR(buf); @@ -1177,7 +1177,7 @@ buffer_list_reset(struct buffer_list *ol) } void -buffer_list_push(struct buffer_list *ol, const unsigned char *str) +buffer_list_push(struct buffer_list *ol, const char *str) { if (str) { @@ -1191,7 +1191,7 @@ buffer_list_push(struct buffer_list *ol, const unsigned char *str) } struct buffer_entry * -buffer_list_push_data(struct buffer_list *ol, const uint8_t *data, size_t size) +buffer_list_push_data(struct buffer_list *ol, const void *data, size_t size) { struct buffer_entry *e = NULL; if (data && (!ol->max_size || ol->size < ol->max_size)) @@ -1231,7 +1231,8 @@ buffer_list_peek(struct buffer_list *ol) } void -buffer_list_aggregate_separator(struct buffer_list *bl, const size_t max, const char *sep) +buffer_list_aggregate_separator(struct buffer_list *bl, const size_t max_len, + const char *sep) { int sep_len = strlen(sep); @@ -1240,9 +1241,15 @@ buffer_list_aggregate_separator(struct buffer_list *bl, const size_t max, const struct buffer_entry *more = bl->head; size_t size = 0; int count = 0; - for (count = 0; more && size <= max; ++count) + for (count = 0; more; ++count) { - size += BLEN(&more->buf) + sep_len; + size_t extra_len = BLEN(&more->buf) + sep_len; + if (size + extra_len > max_len) + { + break; + } + + size += extra_len; more = more->next; } @@ -1252,8 +1259,7 @@ buffer_list_aggregate_separator(struct buffer_list *bl, const size_t max, const struct buffer_entry *e = bl->head, *f; ALLOC_OBJ_CLEAR(f, struct buffer_entry); - f->buf.data = malloc(size); - check_malloc_return(f->buf.data); + f->buf = alloc_buf(size + 1); /* prevent 0-byte malloc */ f->buf.capacity = size; for (i = 0; e && i < count; ++i) { @@ -1265,6 +1271,7 @@ buffer_list_aggregate_separator(struct buffer_list *bl, const size_t max, const e = next; } bl->head = f; + bl->size -= count - 1; f->next = more; if (!more) { @@ -1325,7 +1332,7 @@ buffer_list_file(const char *fn, int max_line_len) bl = buffer_list_new(0); while (fgets(line, max_line_len, fp) != NULL) { - buffer_list_push(bl, (unsigned char *)line); + buffer_list_push(bl, line); } free(line); } diff --git a/src/openvpn/buffer.h b/src/openvpn/buffer.h index 8bc4428..e37254c 100644 --- a/src/openvpn/buffer.h +++ b/src/openvpn/buffer.h @@ -5,7 +5,7 @@ * packet encryption, packet authentication, and * packet compression. * - * Copyright (C) 2002-2017 OpenVPN Technologies, Inc. <sales@openvpn.net> + * Copyright (C) 2002-2018 OpenVPN Inc <sales@openvpn.net> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 @@ -91,7 +91,7 @@ struct gc_entry }; /** - * Gargabe collection entry for a specially allocated structure that needs + * Garbage collection entry for a specially allocated structure that needs * a custom free function to be freed like struct addrinfo * */ @@ -1090,9 +1090,9 @@ bool buffer_list_defined(const struct buffer_list *ol); void buffer_list_reset(struct buffer_list *ol); -void buffer_list_push(struct buffer_list *ol, const unsigned char *str); +void buffer_list_push(struct buffer_list *ol, const char *str); -struct buffer_entry *buffer_list_push_data(struct buffer_list *ol, const uint8_t *data, size_t size); +struct buffer_entry *buffer_list_push_data(struct buffer_list *ol, const void *data, size_t size); struct buffer *buffer_list_peek(struct buffer_list *ol); @@ -1102,7 +1102,8 @@ void buffer_list_pop(struct buffer_list *ol); void buffer_list_aggregate(struct buffer_list *bl, const size_t max); -void buffer_list_aggregate_separator(struct buffer_list *bl, const size_t max, const char *sep); +void buffer_list_aggregate_separator(struct buffer_list *bl, + const size_t max_len, const char *sep); struct buffer_list *buffer_list_file(const char *fn, int max_line_len); diff --git a/src/openvpn/circ_list.h b/src/openvpn/circ_list.h index 386e18d..23b42d2 100644 --- a/src/openvpn/circ_list.h +++ b/src/openvpn/circ_list.h @@ -5,7 +5,7 @@ * packet encryption, packet authentication, and * packet compression. * - * Copyright (C) 2002-2017 OpenVPN Technologies, Inc. <sales@openvpn.net> + * Copyright (C) 2002-2018 OpenVPN Inc <sales@openvpn.net> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 diff --git a/src/openvpn/clinat.c b/src/openvpn/clinat.c index 633cec6..b08fd54 100644 --- a/src/openvpn/clinat.c +++ b/src/openvpn/clinat.c @@ -5,7 +5,7 @@ * packet encryption, packet authentication, and * packet compression. * - * Copyright (C) 2002-2017 OpenVPN Technologies, Inc. <sales@openvpn.net> + * Copyright (C) 2002-2018 OpenVPN Inc <sales@openvpn.net> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 diff --git a/src/openvpn/clinat.h b/src/openvpn/clinat.h index e0cfad5..eec7a03 100644 --- a/src/openvpn/clinat.h +++ b/src/openvpn/clinat.h @@ -5,7 +5,7 @@ * packet encryption, packet authentication, and * packet compression. * - * Copyright (C) 2002-2017 OpenVPN Technologies, Inc. <sales@openvpn.net> + * Copyright (C) 2002-2018 OpenVPN Inc <sales@openvpn.net> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 diff --git a/src/openvpn/common.h b/src/openvpn/common.h index bb08c01..0f73200 100644 --- a/src/openvpn/common.h +++ b/src/openvpn/common.h @@ -5,7 +5,7 @@ * packet encryption, packet authentication, and * packet compression. * - * Copyright (C) 2002-2017 OpenVPN Technologies, Inc. <sales@openvpn.net> + * Copyright (C) 2002-2018 OpenVPN Inc <sales@openvpn.net> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 diff --git a/src/openvpn/comp-lz4.c b/src/openvpn/comp-lz4.c index 6e40c32..f2916bd 100644 --- a/src/openvpn/comp-lz4.c +++ b/src/openvpn/comp-lz4.c @@ -5,8 +5,8 @@ * packet encryption, packet authentication, and * packet compression. * - * Copyright (C) 2002-2017 OpenVPN Technologies, Inc. <sales@openvpn.net> - * Copyright (C) 2013-2017 Gert Doering <gert@greenie.muc.de> + * Copyright (C) 2002-2018 OpenVPN Inc <sales@openvpn.net> + * Copyright (C) 2013-2018 Gert Doering <gert@greenie.muc.de> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 @@ -43,6 +43,7 @@ #include "memdbg.h" + static void lz4_compress_init(struct compress_context *compctx) { @@ -86,7 +87,7 @@ do_lz4_compress(struct buffer *buf, return false; } - zlen = LZ4_compress_limitedOutput((const char *)BPTR(buf), (char *)BPTR(work), BLEN(buf), zlen_max ); + zlen = LZ4_compress_default((const char *)BPTR(buf), (char *)BPTR(work), BLEN(buf), zlen_max); if (zlen <= 0) { @@ -185,7 +186,7 @@ lz4v2_compress(struct buffer *buf, struct buffer work, } } -void +static void do_lz4_decompress(size_t zlen_max, struct buffer *work, struct buffer *buf, diff --git a/src/openvpn/comp-lz4.h b/src/openvpn/comp-lz4.h index c256ba5..8c1ca3a 100644 --- a/src/openvpn/comp-lz4.h +++ b/src/openvpn/comp-lz4.h @@ -5,8 +5,8 @@ * packet encryption, packet authentication, and * packet compression. * - * Copyright (C) 2002-2017 OpenVPN Technologies, Inc. <sales@openvpn.net> - * Copyright (C) 2013-2017 Gert Doering <gert@greenie.muc.de> + * Copyright (C) 2002-2018 OpenVPN Inc <sales@openvpn.net> + * Copyright (C) 2013-2018 Gert Doering <gert@greenie.muc.de> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 diff --git a/src/openvpn/comp.c b/src/openvpn/comp.c index 4cda7e5..a945913 100644 --- a/src/openvpn/comp.c +++ b/src/openvpn/comp.c @@ -5,7 +5,7 @@ * packet encryption, packet authentication, and * packet compression. * - * Copyright (C) 2002-2017 OpenVPN Technologies, Inc. <sales@openvpn.net> + * Copyright (C) 2002-2018 OpenVPN Inc <sales@openvpn.net> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 diff --git a/src/openvpn/comp.h b/src/openvpn/comp.h index e56fd2b..0dadd1e 100644 --- a/src/openvpn/comp.h +++ b/src/openvpn/comp.h @@ -5,7 +5,7 @@ * packet encryption, packet authentication, and * packet compression. * - * Copyright (C) 2002-2017 OpenVPN Technologies, Inc. <sales@openvpn.net> + * Copyright (C) 2002-2018 OpenVPN Inc <sales@openvpn.net> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 diff --git a/src/openvpn/compstub.c b/src/openvpn/compstub.c index ca90924..9123541 100644 --- a/src/openvpn/compstub.c +++ b/src/openvpn/compstub.c @@ -5,7 +5,7 @@ * packet encryption, packet authentication, and * packet compression. * - * Copyright (C) 2002-2017 OpenVPN Technologies, Inc. <sales@openvpn.net> + * Copyright (C) 2002-2018 OpenVPN Inc <sales@openvpn.net> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 diff --git a/src/openvpn/console.c b/src/openvpn/console.c index eb6944d..4d49722 100644 --- a/src/openvpn/console.c +++ b/src/openvpn/console.c @@ -5,9 +5,9 @@ * packet encryption, packet authentication, and * packet compression. * - * Copyright (C) 2002-2017 OpenVPN Technologies, Inc. <sales@openvpn.net> + * Copyright (C) 2002-2018 OpenVPN Inc <sales@openvpn.net> * Copyright (C) 2014-2015 David Sommerseth <davids@redhat.com> - * Copyright (C) 2016-2017 David Sommerseth <davids@openvpn.net> + * Copyright (C) 2016-2018 David Sommerseth <davids@openvpn.net> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 @@ -44,7 +44,7 @@ struct _query_user query_user[QUERY_USER_NUMSLOTS]; /* GLOBAL */ void -query_user_clear() +query_user_clear(void) { int i; diff --git a/src/openvpn/console.h b/src/openvpn/console.h index aa51e6f..5a70e5f 100644 --- a/src/openvpn/console.h +++ b/src/openvpn/console.h @@ -5,9 +5,9 @@ * packet encryption, packet authentication, and * packet compression. * - * Copyright (C) 2002-2017 OpenVPN Technologies, Inc. <sales@openvpn.net> + * Copyright (C) 2002-2018 OpenVPN Inc <sales@openvpn.net> * Copyright (C) 2014-2015 David Sommerseth <davids@redhat.com> - * Copyright (C) 2016-2017 David Sommerseth <davids@openvpn.net> + * Copyright (C) 2016-2018 David Sommerseth <davids@openvpn.net> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 @@ -46,7 +46,7 @@ extern struct _query_user query_user[]; /**< Global variable, declared in conso * Wipes all data put into all of the query_user structs * */ -void query_user_clear(); +void query_user_clear(void); /** @@ -72,7 +72,7 @@ void query_user_add(char *prompt, size_t prompt_len, * * @return True if executing all the defined steps completed successfully */ -bool query_user_exec_builtin(); +bool query_user_exec_builtin(void); #if defined(ENABLE_SYSTEMD) @@ -83,7 +83,7 @@ bool query_user_exec_builtin(); * * @return True if executing all the defined steps completed successfully */ -bool query_user_exec(); +bool query_user_exec(void); #else /* ENABLE_SYSTEMD not defined*/ /** @@ -92,7 +92,7 @@ bool query_user_exec(); * */ static bool -query_user_exec() +query_user_exec(void) { return query_user_exec_builtin(); } diff --git a/src/openvpn/console_builtin.c b/src/openvpn/console_builtin.c index 7b95da9..445928b 100644 --- a/src/openvpn/console_builtin.c +++ b/src/openvpn/console_builtin.c @@ -5,9 +5,9 @@ * packet encryption, packet authentication, and * packet compression. * - * Copyright (C) 2002-2017 OpenVPN Technologies, Inc. <sales@openvpn.net> + * Copyright (C) 2002-2018 OpenVPN Inc <sales@openvpn.net> * Copyright (C) 2014-2015 David Sommerseth <davids@redhat.com> - * Copyright (C) 2016-2017 David Sommerseth <davids@openvpn.net> + * Copyright (C) 2016-2018 David Sommerseth <davids@openvpn.net> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 @@ -267,7 +267,7 @@ get_console_input(const char *prompt, const bool echo, char *input, const int ca * */ bool -query_user_exec_builtin() +query_user_exec_builtin(void) { bool ret = true; /* Presume everything goes okay */ int i; diff --git a/src/openvpn/console_systemd.c b/src/openvpn/console_systemd.c index 8cee8c8..e7a72ae 100644 --- a/src/openvpn/console_systemd.c +++ b/src/openvpn/console_systemd.c @@ -41,7 +41,7 @@ */ static bool -check_systemd_running() +check_systemd_running(void) { struct stat c; @@ -95,7 +95,7 @@ get_console_input_systemd(const char *prompt, const bool echo, char *input, cons * */ bool -query_user_exec() +query_user_exec(void) { bool ret = true; /* Presume everything goes okay */ int i; diff --git a/src/openvpn/crypto.c b/src/openvpn/crypto.c index 5f482d0..dba3aa5 100644 --- a/src/openvpn/crypto.c +++ b/src/openvpn/crypto.c @@ -5,8 +5,8 @@ * packet encryption, packet authentication, and * packet compression. * - * Copyright (C) 2002-2017 OpenVPN Technologies, Inc. <sales@openvpn.net> - * Copyright (C) 2010-2017 Fox Crypto B.V. <openvpn@fox-it.com> + * Copyright (C) 2002-2018 OpenVPN Inc <sales@openvpn.net> + * Copyright (C) 2010-2018 Fox Crypto B.V. <openvpn@fox-it.com> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 @@ -842,7 +842,7 @@ init_key_type(struct key_type *kt, const char *ciphername, /* given a key and key_type, build a key_ctx */ void -init_key_ctx(struct key_ctx *ctx, struct key *key, +init_key_ctx(struct key_ctx *ctx, const struct key *key, const struct key_type *kt, int enc, const char *prefix) { @@ -895,6 +895,26 @@ init_key_ctx(struct key_ctx *ctx, struct key *key, } void +init_key_ctx_bi(struct key_ctx_bi *ctx, const struct key2 *key2, + int key_direction, const struct key_type *kt, const char *name) +{ + char log_prefix[128] = { 0 }; + struct key_direction_state kds; + + key_direction_state_init(&kds, key_direction); + + openvpn_snprintf(log_prefix, sizeof(log_prefix), "Outgoing %s", name); + init_key_ctx(&ctx->encrypt, &key2->keys[kds.out_key], kt, + OPENVPN_OP_ENCRYPT, log_prefix); + + openvpn_snprintf(log_prefix, sizeof(log_prefix), "Incoming %s", name); + init_key_ctx(&ctx->decrypt, &key2->keys[kds.in_key], kt, + OPENVPN_OP_DECRYPT, log_prefix); + + ctx->initialized = true; +} + +void free_key_ctx(struct key_ctx *ctx) { if (ctx->cipher) @@ -1184,7 +1204,6 @@ crypto_read_openvpn_key(const struct key_type *key_type, { struct key2 key2; struct key_direction_state kds; - char log_prefix[128] = { 0 }; if (key_inline) { @@ -1209,13 +1228,7 @@ crypto_read_openvpn_key(const struct key_type *key_type, must_have_n_keys(key_file, opt_name, &key2, kds.need_keys); /* initialize key in both directions */ - openvpn_snprintf(log_prefix, sizeof(log_prefix), "Outgoing %s", key_name); - init_key_ctx(&ctx->encrypt, &key2.keys[kds.out_key], key_type, - OPENVPN_OP_ENCRYPT, log_prefix); - openvpn_snprintf(log_prefix, sizeof(log_prefix), "Incoming %s", key_name); - init_key_ctx(&ctx->decrypt, &key2.keys[kds.in_key], key_type, - OPENVPN_OP_DECRYPT, log_prefix); - + init_key_ctx_bi(ctx, &key2, key_direction, key_type, key_name); secure_memzero(&key2, sizeof(key2)); } @@ -1284,7 +1297,7 @@ read_key_file(struct key2 *key2, const char *file, const unsigned int flags) fd = platform_open(file, O_RDONLY, 0); if (fd == -1) { - msg(M_ERR, "Cannot open file key file '%s'", file); + msg(M_ERR, "Cannot open key file '%s'", file); } size = read(fd, in.data, in.capacity); if (size < 0) @@ -1557,11 +1570,18 @@ ascii2keydirection(int msglevel, const char *str) } const char * -keydirection2ascii(int kd, bool remote) +keydirection2ascii(int kd, bool remote, bool humanreadable) { if (kd == KEY_DIRECTION_BIDIRECTIONAL) { - return NULL; + if (humanreadable) + { + return "not set"; + } + else + { + return NULL; + } } else if (kd == KEY_DIRECTION_NORMAL) { @@ -1676,6 +1696,11 @@ read_key(struct key *key, const struct key_type *kt, struct buffer *buf) goto read_err; } + if (cipher_length != kt->cipher_length || hmac_length != kt->hmac_length) + { + goto key_len_err; + } + if (!buf_read(buf, key->cipher, cipher_length)) { goto read_err; @@ -1685,11 +1710,6 @@ read_key(struct key *key, const struct key_type *kt, struct buffer *buf) goto read_err; } - if (cipher_length != kt->cipher_length || hmac_length != kt->hmac_length) - { - goto key_len_err; - } - return 1; read_err: @@ -1716,7 +1736,7 @@ static int nonce_secret_len = 0; /* GLOBAL */ /* Reset the nonce value, also done periodically to refresh entropy */ static void -prng_reset_nonce() +prng_reset_nonce(void) { const int size = md_kt_size(nonce_md) + nonce_secret_len; #if 1 /* Must be 1 for real usage */ @@ -1795,7 +1815,7 @@ prng_bytes(uint8_t *output, int len) /* an analogue to the random() function, but use prng_bytes */ long int -get_random() +get_random(void) { long int l; prng_bytes((unsigned char *)&l, sizeof(l)); diff --git a/src/openvpn/crypto.h b/src/openvpn/crypto.h index 8818c01..e42f697 100644 --- a/src/openvpn/crypto.h +++ b/src/openvpn/crypto.h @@ -5,8 +5,8 @@ * packet encryption, packet authentication, and * packet compression. * - * Copyright (C) 2002-2017 OpenVPN Technologies, Inc. <sales@openvpn.net> - * Copyright (C) 2010-2017 Fox Crypto B.V. <openvpn@fox-it.com> + * Copyright (C) 2002-2018 OpenVPN Inc <sales@openvpn.net> + * Copyright (C) 2010-2018 Fox Crypto B.V. <openvpn@fox-it.com> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 @@ -317,12 +317,16 @@ void init_key_type(struct key_type *kt, const char *ciphername, * Key context functions */ -void init_key_ctx(struct key_ctx *ctx, struct key *key, +void init_key_ctx(struct key_ctx *ctx, const struct key *key, const struct key_type *kt, int enc, const char *prefix); void free_key_ctx(struct key_ctx *ctx); +void init_key_ctx_bi(struct key_ctx_bi *ctx, const struct key2 *key2, + int key_direction, const struct key_type *kt, + const char *name); + void free_key_ctx_bi(struct key_ctx_bi *ctx); @@ -459,7 +463,7 @@ void prng_init(const char *md_name, const int nonce_secret_len_parm); */ void prng_bytes(uint8_t *output, int len); -void prng_uninit(); +void prng_uninit(void); void test_crypto(struct crypto_options *co, struct frame *f); @@ -474,7 +478,7 @@ void must_have_n_keys(const char *filename, const char *option, const struct key int ascii2keydirection(int msglevel, const char *str); -const char *keydirection2ascii(int kd, bool remote); +const char *keydirection2ascii(int kd, bool remote, bool humanreadable); /* print keys */ void key2_print(const struct key2 *k, diff --git a/src/openvpn/crypto_backend.h b/src/openvpn/crypto_backend.h index b7f519b..1ee2980 100644 --- a/src/openvpn/crypto_backend.h +++ b/src/openvpn/crypto_backend.h @@ -5,8 +5,8 @@ * packet encryption, packet authentication, and * packet compression. * - * Copyright (C) 2002-2017 OpenVPN Technologies, Inc. <sales@openvpn.net> - * Copyright (C) 2010-2017 Fox Crypto B.V. <openvpn@fox-it.com> + * Copyright (C) 2002-2018 OpenVPN Inc <sales@openvpn.net> + * Copyright (C) 2010-2018 Fox Crypto B.V. <openvpn@fox-it.com> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 @@ -323,7 +323,7 @@ void cipher_ctx_free(cipher_ctx_t *ctx); * @param enc Whether to encrypt or decrypt (either * \c MBEDTLS_OP_ENCRYPT or \c MBEDTLS_OP_DECRYPT). */ -void cipher_ctx_init(cipher_ctx_t *ctx, uint8_t *key, int key_len, +void cipher_ctx_init(cipher_ctx_t *ctx, const uint8_t *key, int key_len, const cipher_kt_t *kt, int enc); /** diff --git a/src/openvpn/crypto_mbedtls.c b/src/openvpn/crypto_mbedtls.c index 24bc315..82a92af 100644 --- a/src/openvpn/crypto_mbedtls.c +++ b/src/openvpn/crypto_mbedtls.c @@ -5,8 +5,8 @@ * packet encryption, packet authentication, and * packet compression. * - * Copyright (C) 2002-2017 OpenVPN Technologies, Inc. <sales@openvpn.net> - * Copyright (C) 2010-2017 Fox Crypto B.V. <openvpn@fox-it.com> + * Copyright (C) 2002-2018 OpenVPN Inc <sales@openvpn.net> + * Copyright (C) 2010-2018 Fox Crypto B.V. <openvpn@fox-it.com> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 @@ -159,7 +159,7 @@ print_cipher(const cipher_kt_t *info) } void -show_available_ciphers() +show_available_ciphers(void) { const int *ciphers = mbedtls_cipher_list(); @@ -196,7 +196,7 @@ show_available_ciphers() } void -show_available_digests() +show_available_digests(void) { const int *digests = mbedtls_md_list(); @@ -223,7 +223,7 @@ show_available_digests() } void -show_available_engines() +show_available_engines(void) { printf("Sorry, mbed TLS hardware crypto engine functionality is not " "available\n"); @@ -243,7 +243,7 @@ show_available_engines() * entropy gathering function. */ mbedtls_ctr_drbg_context * -rand_ctx_get() +rand_ctx_get(void) { static mbedtls_entropy_context ec = {0}; static mbedtls_ctr_drbg_context cd_ctx = {0}; @@ -280,7 +280,7 @@ rand_ctx_get() #ifdef ENABLE_PREDICTION_RESISTANCE void -rand_ctx_enable_prediction_resistance() +rand_ctx_enable_prediction_resistance(void) { mbedtls_ctr_drbg_context *cd_ctx = rand_ctx_get(); @@ -523,7 +523,7 @@ cipher_ctx_free(mbedtls_cipher_context_t *ctx) } void -cipher_ctx_init(mbedtls_cipher_context_t *ctx, uint8_t *key, int key_len, +cipher_ctx_init(mbedtls_cipher_context_t *ctx, const uint8_t *key, int key_len, const mbedtls_cipher_info_t *kt, const mbedtls_operation_t operation) { ASSERT(NULL != kt && NULL != ctx); @@ -804,6 +804,7 @@ md_ctx_init(mbedtls_md_context_t *ctx, const mbedtls_md_info_t *kt) void md_ctx_cleanup(mbedtls_md_context_t *ctx) { + mbedtls_md_free(ctx); } int diff --git a/src/openvpn/crypto_mbedtls.h b/src/openvpn/crypto_mbedtls.h index a434ce3..452b06e 100644 --- a/src/openvpn/crypto_mbedtls.h +++ b/src/openvpn/crypto_mbedtls.h @@ -5,8 +5,8 @@ * packet encryption, packet authentication, and * packet compression. * - * Copyright (C) 2002-2017 OpenVPN Technologies, Inc. <sales@openvpn.net> - * Copyright (C) 2010-2017 Fox Crypto B.V. <openvpn@fox-it.com> + * Copyright (C) 2002-2018 OpenVPN Inc <sales@openvpn.net> + * Copyright (C) 2010-2018 Fox Crypto B.V. <openvpn@fox-it.com> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 @@ -85,13 +85,13 @@ typedef mbedtls_md_context_t hmac_ctx_t; * added. During initialisation, a personalisation string will be added based * on the time, the PID, and a pointer to the random context. */ -mbedtls_ctr_drbg_context *rand_ctx_get(); +mbedtls_ctr_drbg_context *rand_ctx_get(void); #ifdef ENABLE_PREDICTION_RESISTANCE /** * Enable prediction resistance on the random number generator. */ -void rand_ctx_enable_prediction_resistance(); +void rand_ctx_enable_prediction_resistance(void); #endif diff --git a/src/openvpn/crypto_openssl.c b/src/openvpn/crypto_openssl.c index a55e65c..eae2b91 100644 --- a/src/openvpn/crypto_openssl.c +++ b/src/openvpn/crypto_openssl.c @@ -5,8 +5,8 @@ * packet encryption, packet authentication, and * packet compression. * - * Copyright (C) 2002-2017 OpenVPN Technologies, Inc. <sales@openvpn.net> - * Copyright (C) 2010-2017 Fox Crypto B.V. <openvpn@fox-it.com> + * Copyright (C) 2002-2018 OpenVPN Inc <sales@openvpn.net> + * Copyright (C) 2010-2018 Fox Crypto B.V. <openvpn@fox-it.com> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 @@ -280,7 +280,7 @@ print_cipher(const EVP_CIPHER *cipher) } void -show_available_ciphers() +show_available_ciphers(void) { int nid; size_t i; @@ -339,7 +339,7 @@ show_available_ciphers() } void -show_available_digests() +show_available_digests(void) { int nid; @@ -364,7 +364,7 @@ show_available_digests() } void -show_available_engines() +show_available_engines(void) { #if HAVE_OPENSSL_ENGINE /* Only defined for OpenSSL */ ENGINE *e; @@ -665,7 +665,7 @@ cipher_ctx_free(EVP_CIPHER_CTX *ctx) } void -cipher_ctx_init(EVP_CIPHER_CTX *ctx, uint8_t *key, int key_len, +cipher_ctx_init(EVP_CIPHER_CTX *ctx, const uint8_t *key, int key_len, const EVP_CIPHER *kt, int enc) { ASSERT(NULL != kt && NULL != ctx); @@ -930,7 +930,7 @@ hmac_ctx_init(HMAC_CTX *ctx, const uint8_t *key, int key_len, { ASSERT(NULL != kt && NULL != ctx); - HMAC_CTX_init(ctx); + HMAC_CTX_reset(ctx); HMAC_Init_ex(ctx, key, key_len, kt, NULL); /* make sure we used a big enough key */ diff --git a/src/openvpn/crypto_openssl.h b/src/openvpn/crypto_openssl.h index 60a2812..0a41370 100644 --- a/src/openvpn/crypto_openssl.h +++ b/src/openvpn/crypto_openssl.h @@ -5,8 +5,8 @@ * packet encryption, packet authentication, and * packet compression. * - * Copyright (C) 2002-2017 OpenVPN Technologies, Inc. <sales@openvpn.net> - * Copyright (C) 2010-2017 Fox Crypto B.V. <openvpn@fox-it.com> + * Copyright (C) 2002-2018 OpenVPN Inc <sales@openvpn.net> + * Copyright (C) 2010-2018 Fox Crypto B.V. <openvpn@fox-it.com> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 diff --git a/src/openvpn/cryptoapi.c b/src/openvpn/cryptoapi.c index d90cc5d..89d253c 100644 --- a/src/openvpn/cryptoapi.c +++ b/src/openvpn/cryptoapi.c @@ -42,11 +42,13 @@ #include <openssl/err.h> #include <windows.h> #include <wincrypt.h> +#include <ncrypt.h> #include <stdio.h> #include <ctype.h> #include <assert.h> #include "buffer.h" +#include "openssl_compat.h" /* MinGW w32api 3.17 is still incomplete when it comes to CryptoAPI while * MinGW32-w64 defines all macros used. This is a hack around that problem. @@ -82,6 +84,7 @@ #define CRYPTOAPI_F_CRYPT_SIGN_HASH 106 #define CRYPTOAPI_F_LOAD_LIBRARY 107 #define CRYPTOAPI_F_GET_PROC_ADDRESS 108 +#define CRYPTOAPI_F_NCRYPT_SIGN_HASH 109 static ERR_STRING_DATA CRYPTOAPI_str_functs[] = { { ERR_PACK(ERR_LIB_CRYPTOAPI, 0, 0), "microsoft cryptoapi"}, @@ -94,12 +97,13 @@ static ERR_STRING_DATA CRYPTOAPI_str_functs[] = { { ERR_PACK(0, CRYPTOAPI_F_CRYPT_SIGN_HASH, 0), "CryptSignHash" }, { ERR_PACK(0, CRYPTOAPI_F_LOAD_LIBRARY, 0), "LoadLibrary" }, { ERR_PACK(0, CRYPTOAPI_F_GET_PROC_ADDRESS, 0), "GetProcAddress" }, + { ERR_PACK(0, CRYPTOAPI_F_NCRYPT_SIGN_HASH, 0), "NCryptSignHash" }, { 0, NULL } }; typedef struct _CAPI_DATA { const CERT_CONTEXT *cert_context; - HCRYPTPROV crypt_prov; + HCRYPTPROV_OR_NCRYPT_KEY_HANDLE crypt_prov; DWORD key_spec; BOOL free_crypt_prov; } CAPI_DATA; @@ -209,26 +213,66 @@ rsa_pub_dec(int flen, const unsigned char *from, unsigned char *to, RSA *rsa, in return 0; } +/** + * Sign the hash in 'from' using NCryptSignHash(). This requires an NCRYPT + * key handle in cd->crypt_prov. On return the signature is in 'to'. Returns + * the length of the signature or 0 on error. + * For now we support only RSA and the padding is assumed to be PKCS1 v1.5 + */ +static int +priv_enc_CNG(const CAPI_DATA *cd, const unsigned char *from, int flen, + unsigned char *to, int tlen, int padding) +{ + NCRYPT_KEY_HANDLE hkey = cd->crypt_prov; + DWORD len; + ASSERT(cd->key_spec == CERT_NCRYPT_KEY_SPEC); + + msg(D_LOW, "Signing hash using CNG: data size = %d", flen); + + /* The hash OID is already in 'from'. So set the hash algorithm + * in the padding info struct to NULL. + */ + BCRYPT_PKCS1_PADDING_INFO padinfo = {NULL}; + DWORD status; + + status = NCryptSignHash(hkey, padding? &padinfo : NULL, (BYTE*) from, flen, + to, tlen, &len, padding? BCRYPT_PAD_PKCS1 : 0); + if (status != ERROR_SUCCESS) + { + SetLastError(status); + CRYPTOAPIerr(CRYPTOAPI_F_NCRYPT_SIGN_HASH); + len = 0; + } + + /* Unlike CAPI, CNG signature is in big endian order. No reversing needed. */ + return len; +} + /* sign arbitrary data */ static int rsa_priv_enc(int flen, const unsigned char *from, unsigned char *to, RSA *rsa, int padding) { - CAPI_DATA *cd = (CAPI_DATA *) rsa->meth->app_data; + CAPI_DATA *cd = (CAPI_DATA *) RSA_meth_get0_app_data(RSA_get_method(rsa)); HCRYPTHASH hash; DWORD hash_size, len, i; unsigned char *buf; if (cd == NULL) { - RSAerr(RSA_F_RSA_EAY_PRIVATE_ENCRYPT, ERR_R_PASSED_NULL_PARAMETER); + RSAerr(RSA_F_RSA_OSSL_PRIVATE_ENCRYPT, ERR_R_PASSED_NULL_PARAMETER); return 0; } if (padding != RSA_PKCS1_PADDING) { /* AFAICS, CryptSignHash() *always* uses PKCS1 padding. */ - RSAerr(RSA_F_RSA_EAY_PRIVATE_ENCRYPT, RSA_R_UNKNOWN_PADDING_TYPE); + RSAerr(RSA_F_RSA_OSSL_PRIVATE_ENCRYPT, RSA_R_UNKNOWN_PADDING_TYPE); return 0; } + if (cd->key_spec == CERT_NCRYPT_KEY_SPEC) + { + return priv_enc_CNG(cd, from, flen, to, RSA_size(rsa), padding); + } + /* Unfortunately, there is no "CryptSign()" function in CryptoAPI, that would * be way to straightforward for M$, I guess... So we have to do it this * tricky way instead, by creating a "Hash", and load the already-made hash @@ -236,7 +280,7 @@ rsa_priv_enc(int flen, const unsigned char *from, unsigned char *to, RSA *rsa, i /* For now, we only support NID_md5_sha1 */ if (flen != SSL_SIG_LENGTH) { - RSAerr(RSA_F_RSA_EAY_PRIVATE_ENCRYPT, RSA_R_INVALID_MESSAGE_LENGTH); + RSAerr(RSA_F_RSA_OSSL_PRIVATE_ENCRYPT, RSA_R_INVALID_MESSAGE_LENGTH); return 0; } if (!CryptCreateHash(cd->crypt_prov, CALG_SSL3_SHAMD5, 0, 0, &hash)) @@ -253,7 +297,7 @@ rsa_priv_enc(int flen, const unsigned char *from, unsigned char *to, RSA *rsa, i } if ((int) hash_size != flen) { - RSAerr(RSA_F_RSA_EAY_PRIVATE_ENCRYPT, RSA_R_INVALID_MESSAGE_LENGTH); + RSAerr(RSA_F_RSA_OSSL_PRIVATE_ENCRYPT, RSA_R_INVALID_MESSAGE_LENGTH); CryptDestroyHash(hash); return 0; } @@ -268,7 +312,7 @@ rsa_priv_enc(int flen, const unsigned char *from, unsigned char *to, RSA *rsa, i buf = malloc(len); if (buf == NULL) { - RSAerr(RSA_F_RSA_EAY_PRIVATE_ENCRYPT, ERR_R_MALLOC_FAILURE); + RSAerr(RSA_F_RSA_OSSL_PRIVATE_ENCRYPT, ERR_R_MALLOC_FAILURE); CryptDestroyHash(hash); return 0; } @@ -312,7 +356,8 @@ init(RSA *rsa) static int finish(RSA *rsa) { - CAPI_DATA *cd = (CAPI_DATA *) rsa->meth->app_data; + const RSA_METHOD *rsa_meth = RSA_get_method(rsa); + CAPI_DATA *cd = (CAPI_DATA *) RSA_meth_get0_app_data(rsa_meth); if (cd == NULL) { @@ -320,15 +365,21 @@ finish(RSA *rsa) } if (cd->crypt_prov && cd->free_crypt_prov) { - CryptReleaseContext(cd->crypt_prov, 0); + if (cd->key_spec == CERT_NCRYPT_KEY_SPEC) + { + NCryptFreeObject(cd->crypt_prov); + } + else + { + CryptReleaseContext(cd->crypt_prov, 0); + } } if (cd->cert_context) { CertFreeCertificateContext(cd->cert_context); } - free(rsa->meth->app_data); - free((char *) rsa->meth); - rsa->meth = NULL; + free(cd); + RSA_meth_free((RSA_METHOD*) rsa_meth); return 1; } @@ -412,9 +463,9 @@ SSL_CTX_use_CryptoAPI_certificate(SSL_CTX *ssl_ctx, const char *cert_prop) X509 *cert = NULL; RSA *rsa = NULL, *pub_rsa; CAPI_DATA *cd = calloc(1, sizeof(*cd)); - RSA_METHOD *my_rsa_method = calloc(1, sizeof(*my_rsa_method)); + RSA_METHOD *my_rsa_method = NULL; - if (cd == NULL || my_rsa_method == NULL) + if (cd == NULL) { SSLerr(SSL_F_SSL_CTX_USE_CERTIFICATE_FILE, ERR_R_MALLOC_FAILURE); goto err; @@ -457,8 +508,11 @@ SSL_CTX_use_CryptoAPI_certificate(SSL_CTX *ssl_ctx, const char *cert_prop) } /* set up stuff to use the private key */ - if (!CryptAcquireCertificatePrivateKey(cd->cert_context, CRYPT_ACQUIRE_COMPARE_KEY_FLAG, - NULL, &cd->crypt_prov, &cd->key_spec, &cd->free_crypt_prov)) + /* We prefer to get an NCRYPT key handle so that TLS1.2 can be supported */ + DWORD flags = CRYPT_ACQUIRE_COMPARE_KEY_FLAG + | CRYPT_ACQUIRE_PREFER_NCRYPT_KEY_FLAG; + if (!CryptAcquireCertificatePrivateKey(cd->cert_context, flags, NULL, + &cd->crypt_prov, &cd->key_spec, &cd->free_crypt_prov)) { /* if we don't have a smart card reader here, and we try to access a * smart card certificate, we get: @@ -469,15 +523,37 @@ SSL_CTX_use_CryptoAPI_certificate(SSL_CTX *ssl_ctx, const char *cert_prop) /* here we don't need to do CryptGetUserKey() or anything; all necessary key * info is in cd->cert_context, and then, in cd->crypt_prov. */ - my_rsa_method->name = "Microsoft CryptoAPI RSA Method"; - my_rsa_method->rsa_pub_enc = rsa_pub_enc; - my_rsa_method->rsa_pub_dec = rsa_pub_dec; - my_rsa_method->rsa_priv_enc = rsa_priv_enc; - my_rsa_method->rsa_priv_dec = rsa_priv_dec; - /* my_rsa_method->init = init; */ - my_rsa_method->finish = finish; - my_rsa_method->flags = RSA_METHOD_FLAG_NO_CHECK; - my_rsa_method->app_data = (char *) cd; + /* if we do not have an NCRYPT key handle restrict TLS to v1.1 or lower */ + int max_version = SSL_CTX_get_max_proto_version(ssl_ctx); + if ((!max_version || max_version > TLS1_1_VERSION) + && cd->key_spec != CERT_NCRYPT_KEY_SPEC) + { + msg(M_WARN, "WARNING: cryptoapicert: private key is in a legacy store." + " Restricting TLS version to 1.1"); + if (SSL_CTX_get_min_proto_version(ssl_ctx) > TLS1_1_VERSION) + { + msg(M_NONFATAL, + "ERROR: cryptoapicert: min TLS version larger than 1.1." + " Try config option --tls-version-min 1.1"); + goto err; + } + if (!SSL_CTX_set_max_proto_version(ssl_ctx, TLS1_1_VERSION)) + { + msg(M_NONFATAL, "ERROR: cryptoapicert: set max TLS version failed"); + goto err; + } + } + + my_rsa_method = RSA_meth_new("Microsoft Cryptography API RSA Method", + RSA_METHOD_FLAG_NO_CHECK); + check_malloc_return(my_rsa_method); + RSA_meth_set_pub_enc(my_rsa_method, rsa_pub_enc); + RSA_meth_set_pub_dec(my_rsa_method, rsa_pub_dec); + RSA_meth_set_priv_enc(my_rsa_method, rsa_priv_enc); + RSA_meth_set_priv_dec(my_rsa_method, rsa_priv_dec); + RSA_meth_set_init(my_rsa_method, NULL); + RSA_meth_set_finish(my_rsa_method, finish); + RSA_meth_set0_app_data(my_rsa_method, cd); rsa = RSA_new(); if (rsa == NULL) @@ -486,23 +562,35 @@ SSL_CTX_use_CryptoAPI_certificate(SSL_CTX *ssl_ctx, const char *cert_prop) goto err; } - /* cert->cert_info->key->pkey is NULL until we call SSL_CTX_use_certificate(), + /* Public key in cert is NULL until we call SSL_CTX_use_certificate(), * so we do it here then... */ if (!SSL_CTX_use_certificate(ssl_ctx, cert)) { goto err; } /* the public key */ - pub_rsa = cert->cert_info->key->pkey->pkey.rsa; + EVP_PKEY *pkey = X509_get0_pubkey(cert); + /* SSL_CTX_use_certificate() increased the reference count in 'cert', so * we decrease it here with X509_free(), or it will never be cleaned up. */ X509_free(cert); cert = NULL; - /* I'm not sure about what we have to fill in in the RSA, trying out stuff... */ - /* rsa->n indicates the key size */ - rsa->n = BN_dup(pub_rsa->n); - rsa->flags |= RSA_FLAG_EXT_PKEY; + if (!(pub_rsa = EVP_PKEY_get0_RSA(pkey))) + { + msg(M_WARN, "cryptoapicert requires an RSA certificate"); + goto err; + } + + /* Our private key is external, so we fill in only n and e from the public key */ + const BIGNUM *n = NULL; + const BIGNUM *e = NULL; + RSA_get0_key(pub_rsa, &n, &e, NULL); + if (!RSA_set0_key(rsa, BN_dup(n), BN_dup(e), NULL)) + { + goto err; + } + RSA_set_flags(rsa, RSA_flags(rsa) | RSA_FLAG_EXT_PKEY); if (!RSA_set_method(rsa, my_rsa_method)) { goto err; @@ -536,7 +624,14 @@ err: { if (cd->free_crypt_prov && cd->crypt_prov) { - CryptReleaseContext(cd->crypt_prov, 0); + if (cd->key_spec == CERT_NCRYPT_KEY_SPEC) + { + NCryptFreeObject(cd->crypt_prov); + } + else + { + CryptReleaseContext(cd->crypt_prov, 0); + } } if (cd->cert_context) { diff --git a/src/openvpn/dhcp.c b/src/openvpn/dhcp.c index a2a5454..fb28b27 100644 --- a/src/openvpn/dhcp.c +++ b/src/openvpn/dhcp.c @@ -5,7 +5,7 @@ * packet encryption, packet authentication, and * packet compression. * - * Copyright (C) 2002-2017 OpenVPN Technologies, Inc. <sales@openvpn.net> + * Copyright (C) 2002-2018 OpenVPN Inc <sales@openvpn.net> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 diff --git a/src/openvpn/dhcp.h b/src/openvpn/dhcp.h index dc41658..32aa15e 100644 --- a/src/openvpn/dhcp.h +++ b/src/openvpn/dhcp.h @@ -5,7 +5,7 @@ * packet encryption, packet authentication, and * packet compression. * - * Copyright (C) 2002-2017 OpenVPN Technologies, Inc. <sales@openvpn.net> + * Copyright (C) 2002-2018 OpenVPN Inc <sales@openvpn.net> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 diff --git a/src/openvpn/errlevel.h b/src/openvpn/errlevel.h index 5bb043b..5ca4fa8 100644 --- a/src/openvpn/errlevel.h +++ b/src/openvpn/errlevel.h @@ -5,7 +5,7 @@ * packet encryption, packet authentication, and * packet compression. * - * Copyright (C) 2002-2017 OpenVPN Technologies, Inc. <sales@openvpn.net> + * Copyright (C) 2002-2018 OpenVPN Inc <sales@openvpn.net> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 diff --git a/src/openvpn/error.c b/src/openvpn/error.c index ce50ff9..bc14e8c 100644 --- a/src/openvpn/error.c +++ b/src/openvpn/error.c @@ -5,7 +5,7 @@ * packet encryption, packet authentication, and * packet compression. * - * Copyright (C) 2002-2017 OpenVPN Technologies, Inc. <sales@openvpn.net> + * Copyright (C) 2002-2018 OpenVPN Inc <sales@openvpn.net> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 @@ -159,7 +159,7 @@ set_machine_readable_output(bool parsable) } void -error_reset() +error_reset(void) { use_syslog = std_redir = false; suppress_timestamps = false; @@ -267,7 +267,7 @@ x_msg_va(const unsigned int flags, const char *format, va_list arglist) if ((flags & M_ERRNO) && e) { openvpn_snprintf(m2, ERR_BUF_SIZE, "%s: %s (errno=%d)", - m1, strerror_ts(e, &gc), e); + m1, strerror(e), e); SWAP; } @@ -342,8 +342,8 @@ x_msg_va(const unsigned int flags, const char *format, va_list arglist) struct timeval tv; gettimeofday(&tv, NULL); - fprintf(fp, "%lu.%06lu %x %s%s%s%s", - tv.tv_sec, + fprintf(fp, "%"PRIi64".%06lu %x %s%s%s%s", + (int64_t)tv.tv_sec, (unsigned long)tv.tv_usec, flags, prefix, @@ -480,7 +480,7 @@ open_syslog(const char *pgmname, bool stdio_to_null) } void -close_syslog() +close_syslog(void) { #if SYSLOG_CAPABILITY if (use_syslog) @@ -635,7 +635,7 @@ unsigned int x_cs_verbose_level; /* GLOBAL */ unsigned int x_cs_err_delay_ms; /* GLOBAL */ void -reset_check_status() +reset_check_status(void) { x_cs_info_level = 0; x_cs_verbose_level = 0; @@ -693,20 +693,15 @@ x_check_status(int status, { if (extended_msg) { - msg(x_cs_info_level, "%s %s [%s]: %s (code=%d)", - description, + msg(x_cs_info_level, "%s %s [%s]: %s (code=%d)", description, sock ? proto2ascii(sock->info.proto, sock->info.af, true) : "", - extended_msg, - strerror_ts(my_errno, &gc), - my_errno); + extended_msg, strerror(my_errno), my_errno); } else { - msg(x_cs_info_level, "%s %s: %s (code=%d)", - description, + msg(x_cs_info_level, "%s %s: %s (code=%d)", description, sock ? proto2ascii(sock->info.proto, sock->info.af, true) : "", - strerror_ts(my_errno, &gc), - my_errno); + strerror(my_errno), my_errno); } if (x_cs_err_delay_ms) diff --git a/src/openvpn/error.h b/src/openvpn/error.h index 14ef7e6..eaedf17 100644 --- a/src/openvpn/error.h +++ b/src/openvpn/error.h @@ -5,7 +5,7 @@ * packet encryption, packet authentication, and * packet compression. * - * Copyright (C) 2002-2017 OpenVPN Technologies, Inc. <sales@openvpn.net> + * Copyright (C) 2002-2018 OpenVPN Inc <sales@openvpn.net> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 @@ -261,7 +261,7 @@ void msg_forked(void); void open_syslog(const char *pgmname, bool stdio_to_null); -void close_syslog(); +void close_syslog(void); /* log file output */ void redirect_stdout_stderr(const char *file, bool append); diff --git a/src/openvpn/event.c b/src/openvpn/event.c index d123070..b22741f 100644 --- a/src/openvpn/event.c +++ b/src/openvpn/event.c @@ -5,7 +5,7 @@ * packet encryption, packet authentication, and * packet compression. * - * Copyright (C) 2002-2017 OpenVPN Technologies, Inc. <sales@openvpn.net> + * Copyright (C) 2002-2018 OpenVPN Inc <sales@openvpn.net> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 diff --git a/src/openvpn/event.h b/src/openvpn/event.h index ff795f4..4af6371 100644 --- a/src/openvpn/event.h +++ b/src/openvpn/event.h @@ -5,7 +5,7 @@ * packet encryption, packet authentication, and * packet compression. * - * Copyright (C) 2002-2017 OpenVPN Technologies, Inc. <sales@openvpn.net> + * Copyright (C) 2002-2018 OpenVPN Inc <sales@openvpn.net> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 diff --git a/src/openvpn/fdmisc.c b/src/openvpn/fdmisc.c index 56e2250..1cea505 100644 --- a/src/openvpn/fdmisc.c +++ b/src/openvpn/fdmisc.c @@ -5,7 +5,7 @@ * packet encryption, packet authentication, and * packet compression. * - * Copyright (C) 2002-2017 OpenVPN Technologies, Inc. <sales@openvpn.net> + * Copyright (C) 2002-2018 OpenVPN Inc <sales@openvpn.net> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 diff --git a/src/openvpn/fdmisc.h b/src/openvpn/fdmisc.h index b6d7101..0fb8b93 100644 --- a/src/openvpn/fdmisc.h +++ b/src/openvpn/fdmisc.h @@ -5,7 +5,7 @@ * packet encryption, packet authentication, and * packet compression. * - * Copyright (C) 2002-2017 OpenVPN Technologies, Inc. <sales@openvpn.net> + * Copyright (C) 2002-2018 OpenVPN Inc <sales@openvpn.net> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 diff --git a/src/openvpn/forward-inline.h b/src/openvpn/forward-inline.h index ab83ea4..7d06b4e 100644 --- a/src/openvpn/forward-inline.h +++ b/src/openvpn/forward-inline.h @@ -5,7 +5,7 @@ * packet encryption, packet authentication, and * packet compression. * - * Copyright (C) 2002-2017 OpenVPN Technologies, Inc. <sales@openvpn.net> + * Copyright (C) 2002-2018 OpenVPN Inc <sales@openvpn.net> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 diff --git a/src/openvpn/forward.c b/src/openvpn/forward.c index 371ddca..8f90418 100644 --- a/src/openvpn/forward.c +++ b/src/openvpn/forward.c @@ -5,7 +5,7 @@ * packet encryption, packet authentication, and * packet compression. * - * Copyright (C) 2002-2017 OpenVPN Technologies, Inc. <sales@openvpn.net> + * Copyright (C) 2002-2018 OpenVPN Inc <sales@openvpn.net> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 @@ -496,7 +496,7 @@ encrypt_sign(struct context *c, bool comp_frag) /* If using P_DATA_V2, prepend the 1-byte opcode and 3-byte peer-id to the * packet before openvpn_encrypt(), so we can authenticate the opcode too. */ - if (c->c2.buf.len > 0 && !c->c2.tls_multi->opt.server && c->c2.tls_multi->use_peer_id) + if (c->c2.buf.len > 0 && c->c2.tls_multi->use_peer_id) { tls_prepend_opcode_v2(c->c2.tls_multi, &b->encrypt_buf); } @@ -512,7 +512,7 @@ encrypt_sign(struct context *c, bool comp_frag) /* Do packet administration */ if (c->c2.tls_multi) { - if (c->c2.buf.len > 0 && (c->c2.tls_multi->opt.server || !c->c2.tls_multi->use_peer_id)) + if (c->c2.buf.len > 0 && !c->c2.tls_multi->use_peer_id) { tls_prepend_opcode_v1(c->c2.tls_multi, &c->c2.buf); } @@ -756,7 +756,7 @@ read_incoming_link(struct context *c) if (event_timeout_defined(&c->c2.explicit_exit_notification_interval)) { msg(D_STREAM_ERRORS, "Connection reset during exit notification period, ignoring [%d]", status); - openvpn_sleep(1); + management_sleep(1); } else #endif @@ -1007,7 +1007,7 @@ process_incoming_link_part2(struct context *c, struct link_socket_info *lsi, con } } -void +static void process_incoming_link(struct context *c) { perf_push(PERF_PROC_IN_LINK); diff --git a/src/openvpn/forward.h b/src/openvpn/forward.h index 9fde5a3..924cc5e 100644 --- a/src/openvpn/forward.h +++ b/src/openvpn/forward.h @@ -5,7 +5,7 @@ * packet encryption, packet authentication, and * packet compression. * - * Copyright (C) 2002-2017 OpenVPN Technologies, Inc. <sales@openvpn.net> + * Copyright (C) 2002-2018 OpenVPN Inc <sales@openvpn.net> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 diff --git a/src/openvpn/fragment.c b/src/openvpn/fragment.c index 38de62f..4eb1dd2 100644 --- a/src/openvpn/fragment.c +++ b/src/openvpn/fragment.c @@ -5,7 +5,7 @@ * packet encryption, packet authentication, and * packet compression. * - * Copyright (C) 2002-2017 OpenVPN Technologies, Inc. <sales@openvpn.net> + * Copyright (C) 2002-2018 OpenVPN Inc <sales@openvpn.net> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 @@ -208,7 +208,7 @@ fragment_incoming(struct fragment_master *f, struct buffer *buf, } /* is this the first fragment for our sequence number? */ - if (!frag->defined || (frag->defined && frag->max_frag_size != size)) + if (!frag->defined || frag->max_frag_size != size) { frag->defined = true; frag->max_frag_size = size; diff --git a/src/openvpn/fragment.h b/src/openvpn/fragment.h index 90ba8f7..6fa9692 100644 --- a/src/openvpn/fragment.h +++ b/src/openvpn/fragment.h @@ -5,7 +5,7 @@ * packet encryption, packet authentication, and * packet compression. * - * Copyright (C) 2002-2017 OpenVPN Technologies, Inc. <sales@openvpn.net> + * Copyright (C) 2002-2018 OpenVPN Inc <sales@openvpn.net> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 diff --git a/src/openvpn/gremlin.c b/src/openvpn/gremlin.c index e85ce9c..114cb19 100644 --- a/src/openvpn/gremlin.c +++ b/src/openvpn/gremlin.c @@ -5,7 +5,7 @@ * packet encryption, packet authentication, and * packet compression. * - * Copyright (C) 2002-2017 OpenVPN Technologies, Inc. <sales@openvpn.net> + * Copyright (C) 2002-2018 OpenVPN Inc <sales@openvpn.net> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 diff --git a/src/openvpn/gremlin.h b/src/openvpn/gremlin.h index 8b23b34..22c90b9 100644 --- a/src/openvpn/gremlin.h +++ b/src/openvpn/gremlin.h @@ -5,7 +5,7 @@ * packet encryption, packet authentication, and * packet compression. * - * Copyright (C) 2002-2017 OpenVPN Technologies, Inc. <sales@openvpn.net> + * Copyright (C) 2002-2018 OpenVPN Inc <sales@openvpn.net> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 diff --git a/src/openvpn/helper.c b/src/openvpn/helper.c index 17d1528..ff9df50 100644 --- a/src/openvpn/helper.c +++ b/src/openvpn/helper.c @@ -5,7 +5,7 @@ * packet encryption, packet authentication, and * packet compression. * - * Copyright (C) 2002-2017 OpenVPN Technologies, Inc. <sales@openvpn.net> + * Copyright (C) 2002-2018 OpenVPN Inc <sales@openvpn.net> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 diff --git a/src/openvpn/helper.h b/src/openvpn/helper.h index c5b438b..866a398 100644 --- a/src/openvpn/helper.h +++ b/src/openvpn/helper.h @@ -5,7 +5,7 @@ * packet encryption, packet authentication, and * packet compression. * - * Copyright (C) 2002-2017 OpenVPN Technologies, Inc. <sales@openvpn.net> + * Copyright (C) 2002-2018 OpenVPN Inc <sales@openvpn.net> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 diff --git a/src/openvpn/httpdigest.c b/src/openvpn/httpdigest.c index c553f93..7cf74fd 100644 --- a/src/openvpn/httpdigest.c +++ b/src/openvpn/httpdigest.c @@ -5,7 +5,7 @@ * packet encryption, packet authentication, and * packet compression. * - * Copyright (C) 2002-2017 OpenVPN Technologies, Inc. <sales@openvpn.net> + * Copyright (C) 2002-2018 OpenVPN Inc <sales@openvpn.net> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 diff --git a/src/openvpn/httpdigest.h b/src/openvpn/httpdigest.h index aae7b8c..959220f 100644 --- a/src/openvpn/httpdigest.h +++ b/src/openvpn/httpdigest.h @@ -5,7 +5,7 @@ * packet encryption, packet authentication, and * packet compression. * - * Copyright (C) 2002-2017 OpenVPN Technologies, Inc. <sales@openvpn.net> + * Copyright (C) 2002-2018 OpenVPN Inc <sales@openvpn.net> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 diff --git a/src/openvpn/init.c b/src/openvpn/init.c index 0652ef4..6968c77 100644 --- a/src/openvpn/init.c +++ b/src/openvpn/init.c @@ -5,7 +5,7 @@ * packet encryption, packet authentication, and * packet compression. * - * Copyright (C) 2002-2017 OpenVPN Technologies, Inc. <sales@openvpn.net> + * Copyright (C) 2002-2018 OpenVPN Inc <sales@openvpn.net> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 @@ -94,6 +94,94 @@ context_clear_all_except_first_time(struct context *c) } /* + * Pass tunnel endpoint and MTU parms to a user-supplied script. + * Used to execute the up/down script/plugins. + */ +static void +run_up_down(const char *command, + const struct plugin_list *plugins, + int plugin_type, + const char *arg, +#ifdef _WIN32 + DWORD adapter_index, +#endif + const char *dev_type, + int tun_mtu, + int link_mtu, + const char *ifconfig_local, + const char *ifconfig_remote, + const char *context, + const char *signal_text, + const char *script_type, + struct env_set *es) +{ + struct gc_arena gc = gc_new(); + + if (signal_text) + { + setenv_str(es, "signal", signal_text); + } + setenv_str(es, "script_context", context); + setenv_int(es, "tun_mtu", tun_mtu); + setenv_int(es, "link_mtu", link_mtu); + setenv_str(es, "dev", arg); + if (dev_type) + { + setenv_str(es, "dev_type", dev_type); + } +#ifdef _WIN32 + setenv_int(es, "dev_idx", adapter_index); +#endif + + if (!ifconfig_local) + { + ifconfig_local = ""; + } + if (!ifconfig_remote) + { + ifconfig_remote = ""; + } + if (!context) + { + context = ""; + } + + if (plugin_defined(plugins, plugin_type)) + { + struct argv argv = argv_new(); + ASSERT(arg); + argv_printf(&argv, + "%s %d %d %s %s %s", + arg, + tun_mtu, link_mtu, + ifconfig_local, ifconfig_remote, + context); + + if (plugin_call(plugins, plugin_type, &argv, NULL, es) != OPENVPN_PLUGIN_FUNC_SUCCESS) + { + msg(M_FATAL, "ERROR: up/down plugin call failed"); + } + + argv_reset(&argv); + } + + if (command) + { + struct argv argv = argv_new(); + ASSERT(arg); + setenv_str(es, "script_type", script_type); + argv_parse_cmd(&argv, command); + argv_printf_cat(&argv, "%s %d %d %s %s %s", arg, tun_mtu, link_mtu, + ifconfig_local, ifconfig_remote, context); + argv_msg(M_INFO, &argv); + openvpn_run_script(&argv, es, S_FATAL, "--up/--down"); + argv_reset(&argv); + } + + gc_free(&gc); +} + +/* * Should be called after options->ce is modified at the top * of a SIGUSR1 restart. */ @@ -150,7 +238,7 @@ management_callback_proxy_cmd(void *arg, const char **p) else if (streq(p[1], "SOCKS")) { ce->socks_proxy_server = string_alloc(p[2], gc); - ce->socks_proxy_port = p[3]; + ce->socks_proxy_port = string_alloc(p[3], gc); ret = true; } } @@ -610,6 +698,7 @@ init_port_share(struct context *c) #endif /* if PORT_SHARE */ + bool init_static(void) { @@ -619,8 +708,20 @@ init_static(void) crypto_init_dmalloc(); #endif - init_random_seed(); /* init random() function, only used as - * source for weak random numbers */ + + /* + * Initialize random number seed. random() is only used + * when "weak" random numbers are acceptable. + * SSL library routines are always used when cryptographically + * strong random numbers are required. + */ + struct timeval tv; + if (!gettimeofday(&tv, NULL)) + { + const unsigned int seed = (unsigned int) tv.tv_sec ^ tv.tv_usec; + srandom(seed); + } + error_reset(); /* initialize error.c */ reset_check_status(); /* initialize status check code in socket.c */ @@ -915,7 +1016,8 @@ print_openssl_info(const struct options *options) } if (options->show_tls_ciphers) { - show_available_tls_ciphers(options->cipher_list); + show_available_tls_ciphers(options->cipher_list, + options->tls_cert_profile); } if (options->show_curves) { @@ -1904,7 +2006,7 @@ do_close_tun(struct context *c, bool force) } void -tun_abort() +tun_abort(void) { struct context *c = static_context; if (c) @@ -1969,7 +2071,7 @@ do_up(struct context *c, bool pulled_options, unsigned int option_types_found) /* if so, close tun, delete routes, then reinitialize tun and add routes */ msg(M_INFO, "NOTE: Pulled options changed on restart, will need to close and reopen TUN/TAP device."); do_close_tun(c, true); - openvpn_sleep(1); + management_sleep(1); c->c2.did_open_tun = do_open_tun(c); update_time(); } @@ -2263,7 +2365,7 @@ socket_restart_pause(struct context *c) if (sec) { msg(D_RESTART, "Restart pause, %d second(s)", sec); - openvpn_sleep(sec); + management_sleep(sec); } } @@ -3332,6 +3434,12 @@ do_close_tls(struct context *c) } c->c2.options_string_local = c->c2.options_string_remote = NULL; #endif + + if (c->c2.pulled_options_state) + { + md_ctx_cleanup(c->c2.pulled_options_state); + md_ctx_free(c->c2.pulled_options_state); + } #endif } diff --git a/src/openvpn/init.h b/src/openvpn/init.h index 15feb67..c8ebe76 100644 --- a/src/openvpn/init.h +++ b/src/openvpn/init.h @@ -5,7 +5,7 @@ * packet encryption, packet authentication, and * packet compression. * - * Copyright (C) 2002-2017 OpenVPN Technologies, Inc. <sales@openvpn.net> + * Copyright (C) 2002-2018 OpenVPN Inc <sales@openvpn.net> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 diff --git a/src/openvpn/integer.h b/src/openvpn/integer.h index 240781b..a7e19d3 100644 --- a/src/openvpn/integer.h +++ b/src/openvpn/integer.h @@ -5,7 +5,7 @@ * packet encryption, packet authentication, and * packet compression. * - * Copyright (C) 2002-2017 OpenVPN Technologies, Inc. <sales@openvpn.net> + * Copyright (C) 2002-2018 OpenVPN Inc <sales@openvpn.net> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 @@ -118,6 +118,24 @@ modulo_add(int x, int y, int mod) return sum; } +/* + * Return the next largest power of 2 + * or u if u is a power of 2. + */ +static inline size_t +adjust_power_of_2(size_t u) +{ + size_t ret = 1; + + while (ret < u) + { + ret <<= 1; + ASSERT(ret > 0); + } + + return ret; +} + static inline int index_verify(int index, int size, const char *file, int line) { diff --git a/src/openvpn/interval.c b/src/openvpn/interval.c index 1634386..00ee627 100644 --- a/src/openvpn/interval.c +++ b/src/openvpn/interval.c @@ -5,7 +5,7 @@ * packet encryption, packet authentication, and * packet compression. * - * Copyright (C) 2002-2017 OpenVPN Technologies, Inc. <sales@openvpn.net> + * Copyright (C) 2002-2018 OpenVPN Inc <sales@openvpn.net> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 diff --git a/src/openvpn/interval.h b/src/openvpn/interval.h index 8095c0b..826a08b 100644 --- a/src/openvpn/interval.h +++ b/src/openvpn/interval.h @@ -5,7 +5,7 @@ * packet encryption, packet authentication, and * packet compression. * - * Copyright (C) 2002-2017 OpenVPN Technologies, Inc. <sales@openvpn.net> + * Copyright (C) 2002-2018 OpenVPN Inc <sales@openvpn.net> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 @@ -155,7 +155,7 @@ event_timeout_clear(struct event_timeout *et) } static inline struct event_timeout -event_timeout_clear_ret() +event_timeout_clear_ret(void) { struct event_timeout ret; event_timeout_clear(&ret); diff --git a/src/openvpn/list.c b/src/openvpn/list.c index edca6f7..09e393a 100644 --- a/src/openvpn/list.c +++ b/src/openvpn/list.c @@ -5,7 +5,7 @@ * packet encryption, packet authentication, and * packet compression. * - * Copyright (C) 2002-2017 OpenVPN Technologies, Inc. <sales@openvpn.net> + * Copyright (C) 2002-2018 OpenVPN Inc <sales@openvpn.net> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 @@ -31,6 +31,7 @@ #if P2MP_SERVER +#include "integer.h" #include "list.h" #include "misc.h" diff --git a/src/openvpn/list.h b/src/openvpn/list.h index c808efa..b67301c 100644 --- a/src/openvpn/list.h +++ b/src/openvpn/list.h @@ -5,7 +5,7 @@ * packet encryption, packet authentication, and * packet compression. * - * Copyright (C) 2002-2017 OpenVPN Technologies, Inc. <sales@openvpn.net> + * Copyright (C) 2002-2018 OpenVPN Inc <sales@openvpn.net> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 diff --git a/src/openvpn/lzo.c b/src/openvpn/lzo.c index f754865..8d9efea 100644 --- a/src/openvpn/lzo.c +++ b/src/openvpn/lzo.c @@ -5,7 +5,7 @@ * packet encryption, packet authentication, and * packet compression. * - * Copyright (C) 2002-2017 OpenVPN Technologies, Inc. <sales@openvpn.net> + * Copyright (C) 2002-2018 OpenVPN Inc <sales@openvpn.net> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 diff --git a/src/openvpn/lzo.h b/src/openvpn/lzo.h index deaeb8d..11e1c39 100644 --- a/src/openvpn/lzo.h +++ b/src/openvpn/lzo.h @@ -5,7 +5,7 @@ * packet encryption, packet authentication, and * packet compression. * - * Copyright (C) 2002-2017 OpenVPN Technologies, Inc. <sales@openvpn.net> + * Copyright (C) 2002-2018 OpenVPN Inc <sales@openvpn.net> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 diff --git a/src/openvpn/manage.c b/src/openvpn/manage.c index c2e8dc7..61d61ef 100644 --- a/src/openvpn/manage.c +++ b/src/openvpn/manage.c @@ -5,7 +5,7 @@ * packet encryption, packet authentication, and * packet compression. * - * Copyright (C) 2002-2017 OpenVPN Technologies, Inc. <sales@openvpn.net> + * Copyright (C) 2002-2018 OpenVPN Inc <sales@openvpn.net> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 @@ -68,7 +68,7 @@ static void man_output_standalone(struct management *man, volatile int *signal_r static void man_reset_client_socket(struct management *man, const bool exiting); static void -man_help() +man_help(void) { msg(M_CLIENT, "Management Interface for %s", title_string); msg(M_CLIENT, "Commands:"); @@ -250,7 +250,7 @@ man_output_list_push_str(struct management *man, const char *str) { if (management_connected(man) && str) { - buffer_list_push(man->connection.out, (const unsigned char *) str); + buffer_list_push(man->connection.out, str); } } @@ -1878,17 +1878,15 @@ man_connect(struct management *man) #if UNIX_SOCK_SUPPORT if (man->settings.flags & MF_UNIX_SOCK) { - msg(D_LINK_ERRORS, - "MANAGEMENT: connect to unix socket %s failed: %s", - sockaddr_unix_name(&man->settings.local_unix, "NULL"), - strerror_ts(status, &gc)); + msg(D_LINK_ERRORS | M_ERRNO, + "MANAGEMENT: connect to unix socket %s failed", + sockaddr_unix_name(&man->settings.local_unix, "NULL")); } else #endif - msg(D_LINK_ERRORS, - "MANAGEMENT: connect to %s failed: %s", - print_sockaddr(man->settings.local->ai_addr, &gc), - strerror_ts(status, &gc)); + msg(D_LINK_ERRORS | M_ERRNO, + "MANAGEMENT: connect to %s failed", + print_sockaddr(man->settings.local->ai_addr, &gc)); throw_signal_soft(SIGTERM, "management-connect-failed"); goto done; } @@ -2008,9 +2006,8 @@ man_io_error(struct management *man, const char *prefix) if (!ignore_sys_error(err)) { struct gc_arena gc = gc_new(); - msg(D_MANAGEMENT, "MANAGEMENT: TCP %s error: %s", - prefix, - strerror_ts(err, &gc)); + msg(D_MANAGEMENT, "MANAGEMENT: TCP %s error: %s", prefix, + strerror(err)); gc_free(&gc); return true; } @@ -2196,13 +2193,13 @@ man_read(struct management *man) * process command line if complete */ { - const unsigned char *line; + const char *line; while ((line = command_line_get(man->connection.in))) { #ifdef MANAGEMENT_IN_EXTRA if (man->connection.in_extra) { - if (!strcmp((char *)line, "END")) + if (!strcmp(line, "END")) { in_extra_dispatch(man); } @@ -3504,7 +3501,9 @@ management_query_user_pass(struct management *man, */ if (ret) { - man->connection.up_query.nocache = up->nocache; /* preserve caller's nocache setting */ + /* preserve caller's settings */ + man->connection.up_query.nocache = up->nocache; + man->connection.up_query.wait_for_push = up->wait_for_push; *up = man->connection.up_query; } secure_memzero(&man->connection.up_query, sizeof(man->connection.up_query)); @@ -3516,7 +3515,7 @@ management_query_user_pass(struct management *man, #ifdef MANAGMENT_EXTERNAL_KEY -int +static int management_query_multiline(struct management *man, const char *b64_data, const char *prompt, const char *cmd, int *state, struct buffer_list **input) { @@ -3592,7 +3591,7 @@ done: return ret; } -char * +static char * /* returns allocated base64 signature */ management_query_multiline_flatten_newline(struct management *man, const char *b64_data, const char *prompt, const char *cmd, int *state, struct buffer_list **input) @@ -3621,7 +3620,7 @@ management_query_multiline_flatten_newline(struct management *man, return result; } -char * +static char * /* returns allocated base64 signature */ management_query_multiline_flatten(struct management *man, const char *b64_data, const char *prompt, const char *cmd, int *state, struct buffer_list **input) @@ -3795,18 +3794,18 @@ command_line_add(struct command_line *cl, const unsigned char *buf, const int le } } -const unsigned char * +const char * command_line_get(struct command_line *cl) { int i; - const unsigned char *ret = NULL; + const char *ret = NULL; i = buf_substring_len(&cl->buf, '\n'); if (i >= 0) { buf_copy_excess(&cl->residual, &cl->buf, i); buf_chomp(&cl->buf); - ret = (const unsigned char *) BSTR(&cl->buf); + ret = BSTR(&cl->buf); } return ret; } @@ -4000,9 +3999,25 @@ log_history_ref(const struct log_history *h, const int index) } } +void +management_sleep(const int n) +{ + if (management) + { + management_event_loop_n_seconds(management, n); + } + else + { + sleep(n); + } +} + #else /* ifdef ENABLE_MANAGEMENT */ -static void -dummy(void) + +void +management_sleep(const int n) { + sleep(n); } + #endif /* ENABLE_MANAGEMENT */ diff --git a/src/openvpn/manage.h b/src/openvpn/manage.h index 542cc07..f286754 100644 --- a/src/openvpn/manage.h +++ b/src/openvpn/manage.h @@ -5,7 +5,7 @@ * packet encryption, packet authentication, and * packet compression. * - * Copyright (C) 2002-2017 OpenVPN Technologies, Inc. <sales@openvpn.net> + * Copyright (C) 2002-2018 OpenVPN Inc <sales@openvpn.net> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 @@ -70,7 +70,7 @@ void command_line_free(struct command_line *cl); void command_line_add(struct command_line *cl, const unsigned char *buf, const int len); -const unsigned char *command_line_get(struct command_line *cl); +const char *command_line_get(struct command_line *cl); void command_line_reset(struct command_line *cl); @@ -605,4 +605,11 @@ management_bytes_server(struct management *man, #endif /* MANAGEMENT_DEF_AUTH */ #endif /* ifdef ENABLE_MANAGEMENT */ + +/** + * A sleep function that services the management layer for n seconds rather + * than doing nothing. + */ +void management_sleep(const int n); + #endif /* ifndef MANAGE_H */ diff --git a/src/openvpn/mbuf.c b/src/openvpn/mbuf.c index fafbce0..87faff0 100644 --- a/src/openvpn/mbuf.c +++ b/src/openvpn/mbuf.c @@ -5,7 +5,7 @@ * packet encryption, packet authentication, and * packet compression. * - * Copyright (C) 2002-2017 OpenVPN Technologies, Inc. <sales@openvpn.net> + * Copyright (C) 2002-2018 OpenVPN Inc <sales@openvpn.net> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 @@ -33,6 +33,7 @@ #include "buffer.h" #include "error.h" +#include "integer.h" #include "misc.h" #include "mbuf.h" diff --git a/src/openvpn/mbuf.h b/src/openvpn/mbuf.h index e0643de..4912c95 100644 --- a/src/openvpn/mbuf.h +++ b/src/openvpn/mbuf.h @@ -5,7 +5,7 @@ * packet encryption, packet authentication, and * packet compression. * - * Copyright (C) 2002-2017 OpenVPN Technologies, Inc. <sales@openvpn.net> + * Copyright (C) 2002-2018 OpenVPN Inc <sales@openvpn.net> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 diff --git a/src/openvpn/memdbg.h b/src/openvpn/memdbg.h index 0ba695f..70c6365 100644 --- a/src/openvpn/memdbg.h +++ b/src/openvpn/memdbg.h @@ -5,7 +5,7 @@ * packet encryption, packet authentication, and * packet compression. * - * Copyright (C) 2002-2017 OpenVPN Technologies, Inc. <sales@openvpn.net> + * Copyright (C) 2002-2018 OpenVPN Inc <sales@openvpn.net> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 diff --git a/src/openvpn/misc.c b/src/openvpn/misc.c index fbd9938..77bb671 100644 --- a/src/openvpn/misc.c +++ b/src/openvpn/misc.c @@ -5,9 +5,9 @@ * packet encryption, packet authentication, and * packet compression. * - * Copyright (C) 2002-2017 OpenVPN Technologies, Inc. <sales@openvpn.net> + * Copyright (C) 2002-2018 OpenVPN Inc <sales@openvpn.net> * Copyright (C) 2014-2015 David Sommerseth <davids@redhat.com> - * Copyright (C) 2016-2017 David Sommerseth <davids@openvpn.net> + * Copyright (C) 2016-2018 David Sommerseth <davids@openvpn.net> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 @@ -55,116 +55,6 @@ const char *iproute_path = IPROUTE_PATH; /* GLOBAL */ int script_security = SSEC_BUILT_IN; /* GLOBAL */ /* - * Pass tunnel endpoint and MTU parms to a user-supplied script. - * Used to execute the up/down script/plugins. - */ -void -run_up_down(const char *command, - const struct plugin_list *plugins, - int plugin_type, - const char *arg, -#ifdef _WIN32 - DWORD adapter_index, -#endif - const char *dev_type, - int tun_mtu, - int link_mtu, - const char *ifconfig_local, - const char *ifconfig_remote, - const char *context, - const char *signal_text, - const char *script_type, - struct env_set *es) -{ - struct gc_arena gc = gc_new(); - - if (signal_text) - { - setenv_str(es, "signal", signal_text); - } - setenv_str(es, "script_context", context); - setenv_int(es, "tun_mtu", tun_mtu); - setenv_int(es, "link_mtu", link_mtu); - setenv_str(es, "dev", arg); - if (dev_type) - { - setenv_str(es, "dev_type", dev_type); - } -#ifdef _WIN32 - setenv_int(es, "dev_idx", adapter_index); -#endif - - if (!ifconfig_local) - { - ifconfig_local = ""; - } - if (!ifconfig_remote) - { - ifconfig_remote = ""; - } - if (!context) - { - context = ""; - } - - if (plugin_defined(plugins, plugin_type)) - { - struct argv argv = argv_new(); - ASSERT(arg); - argv_printf(&argv, - "%s %d %d %s %s %s", - arg, - tun_mtu, link_mtu, - ifconfig_local, ifconfig_remote, - context); - - if (plugin_call(plugins, plugin_type, &argv, NULL, es) != OPENVPN_PLUGIN_FUNC_SUCCESS) - { - msg(M_FATAL, "ERROR: up/down plugin call failed"); - } - - argv_reset(&argv); - } - - if (command) - { - struct argv argv = argv_new(); - ASSERT(arg); - setenv_str(es, "script_type", script_type); - argv_parse_cmd(&argv, command); - argv_printf_cat(&argv, "%s %d %d %s %s %s", arg, tun_mtu, link_mtu, - ifconfig_local, ifconfig_remote, context); - argv_msg(M_INFO, &argv); - openvpn_run_script(&argv, es, S_FATAL, "--up/--down"); - argv_reset(&argv); - } - - gc_free(&gc); -} - -/* Write our PID to a file */ -void -write_pid(const char *filename) -{ - if (filename) - { - unsigned int pid = 0; - FILE *fp = platform_fopen(filename, "w"); - if (!fp) - { - msg(M_ERR, "Open error on pid file %s", filename); - } - - pid = platform_getpid(); - fprintf(fp, "%u\n", pid); - if (fclose(fp)) - { - msg(M_ERR, "Close error on pid file %s", filename); - } - } -} - -/* * Set standard file descriptors to /dev/null */ void @@ -426,40 +316,6 @@ openvpn_popen(const struct argv *a, const struct env_set *es) /* - * Initialize random number seed. random() is only used - * when "weak" random numbers are acceptable. - * OpenSSL routines are always used when cryptographically - * strong random numbers are required. - */ - -void -init_random_seed(void) -{ - struct timeval tv; - - if (!gettimeofday(&tv, NULL)) - { - const unsigned int seed = (unsigned int) tv.tv_sec ^ tv.tv_usec; - srandom(seed); - } -} - -/* thread-safe strerror */ - -const char * -strerror_ts(int errnum, struct gc_arena *gc) -{ -#ifdef HAVE_STRERROR - struct buffer out = alloc_buf_gc(256, gc); - - buf_printf(&out, "%s", openvpn_strerror(errnum, gc)); - return BSTR(&out); -#else - return "[error string unavailable]"; -#endif -} - -/* * Set environmental variable (int or string). * * On Posix, we use putenv for portability, @@ -484,29 +340,6 @@ construct_name_value(const char *name, const char *value, struct gc_arena *gc) return BSTR(&out); } -bool -deconstruct_name_value(const char *str, const char **name, const char **value, struct gc_arena *gc) -{ - char *cp; - - ASSERT(str); - ASSERT(name && value); - - *name = cp = string_alloc(str, gc); - *value = NULL; - - while ((*cp)) - { - if (*cp == '=' && !*value) - { - *cp = 0; - *value = cp + 1; - } - ++cp; - } - return *name && *value; -} - static bool env_string_equal(const char *s1, const char *s2) { @@ -886,8 +719,6 @@ test_file(const char *filename) return ret; } -#ifdef ENABLE_CRYPTO - /* create a temporary filename in directory */ const char * create_temp_file(const char *directory, const char *prefix, struct gc_arena *gc) @@ -900,20 +731,16 @@ create_temp_file(const char *directory, const char *prefix, struct gc_arena *gc) do { - uint8_t rndbytes[16]; - const char *rndstr; - ++attempts; ++counter; - prng_bytes(rndbytes, sizeof rndbytes); - rndstr = format_hex_ex(rndbytes, sizeof rndbytes, 40, 0, NULL, gc); - buf_printf(&fname, PACKAGE "_%s_%s.tmp", prefix, rndstr); + buf_printf(&fname, PACKAGE "_%s_%08lx%08lx.tmp", prefix, + (unsigned long) get_random(), (unsigned long) get_random()); retfname = gen_path(directory, BSTR(&fname), gc); if (!retfname) { - msg(M_FATAL, "Failed to create temporary filename and path"); + msg(M_WARN, "Failed to create temporary filename and path"); return NULL; } @@ -928,19 +755,19 @@ create_temp_file(const char *directory, const char *prefix, struct gc_arena *gc) else if (fd == -1 && errno != EEXIST) { /* Something else went wrong, no need to retry. */ - struct gc_arena gcerr = gc_new(); - msg(M_FATAL, "Could not create temporary file '%s': %s", - retfname, strerror_ts(errno, &gcerr)); - gc_free(&gcerr); + msg(M_WARN | M_ERRNO, "Could not create temporary file '%s'", + retfname); return NULL; } } while (attempts < 6); - msg(M_FATAL, "Failed to create temporary file after %i attempts", attempts); + msg(M_WARN, "Failed to create temporary file after %i attempts", attempts); return NULL; } +#ifdef ENABLE_CRYPTO + /* * Prepend a random string to hostname to prevent DNS caching. * For example, foo.bar.gov would be modified to <random-chars>.foo.bar.gov. @@ -1632,37 +1459,6 @@ make_extended_arg_array(char **p, struct gc_arena *gc) } } -void -openvpn_sleep(const int n) -{ -#ifdef ENABLE_MANAGEMENT - if (management) - { - management_event_loop_n_seconds(management, n); - return; - } -#endif - sleep(n); -} - -/* - * Return the next largest power of 2 - * or u if u is a power of 2. - */ -size_t -adjust_power_of_2(size_t u) -{ - size_t ret = 1; - - while (ret < u) - { - ret <<= 1; - ASSERT(ret > 0); - } - - return ret; -} - /* * Remove security-sensitive strings from control message * so that they will not be output to log file. diff --git a/src/openvpn/misc.h b/src/openvpn/misc.h index ce96549..9f358ae 100644 --- a/src/openvpn/misc.h +++ b/src/openvpn/misc.h @@ -5,7 +5,7 @@ * packet encryption, packet authentication, and * packet compression. * - * Copyright (C) 2002-2017 OpenVPN Technologies, Inc. <sales@openvpn.net> + * Copyright (C) 2002-2018 OpenVPN Inc <sales@openvpn.net> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 @@ -51,25 +51,6 @@ struct env_set { struct env_item *list; }; -void run_up_down(const char *command, - const struct plugin_list *plugins, - int plugin_type, - const char *arg, -#ifdef _WIN32 - DWORD adapter_index, -#endif - const char *dev_type, - int tun_mtu, - int link_mtu, - const char *ifconfig_local, - const char *ifconfig_remote, - const char *context, - const char *signal_text, - const char *script_type, - struct env_set *es); - -void write_pid(const char *filename); - /* system flags */ #define S_SCRIPT (1<<0) #define S_FATAL (1<<1) @@ -95,12 +76,6 @@ openvpn_run_script(const struct argv *a, const struct env_set *es, const unsigne } -#ifdef HAVE_STRERROR -/* a thread-safe version of strerror */ -const char *strerror_ts(int errnum, struct gc_arena *gc); - -#endif - /* Set standard file descriptors to /dev/null */ void set_std_files_to_null(bool stdin_only); @@ -108,9 +83,6 @@ void set_std_files_to_null(bool stdin_only); extern int inetd_socket_descriptor; void save_inetd_socket_descriptor(void); -/* init random() function, only used as source for weak random numbers, when !ENABLE_CRYPTO */ -void init_random_seed(void); - /* set/delete environmental variable */ void setenv_str_ex(struct env_set *es, const char *name, @@ -298,12 +270,6 @@ bool env_safe_to_print(const char *str); /* returns true if environmental variable may be passed to an external program */ bool env_allowed(const char *str); -/* - * A sleep function that services the management layer for n - * seconds rather than doing nothing. - */ -void openvpn_sleep(const int n); - void configure_path(void); const char *sanitize_control_message(const char *str, struct gc_arena *gc); @@ -327,8 +293,6 @@ extern const char *iproute_path; #define SSEC_PW_ENV 3 /* allow calling of built-in programs and user-defined scripts that may receive a password as an environmental variable */ extern int script_security; /* GLOBAL */ -/* return the next largest power of 2 */ -size_t adjust_power_of_2(size_t u); #define COMPAT_FLAG_QUERY 0 /** compat_flags operator: Query for a flag */ #define COMPAT_FLAG_SET (1<<0) /** compat_flags operator: Set a compat flag */ diff --git a/src/openvpn/mroute.c b/src/openvpn/mroute.c index 7b46a6a..28940a8 100644 --- a/src/openvpn/mroute.c +++ b/src/openvpn/mroute.c @@ -5,7 +5,7 @@ * packet encryption, packet authentication, and * packet compression. * - * Copyright (C) 2002-2017 OpenVPN Technologies, Inc. <sales@openvpn.net> + * Copyright (C) 2002-2018 OpenVPN Inc <sales@openvpn.net> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 @@ -65,25 +65,49 @@ is_mac_mcast_maddr(const struct mroute_addr *addr) * Don't learn certain addresses. */ bool -mroute_learnable_address(const struct mroute_addr *addr) +mroute_learnable_address(const struct mroute_addr *addr, struct gc_arena *gc) { int i; - bool not_all_zeros = false; - bool not_all_ones = false; + bool all_zeros = true; + bool all_ones = true; for (i = 0; i < addr->len; ++i) { int b = addr->raw_addr[i]; if (b != 0x00) { - not_all_zeros = true; + all_zeros = false; } if (b != 0xFF) { - not_all_ones = true; + all_ones = false; } } - return not_all_zeros && not_all_ones && !is_mac_mcast_maddr(addr); + + /* only networkss shorter than 8 bits are allowed to be all 0s. */ + if (all_zeros + && !((addr->type & MR_WITH_NETBITS) && (addr->netbits < 8))) + { + msg(D_MULTI_LOW, "Can't learn %s: network is all 0s, but netbits >= 8", + mroute_addr_print(addr, gc)); + return false; + } + + if (all_ones) + { + msg(D_MULTI_LOW, "Can't learn %s: network is all 1s", + mroute_addr_print(addr, gc)); + return false; + } + + if (is_mac_mcast_maddr(addr)) + { + msg(D_MULTI_LOW, "Can't learn %s: network is a multicast address", + mroute_addr_print(addr, gc)); + return false; + } + + return true; } static inline void @@ -159,9 +183,8 @@ mroute_extract_addr_arp(struct mroute_addr *src, #endif /* ifdef ENABLE_PF */ unsigned int -mroute_extract_addr_ipv4(struct mroute_addr *src, - struct mroute_addr *dest, - const struct buffer *buf) +mroute_extract_addr_ip(struct mroute_addr *src, struct mroute_addr *dest, + const struct buffer *buf) { unsigned int ret = 0; if (BLEN(buf) >= 1) @@ -267,7 +290,7 @@ mroute_extract_addr_ether(struct mroute_addr *src, switch (ntohs(eth->proto)) { case OPENVPN_ETH_P_IPV4: - ret |= (mroute_extract_addr_ipv4(esrc, edest, &b) << MROUTE_SEC_SHIFT); + ret |= (mroute_extract_addr_ip(esrc, edest, &b) << MROUTE_SEC_SHIFT); break; case OPENVPN_ETH_P_ARP: diff --git a/src/openvpn/mroute.h b/src/openvpn/mroute.h index e57a950..1063a18 100644 --- a/src/openvpn/mroute.h +++ b/src/openvpn/mroute.h @@ -5,7 +5,7 @@ * packet encryption, packet authentication, and * packet compression. * - * Copyright (C) 2002-2017 OpenVPN Technologies, Inc. <sales@openvpn.net> + * Copyright (C) 2002-2018 OpenVPN Inc <sales@openvpn.net> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 @@ -141,7 +141,8 @@ bool mroute_extract_openvpn_sockaddr(struct mroute_addr *addr, const struct openvpn_sockaddr *osaddr, bool use_port); -bool mroute_learnable_address(const struct mroute_addr *addr); +bool mroute_learnable_address(const struct mroute_addr *addr, + struct gc_arena *gc); uint32_t mroute_addr_hash_function(const void *key, uint32_t iv); @@ -181,9 +182,9 @@ mroute_extract_addr_from_packet(struct mroute_addr *src, const struct buffer *buf, int tunnel_type) { - unsigned int mroute_extract_addr_ipv4(struct mroute_addr *src, - struct mroute_addr *dest, - const struct buffer *buf); + unsigned int mroute_extract_addr_ip(struct mroute_addr *src, + struct mroute_addr *dest, + const struct buffer *buf); unsigned int mroute_extract_addr_ether(struct mroute_addr *src, struct mroute_addr *dest, @@ -195,7 +196,7 @@ mroute_extract_addr_from_packet(struct mroute_addr *src, verify_align_4(buf); if (tunnel_type == DEV_TYPE_TUN) { - ret = mroute_extract_addr_ipv4(src, dest, buf); + ret = mroute_extract_addr_ip(src, dest, buf); } else if (tunnel_type == DEV_TYPE_TAP) { diff --git a/src/openvpn/mss.c b/src/openvpn/mss.c index c36e004..facdf7b 100644 --- a/src/openvpn/mss.c +++ b/src/openvpn/mss.c @@ -5,7 +5,7 @@ * packet encryption, packet authentication, and * packet compression. * - * Copyright (C) 2002-2017 OpenVPN Technologies, Inc. <sales@openvpn.net> + * Copyright (C) 2002-2018 OpenVPN Inc <sales@openvpn.net> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 diff --git a/src/openvpn/mss.h b/src/openvpn/mss.h index 0de2042..9350102 100644 --- a/src/openvpn/mss.h +++ b/src/openvpn/mss.h @@ -5,7 +5,7 @@ * packet encryption, packet authentication, and * packet compression. * - * Copyright (C) 2002-2017 OpenVPN Technologies, Inc. <sales@openvpn.net> + * Copyright (C) 2002-2018 OpenVPN Inc <sales@openvpn.net> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 diff --git a/src/openvpn/mstats.c b/src/openvpn/mstats.c index 9b09188..281a835 100644 --- a/src/openvpn/mstats.c +++ b/src/openvpn/mstats.c @@ -5,7 +5,7 @@ * packet encryption, packet authentication, and * packet compression. * - * Copyright (C) 2002-2017 OpenVPN Technologies, Inc. <sales@openvpn.net> + * Copyright (C) 2002-2018 OpenVPN Inc <sales@openvpn.net> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 diff --git a/src/openvpn/mstats.h b/src/openvpn/mstats.h index 486035f..0d58cbf 100644 --- a/src/openvpn/mstats.h +++ b/src/openvpn/mstats.h @@ -5,7 +5,7 @@ * packet encryption, packet authentication, and * packet compression. * - * Copyright (C) 2002-2017 OpenVPN Technologies, Inc. <sales@openvpn.net> + * Copyright (C) 2002-2018 OpenVPN Inc <sales@openvpn.net> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 diff --git a/src/openvpn/mtcp.c b/src/openvpn/mtcp.c index cb940d8..3756c27 100644 --- a/src/openvpn/mtcp.c +++ b/src/openvpn/mtcp.c @@ -5,7 +5,7 @@ * packet encryption, packet authentication, and * packet compression. * - * Copyright (C) 2002-2017 OpenVPN Technologies, Inc. <sales@openvpn.net> + * Copyright (C) 2002-2018 OpenVPN Inc <sales@openvpn.net> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 @@ -521,7 +521,7 @@ multi_tcp_dispatch(struct multi_context *m, struct multi_instance *mi, const int return touched; } -int +static int multi_tcp_post(struct multi_context *m, struct multi_instance *mi, const int action) { struct context *c = multi_tcp_context(m, mi); @@ -797,7 +797,7 @@ tunnel_server_tcp(struct context *top) multi.top.c2.inotify_fd = inotify_init(); if (multi.top.c2.inotify_fd < 0) { - msg(D_MULTI_ERRORS, "MULTI: inotify_init error: %s", strerror(errno)); + msg(D_MULTI_ERRORS | M_ERRNO, "MULTI: inotify_init error"); } #endif diff --git a/src/openvpn/mtcp.h b/src/openvpn/mtcp.h index 79dcb13..bba455b 100644 --- a/src/openvpn/mtcp.h +++ b/src/openvpn/mtcp.h @@ -5,7 +5,7 @@ * packet encryption, packet authentication, and * packet compression. * - * Copyright (C) 2002-2017 OpenVPN Technologies, Inc. <sales@openvpn.net> + * Copyright (C) 2002-2018 OpenVPN Inc <sales@openvpn.net> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 diff --git a/src/openvpn/mtu.c b/src/openvpn/mtu.c index 44bef68..04868cd 100644 --- a/src/openvpn/mtu.c +++ b/src/openvpn/mtu.c @@ -5,7 +5,7 @@ * packet encryption, packet authentication, and * packet compression. * - * Copyright (C) 2002-2017 OpenVPN Technologies, Inc. <sales@openvpn.net> + * Copyright (C) 2002-2018 OpenVPN Inc <sales@openvpn.net> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 diff --git a/src/openvpn/mtu.h b/src/openvpn/mtu.h index d1e8c18..a82154a 100644 --- a/src/openvpn/mtu.h +++ b/src/openvpn/mtu.h @@ -5,7 +5,7 @@ * packet encryption, packet authentication, and * packet compression. * - * Copyright (C) 2002-2017 OpenVPN Technologies, Inc. <sales@openvpn.net> + * Copyright (C) 2002-2018 OpenVPN Inc <sales@openvpn.net> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 diff --git a/src/openvpn/mudp.c b/src/openvpn/mudp.c index 793678d..b3690ab 100644 --- a/src/openvpn/mudp.c +++ b/src/openvpn/mudp.c @@ -5,7 +5,7 @@ * packet encryption, packet authentication, and * packet compression. * - * Copyright (C) 2002-2017 OpenVPN Technologies, Inc. <sales@openvpn.net> + * Copyright (C) 2002-2018 OpenVPN Inc <sales@openvpn.net> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 @@ -325,7 +325,7 @@ tunnel_server_udp_single_threaded(struct context *top) multi.top.c2.inotify_fd = inotify_init(); if (multi.top.c2.inotify_fd < 0) { - msg(D_MULTI_ERRORS, "MULTI: inotify_init error: %s", strerror(errno)); + msg(D_MULTI_ERRORS | M_ERRNO, "MULTI: inotify_init error"); } #endif diff --git a/src/openvpn/mudp.h b/src/openvpn/mudp.h index b9ceaf7..7e31151 100644 --- a/src/openvpn/mudp.h +++ b/src/openvpn/mudp.h @@ -5,7 +5,7 @@ * packet encryption, packet authentication, and * packet compression. * - * Copyright (C) 2002-2017 OpenVPN Technologies, Inc. <sales@openvpn.net> + * Copyright (C) 2002-2018 OpenVPN Inc <sales@openvpn.net> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 diff --git a/src/openvpn/multi.c b/src/openvpn/multi.c index 8d3d67f..28c3b88 100644 --- a/src/openvpn/multi.c +++ b/src/openvpn/multi.c @@ -5,7 +5,7 @@ * packet encryption, packet authentication, and * packet compression. * - * Copyright (C) 2002-2017 OpenVPN Technologies, Inc. <sales@openvpn.net> + * Copyright (C) 2002-2018 OpenVPN Inc <sales@openvpn.net> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 @@ -485,7 +485,7 @@ multi_instance_string(const struct multi_instance *mi, bool null, struct gc_aren } } -void +static void generate_prefix(struct multi_instance *mi) { struct gc_arena gc = gc_new(); @@ -1077,6 +1077,7 @@ multi_learn_addr(struct multi_context *m, struct hash_bucket *bucket = hash_bucket(m->vhash, hv); struct multi_route *oldroute = NULL; struct multi_instance *owner = NULL; + struct gc_arena gc = gc_new(); /* if route currently exists, get the instance which owns it */ he = hash_lookup_fast(m->vhash, bucket, addr, hv); @@ -1090,11 +1091,9 @@ multi_learn_addr(struct multi_context *m, } /* do we need to add address to hash table? */ - if ((!owner || owner != mi) - && mroute_learnable_address(addr) + if ((!owner || owner != mi) && mroute_learnable_address(addr, &gc) && !mroute_addr_equal(addr, &m->local)) { - struct gc_arena gc = gc_new(); struct multi_route *newroute; bool learn_succeeded = false; @@ -1151,9 +1150,8 @@ multi_learn_addr(struct multi_context *m, { free(newroute); } - - gc_free(&gc); } + gc_free(&gc); return owner; } @@ -2355,7 +2353,7 @@ multi_process_post(struct multi_context *m, struct multi_instance *mi, const uns } else { - msg(M_NONFATAL, "MULTI: inotify_add_watch error: %s", strerror(errno)); + msg(M_NONFATAL | M_ERRNO, "MULTI: inotify_add_watch error"); } } #endif @@ -2967,7 +2965,7 @@ gremlin_flood_clients(struct multi_context *m) } #endif /* ifdef ENABLE_DEBUG */ -bool +static bool stale_route_check_trigger(struct multi_context *m) { struct timeval null; diff --git a/src/openvpn/multi.h b/src/openvpn/multi.h index 63afbaf..d7e5c29 100644 --- a/src/openvpn/multi.h +++ b/src/openvpn/multi.h @@ -5,7 +5,7 @@ * packet encryption, packet authentication, and * packet compression. * - * Copyright (C) 2002-2017 OpenVPN Technologies, Inc. <sales@openvpn.net> + * Copyright (C) 2002-2018 OpenVPN Inc <sales@openvpn.net> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 diff --git a/src/openvpn/ntlm.c b/src/openvpn/ntlm.c index 0b1163e..077fa3e 100644 --- a/src/openvpn/ntlm.c +++ b/src/openvpn/ntlm.c @@ -60,45 +60,47 @@ static void create_des_keys(const unsigned char *hash, unsigned char *key) { key[0] = hash[0]; - key[1] = ((hash[0]&1)<<7)|(hash[1]>>1); - key[2] = ((hash[1]&3)<<6)|(hash[2]>>2); - key[3] = ((hash[2]&7)<<5)|(hash[3]>>3); - key[4] = ((hash[3]&15)<<4)|(hash[4]>>4); - key[5] = ((hash[4]&31)<<3)|(hash[5]>>5); - key[6] = ((hash[5]&63)<<2)|(hash[6]>>6); - key[7] = ((hash[6]&127)<<1); + key[1] = ((hash[0] & 1) << 7) | (hash[1] >> 1); + key[2] = ((hash[1] & 3) << 6) | (hash[2] >> 2); + key[3] = ((hash[2] & 7) << 5) | (hash[3] >> 3); + key[4] = ((hash[3] & 15) << 4) | (hash[4] >> 4); + key[5] = ((hash[4] & 31) << 3) | (hash[5] >> 5); + key[6] = ((hash[5] & 63) << 2) | (hash[6] >> 6); + key[7] = ((hash[6] & 127) << 1); key_des_fixup(key, 8, 1); } static void -gen_md4_hash(const char *data, int data_len, char *result) +gen_md4_hash(const uint8_t *data, int data_len, uint8_t *result) { /* result is 16 byte md4 hash */ const md_kt_t *md4_kt = md_kt_get("MD4"); - char md[MD4_DIGEST_LENGTH]; + uint8_t md[MD4_DIGEST_LENGTH]; md_full(md4_kt, data, data_len, md); memcpy(result, md, MD4_DIGEST_LENGTH); } static void -gen_hmac_md5(const char *data, int data_len, const char *key, int key_len,char *result) +gen_hmac_md5(const uint8_t *data, int data_len, const uint8_t *key, int key_len, + uint8_t *result) { const md_kt_t *md5_kt = md_kt_get("MD5"); hmac_ctx_t *hmac_ctx = hmac_ctx_new(); hmac_ctx_init(hmac_ctx, key, key_len, md5_kt); - hmac_ctx_update(hmac_ctx, (const unsigned char *)data, data_len); - hmac_ctx_final(hmac_ctx, (unsigned char *)result); + hmac_ctx_update(hmac_ctx, data, data_len); + hmac_ctx_final(hmac_ctx, result); hmac_ctx_cleanup(hmac_ctx); hmac_ctx_free(hmac_ctx); } static void -gen_timestamp(unsigned char *timestamp) +gen_timestamp(uint8_t *timestamp) { /* Copies 8 bytes long timestamp into "timestamp" buffer. - * Timestamp is Little-endian, 64-bit signed value representing the number of tenths of a microsecond since January 1, 1601. + * Timestamp is Little-endian, 64-bit signed value representing the + * number of tenths of a microsecond since January 1, 1601. */ UINTEGER64 timestamp_ull; @@ -129,8 +131,8 @@ gen_nonce(unsigned char *nonce) } } -void -my_strupr(unsigned char *str) +static void +my_strupr(char *str) { /* converts string to uppercase in place */ @@ -150,16 +152,17 @@ unicodize(char *dst, const char *src) { dst[i++] = *src; dst[i++] = 0; - } - while (*src++); + } while (*src++); return i; } static void -add_security_buffer(int sb_offset, void *data, int length, unsigned char *msg_buf, int *msg_bufpos) +add_security_buffer(int sb_offset, void *data, int length, + unsigned char *msg_buf, int *msg_bufpos) { - /* Adds security buffer data to a message and sets security buffer's offset and length */ + /* Adds security buffer data to a message and sets security buffer's + * offset and length */ msg_buf[sb_offset] = (unsigned char)length; msg_buf[sb_offset + 2] = msg_buf[sb_offset]; msg_buf[sb_offset + 4] = (unsigned char)(*msg_bufpos & 0xff); @@ -186,7 +189,8 @@ ntlm_phase_1(const struct http_proxy_info *p, struct gc_arena *gc) } const char * -ntlm_phase_3(const struct http_proxy_info *p, const char *phase_2, struct gc_arena *gc) +ntlm_phase_3(const struct http_proxy_info *p, const char *phase_2, + struct gc_arena *gc) { /* NTLM handshake * @@ -195,19 +199,19 @@ ntlm_phase_3(const struct http_proxy_info *p, const char *phase_2, struct gc_are */ char pwbuf[sizeof(p->up.password) * 2]; /* for unicode password */ - unsigned char buf2[128]; /* decoded reply from proxy */ - unsigned char phase3[464]; + uint8_t buf2[128]; /* decoded reply from proxy */ + uint8_t phase3[464]; - char md4_hash[MD4_DIGEST_LENGTH+5]; - char challenge[8], ntlm_response[24]; + uint8_t md4_hash[MD4_DIGEST_LENGTH + 5]; + uint8_t challenge[8], ntlm_response[24]; int i, ret_val; - char ntlmv2_response[144]; + uint8_t ntlmv2_response[144]; char userdomain_u[256]; /* for uppercase unicode username and domain */ char userdomain[128]; /* the same as previous but ascii */ - char ntlmv2_hash[MD5_DIGEST_LENGTH]; - char ntlmv2_hmacmd5[16]; - char *ntlmv2_blob = ntlmv2_response + 16; /* inside ntlmv2_response, length: 128 */ + uint8_t ntlmv2_hash[MD5_DIGEST_LENGTH]; + uint8_t ntlmv2_hmacmd5[16]; + uint8_t *ntlmv2_blob = ntlmv2_response + 16; /* inside ntlmv2_response, length: 128 */ int ntlmv2_blob_size = 0; int phase3_bufpos = 0x40; /* offset to next security buffer data to be added */ size_t len; @@ -246,12 +250,13 @@ ntlm_phase_3(const struct http_proxy_info *p, const char *phase_2, struct gc_are /* fill 1st 16 bytes with md4 hash, disregard terminating null */ - gen_md4_hash(pwbuf, unicodize(pwbuf, p->up.password) - 2, md4_hash); + int unicode_len = unicodize(pwbuf, p->up.password) - 2; + gen_md4_hash((uint8_t *)pwbuf, unicode_len, md4_hash); /* pad to 21 bytes */ memset(md4_hash + MD4_DIGEST_LENGTH, 0, 5); - ret_val = openvpn_base64_decode( phase_2, (void *)buf2, -1); + ret_val = openvpn_base64_decode(phase_2, buf2, -1); if (ret_val < 0) { return NULL; @@ -271,7 +276,8 @@ ntlm_phase_3(const struct http_proxy_info *p, const char *phase_2, struct gc_are int tib_len; /* NTLMv2 hash */ - my_strupr((unsigned char *)strcpy(userdomain, username)); + strcpy(userdomain, username); + my_strupr(userdomain); if (strlen(username) + strlen(domain) < sizeof(userdomain)) { strcat(userdomain, domain); @@ -281,34 +287,54 @@ ntlm_phase_3(const struct http_proxy_info *p, const char *phase_2, struct gc_are msg(M_INFO, "Warning: Username or domain too long"); } unicodize(userdomain_u, userdomain); - gen_hmac_md5(userdomain_u, 2 * strlen(userdomain), md4_hash, MD5_DIGEST_LENGTH, ntlmv2_hash); + gen_hmac_md5((uint8_t *)userdomain_u, 2 * strlen(userdomain), md4_hash, + MD5_DIGEST_LENGTH, ntlmv2_hash); /* NTLMv2 Blob */ memset(ntlmv2_blob, 0, 128); /* Clear blob buffer */ ntlmv2_blob[0x00] = 1; /* Signature */ ntlmv2_blob[0x01] = 1; /* Signature */ ntlmv2_blob[0x04] = 0; /* Reserved */ - gen_timestamp((unsigned char *)&ntlmv2_blob[0x08]); /* 64-bit Timestamp */ - gen_nonce((unsigned char *)&ntlmv2_blob[0x10]); /* 64-bit Client Nonce */ + gen_timestamp(&ntlmv2_blob[0x08]); /* 64-bit Timestamp */ + gen_nonce(&ntlmv2_blob[0x10]); /* 64-bit Client Nonce */ ntlmv2_blob[0x18] = 0; /* Unknown, zero should work */ /* Add target information block to the blob */ - if (( *((long *)&buf2[0x14]) & 0x00800000) == 0x00800000) /* Check for Target Information block */ + + /* Check for Target Information block */ + /* The NTLM spec instructs to interpret these 4 consecutive bytes as a + * 32bit long integer. However, no endianness is specified. + * The code here and that found in other NTLM implementations point + * towards the assumption that the byte order on the wire has to + * match the order on the sending and receiving hosts. Probably NTLM has + * been thought to be always running on x86_64/i386 machine thus + * implying Little-Endian everywhere. + * + * This said, in case of future changes, we should keep in mind that the + * byte order on the wire for the NTLM header is LE. + */ + const size_t hoff = 0x14; + unsigned long flags = buf2[hoff] | (buf2[hoff + 1] << 8) | + (buf2[hoff + 2] << 16) | (buf2[hoff + 3] << 24); + if ((flags & 0x00800000) == 0x00800000) { tib_len = buf2[0x28]; /* Get Target Information block size */ if (tib_len > 96) { tib_len = 96; } + { - char *tib_ptr; - int tib_pos = buf2[0x2c]; + uint8_t *tib_ptr; + uint8_t tib_pos = buf2[0x2c]; if (tib_pos + tib_len > sizeof(buf2)) { return NULL; } - tib_ptr = buf2 + tib_pos; /* Get Target Information block pointer */ - memcpy(&ntlmv2_blob[0x1c], tib_ptr, tib_len); /* Copy Target Information block into the blob */ + /* Get Target Information block pointer */ + tib_ptr = buf2 + tib_pos; + /* Copy Target Information block into the blob */ + memcpy(&ntlmv2_blob[0x1c], tib_ptr, tib_len); } } else @@ -316,7 +342,8 @@ ntlm_phase_3(const struct http_proxy_info *p, const char *phase_2, struct gc_are tib_len = 0; } - ntlmv2_blob[0x1c + tib_len] = 0; /* Unknown, zero works */ + /* Unknown, zero works */ + ntlmv2_blob[0x1c + tib_len] = 0; /* Get blob length */ ntlmv2_blob_size = 0x20 + tib_len; @@ -325,24 +352,28 @@ ntlm_phase_3(const struct http_proxy_info *p, const char *phase_2, struct gc_are memcpy(&ntlmv2_response[8], challenge, 8); /* hmac-md5 */ - gen_hmac_md5(&ntlmv2_response[8], ntlmv2_blob_size + 8, ntlmv2_hash, MD5_DIGEST_LENGTH, ntlmv2_hmacmd5); - - /* Add hmac-md5 result to the blob */ - memcpy(ntlmv2_response, ntlmv2_hmacmd5, MD5_DIGEST_LENGTH); /* Note: This overwrites challenge previously written at ntlmv2_response[8..15] */ + gen_hmac_md5(&ntlmv2_response[8], ntlmv2_blob_size + 8, ntlmv2_hash, + MD5_DIGEST_LENGTH, ntlmv2_hmacmd5); + /* Add hmac-md5 result to the blob. + * Note: This overwrites challenge previously written at + * ntlmv2_response[8..15] */ + memcpy(ntlmv2_response, ntlmv2_hmacmd5, MD5_DIGEST_LENGTH); } - else /* Generate NTLM response */ + else /* Generate NTLM response */ { - unsigned char key1[DES_KEY_LENGTH], key2[DES_KEY_LENGTH], key3[DES_KEY_LENGTH]; + unsigned char key1[DES_KEY_LENGTH], key2[DES_KEY_LENGTH]; + unsigned char key3[DES_KEY_LENGTH]; - create_des_keys((unsigned char *)md4_hash, key1); + create_des_keys(md4_hash, key1); cipher_des_encrypt_ecb(key1, challenge, ntlm_response); - create_des_keys((unsigned char *)&(md4_hash[DES_KEY_LENGTH-1]), key2); + create_des_keys(&md4_hash[DES_KEY_LENGTH - 1], key2); cipher_des_encrypt_ecb(key2, challenge, &ntlm_response[DES_KEY_LENGTH]); - create_des_keys((unsigned char *)&(md4_hash[2*(DES_KEY_LENGTH-1)]), key3); - cipher_des_encrypt_ecb(key3, challenge, &ntlm_response[DES_KEY_LENGTH*2]); + create_des_keys(&md4_hash[2 * (DES_KEY_LENGTH - 1)], key3); + cipher_des_encrypt_ecb(key3, challenge, + &ntlm_response[DES_KEY_LENGTH * 2]); } @@ -353,7 +384,8 @@ ntlm_phase_3(const struct http_proxy_info *p, const char *phase_2, struct gc_are if (ntlmv2_enabled) /* NTLMv2 response */ { - add_security_buffer(0x14, ntlmv2_response, ntlmv2_blob_size + 16, phase3, &phase3_bufpos); + add_security_buffer(0x14, ntlmv2_response, ntlmv2_blob_size + 16, + phase3, &phase3_bufpos); } else /* NTLM response */ { @@ -361,12 +393,13 @@ ntlm_phase_3(const struct http_proxy_info *p, const char *phase_2, struct gc_are } /* username in ascii */ - add_security_buffer(0x24, username, strlen(username), phase3, &phase3_bufpos); + add_security_buffer(0x24, username, strlen(username), phase3, + &phase3_bufpos); - /* Set domain. If <domain> is empty, default domain will be used (i.e. proxy's domain) */ + /* Set domain. If <domain> is empty, default domain will be used + * (i.e. proxy's domain) */ add_security_buffer(0x1c, domain, strlen(domain), phase3, &phase3_bufpos); - /* other security buffers will be empty */ phase3[0x10] = phase3_bufpos; /* lm not used */ phase3[0x30] = phase3_bufpos; /* no workstation name supplied */ @@ -376,7 +409,8 @@ ntlm_phase_3(const struct http_proxy_info *p, const char *phase_2, struct gc_are phase3[0x3c] = 0x02; /* negotiate oem */ phase3[0x3d] = 0x02; /* negotiate ntlm */ - return ((const char *)make_base64_string2((unsigned char *)phase3, phase3_bufpos, gc)); + return ((const char *)make_base64_string2((unsigned char *)phase3, + phase3_bufpos, gc)); } #else /* if NTLM */ diff --git a/src/openvpn/occ-inline.h b/src/openvpn/occ-inline.h index 68e9098..7f6f1b2 100644 --- a/src/openvpn/occ-inline.h +++ b/src/openvpn/occ-inline.h @@ -5,7 +5,7 @@ * packet encryption, packet authentication, and * packet compression. * - * Copyright (C) 2002-2017 OpenVPN Technologies, Inc. <sales@openvpn.net> + * Copyright (C) 2002-2018 OpenVPN Inc <sales@openvpn.net> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 @@ -31,7 +31,7 @@ */ static inline int -occ_reset_op() +occ_reset_op(void) { return -1; } diff --git a/src/openvpn/occ.c b/src/openvpn/occ.c index 40f7e76..80504af 100644 --- a/src/openvpn/occ.c +++ b/src/openvpn/occ.c @@ -5,7 +5,7 @@ * packet encryption, packet authentication, and * packet compression. * - * Copyright (C) 2002-2017 OpenVPN Technologies, Inc. <sales@openvpn.net> + * Copyright (C) 2002-2018 OpenVPN Inc <sales@openvpn.net> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 diff --git a/src/openvpn/occ.h b/src/openvpn/occ.h index 12d7bc5..f6ff5f9 100644 --- a/src/openvpn/occ.h +++ b/src/openvpn/occ.h @@ -5,7 +5,7 @@ * packet encryption, packet authentication, and * packet compression. * - * Copyright (C) 2002-2017 OpenVPN Technologies, Inc. <sales@openvpn.net> + * Copyright (C) 2002-2018 OpenVPN Inc <sales@openvpn.net> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 diff --git a/src/openvpn/openssl_compat.h b/src/openvpn/openssl_compat.h index c765f0b..c3152d0 100644 --- a/src/openvpn/openssl_compat.h +++ b/src/openvpn/openssl_compat.h @@ -5,8 +5,8 @@ * packet encryption, packet authentication, and * packet compression. * - * Copyright (C) 2002-2017 OpenVPN Technologies, Inc. <sales@openvpn.net> - * Copyright (C) 2010-2017 Fox Crypto B.V. <openvpn@fox-it.com> + * Copyright (C) 2002-2018 OpenVPN Inc <sales@openvpn.net> + * Copyright (C) 2010-2018 Fox Crypto B.V. <openvpn@fox-it.com> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 @@ -88,38 +88,19 @@ EVP_MD_CTX_new(void) } #endif -#if !defined(HAVE_EVP_CIPHER_CTX_FREE) -/** - * Free an existing cipher context - * - * @param ctx The cipher context - */ -static inline void -EVP_CIPHER_CTX_free(EVP_CIPHER_CTX *c) -{ - free(c); -} -#endif - -#if !defined(HAVE_EVP_CIPHER_CTX_NEW) -/** - * Allocate a new cipher context object - * - * @return A zero'ed cipher context object - */ -static inline EVP_CIPHER_CTX * -EVP_CIPHER_CTX_new(void) -{ - EVP_CIPHER_CTX *ctx = NULL; - ALLOC_OBJ_CLEAR(ctx, EVP_CIPHER_CTX); - return ctx; -} -#endif - #if !defined(HAVE_HMAC_CTX_RESET) /** * Reset a HMAC context * + * OpenSSL 1.1+ removes APIs HMAC_CTX_init() and HMAC_CTX_cleanup() + * and replace them with a single call that does a cleanup followed + * by an init. A proper _reset() for OpenSSL < 1.1 should perform + * a similar set of operations. + * + * It means that before we kill a HMAC context, we'll have to cleanup + * again, as we probably have allocated a few resources when we forced + * an init. + * * @param ctx The HMAC context * @return 1 on success, 0 on error */ @@ -127,42 +108,22 @@ static inline int HMAC_CTX_reset(HMAC_CTX *ctx) { HMAC_CTX_cleanup(ctx); + HMAC_CTX_init(ctx); return 1; } #endif -#if !defined(HAVE_HMAC_CTX_INIT) -/** - * Init a HMAC context - * - * @param ctx The HMAC context - * - * Contrary to many functions in this file, HMAC_CTX_init() is not - * an OpenSSL 1.1 function: it comes from previous versions and was - * removed in v1.1. As a consequence, there is no distincting in - * v1.1 between a cleanup, and init and a reset. Yet, previous OpenSSL - * version need this distinction. - * - * In order to respect previous OpenSSL versions, we implement init - * as reset for OpenSSL 1.1+. - */ -static inline void -HMAC_CTX_init(HMAC_CTX *ctx) -{ - HMAC_CTX_reset(ctx); -} -#endif - #if !defined(HAVE_HMAC_CTX_FREE) /** - * Free an existing HMAC context + * Cleanup and free an existing HMAC context * * @param ctx The HMAC context */ static inline void -HMAC_CTX_free(HMAC_CTX *c) +HMAC_CTX_free(HMAC_CTX *ctx) { - free(c); + HMAC_CTX_cleanup(ctx); + free(ctx); } #endif @@ -279,7 +240,21 @@ X509_OBJECT_get_type(const X509_OBJECT *obj) static inline RSA * EVP_PKEY_get0_RSA(EVP_PKEY *pkey) { - return pkey ? pkey->pkey.rsa : NULL; + return (pkey && pkey->type == EVP_PKEY_RSA) ? pkey->pkey.rsa : NULL; +} +#endif + +#if !defined(HAVE_EVP_PKEY_GET0_EC_KEY) && !defined(OPENSSL_NO_EC) +/** + * Get the EC_KEY object of a public key + * + * @param pkey Public key object + * @return The underlying EC_KEY object + */ +static inline EC_KEY * +EVP_PKEY_get0_EC_KEY(EVP_PKEY *pkey) +{ + return (pkey && pkey->type == EVP_PKEY_EC) ? pkey->pkey.ec : NULL; } #endif @@ -307,7 +282,7 @@ EVP_PKEY_id(const EVP_PKEY *pkey) static inline DSA * EVP_PKEY_get0_DSA(EVP_PKEY *pkey) { - return pkey ? pkey->pkey.dsa : NULL; + return (pkey && pkey->type == EVP_PKEY_DSA) ? pkey->pkey.dsa : NULL; } #endif @@ -649,9 +624,149 @@ RSA_meth_set0_app_data(RSA_METHOD *meth, void *app_data) } #endif +#if !defined(HAVE_RSA_METH_GET0_APP_DATA) +/** + * Get the application data of an RSA_METHOD object + * + * @param meth The RSA_METHOD object + * @return pointer to application data, may be NULL + */ +static inline void * +RSA_meth_get0_app_data(const RSA_METHOD *meth) +{ + return meth ? meth->app_data : NULL; +} +#endif + +#if !defined(HAVE_EC_GROUP_ORDER_BITS) && !defined(OPENSSL_NO_EC) +/** + * Gets the number of bits of the order of an EC_GROUP + * + * @param group EC_GROUP object + * @return number of bits of group order. + */ +static inline int +EC_GROUP_order_bits(const EC_GROUP *group) +{ + BIGNUM* order = BN_new(); + EC_GROUP_get_order(group, order, NULL); + int bits = BN_num_bits(order); + BN_free(order); + return bits; +} +#endif + /* SSLeay symbols have been renamed in OpenSSL 1.1 */ #if !defined(RSA_F_RSA_OSSL_PRIVATE_ENCRYPT) #define RSA_F_RSA_OSSL_PRIVATE_ENCRYPT RSA_F_RSA_EAY_PRIVATE_ENCRYPT #endif +#ifndef SSL_CTX_get_min_proto_version +/** Return the min SSL protocol version currently enabled in the context. + * If no valid version >= TLS1.0 is found, return 0. */ +static inline int +SSL_CTX_get_min_proto_version(SSL_CTX *ctx) +{ + long sslopt = SSL_CTX_get_options(ctx); + if (!(sslopt & SSL_OP_NO_TLSv1)) + { + return TLS1_VERSION; + } + if (!(sslopt & SSL_OP_NO_TLSv1_1)) + { + return TLS1_1_VERSION; + } + if (!(sslopt & SSL_OP_NO_TLSv1_2)) + { + return TLS1_2_VERSION; + } + return 0; +} +#endif /* SSL_CTX_get_min_proto_version */ + +#ifndef SSL_CTX_get_max_proto_version +/** Return the max SSL protocol version currently enabled in the context. + * If no valid version >= TLS1.0 is found, return 0. */ +static inline int +SSL_CTX_get_max_proto_version(SSL_CTX *ctx) +{ + long sslopt = SSL_CTX_get_options(ctx); +#ifdef SSL_OP_NO_TLSv1_2 + if (!(sslopt & SSL_OP_NO_TLSv1_2)) + { + return TLS1_2_VERSION; + } +#endif +#ifdef SSL_OP_NO_TLSv1_1 + if (!(sslopt & SSL_OP_NO_TLSv1_1)) + { + return TLS1_1_VERSION; + } +#endif + if (!(sslopt & SSL_OP_NO_TLSv1)) + { + return TLS1_VERSION; + } + return 0; +} +#endif /* SSL_CTX_get_max_proto_version */ + +#ifndef SSL_CTX_set_min_proto_version +/** Mimics SSL_CTX_set_min_proto_version for OpenSSL < 1.1 */ +static inline int +SSL_CTX_set_min_proto_version(SSL_CTX *ctx, long tls_ver_min) +{ + long sslopt = SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3; /* Never do < TLS 1.0 */ + + if (tls_ver_min > TLS1_VERSION) + { + sslopt |= SSL_OP_NO_TLSv1; + } +#ifdef SSL_OP_NO_TLSv1_1 + if (tls_ver_min > TLS1_1_VERSION) + { + sslopt |= SSL_OP_NO_TLSv1_1; + } +#endif +#ifdef SSL_OP_NO_TLSv1_2 + if (tls_ver_min > TLS1_2_VERSION) + { + sslopt |= SSL_OP_NO_TLSv1_2; + } +#endif + SSL_CTX_set_options(ctx, sslopt); + + return 1; +} +#endif /* SSL_CTX_set_min_proto_version */ + +#ifndef SSL_CTX_set_max_proto_version +/** Mimics SSL_CTX_set_max_proto_version for OpenSSL < 1.1 */ +static inline int +SSL_CTX_set_max_proto_version(SSL_CTX *ctx, long tls_ver_max) +{ + long sslopt = 0; + + if (tls_ver_max < TLS1_VERSION) + { + sslopt |= SSL_OP_NO_TLSv1; + } +#ifdef SSL_OP_NO_TLSv1_1 + if (tls_ver_max < TLS1_1_VERSION) + { + sslopt |= SSL_OP_NO_TLSv1_1; + } +#endif +#ifdef SSL_OP_NO_TLSv1_2 + if (tls_ver_max < TLS1_2_VERSION) + { + sslopt |= SSL_OP_NO_TLSv1_2; + } +#endif + SSL_CTX_set_options(ctx, sslopt); + + return 1; +} +#endif /* SSL_CTX_set_max_proto_version */ + #endif /* OPENSSL_COMPAT_H_ */ diff --git a/src/openvpn/openvpn.c b/src/openvpn/openvpn.c index 08c09e6..b9e914a 100644 --- a/src/openvpn/openvpn.c +++ b/src/openvpn/openvpn.c @@ -5,7 +5,7 @@ * packet encryption, packet authentication, and * packet compression. * - * Copyright (C) 2002-2017 OpenVPN Technologies, Inc. <sales@openvpn.net> + * Copyright (C) 2002-2018 OpenVPN Inc <sales@openvpn.net> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 @@ -33,6 +33,7 @@ #include "forward.h" #include "multi.h" #include "win32.h" +#include "platform.h" #include "memdbg.h" @@ -47,6 +48,27 @@ process_signal_p2p(struct context *c) return process_signal(c); } +/* Write our PID to a file */ +static void +write_pid(const char *filename) +{ + if (filename) + { + unsigned int pid = 0; + FILE *fp = platform_fopen(filename, "w"); + if (!fp) + { + msg(M_ERR, "Open error on pid file %s", filename); + } + + pid = platform_getpid(); + fprintf(fp, "%u\n", pid); + if (fclose(fp)) + { + msg(M_ERR, "Close error on pid file %s", filename); + } + } +} /**************************************************************************/ diff --git a/src/openvpn/openvpn.h b/src/openvpn/openvpn.h index 9262e68..7736183 100644 --- a/src/openvpn/openvpn.h +++ b/src/openvpn/openvpn.h @@ -5,7 +5,7 @@ * packet encryption, packet authentication, and * packet compression. * - * Copyright (C) 2002-2017 OpenVPN Technologies, Inc. <sales@openvpn.net> + * Copyright (C) 2002-2018 OpenVPN Inc <sales@openvpn.net> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 diff --git a/src/openvpn/options.c b/src/openvpn/options.c index fef5e90..3f9164c 100644 --- a/src/openvpn/options.c +++ b/src/openvpn/options.c @@ -5,7 +5,7 @@ * packet encryption, packet authentication, and * packet compression. * - * Copyright (C) 2002-2017 OpenVPN Technologies, Inc. <sales@openvpn.net> + * Copyright (C) 2002-2018 OpenVPN Inc <sales@openvpn.net> * Copyright (C) 2008-2013 David Sommerseth <dazo@users.sourceforge.net> * * This program is free software; you can redistribute it and/or modify @@ -415,8 +415,9 @@ static const char usage_message[] = " client instance.\n" "--ifconfig-pool start-IP end-IP [netmask] : Set aside a pool of subnets\n" " to be dynamically allocated to connecting clients.\n" - "--ifconfig-pool-linear : Use individual addresses rather than /30 subnets\n" - " in tun mode. Not compatible with Windows clients.\n" + "--ifconfig-pool-linear : (DEPRECATED) Use individual addresses rather \n" + " than /30 subnets\n in tun mode. Not compatible with\n" + " Windows clients.\n" "--ifconfig-pool-persist file [seconds] : Persist/unpersist ifconfig-pool\n" " data to file, at seconds intervals (default=600).\n" " If seconds=0, file will be treated as read-only.\n" @@ -434,7 +435,7 @@ static const char usage_message[] = " Only valid in a client-specific config file.\n" "--disable : Client is disabled.\n" " Only valid in a client-specific config file.\n" - "--client-cert-not-required : Don't require client certificate, client\n" + "--client-cert-not-required : (DEPRECATED) Don't require client certificate, client\n" " will authenticate using username/password.\n" "--verify-client-cert [none|optional|require] : perform no, optional or\n" " mandatory client certificate verification.\n" @@ -455,7 +456,7 @@ static const char usage_message[] = " with those of the server will be disconnected.\n" "--auth-user-pass-optional : Allow connections by clients that don't\n" " specify a username/password.\n" - "--no-name-remapping : Allow Common Name and X509 Subject to include\n" + "--no-name-remapping : (DEPRECATED) Allow Common Name and X509 Subject to include\n" " any printable character.\n" "--client-to-client : Internally route client-to-client traffic.\n" "--duplicate-cn : Allow multiple clients with the same common name to\n" @@ -539,13 +540,13 @@ static const char usage_message[] = "--prng alg [nsl] : For PRNG, use digest algorithm alg, and\n" " nonce_secret_len=nsl. Set alg=none to disable PRNG.\n" #ifdef HAVE_EVP_CIPHER_CTX_SET_KEY_LENGTH - "--keysize n : Size of cipher key in bits (optional).\n" + "--keysize n : (DEPRECATED) Size of cipher key in bits (optional).\n" " If unspecified, defaults to cipher-specific default.\n" #endif #ifndef ENABLE_CRYPTO_MBEDTLS "--engine [name] : Enable OpenSSL hardware crypto engine functionality.\n" #endif - "--no-replay : Disable replay protection.\n" + "--no-replay : (DEPRECATED) Disable replay protection.\n" "--mute-replay-warnings : Silence the output of replay warnings to log file.\n" "--replay-window n [t] : Use a replay protection sliding window of size n\n" " and a time window of t seconds.\n" @@ -564,7 +565,7 @@ static const char usage_message[] = "(These options are meaningful only for TLS-mode)\n" "--tls-server : Enable TLS and assume server role during TLS handshake.\n" "--tls-client : Enable TLS and assume client role during TLS handshake.\n" - "--key-method m : Data channel key exchange method. m should be a method\n" + "--key-method m : (DEPRECATED) Data channel key exchange method. m should be a method\n" " number, such as 1 (default), 2, etc.\n" "--ca file : Certificate authority file in .pem format containing\n" " root certificate.\n" @@ -599,6 +600,8 @@ static const char usage_message[] = #endif "--tls-cipher l : A list l of allowable TLS ciphers separated by : (optional).\n" " : Use --show-tls to see a list of supported TLS ciphers.\n" + "--tls-cert-profile p : Set the allowed certificate crypto algorithm profile\n" + " (default=legacy).\n" "--tls-timeout n : Packet retransmit timeout on TLS control channel\n" " if no ACK from remote within n seconds (default=%d).\n" "--reneg-bytes n : Renegotiate data chan. key after n bytes sent and recvd.\n" @@ -704,8 +707,7 @@ static const char usage_message[] = " which allow multiple addresses,\n" " --dhcp-option must be repeated.\n" " DOMAIN name : Set DNS suffix\n" - " DNS addr : Set domain name server address(es) (IPv4)\n" - " DNS6 addr : Set domain name server address(es) (IPv6)\n" + " DNS addr : Set domain name server address(es) (IPv4 and IPv6)\n" " NTP : Set NTP server address(es)\n" " NBDD : Set NBDD server address(es)\n" " WINS addr : Set WINS server address(es)\n" @@ -873,6 +875,7 @@ init_options(struct options *o, const bool init_gc) o->renegotiate_seconds = 3600; o->handshake_window = 60; o->transition_window = 3600; + o->tls_cert_profile = NULL; o->ecdh_curve = NULL; #ifdef ENABLE_X509ALTUSERNAME o->x509_username_field = X509_USERNAME_FIELD_DEFAULT; @@ -961,7 +964,7 @@ pull_filter_type_name(int type) #endif -void +static void setenv_connection_entry(struct env_set *es, const struct connection_entry *e, const int i) @@ -1231,6 +1234,20 @@ show_tuntap_options(const struct tuntap_options *o) #if defined(_WIN32) || defined(TARGET_ANDROID) static void +dhcp_option_dns6_parse(const char *parm, struct in6_addr *dns6_list, int *len, int msglevel) +{ + struct in6_addr addr; + if (*len >= N_DHCP_ADDR) + { + msg(msglevel, "--dhcp-option DNS: maximum of %d IPv6 dns servers can be specified", + N_DHCP_ADDR); + } + else if (get_ipv6_addr(parm, &addr, NULL, msglevel)) + { + dns6_list[(*len)++] = addr; + } +} +static void dhcp_option_address_parse(const char *name, const char *parm, in_addr_t *array, int *len, int msglevel) { if (*len >= N_DHCP_ADDR) @@ -1441,7 +1458,7 @@ rol_check_alloc(struct options *options) } } -void +static void rol6_check_alloc(struct options *options) { if (!options->routes_ipv6) @@ -1699,7 +1716,7 @@ show_settings(const struct options *o) #ifdef ENABLE_CRYPTO SHOW_STR(shared_secret_file); - SHOW_INT(key_direction); + SHOW_PARM(key_direction, keydirection2ascii(o->key_direction, false, true), "%s"); SHOW_STR(ciphername); SHOW_BOOL(ncp_enabled); SHOW_STR(ncp_ciphers); @@ -1752,6 +1769,7 @@ show_settings(const struct options *o) SHOW_STR(cryptoapi_cert); #endif SHOW_STR(cipher_list); + SHOW_STR(tls_cert_profile); SHOW_STR(tls_verify); SHOW_STR(tls_export_cert); SHOW_INT(verify_x509_type); @@ -1872,7 +1890,7 @@ parse_http_proxy_override(const char *server, } } -void +static void options_postprocess_http_proxy_override(struct options *o) { const struct connection_list *l = o->connection_list; @@ -1989,7 +2007,7 @@ alloc_pull_filter(struct options *o, const int msglevel) return f; } -void +static void connection_entry_load_re(struct connection_entry *ce, const struct remote_entry *re) { if (re->remote) @@ -2495,6 +2513,16 @@ options_postprocess_verify_ce(const struct options *options, const struct connec msg(M_WARN, "WARNING: --no-iv is deprecated and will be removed in 2.5"); } + if (options->keysize) + { + msg(M_WARN, "WARNING: --keysize is DEPRECATED and will be removed in OpenVPN 2.6"); + } + + if (!options->replay) + { + msg(M_WARN, "WARNING: --no-replay is DEPRECATED and will be removed in OpenVPN 2.5"); + } + /* * Check consistency of replay options */ @@ -2528,6 +2556,18 @@ options_postprocess_verify_ce(const struct options *options, const struct connec "in the configuration file, which is the recommended approach."); } + const int tls_version_max = + (options->ssl_flags >> SSLF_TLS_VERSION_MAX_SHIFT) + & SSLF_TLS_VERSION_MAX_MASK; + const int tls_version_min = + (options->ssl_flags >> SSLF_TLS_VERSION_MIN_SHIFT) + & SSLF_TLS_VERSION_MIN_MASK; + + if (tls_version_max > 0 && tls_version_max < tls_version_min) + { + msg(M_USAGE, "--tls-version-min bigger than --tls-version-max"); + } + if (options->tls_server || options->tls_client) { #ifdef ENABLE_PKCS11 @@ -2734,6 +2774,7 @@ options_postprocess_verify_ce(const struct options *options, const struct connec MUST_BE_UNDEF(pkcs12_file); #endif MUST_BE_UNDEF(cipher_list); + MUST_BE_UNDEF(tls_cert_profile); MUST_BE_UNDEF(tls_verify); MUST_BE_UNDEF(tls_export_cert); MUST_BE_UNDEF(verify_x509_name); @@ -3016,6 +3057,13 @@ options_postprocess_mutate(struct options *o) o->dh_file = NULL; } } + else if (o->dh_file) + { + /* DH file is only meaningful in a tls-server context. */ + msg(M_WARN, "WARNING: Ignoring option 'dh' in tls-client mode, please only " + "include this in your server configuration"); + o->dh_file = NULL; + } /* cipher negotiation (NCP) currently assumes --pull or --mode server */ if (o->ncp_enabled @@ -3034,24 +3082,6 @@ options_postprocess_mutate(struct options *o) } #endif -#ifdef ENABLE_CRYPTOAPI - if (o->cryptoapi_cert) - { - const int tls_version_max = - (o->ssl_flags >> SSLF_TLS_VERSION_MAX_SHIFT) - &SSLF_TLS_VERSION_MAX_MASK; - - if (tls_version_max == TLS_VER_UNSPEC || tls_version_max > TLS_VER_1_1) - { - msg(M_WARN, "Warning: cryptapicert used, setting maximum TLS " - "version to 1.1."); - o->ssl_flags &= ~(SSLF_TLS_VERSION_MAX_MASK - <<SSLF_TLS_VERSION_MAX_SHIFT); - o->ssl_flags |= (TLS_VER_1_1 << SSLF_TLS_VERSION_MAX_SHIFT); - } - } -#endif /* ENABLE_CRYPTOAPI */ - #if P2MP /* * Save certain parms before modifying options via --pull @@ -3148,8 +3178,7 @@ check_file_access(const int type, const char *file, const int mode, const char * /* Scream if an error is found */ if (errcode > 0) { - msg(M_NOPREFIX|M_OPTERR, "%s fails with '%s': %s", - opt, file, strerror(errno)); + msg(M_NOPREFIX | M_OPTERR | M_ERRNO, "%s fails with '%s'", opt, file); } /* Return true if an error occured */ @@ -3607,7 +3636,7 @@ options_string(const struct options *o, * Key direction */ { - const char *kd = keydirection2ascii(o->key_direction, remote); + const char *kd = keydirection2ascii(o->key_direction, remote, false); if (kd) { buf_printf(&out, ",keydir %s", kd); @@ -4154,7 +4183,7 @@ usage_version(void) show_windows_version( M_INFO|M_NOPREFIX ); #endif msg(M_INFO|M_NOPREFIX, "Originally developed by James Yonan"); - msg(M_INFO|M_NOPREFIX, "Copyright (C) 2002-2017 OpenVPN Technologies, Inc. <sales@openvpn.net>"); + msg(M_INFO|M_NOPREFIX, "Copyright (C) 2002-2018 OpenVPN Inc <sales@openvpn.net>"); #ifndef ENABLE_SMALL #ifdef CONFIGURE_DEFINES msg(M_INFO|M_NOPREFIX, "Compile time defines: %s", CONFIGURE_DEFINES); @@ -4569,7 +4598,7 @@ read_config_file(struct options *options, ++line_num; if (strlen(line) == OPTION_LINE_SIZE) { - msg(msglevel, "In %s:%d: Maximum optione line length (%d) exceeded, line starts with %s", + msg(msglevel, "In %s:%d: Maximum option line length (%d) exceeded, line starts with %s", file, line_num, OPTION_LINE_SIZE, line); } @@ -4828,11 +4857,13 @@ verify_permission(const char *name, #ifndef ENABLE_SMALL /* Check if this options is allowed in connection block, * but we are currently not in a connection block + * unless this is a pushed option. * Parsing a connection block uses a temporary options struct without * connection_list */ - if ((type & OPT_P_CONNECTION) && options->connection_list) + if ((type & OPT_P_CONNECTION) && options->connection_list + && !(allowed & OPT_P_PULL_MODE)) { if (file) { @@ -5235,8 +5266,10 @@ add_option(struct options *options, } else if (streq(p[0], "tun-ipv6") && !p[1]) { - VERIFY_PERMISSION(OPT_P_UP); - msg(M_WARN, "Note: option tun-ipv6 is ignored because modern operating systems do not need special IPv6 tun handling anymore."); + if (!pull_mode) + { + msg(M_WARN, "Note: option tun-ipv6 is ignored because modern operating systems do not need special IPv6 tun handling anymore."); + } } #ifdef ENABLE_IPROUTE else if (streq(p[0], "iproute") && p[1] && !p[2]) @@ -5885,7 +5918,7 @@ add_option(struct options *options, VERIFY_PERMISSION(OPT_P_GENERAL|OPT_P_CONNECTION); options->ce.remote_port = p[1]; } - else if (streq(p[0], "bind") && !p[1]) + else if (streq(p[0], "bind") && !p[2]) { VERIFY_PERMISSION(OPT_P_GENERAL|OPT_P_CONNECTION); options->ce.bind_defined = true; @@ -6198,7 +6231,7 @@ add_option(struct options *options, else if (streq(p[0], "max-routes") && !p[2]) { msg(M_WARN, "DEPRECATED OPTION: --max-routes option ignored." - "The number of routes is unlimited as of version 2.4. " + "The number of routes is unlimited as of OpenVPN 2.4. " "This option will be removed in a future version, " "please remove it from your configuration."); } @@ -6582,6 +6615,7 @@ add_option(struct options *options, { VERIFY_PERMISSION(OPT_P_GENERAL); options->topology = TOP_P2P; + msg(M_WARN, "DEPRECATED OPTION: --ifconfig-pool-linear, use --topology p2p instead"); } else if (streq(p[0], "ifconfig-ipv6-pool") && p[1] && !p[2]) { @@ -7028,7 +7062,7 @@ add_option(struct options *options, VERIFY_PERMISSION(OPT_P_GENERAL); if (streq(p[1], "env")) { - msg(M_INFO, "NOTE: --win-sys env is default from OpenVPN v2.3. " + msg(M_INFO, "NOTE: --win-sys env is default from OpenVPN 2.3. " "This entry will now be ignored. " "Please remove this entry from your configuration file."); } @@ -7120,6 +7154,7 @@ add_option(struct options *options, { struct tuntap_options *o = &options->tuntap_options; VERIFY_PERMISSION(OPT_P_IPWIN32); + bool ipv6dns = false; if (streq(p[1], "DOMAIN") && p[2]) { @@ -7140,22 +7175,17 @@ add_option(struct options *options, } o->netbios_node_type = t; } - else if (streq(p[1], "DNS") && p[2]) + else if ((streq(p[1], "DNS") || streq(p[1], "DNS6")) && p[2] && (!strstr(p[2], ":") || ipv6_addr_safe(p[2]))) { - dhcp_option_address_parse("DNS", p[2], o->dns, &o->dns_len, msglevel); - } - else if (streq(p[1], "DNS6") && p[2] && ipv6_addr_safe(p[2])) - { - struct in6_addr addr; - foreign_option(options, p, 3, es); - if (o->dns6_len >= N_DHCP_ADDR) + if (strstr(p[2], ":")) { - msg(msglevel, "--dhcp-option DNS6: maximum of %d dns servers can be specified", - N_DHCP_ADDR); + ipv6dns=true; + foreign_option(options, p, 3, es); + dhcp_option_dns6_parse(p[2], o->dns6, &o->dns6_len, msglevel); } - else if (get_ipv6_addr(p[2], &addr, NULL, msglevel)) + else { - o->dns6[o->dns6_len++] = addr; + dhcp_option_address_parse("DNS", p[2], o->dns, &o->dns_len, msglevel); } } else if (streq(p[1], "WINS") && p[2]) @@ -7183,7 +7213,7 @@ add_option(struct options *options, /* flag that we have options to give to the TAP driver's DHCPv4 server * - skipped for "DNS6", as that's not a DHCPv4 option */ - if (!streq(p[1], "DNS6")) + if (!ipv6dns) { o->dhcp_options = true; } @@ -7830,6 +7860,11 @@ add_option(struct options *options, VERIFY_PERMISSION(OPT_P_GENERAL); options->cipher_list = p[1]; } + else if (streq(p[0], "tls-cert-profile") && p[1] && !p[2]) + { + VERIFY_PERMISSION(OPT_P_GENERAL); + options->tls_cert_profile = p[1]; + } else if (streq(p[0], "crl-verify") && p[1] && ((p[2] && streq(p[2], "dir")) || (p[2] && streq(p[1], INLINE_FILE_TAG) ) || !p[2]) && !p[3]) { @@ -7874,7 +7909,7 @@ add_option(struct options *options, msg(msglevel, "you cannot use --compat-names with --verify-x509-name"); goto err; } - msg(M_WARN, "DEPRECATED OPTION: --compat-names, please update your configuration. This will be removed in OpenVPN v2.5."); + msg(M_WARN, "DEPRECATED OPTION: --compat-names, please update your configuration. This will be removed in OpenVPN 2.5."); compat_flag(COMPAT_FLAG_SET | COMPAT_NAMES); #if P2MP_SERVER if (p[1] && streq(p[1], "no-remapping")) @@ -7890,7 +7925,7 @@ add_option(struct options *options, msg(msglevel, "you cannot use --no-name-remapping with --verify-x509-name"); goto err; } - msg(M_WARN, "DEPRECATED OPTION: --no-name-remapping, please update your configuration. This will be removed in OpenVPN v2.5."); + msg(M_WARN, "DEPRECATED OPTION: --no-name-remapping, please update your configuration. This will be removed in OpenVPN 2.5."); compat_flag(COMPAT_FLAG_SET | COMPAT_NAMES); compat_flag(COMPAT_FLAG_SET | COMPAT_NO_NAME_REMAPPING); #endif diff --git a/src/openvpn/options.h b/src/openvpn/options.h index 67b9b94..0421c93 100644 --- a/src/openvpn/options.h +++ b/src/openvpn/options.h @@ -5,7 +5,7 @@ * packet encryption, packet authentication, and * packet compression. * - * Copyright (C) 2002-2017 OpenVPN Technologies, Inc. <sales@openvpn.net> + * Copyright (C) 2002-2018 OpenVPN Inc <sales@openvpn.net> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 @@ -181,7 +181,7 @@ struct options /* enable forward compatibility for post-2.1 features */ bool forward_compatible; - /* list of options that should be ignored even if unkown */ + /* list of options that should be ignored even if unknown */ const char **ignore_unknown_option; /* persist parms */ @@ -503,6 +503,7 @@ struct options const char *priv_key_file; const char *pkcs12_file; const char *cipher_list; + const char *tls_cert_profile; const char *ecdh_curve; const char *tls_verify; int verify_x509_type; diff --git a/src/openvpn/otime.c b/src/openvpn/otime.c index 3e576cc..805aac9 100644 --- a/src/openvpn/otime.c +++ b/src/openvpn/otime.c @@ -5,7 +5,7 @@ * packet encryption, packet authentication, and * packet compression. * - * Copyright (C) 2002-2017 OpenVPN Technologies, Inc. <sales@openvpn.net> + * Copyright (C) 2002-2018 OpenVPN Inc <sales@openvpn.net> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 diff --git a/src/openvpn/otime.h b/src/openvpn/otime.h index 8731472..a6f7ec2 100644 --- a/src/openvpn/otime.h +++ b/src/openvpn/otime.h @@ -5,7 +5,7 @@ * packet encryption, packet authentication, and * packet compression. * - * Copyright (C) 2002-2017 OpenVPN Technologies, Inc. <sales@openvpn.net> + * Copyright (C) 2002-2018 OpenVPN Inc <sales@openvpn.net> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 diff --git a/src/openvpn/packet_id.c b/src/openvpn/packet_id.c index 30ae8fb..d58761b 100644 --- a/src/openvpn/packet_id.c +++ b/src/openvpn/packet_id.c @@ -5,7 +5,7 @@ * packet encryption, packet authentication, and * packet compression. * - * Copyright (C) 2002-2017 OpenVPN Technologies, Inc. <sales@openvpn.net> + * Copyright (C) 2002-2018 OpenVPN Inc <sales@openvpn.net> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 @@ -643,7 +643,7 @@ packet_id_debug_print(int msglevel, #ifdef PID_TEST void -packet_id_interactive_test() +packet_id_interactive_test(void) { struct packet_id pid; struct packet_id_net pin; diff --git a/src/openvpn/packet_id.h b/src/openvpn/packet_id.h index a370936..f984e7c 100644 --- a/src/openvpn/packet_id.h +++ b/src/openvpn/packet_id.h @@ -5,7 +5,7 @@ * packet encryption, packet authentication, and * packet compression. * - * Copyright (C) 2002-2017 OpenVPN Technologies, Inc. <sales@openvpn.net> + * Copyright (C) 2002-2018 OpenVPN Inc <sales@openvpn.net> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 @@ -299,7 +299,7 @@ packet_id_persist_save_obj(struct packet_id_persist *p, const struct packet_id * const char *packet_id_net_print(const struct packet_id_net *pin, bool print_timestamp, struct gc_arena *gc); #ifdef PID_TEST -void packet_id_interactive_test(); +void packet_id_interactive_test(void); #endif diff --git a/src/openvpn/perf.c b/src/openvpn/perf.c index 16cf749..d882358 100644 --- a/src/openvpn/perf.c +++ b/src/openvpn/perf.c @@ -5,7 +5,7 @@ * packet encryption, packet authentication, and * packet compression. * - * Copyright (C) 2002-2017 OpenVPN Technologies, Inc. <sales@openvpn.net> + * Copyright (C) 2002-2018 OpenVPN Inc <sales@openvpn.net> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 diff --git a/src/openvpn/perf.h b/src/openvpn/perf.h index ae5ae08..9cf0343 100644 --- a/src/openvpn/perf.h +++ b/src/openvpn/perf.h @@ -5,7 +5,7 @@ * packet encryption, packet authentication, and * packet compression. * - * Copyright (C) 2002-2017 OpenVPN Technologies, Inc. <sales@openvpn.net> + * Copyright (C) 2002-2018 OpenVPN Inc <sales@openvpn.net> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 diff --git a/src/openvpn/pf-inline.h b/src/openvpn/pf-inline.h index ac19ac4..90cc41c 100644 --- a/src/openvpn/pf-inline.h +++ b/src/openvpn/pf-inline.h @@ -5,7 +5,7 @@ * packet encryption, packet authentication, and * packet compression. * - * Copyright (C) 2002-2017 OpenVPN Technologies, Inc. <sales@openvpn.net> + * Copyright (C) 2002-2018 OpenVPN Inc <sales@openvpn.net> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 diff --git a/src/openvpn/pf.c b/src/openvpn/pf.c index 5cb002b..7277ae6 100644 --- a/src/openvpn/pf.c +++ b/src/openvpn/pf.c @@ -5,7 +5,7 @@ * packet encryption, packet authentication, and * packet compression. * - * Copyright (C) 2002-2017 OpenVPN Technologies, Inc. <sales@openvpn.net> + * Copyright (C) 2002-2018 OpenVPN Inc <sales@openvpn.net> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 diff --git a/src/openvpn/pf.h b/src/openvpn/pf.h index 414c85b..ff75a00 100644 --- a/src/openvpn/pf.h +++ b/src/openvpn/pf.h @@ -5,7 +5,7 @@ * packet encryption, packet authentication, and * packet compression. * - * Copyright (C) 2002-2017 OpenVPN Technologies, Inc. <sales@openvpn.net> + * Copyright (C) 2002-2018 OpenVPN Inc <sales@openvpn.net> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 diff --git a/src/openvpn/ping-inline.h b/src/openvpn/ping-inline.h index 0642b85..1a5c8bc 100644 --- a/src/openvpn/ping-inline.h +++ b/src/openvpn/ping-inline.h @@ -5,7 +5,7 @@ * packet encryption, packet authentication, and * packet compression. * - * Copyright (C) 2002-2017 OpenVPN Technologies, Inc. <sales@openvpn.net> + * Copyright (C) 2002-2018 OpenVPN Inc <sales@openvpn.net> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 diff --git a/src/openvpn/ping.c b/src/openvpn/ping.c index 728d6c2..208170d 100644 --- a/src/openvpn/ping.c +++ b/src/openvpn/ping.c @@ -5,7 +5,7 @@ * packet encryption, packet authentication, and * packet compression. * - * Copyright (C) 2002-2017 OpenVPN Technologies, Inc. <sales@openvpn.net> + * Copyright (C) 2002-2018 OpenVPN Inc <sales@openvpn.net> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 diff --git a/src/openvpn/ping.h b/src/openvpn/ping.h index 5bd5c08..05793b4 100644 --- a/src/openvpn/ping.h +++ b/src/openvpn/ping.h @@ -5,7 +5,7 @@ * packet encryption, packet authentication, and * packet compression. * - * Copyright (C) 2002-2017 OpenVPN Technologies, Inc. <sales@openvpn.net> + * Copyright (C) 2002-2018 OpenVPN Inc <sales@openvpn.net> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 diff --git a/src/openvpn/pkcs11.c b/src/openvpn/pkcs11.c index 6041828..93f8580 100644 --- a/src/openvpn/pkcs11.c +++ b/src/openvpn/pkcs11.c @@ -5,7 +5,7 @@ * packet encryption, packet authentication, and * packet compression. * - * Copyright (C) 2002-2017 OpenVPN Technologies, Inc. <sales@openvpn.net> + * Copyright (C) 2002-2018 OpenVPN Inc <sales@openvpn.net> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 @@ -356,7 +356,7 @@ cleanup: } void -pkcs11_terminate() +pkcs11_terminate(void) { dmsg( D_PKCS11_DEBUG, @@ -422,13 +422,13 @@ pkcs11_addProvider( } int -pkcs11_logout() +pkcs11_logout(void) { return pkcs11h_logout() == CKR_OK; } int -pkcs11_management_id_count() +pkcs11_management_id_count(void) { pkcs11h_certificate_id_list_t id_list = NULL; pkcs11h_certificate_id_list_t t = NULL; diff --git a/src/openvpn/pkcs11.h b/src/openvpn/pkcs11.h index f1722c0..66c6a7e 100644 --- a/src/openvpn/pkcs11.h +++ b/src/openvpn/pkcs11.h @@ -5,7 +5,7 @@ * packet encryption, packet authentication, and * packet compression. * - * Copyright (C) 2002-2017 OpenVPN Technologies, Inc. <sales@openvpn.net> + * Copyright (C) 2002-2018 OpenVPN Inc <sales@openvpn.net> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 diff --git a/src/openvpn/pkcs11_backend.h b/src/openvpn/pkcs11_backend.h index b47b757..e8fb664 100644 --- a/src/openvpn/pkcs11_backend.h +++ b/src/openvpn/pkcs11_backend.h @@ -5,8 +5,8 @@ * packet encryption, packet authentication, and * packet compression. * - * Copyright (C) 2002-2017 OpenVPN Technologies, Inc. <sales@openvpn.net> - * Copyright (C) 2010-2017 Fox Crypto B.V. <openvpn@fox-it.com> + * Copyright (C) 2002-2018 OpenVPN Inc <sales@openvpn.net> + * Copyright (C) 2010-2018 Fox Crypto B.V. <openvpn@fox-it.com> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 diff --git a/src/openvpn/pkcs11_mbedtls.c b/src/openvpn/pkcs11_mbedtls.c index 45372e4..7620624 100644 --- a/src/openvpn/pkcs11_mbedtls.c +++ b/src/openvpn/pkcs11_mbedtls.c @@ -5,8 +5,8 @@ * packet encryption, packet authentication, and * packet compression. * - * Copyright (C) 2002-2017 OpenVPN Technologies, Inc. <sales@openvpn.net> - * Copyright (C) 2010-2017 Fox Crypto B.V. <openvpn@fox-it.com> + * Copyright (C) 2002-2018 OpenVPN Inc <sales@openvpn.net> + * Copyright (C) 2010-2018 Fox Crypto B.V. <openvpn@fox-it.com> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 diff --git a/src/openvpn/pkcs11_openssl.c b/src/openvpn/pkcs11_openssl.c index c37425b..642769c 100644 --- a/src/openvpn/pkcs11_openssl.c +++ b/src/openvpn/pkcs11_openssl.c @@ -5,8 +5,8 @@ * packet encryption, packet authentication, and * packet compression. * - * Copyright (C) 2002-2017 OpenVPN Technologies, Inc. <sales@openvpn.net> - * Copyright (C) 2010-2017 Fox Crypto B.V. <openvpn@fox-it.com> + * Copyright (C) 2002-2018 OpenVPN Inc <sales@openvpn.net> + * Copyright (C) 2010-2018 Fox Crypto B.V. <openvpn@fox-it.com> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 diff --git a/src/openvpn/platform.c b/src/openvpn/platform.c index 2495523..fbffd0f 100644 --- a/src/openvpn/platform.c +++ b/src/openvpn/platform.c @@ -5,7 +5,7 @@ * packet encryption, packet authentication, and * packet compression. * - * Copyright (C) 2002-2017 OpenVPN Technologies, Inc. <sales@openvpn.net> + * Copyright (C) 2002-2018 OpenVPN Inc <sales@openvpn.net> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 @@ -159,7 +159,7 @@ platform_nice(int niceval) errno = 0; if (nice(niceval) < 0 && errno != 0) { - msg(M_WARN | M_ERRNO, "WARNING: nice %d failed: %s", niceval, strerror(errno)); + msg(M_WARN | M_ERRNO, "WARNING: nice %d failed", niceval); } else { @@ -173,7 +173,7 @@ platform_nice(int niceval) /* Get current PID */ unsigned int -platform_getpid() +platform_getpid(void) { #ifdef _WIN32 return (unsigned int) GetCurrentProcessId(); diff --git a/src/openvpn/platform.h b/src/openvpn/platform.h index cd2bbc9..288937d 100644 --- a/src/openvpn/platform.h +++ b/src/openvpn/platform.h @@ -5,7 +5,7 @@ * packet encryption, packet authentication, and * packet compression. * - * Copyright (C) 2002-2017 OpenVPN Technologies, Inc. <sales@openvpn.net> + * Copyright (C) 2002-2018 OpenVPN Inc <sales@openvpn.net> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 diff --git a/src/openvpn/plugin.c b/src/openvpn/plugin.c index 557b6bc..ddd9e85 100644 --- a/src/openvpn/plugin.c +++ b/src/openvpn/plugin.c @@ -5,7 +5,7 @@ * packet encryption, packet authentication, and * packet compression. * - * Copyright (C) 2002-2017 OpenVPN Technologies, Inc. <sales@openvpn.net> + * Copyright (C) 2002-2018 OpenVPN Inc <sales@openvpn.net> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 diff --git a/src/openvpn/plugin.h b/src/openvpn/plugin.h index 0cffee0..ec2d1fe 100644 --- a/src/openvpn/plugin.h +++ b/src/openvpn/plugin.h @@ -5,7 +5,7 @@ * packet encryption, packet authentication, and * packet compression. * - * Copyright (C) 2002-2017 OpenVPN Technologies, Inc. <sales@openvpn.net> + * Copyright (C) 2002-2018 OpenVPN Inc <sales@openvpn.net> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 diff --git a/src/openvpn/pool.c b/src/openvpn/pool.c index a8f15b9..da28bc0 100644 --- a/src/openvpn/pool.c +++ b/src/openvpn/pool.c @@ -5,7 +5,7 @@ * packet encryption, packet authentication, and * packet compression. * - * Copyright (C) 2002-2017 OpenVPN Technologies, Inc. <sales@openvpn.net> + * Copyright (C) 2002-2018 OpenVPN Inc <sales@openvpn.net> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 diff --git a/src/openvpn/pool.h b/src/openvpn/pool.h index ee91d82..6de28ac 100644 --- a/src/openvpn/pool.h +++ b/src/openvpn/pool.h @@ -5,7 +5,7 @@ * packet encryption, packet authentication, and * packet compression. * - * Copyright (C) 2002-2017 OpenVPN Technologies, Inc. <sales@openvpn.net> + * Copyright (C) 2002-2018 OpenVPN Inc <sales@openvpn.net> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 diff --git a/src/openvpn/proto.c b/src/openvpn/proto.c index 2cbea3a..87c18e8 100644 --- a/src/openvpn/proto.c +++ b/src/openvpn/proto.c @@ -5,7 +5,7 @@ * packet encryption, packet authentication, and * packet compression. * - * Copyright (C) 2002-2017 OpenVPN Technologies, Inc. <sales@openvpn.net> + * Copyright (C) 2002-2018 OpenVPN Inc <sales@openvpn.net> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 diff --git a/src/openvpn/proto.h b/src/openvpn/proto.h index 57f25c9..985aa99 100644 --- a/src/openvpn/proto.h +++ b/src/openvpn/proto.h @@ -5,7 +5,7 @@ * packet encryption, packet authentication, and * packet compression. * - * Copyright (C) 2002-2017 OpenVPN Technologies, Inc. <sales@openvpn.net> + * Copyright (C) 2002-2018 OpenVPN Inc <sales@openvpn.net> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 diff --git a/src/openvpn/proxy.c b/src/openvpn/proxy.c index 7a737ea..3fdec86 100644 --- a/src/openvpn/proxy.c +++ b/src/openvpn/proxy.c @@ -5,7 +5,7 @@ * packet encryption, packet authentication, and * packet compression. * - * Copyright (C) 2002-2017 OpenVPN Technologies, Inc. <sales@openvpn.net> + * Copyright (C) 2002-2018 OpenVPN Inc <sales@openvpn.net> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 @@ -253,9 +253,24 @@ username_password_as_base64(const struct http_proxy_info *p, } static void +clear_user_pass_http(void) +{ + purge_user_pass(&static_proxy_user_pass, true); +} + +static void get_user_pass_http(struct http_proxy_info *p, const bool force) { - if (!static_proxy_user_pass.defined || force) + /* + * in case of forced (re)load, make sure the static storage is set as + * undefined, otherwise get_user_pass() won't try to load any credential + */ + if (force) + { + clear_user_pass_http(); + } + + if (!static_proxy_user_pass.defined) { unsigned int flags = GET_USER_PASS_MANAGEMENT; if (p->queried_creds) @@ -274,11 +289,6 @@ get_user_pass_http(struct http_proxy_info *p, const bool force) p->up = static_proxy_user_pass; } } -static void -clear_user_pass_http(void) -{ - purge_user_pass(&static_proxy_user_pass, true); -} #if 0 /* function only used in #if 0 debug statement */ @@ -550,7 +560,7 @@ http_proxy_close(struct http_proxy_info *hp) free(hp); } -bool +static bool add_proxy_headers(struct http_proxy_info *p, socket_descriptor_t sd, /* already open to proxy */ const char *host, /* openvpn server remote */ diff --git a/src/openvpn/proxy.h b/src/openvpn/proxy.h index 3ce79de..707f7fa 100644 --- a/src/openvpn/proxy.h +++ b/src/openvpn/proxy.h @@ -5,7 +5,7 @@ * packet encryption, packet authentication, and * packet compression. * - * Copyright (C) 2002-2017 OpenVPN Technologies, Inc. <sales@openvpn.net> + * Copyright (C) 2002-2018 OpenVPN Inc <sales@openvpn.net> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 diff --git a/src/openvpn/ps.c b/src/openvpn/ps.c index c2b05cd..25ab374 100644 --- a/src/openvpn/ps.c +++ b/src/openvpn/ps.c @@ -5,7 +5,7 @@ * packet encryption, packet authentication, and * packet compression. * - * Copyright (C) 2002-2017 OpenVPN Technologies, Inc. <sales@openvpn.net> + * Copyright (C) 2002-2018 OpenVPN Inc <sales@openvpn.net> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 @@ -172,7 +172,7 @@ send_control(const socket_descriptor_t fd, int code) } static int -cmsg_size() +cmsg_size(void) { return CMSG_SPACE(sizeof(socket_descriptor_t)); } @@ -922,7 +922,7 @@ port_share_open(const char *host, openvpn_close_socket(fd[1]); exit(0); - return 0; /* NOTREACHED */ + return NULL; /* NOTREACHED */ } error: diff --git a/src/openvpn/ps.h b/src/openvpn/ps.h index b8c6853..b4490f5 100644 --- a/src/openvpn/ps.h +++ b/src/openvpn/ps.h @@ -5,7 +5,7 @@ * packet encryption, packet authentication, and * packet compression. * - * Copyright (C) 2002-2017 OpenVPN Technologies, Inc. <sales@openvpn.net> + * Copyright (C) 2002-2018 OpenVPN Inc <sales@openvpn.net> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 diff --git a/src/openvpn/push.c b/src/openvpn/push.c index 5947a31..6a30e47 100644 --- a/src/openvpn/push.c +++ b/src/openvpn/push.c @@ -5,7 +5,7 @@ * packet encryption, packet authentication, and * packet compression. * - * Copyright (C) 2002-2017 OpenVPN Technologies, Inc. <sales@openvpn.net> + * Copyright (C) 2002-2018 OpenVPN Inc <sales@openvpn.net> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 @@ -365,6 +365,7 @@ prepare_push_reply(struct context *c, struct gc_arena *gc, { push_option_fmt(gc, push_list, M_USAGE, "peer-id %d", tls_multi->peer_id); + tls_multi->use_peer_id = true; } } diff --git a/src/openvpn/push.h b/src/openvpn/push.h index 4d42e81..5f6181e 100644 --- a/src/openvpn/push.h +++ b/src/openvpn/push.h @@ -5,7 +5,7 @@ * packet encryption, packet authentication, and * packet compression. * - * Copyright (C) 2002-2017 OpenVPN Technologies, Inc. <sales@openvpn.net> + * Copyright (C) 2002-2018 OpenVPN Inc <sales@openvpn.net> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 diff --git a/src/openvpn/pushlist.h b/src/openvpn/pushlist.h index 57216b2..23b0ee5 100644 --- a/src/openvpn/pushlist.h +++ b/src/openvpn/pushlist.h @@ -5,7 +5,7 @@ * packet encryption, packet authentication, and * packet compression. * - * Copyright (C) 2002-2017 OpenVPN Technologies, Inc. <sales@openvpn.net> + * Copyright (C) 2002-2018 OpenVPN Inc <sales@openvpn.net> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 diff --git a/src/openvpn/reliable.c b/src/openvpn/reliable.c index 93541a9..8f5e173 100644 --- a/src/openvpn/reliable.c +++ b/src/openvpn/reliable.c @@ -5,7 +5,7 @@ * packet encryption, packet authentication, and * packet compression. * - * Copyright (C) 2002-2017 OpenVPN Technologies, Inc. <sales@openvpn.net> + * Copyright (C) 2002-2018 OpenVPN Inc <sales@openvpn.net> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 diff --git a/src/openvpn/reliable.h b/src/openvpn/reliable.h index aa34b02..bc32ad9 100644 --- a/src/openvpn/reliable.h +++ b/src/openvpn/reliable.h @@ -5,7 +5,7 @@ * packet encryption, packet authentication, and * packet compression. * - * Copyright (C) 2002-2017 OpenVPN Technologies, Inc. <sales@openvpn.net> + * Copyright (C) 2002-2018 OpenVPN Inc <sales@openvpn.net> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 diff --git a/src/openvpn/route.c b/src/openvpn/route.c index a1811f4..2d6428b 100644 --- a/src/openvpn/route.c +++ b/src/openvpn/route.c @@ -5,7 +5,7 @@ * packet encryption, packet authentication, and * packet compression. * - * Copyright (C) 2002-2017 OpenVPN Technologies, Inc. <sales@openvpn.net> + * Copyright (C) 2002-2018 OpenVPN Inc <sales@openvpn.net> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 @@ -518,14 +518,14 @@ add_route_ipv6_to_option_list(struct route_ipv6_option_list *l, l->routes_ipv6 = ro; } -void +static void clear_route_list(struct route_list *rl) { gc_free(&rl->gc); CLEAR(*rl); } -void +static void clear_route_ipv6_list(struct route_ipv6_list *rl6) { gc_free(&rl6->gc); @@ -1530,7 +1530,9 @@ add_route(struct route_ipv4 *r, struct gc_arena gc; struct argv argv = argv_new(); const char *network; +#if !defined(ENABLE_IPROUTE) && !defined(TARGET_AIX) const char *netmask; +#endif const char *gateway; bool status = false; int is_local_route; @@ -1543,7 +1545,9 @@ add_route(struct route_ipv4 *r, gc_init(&gc); network = print_in_addr_t(r->network, 0, &gc); +#if !defined(ENABLE_IPROUTE) && !defined(TARGET_AIX) netmask = print_in_addr_t(r->netmask, 0, &gc); +#endif gateway = print_in_addr_t(r->gateway, 0, &gc); is_local_route = local_route(r->network, r->netmask, r->gateway, rgi); @@ -1816,7 +1820,7 @@ done: } -static void +void route_ipv6_clear_host_bits( struct route_ipv6 *r6 ) { /* clear host bit parts of route @@ -1965,12 +1969,12 @@ add_route_ipv6(struct route_ipv6 *r6, const struct tuntap *tt, unsigned int flag struct buffer out = alloc_buf_gc(64, &gc); if (r6->adapter_index) /* vpn server special route */ { - buf_printf(&out, "interface=%d", r6->adapter_index ); + buf_printf(&out, "interface=%lu", r6->adapter_index ); gateway_needed = true; } else { - buf_printf(&out, "interface=%d", tt->adapter_index ); + buf_printf(&out, "interface=%lu", tt->adapter_index ); } device = buf_bptr(&out); @@ -2132,8 +2136,12 @@ delete_route(struct route_ipv4 *r, struct gc_arena gc; struct argv argv = argv_new(); const char *network; +#if !defined(ENABLE_IPROUTE) && !defined(TARGET_AIX) const char *netmask; +#endif +#if !defined(TARGET_LINUX) && !defined(TARGET_ANDROID) const char *gateway; +#endif int is_local_route; if ((r->flags & (RT_DEFINED|RT_ADDED)) != (RT_DEFINED|RT_ADDED)) @@ -2144,8 +2152,12 @@ delete_route(struct route_ipv4 *r, gc_init(&gc); network = print_in_addr_t(r->network, 0, &gc); +#if !defined(ENABLE_IPROUTE) && !defined(TARGET_AIX) netmask = print_in_addr_t(r->netmask, 0, &gc); +#endif +#if !defined(TARGET_LINUX) && !defined(TARGET_ANDROID) gateway = print_in_addr_t(r->gateway, 0, &gc); +#endif is_local_route = local_route(r->network, r->netmask, r->gateway, rgi); if (is_local_route == LR_ERROR) @@ -2404,12 +2416,12 @@ delete_route_ipv6(const struct route_ipv6 *r6, const struct tuntap *tt, unsigned struct buffer out = alloc_buf_gc(64, &gc); if (r6->adapter_index) /* vpn server special route */ { - buf_printf(&out, "interface=%d", r6->adapter_index ); + buf_printf(&out, "interface=%lu", r6->adapter_index ); gateway_needed = true; } else { - buf_printf(&out, "interface=%d", tt->adapter_index ); + buf_printf(&out, "interface=%lu", tt->adapter_index ); } device = buf_bptr(&out); @@ -2768,7 +2780,6 @@ windows_route_find_if_index(const struct route_ipv4 *r, const struct tuntap *tt) msg(M_WARN, "Warning: route gateway is ambiguous: %s (%d matches)", print_in_addr_t(r->gateway, 0, &gc), count); - ret = TUN_ADAPTER_INDEX_INVALID; } dmsg(D_ROUTE_DEBUG, "DEBUG: route find if: on_tun=%d count=%d index=%d", @@ -2830,7 +2841,7 @@ get_default_gateway_ipv6(struct route_ipv6_gateway_info *rgi6, goto done; } - msg( D_ROUTE, "GDG6: II=%d DP=%s/%d NH=%s", + msg( D_ROUTE, "GDG6: II=%lu DP=%s/%d NH=%s", BestRoute.InterfaceIndex, print_in6_addr( BestRoute.DestinationPrefix.Prefix.Ipv6.sin6_addr, 0, &gc), BestRoute.DestinationPrefix.PrefixLength, @@ -2991,7 +3002,7 @@ do_route_service(const bool add, const route_message_t *rt, const size_t size, H if (ack.error_number != NO_ERROR) { - msg(M_WARN, "ROUTE: route %s failed using service: %s [status=%u if_index=%lu]", + msg(M_WARN, "ROUTE: route %s failed using service: %s [status=%u if_index=%d]", (add ? "addition" : "deletion"), strerror_win32(ack.error_number, &gc), ack.error_number, rt->iface.index); goto out; @@ -3441,7 +3452,14 @@ get_default_gateway_ipv6(struct route_ipv6_gateway_info *rgi6, if (nh->nlmsg_type == NLMSG_ERROR) { struct nlmsgerr *ne = (struct nlmsgerr *)NLMSG_DATA(nh); - msg(M_WARN, "GDG6: NLSMG_ERROR: error %d\n", ne->error); + + /* since linux-4.11 -ENETUNREACH is returned when no route can be + * found. Don't print any error message in this case */ + if (ne->error != -ENETUNREACH) + { + msg(M_WARN, "GDG6: NLMSG_ERROR: error %s\n", + strerror(-ne->error)); + } break; } diff --git a/src/openvpn/route.h b/src/openvpn/route.h index 6414d6c..6942022 100644 --- a/src/openvpn/route.h +++ b/src/openvpn/route.h @@ -5,7 +5,7 @@ * packet encryption, packet authentication, and * packet compression. * - * Copyright (C) 2002-2017 OpenVPN Technologies, Inc. <sales@openvpn.net> + * Copyright (C) 2002-2018 OpenVPN Inc <sales@openvpn.net> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 @@ -254,6 +254,8 @@ void copy_route_ipv6_option_list(struct route_ipv6_option_list *dest, const struct route_ipv6_option_list *src, struct gc_arena *a); +void route_ipv6_clear_host_bits( struct route_ipv6 *r6 ); + void add_route_ipv6(struct route_ipv6 *r, const struct tuntap *tt, unsigned int flags, const struct env_set *es); void delete_route_ipv6(const struct route_ipv6 *r, const struct tuntap *tt, unsigned int flags, const struct env_set *es); diff --git a/src/openvpn/schedule.c b/src/openvpn/schedule.c index b1ba5d4..76cf7c3 100644 --- a/src/openvpn/schedule.c +++ b/src/openvpn/schedule.c @@ -5,7 +5,7 @@ * packet encryption, packet authentication, and * packet compression. * - * Copyright (C) 2002-2017 OpenVPN Technologies, Inc. <sales@openvpn.net> + * Copyright (C) 2002-2018 OpenVPN Inc <sales@openvpn.net> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 diff --git a/src/openvpn/schedule.h b/src/openvpn/schedule.h index e6c1b7e..74d37fb 100644 --- a/src/openvpn/schedule.h +++ b/src/openvpn/schedule.h @@ -5,7 +5,7 @@ * packet encryption, packet authentication, and * packet compression. * - * Copyright (C) 2002-2017 OpenVPN Technologies, Inc. <sales@openvpn.net> + * Copyright (C) 2002-2018 OpenVPN Inc <sales@openvpn.net> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 diff --git a/src/openvpn/session_id.c b/src/openvpn/session_id.c index dce42e7..2b50feb 100644 --- a/src/openvpn/session_id.c +++ b/src/openvpn/session_id.c @@ -5,7 +5,7 @@ * packet encryption, packet authentication, and * packet compression. * - * Copyright (C) 2002-2017 OpenVPN Technologies, Inc. <sales@openvpn.net> + * Copyright (C) 2002-2018 OpenVPN Inc <sales@openvpn.net> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 diff --git a/src/openvpn/session_id.h b/src/openvpn/session_id.h index 6611a3c..5e950a6 100644 --- a/src/openvpn/session_id.h +++ b/src/openvpn/session_id.h @@ -5,7 +5,7 @@ * packet encryption, packet authentication, and * packet compression. * - * Copyright (C) 2002-2017 OpenVPN Technologies, Inc. <sales@openvpn.net> + * Copyright (C) 2002-2018 OpenVPN Inc <sales@openvpn.net> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 diff --git a/src/openvpn/shaper.c b/src/openvpn/shaper.c index 19dd54d..00eb2e9 100644 --- a/src/openvpn/shaper.c +++ b/src/openvpn/shaper.c @@ -5,7 +5,7 @@ * packet encryption, packet authentication, and * packet compression. * - * Copyright (C) 2002-2017 OpenVPN Technologies, Inc. <sales@openvpn.net> + * Copyright (C) 2002-2018 OpenVPN Inc <sales@openvpn.net> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 diff --git a/src/openvpn/shaper.h b/src/openvpn/shaper.h index 6fac16d..0496c71 100644 --- a/src/openvpn/shaper.h +++ b/src/openvpn/shaper.h @@ -5,7 +5,7 @@ * packet encryption, packet authentication, and * packet compression. * - * Copyright (C) 2002-2017 OpenVPN Technologies, Inc. <sales@openvpn.net> + * Copyright (C) 2002-2018 OpenVPN Inc <sales@openvpn.net> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 diff --git a/src/openvpn/sig.c b/src/openvpn/sig.c index 87cef71..d7f2abb 100644 --- a/src/openvpn/sig.c +++ b/src/openvpn/sig.c @@ -5,7 +5,7 @@ * packet encryption, packet authentication, and * packet compression. * - * Copyright (C) 2002-2017 OpenVPN Technologies, Inc. <sales@openvpn.net> + * Copyright (C) 2002-2018 OpenVPN Inc <sales@openvpn.net> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 diff --git a/src/openvpn/sig.h b/src/openvpn/sig.h index 7c41070..887d833 100644 --- a/src/openvpn/sig.h +++ b/src/openvpn/sig.h @@ -5,7 +5,7 @@ * packet encryption, packet authentication, and * packet compression. * - * Copyright (C) 2002-2017 OpenVPN Technologies, Inc. <sales@openvpn.net> + * Copyright (C) 2002-2018 OpenVPN Inc <sales@openvpn.net> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 diff --git a/src/openvpn/socket.c b/src/openvpn/socket.c index 4e7e3f9..211e744 100644 --- a/src/openvpn/socket.c +++ b/src/openvpn/socket.c @@ -5,7 +5,7 @@ * packet encryption, packet authentication, and * packet compression. * - * Copyright (C) 2002-2017 OpenVPN Technologies, Inc. <sales@openvpn.net> + * Copyright (C) 2002-2018 OpenVPN Inc <sales@openvpn.net> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 @@ -496,7 +496,7 @@ openvpn_getaddrinfo(unsigned int flags, goto done; } - openvpn_sleep(fail_wait_interval); + management_sleep(fail_wait_interval); } ASSERT(res); @@ -1122,7 +1122,7 @@ socket_do_accept(socket_descriptor_t sd, if (!socket_defined(new_sd)) { - msg(D_LINK_ERRORS | M_ERRNO, "TCP: accept(%d) failed", sd); + msg(D_LINK_ERRORS | M_ERRNO, "TCP: accept(%d) failed", (int)sd); } /* only valid if we have remote_len_af!=0 */ else if (remote_len_af && remote_len != remote_len_af) @@ -1193,7 +1193,7 @@ socket_listen_accept(socket_descriptor_t sd, if (status <= 0) { - openvpn_sleep(1); + management_sleep(1); continue; } @@ -1228,7 +1228,7 @@ socket_listen_accept(socket_descriptor_t sd, break; } } - openvpn_sleep(1); + management_sleep(1); } if (!nowait && openvpn_close_socket(sd)) @@ -1297,11 +1297,9 @@ socket_bind(socket_descriptor_t sd, } if (bind(sd, cur->ai_addr, cur->ai_addrlen)) { - const int errnum = openvpn_errno(); - msg(M_FATAL, "%s: Socket bind failed on local address %s: %s", + msg(M_FATAL | M_ERRNO, "%s: Socket bind failed on local address %s", prefix, - print_sockaddr_ex(local->ai_addr, ":", PS_SHOW_PORT, &gc), - strerror_ts(errnum, &gc)); + print_sockaddr_ex(local->ai_addr, ":", PS_SHOW_PORT, &gc)); } gc_free(&gc); } @@ -1376,7 +1374,7 @@ openvpn_connect(socket_descriptor_t sd, #endif break; } - openvpn_sleep(1); + management_sleep(1); continue; } @@ -1433,7 +1431,7 @@ set_actual_address(struct link_socket_actual *actual, struct addrinfo *ai) } -void +static void socket_connect(socket_descriptor_t *sd, const struct sockaddr *dest, const int connect_timeout, @@ -1475,10 +1473,8 @@ socket_connect(socket_descriptor_t *sd, if (status) { - msg(D_LINK_ERRORS, - "TCP: connect to %s failed: %s", - print_sockaddr(dest, &gc), - strerror_ts(status, &gc)); + msg(D_LINK_ERRORS, "TCP: connect to %s failed: %s", + print_sockaddr(dest, &gc), strerror(status)); openvpn_close_socket(*sd); *sd = SOCKET_UNDEFINED; @@ -1790,6 +1786,8 @@ link_socket_init_phase1(struct link_socket *sock, ASSERT(sock->info.proto == PROTO_TCP_SERVER); ASSERT(!sock->inetd); sock->sd = accept_from->sd; + /* inherit (possibly guessed) info AF from parent context */ + sock->info.af = accept_from->info.af; } /* are we running in HTTP proxy mode? */ @@ -1877,12 +1875,12 @@ phase2_inetd(struct link_socket *sock, const struct frame *frame, sock->info.lsa->actual.dest.addr.sa.sa_family = local_addr.addr.sa.sa_family; dmsg(D_SOCKET_DEBUG, "inetd(%s): using sa_family=%d from getsockname(%d)", proto2ascii(sock->info.proto, sock->info.af, false), - local_addr.addr.sa.sa_family, sock->sd); + local_addr.addr.sa.sa_family, (int)sock->sd); } else { msg(M_WARN, "inetd(%s): getsockname(%d) failed, using AF_INET", - proto2ascii(sock->info.proto, sock->info.af, false), sock->sd); + proto2ascii(sock->info.proto, sock->info.af, false), (int)sock->sd); } } #else /* ifdef HAVE_GETSOCKNAME */ @@ -3888,12 +3886,11 @@ socket_bind_unix(socket_descriptor_t sd, if (bind(sd, (struct sockaddr *) local, sizeof(struct sockaddr_un))) { - const int errnum = openvpn_errno(); - msg(M_FATAL, "%s: Socket bind[%d] failed on unix domain socket %s: %s", + msg(M_FATAL | M_ERRNO, + "%s: Socket bind[%d] failed on unix domain socket %s", prefix, (int)sd, - sockaddr_unix_name(local, "NULL"), - strerror_ts(errnum, &gc)); + sockaddr_unix_name(local, "NULL")); } #ifdef HAVE_UMASK diff --git a/src/openvpn/socket.h b/src/openvpn/socket.h index 2d7f218..479d115 100644 --- a/src/openvpn/socket.h +++ b/src/openvpn/socket.h @@ -5,7 +5,7 @@ * packet encryption, packet authentication, and * packet compression. * - * Copyright (C) 2002-2017 OpenVPN Technologies, Inc. <sales@openvpn.net> + * Copyright (C) 2002-2018 OpenVPN Inc <sales@openvpn.net> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 diff --git a/src/openvpn/socks.c b/src/openvpn/socks.c index 92747ec..c61ef55 100644 --- a/src/openvpn/socks.c +++ b/src/openvpn/socks.c @@ -5,7 +5,7 @@ * packet encryption, packet authentication, and * packet compression. * - * Copyright (C) 2002-2017 OpenVPN Technologies, Inc. <sales@openvpn.net> + * Copyright (C) 2002-2018 OpenVPN Inc <sales@openvpn.net> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 diff --git a/src/openvpn/socks.h b/src/openvpn/socks.h index 39b96c5..aef873c 100644 --- a/src/openvpn/socks.h +++ b/src/openvpn/socks.h @@ -5,7 +5,7 @@ * packet encryption, packet authentication, and * packet compression. * - * Copyright (C) 2002-2017 OpenVPN Technologies, Inc. <sales@openvpn.net> + * Copyright (C) 2002-2018 OpenVPN Inc <sales@openvpn.net> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 diff --git a/src/openvpn/ssl.c b/src/openvpn/ssl.c index 15cd94a..effb8b2 100644 --- a/src/openvpn/ssl.c +++ b/src/openvpn/ssl.c @@ -5,8 +5,8 @@ * packet encryption, packet authentication, and * packet compression. * - * Copyright (C) 2002-2017 OpenVPN Technologies, Inc. <sales@openvpn.net> - * Copyright (C) 2010-2017 Fox Crypto B.V. <openvpn@fox-it.com> + * Copyright (C) 2002-2018 OpenVPN Inc <sales@openvpn.net> + * Copyright (C) 2010-2018 Fox Crypto B.V. <openvpn@fox-it.com> * Copyright (C) 2008-2013 David Sommerseth <dazo@users.sourceforge.net> * * This program is free software; you can redistribute it and/or modify @@ -347,7 +347,7 @@ tls_init_control_channel_frame_parameters(const struct frame *data_channel_frame } void -init_ssl_lib() +init_ssl_lib(void) { tls_init_lib(); @@ -355,7 +355,7 @@ init_ssl_lib() } void -free_ssl_lib() +free_ssl_lib(void) { crypto_uninit_lib(); prng_uninit(); @@ -530,6 +530,10 @@ tls_version_parse(const char *vstr, const char *extra) { return TLS_VER_1_2; } + else if (!strcmp(vstr, "1.3") && TLS_VER_1_3 <= max_version) + { + return TLS_VER_1_3; + } else if (extra && !strcmp(extra, "or-highest")) { return max_version; @@ -616,7 +620,18 @@ init_ssl(const struct options *options, struct tls_root_ctx *new_ctx) tls_ctx_client_new(new_ctx); } - tls_ctx_set_options(new_ctx, options->ssl_flags); + /* Restrict allowed certificate crypto algorithms */ + tls_ctx_set_cert_profile(new_ctx, options->tls_cert_profile); + + /* Allowable ciphers */ + /* Since @SECLEVEL also influces loading of certificates, set the + * cipher restrictions before loading certificates */ + tls_ctx_restrict_ciphers(new_ctx, options->cipher_list); + + if (!tls_ctx_set_options(new_ctx, options->ssl_flags)) + { + goto err; + } if (options->pkcs12_file) { @@ -708,9 +723,6 @@ init_ssl(const struct options *options, struct tls_root_ctx *new_ctx) tls_ctx_load_ecdh_params(new_ctx, options->ecdh_curve); } - /* Allowable ciphers */ - tls_ctx_restrict_ciphers(new_ctx, options->cipher_list); - #ifdef ENABLE_CRYPTO_MBEDTLS /* Personalise the random by mixing in the certificate */ tls_ctx_personalise_random(new_ctx); @@ -1532,7 +1544,7 @@ read_control_auth(struct buffer *buf, } else if (ctx->mode == TLS_WRAP_CRYPT) { - struct buffer tmp = alloc_buf(buf_forward_capacity_total(buf)); + struct buffer tmp = alloc_buf_gc(buf_forward_capacity_total(buf), &gc); if (!tls_crypt_unwrap(buf, &tmp, &ctx->opt)) { msg(D_TLS_ERRORS, "TLS Error: tls-crypt unwrapping failed from %s", @@ -1541,7 +1553,7 @@ read_control_auth(struct buffer *buf, } ASSERT(buf_init(buf, buf->offset)); ASSERT(buf_copy(buf, &tmp)); - free_buf(&tmp); + buf_clear(&tmp); } if (ctx->mode == TLS_WRAP_NONE || ctx->mode == TLS_WRAP_AUTH) @@ -1605,7 +1617,7 @@ key_source2_print(const struct key_source2 *k) * @param out Output buffer * @param olen Length of the output buffer */ -void +static void tls1_P_hash(const md_kt_t *md_kt, const uint8_t *sec, int sec_len, @@ -1838,20 +1850,8 @@ generate_key_expansion(struct key_ctx_bi *key, } /* Initialize OpenSSL key contexts */ - - ASSERT(server == true || server == false); - - init_key_ctx(&key->encrypt, - &key2.keys[(int)server], - key_type, - OPENVPN_OP_ENCRYPT, - "Data Channel Encrypt"); - - init_key_ctx(&key->decrypt, - &key2.keys[1-(int)server], - key_type, - OPENVPN_OP_DECRYPT, - "Data Channel Decrypt"); + int key_direction = server ? KEY_DIRECTION_INVERSE : KEY_DIRECTION_NORMAL; + init_key_ctx_bi(key, &key2, key_direction, key_type, "Data Channel"); /* Initialize implicit IVs */ key_ctx_update_implicit_iv(&key->encrypt, key2.keys[(int)server].hmac, @@ -1859,7 +1859,6 @@ generate_key_expansion(struct key_ctx_bi *key, key_ctx_update_implicit_iv(&key->decrypt, key2.keys[1-(int)server].hmac, MAX_HMAC_KEY_LENGTH); - key->initialized = true; ret = true; exit: @@ -1958,7 +1957,7 @@ cleanup: bool tls_session_update_crypto_params(struct tls_session *session, - const struct options *options, struct frame *frame) + struct options *options, struct frame *frame) { if (!session->opt->server && 0 != strcmp(options->ciphername, session->opt->config_ciphername) @@ -1967,6 +1966,8 @@ tls_session_update_crypto_params(struct tls_session *session, msg(D_TLS_ERRORS, "Error: pushed cipher not allowed - %s not in %s or %s", options->ciphername, session->opt->config_ciphername, options->ncp_ciphers); + /* undo cipher push, abort connection setup */ + options->ciphername = session->opt->config_ciphername; return false; } @@ -1974,6 +1975,11 @@ tls_session_update_crypto_params(struct tls_session *session, { msg(D_HANDSHAKE, "Data Channel: using negotiated cipher '%s'", options->ciphername); + if (options->keysize) + { + msg(D_HANDSHAKE, "NCP: overriding user-set keysize with default"); + options->keysize = 0; + } } init_key_type(&session->opt->key_type, options->ciphername, @@ -2186,16 +2192,6 @@ read_string_alloc(struct buffer *buf) return str; } -void -read_string_discard(struct buffer *buf) -{ - char *data = read_string_alloc(buf); - if (data) - { - free(data); - } -} - /* * Handle the reading and writing of key data to and from * the TLS control channel (cleartext). @@ -3369,7 +3365,7 @@ tls_pre_decrypt(struct tls_multi *multi, { if (!ks->crypto_options.key_ctx_bi.initialized) { - msg(D_TLS_DEBUG_LOW, + msg(D_MULTI_DROPPED, "Key %s [%d] not initialized (yet), dropping packet.", print_link_socket_actual(from, &gc), key_id); goto error_lite; diff --git a/src/openvpn/ssl.h b/src/openvpn/ssl.h index 56ea601..132424e 100644 --- a/src/openvpn/ssl.h +++ b/src/openvpn/ssl.h @@ -5,8 +5,8 @@ * packet encryption, packet authentication, and * packet compression. * - * Copyright (C) 2002-2017 OpenVPN Technologies, Inc. <sales@openvpn.net> - * Copyright (C) 2010-2017 Fox Crypto B.V. <openvpn@fox-it.com> + * Copyright (C) 2002-2018 OpenVPN Inc <sales@openvpn.net> + * Copyright (C) 2010-2018 Fox Crypto B.V. <openvpn@fox-it.com> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 @@ -481,7 +481,7 @@ void tls_update_remote_addr(struct tls_multi *multi, * @return true if updating succeeded, false otherwise. */ bool tls_session_update_crypto_params(struct tls_session *session, - const struct options *options, struct frame *frame); + struct options *options, struct frame *frame); /** * "Poor man's NCP": Use peer cipher if it is an allowed (NCP) cipher. diff --git a/src/openvpn/ssl_backend.h b/src/openvpn/ssl_backend.h index a738f0f..e704de8 100644 --- a/src/openvpn/ssl_backend.h +++ b/src/openvpn/ssl_backend.h @@ -5,8 +5,8 @@ * packet encryption, packet authentication, and * packet compression. * - * Copyright (C) 2002-2017 OpenVPN Technologies, Inc. <sales@openvpn.net> - * Copyright (C) 2010-2017 Fox Crypto B.V. <openvpn@fox-it.com> + * Copyright (C) 2002-2018 OpenVPN Inc <sales@openvpn.net> + * Copyright (C) 2010-2018 Fox Crypto B.V. <openvpn@fox-it.com> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 @@ -88,17 +88,17 @@ int pem_password_callback(char *buf, int size, int rwflag, void *u); * Perform any static initialisation necessary by the library. * Called on OpenVPN initialisation */ -void tls_init_lib(); +void tls_init_lib(void); /** * Free any global SSL library-specific data structures. */ -void tls_free_lib(); +void tls_free_lib(void); /** * Clear the underlying SSL library's error state. */ -void tls_clear_error(); +void tls_clear_error(void); /** * Parse a TLS version specifier @@ -114,6 +114,7 @@ void tls_clear_error(); #define TLS_VER_1_0 1 #define TLS_VER_1_1 2 #define TLS_VER_1_2 3 +#define TLS_VER_1_3 4 int tls_version_parse(const char *vstr, const char *extra); /** @@ -164,8 +165,10 @@ bool tls_ctx_initialised(struct tls_root_ctx *ctx); * * @param ctx TLS context to set options on * @param ssl_flags SSL flags to set + * + * @return true on success, false otherwise. */ -void tls_ctx_set_options(struct tls_root_ctx *ctx, unsigned int ssl_flags); +bool tls_ctx_set_options(struct tls_root_ctx *ctx, unsigned int ssl_flags); /** * Restrict the list of ciphers that can be used within the TLS context. @@ -177,6 +180,16 @@ void tls_ctx_set_options(struct tls_root_ctx *ctx, unsigned int ssl_flags); void tls_ctx_restrict_ciphers(struct tls_root_ctx *ctx, const char *ciphers); /** + * Set the TLS certificate profile. The profile defines which crypto + * algorithms may be used in the supplied certificate. + * + * @param ctx TLS context to restrict, must be valid. + * @param profile The profile name ('preferred', 'legacy' or 'suiteb'). + * Defaults to 'preferred' if NULL. + */ +void tls_ctx_set_cert_profile(struct tls_root_ctx *ctx, const char *profile); + +/** * Check our certificate notBefore and notAfter fields, and warn if the cert is * either not yet valid or has expired. Note that this is a non-fatal error, * since we compare against the system time, which might be incorrect. @@ -505,9 +518,12 @@ void print_details(struct key_state_ssl *ks_ssl, const char *prefix); * Show the TLS ciphers that are available for us to use in the OpenSSL * library. * - * @param - list of allowed TLS cipher, or NULL. + * @param cipher_list list of allowed TLS cipher, or NULL. + * @param tls_cert_profile TLS certificate crypto profile name. */ -void show_available_tls_ciphers(const char *tls_ciphers); +void +show_available_tls_ciphers(const char *cipher_list, + const char *tls_cert_profile); /* * Show the available elliptic curves in the crypto library diff --git a/src/openvpn/ssl_common.h b/src/openvpn/ssl_common.h index 25bffd5..c7565d8 100644 --- a/src/openvpn/ssl_common.h +++ b/src/openvpn/ssl_common.h @@ -5,8 +5,8 @@ * packet encryption, packet authentication, and * packet compression. * - * Copyright (C) 2002-2017 OpenVPN Technologies, Inc. <sales@openvpn.net> - * Copyright (C) 2010-2017 Fox Crypto B.V. <openvpn@fox-it.com> + * Copyright (C) 2002-2018 OpenVPN Inc <sales@openvpn.net> + * Copyright (C) 2010-2018 Fox Crypto B.V. <openvpn@fox-it.com> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 diff --git a/src/openvpn/ssl_mbedtls.c b/src/openvpn/ssl_mbedtls.c index ef583e6..74b4726 100644 --- a/src/openvpn/ssl_mbedtls.c +++ b/src/openvpn/ssl_mbedtls.c @@ -5,8 +5,8 @@ * packet encryption, packet authentication, and * packet compression. * - * Copyright (C) 2002-2017 OpenVPN Technologies, Inc. <sales@openvpn.net> - * Copyright (C) 2010-2017 Fox Crypto B.V. <openvpn@fox-it.com> + * Copyright (C) 2002-2018 OpenVPN Inc <sales@openvpn.net> + * Copyright (C) 2010-2018 Fox Crypto B.V. <openvpn@fox-it.com> * Copyright (C) 2006-2010, Brainspark B.V. * * This program is free software; you can redistribute it and/or modify @@ -60,20 +60,47 @@ #include <mbedtls/oid.h> #include <mbedtls/pem.h> -#include <mbedtls/sha256.h> + +static const mbedtls_x509_crt_profile openvpn_x509_crt_profile_legacy = +{ + /* Hashes from SHA-1 and above */ + MBEDTLS_X509_ID_FLAG( MBEDTLS_MD_SHA1 ) | + MBEDTLS_X509_ID_FLAG( MBEDTLS_MD_RIPEMD160 ) | + MBEDTLS_X509_ID_FLAG( MBEDTLS_MD_SHA224 ) | + MBEDTLS_X509_ID_FLAG( MBEDTLS_MD_SHA256 ) | + MBEDTLS_X509_ID_FLAG( MBEDTLS_MD_SHA384 ) | + MBEDTLS_X509_ID_FLAG( MBEDTLS_MD_SHA512 ), + 0xFFFFFFF, /* Any PK alg */ + 0xFFFFFFF, /* Any curve */ + 1024, /* RSA-1024 and larger */ +}; + +static const mbedtls_x509_crt_profile openvpn_x509_crt_profile_preferred = +{ + /* SHA-2 and above */ + MBEDTLS_X509_ID_FLAG( MBEDTLS_MD_SHA224 ) | + MBEDTLS_X509_ID_FLAG( MBEDTLS_MD_SHA256 ) | + MBEDTLS_X509_ID_FLAG( MBEDTLS_MD_SHA384 ) | + MBEDTLS_X509_ID_FLAG( MBEDTLS_MD_SHA512 ), + 0xFFFFFFF, /* Any PK alg */ + 0xFFFFFFF, /* Any curve */ + 2048, /* RSA-2048 and larger */ +}; + +#define openvpn_x509_crt_profile_suiteb mbedtls_x509_crt_profile_suiteb; void -tls_init_lib() +tls_init_lib(void) { } void -tls_free_lib() +tls_free_lib(void) { } void -tls_clear_error() +tls_clear_error(void) { } @@ -178,9 +205,10 @@ key_state_export_keying_material(struct key_state_ssl *ssl, { } -void +bool tls_ctx_set_options(struct tls_root_ctx *ctx, unsigned int ssl_flags) { + return true; } static const char * @@ -251,6 +279,27 @@ tls_ctx_restrict_ciphers(struct tls_root_ctx *ctx, const char *ciphers) } void +tls_ctx_set_cert_profile(struct tls_root_ctx *ctx, const char *profile) +{ + if (!profile || 0 == strcmp(profile, "legacy")) + { + ctx->cert_profile = openvpn_x509_crt_profile_legacy; + } + else if (0 == strcmp(profile, "preferred")) + { + ctx->cert_profile = openvpn_x509_crt_profile_preferred; + } + else if (0 == strcmp(profile, "suiteb")) + { + ctx->cert_profile = openvpn_x509_crt_profile_suiteb; + } + else + { + msg (M_FATAL, "ERROR: Invalid cert profile: %s", profile); + } +} + +void tls_ctx_check_cert_time(const struct tls_root_ctx *ctx) { ASSERT(ctx); @@ -801,9 +850,14 @@ tls_ctx_personalise_random(struct tls_root_ctx *ctx) if (NULL != ctx->crt_chain) { + const md_kt_t *sha256_kt = md_kt_get("SHA256"); mbedtls_x509_crt *cert = ctx->crt_chain; - mbedtls_sha256(cert->tbs.p, cert->tbs.len, sha256_hash, false); + if (0 != md_full(sha256_kt, cert->tbs.p, cert->tbs.len, sha256_hash)) + { + msg(M_WARN, "WARNING: failed to personalise random"); + } + if (0 != memcmp(old_sha256_hash, sha256_hash, sizeof(sha256_hash))) { mbedtls_ctr_drbg_update(cd_ctx, sha256_hash, 32); @@ -917,6 +971,8 @@ key_state_ssl_init(struct key_state_ssl *ks_ssl, mbedtls_ssl_conf_rng(&ks_ssl->ssl_config, mbedtls_ctr_drbg_random, rand_ctx_get()); + mbedtls_ssl_conf_cert_profile(&ks_ssl->ssl_config, &ssl_ctx->cert_profile); + if (ssl_ctx->allowed_ciphers) { mbedtls_ssl_conf_ciphersuites(&ks_ssl->ssl_config, ssl_ctx->allowed_ciphers); @@ -1271,12 +1327,14 @@ print_details(struct key_state_ssl *ks_ssl, const char *prefix) } void -show_available_tls_ciphers(const char *cipher_list) +show_available_tls_ciphers(const char *cipher_list, + const char *tls_cert_profile) { struct tls_root_ctx tls_ctx; const int *ciphers = mbedtls_ssl_list_ciphersuites(); tls_ctx_server_new(&tls_ctx); + tls_ctx_set_cert_profile(&tls_ctx, tls_cert_profile); tls_ctx_restrict_ciphers(&tls_ctx, cipher_list); if (tls_ctx.allowed_ciphers) diff --git a/src/openvpn/ssl_mbedtls.h b/src/openvpn/ssl_mbedtls.h index f69b610..dd8ca75 100644 --- a/src/openvpn/ssl_mbedtls.h +++ b/src/openvpn/ssl_mbedtls.h @@ -5,8 +5,8 @@ * packet encryption, packet authentication, and * packet compression. * - * Copyright (C) 2002-2017 OpenVPN Technologies, Inc. <sales@openvpn.net> - * Copyright (C) 2010-2017 Fox Crypto B.V. <openvpn@fox-it.com> + * Copyright (C) 2002-2018 OpenVPN Inc <sales@openvpn.net> + * Copyright (C) 2010-2018 Fox Crypto B.V. <openvpn@fox-it.com> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 @@ -82,6 +82,7 @@ struct tls_root_ctx { struct external_context *external_key; /**< Management external key */ #endif int *allowed_ciphers; /**< List of allowed ciphers for this connection */ + mbedtls_x509_crt_profile cert_profile; /**< Allowed certificate types */ }; struct key_state_ssl { diff --git a/src/openvpn/ssl_openssl.c b/src/openvpn/ssl_openssl.c index e589dcd..f23d246 100644 --- a/src/openvpn/ssl_openssl.c +++ b/src/openvpn/ssl_openssl.c @@ -5,8 +5,8 @@ * packet encryption, packet authentication, and * packet compression. * - * Copyright (C) 2002-2017 OpenVPN Technologies, Inc. <sales@openvpn.net> - * Copyright (C) 2010-2017 Fox Crypto B.V. <openvpn@fox-it.com> + * Copyright (C) 2002-2018 OpenVPN Inc <sales@openvpn.net> + * Copyright (C) 2010-2018 Fox Crypto B.V. <openvpn@fox-it.com> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 @@ -69,7 +69,7 @@ int mydata_index; /* GLOBAL */ void -tls_init_lib() +tls_init_lib(void) { SSL_library_init(); #ifndef ENABLE_SMALL @@ -82,7 +82,7 @@ tls_init_lib() } void -tls_free_lib() +tls_free_lib(void) { EVP_cleanup(); #ifndef ENABLE_SMALL @@ -91,7 +91,7 @@ tls_free_lib() } void -tls_clear_error() +tls_clear_error(void) { ERR_clear_error(); } @@ -206,16 +206,73 @@ info_callback(INFO_CALLBACK_SSL_CONST SSL *s, int where, int ret) int tls_version_max(void) { -#if defined(SSL_OP_NO_TLSv1_2) +#if defined(TLS1_3_VERSION) + return TLS_VER_1_3; +#elif defined(TLS1_2_VERSION) || defined(SSL_OP_NO_TLSv1_2) return TLS_VER_1_2; -#elif defined(SSL_OP_NO_TLSv1_1) +#elif defined(TLS1_1_VERSION) || defined(SSL_OP_NO_TLSv1_1) return TLS_VER_1_1; #else return TLS_VER_1_0; #endif } -void +/** Convert internal version number to openssl version number */ +static int +openssl_tls_version(int ver) +{ + if (ver == TLS_VER_1_0) + { + return TLS1_VERSION; + } + else if (ver == TLS_VER_1_1) + { + return TLS1_1_VERSION; + } + else if (ver == TLS_VER_1_2) + { + return TLS1_2_VERSION; + } +#if defined(TLS1_3_VERSION) + else if (ver == TLS_VER_1_3) + { + return TLS1_3_VERSION; + } +#endif + return 0; +} + +static bool +tls_ctx_set_tls_versions(struct tls_root_ctx *ctx, unsigned int ssl_flags) +{ + int tls_ver_min = openssl_tls_version( + (ssl_flags >> SSLF_TLS_VERSION_MIN_SHIFT) & SSLF_TLS_VERSION_MIN_MASK); + int tls_ver_max = openssl_tls_version( + (ssl_flags >> SSLF_TLS_VERSION_MAX_SHIFT) & SSLF_TLS_VERSION_MAX_MASK); + + if (!tls_ver_min) + { + /* Enforce at least TLS 1.0 */ + int cur_min = SSL_CTX_get_min_proto_version(ctx->ctx); + tls_ver_min = cur_min < TLS1_VERSION ? TLS1_VERSION : cur_min; + } + + if (!SSL_CTX_set_min_proto_version(ctx->ctx, tls_ver_min)) + { + msg(D_TLS_ERRORS, "%s: failed to set minimum TLS version", __func__); + return false; + } + + if (tls_ver_max && !SSL_CTX_set_max_proto_version(ctx->ctx, tls_ver_max)) + { + msg(D_TLS_ERRORS, "%s: failed to set maximum TLS version", __func__); + return false; + } + + return true; +} + +bool tls_ctx_set_options(struct tls_root_ctx *ctx, unsigned int ssl_flags) { ASSERT(NULL != ctx); @@ -223,41 +280,21 @@ tls_ctx_set_options(struct tls_root_ctx *ctx, unsigned int ssl_flags) /* default certificate verification flags */ int flags = SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT; - /* process SSL options including minimum TLS version we will accept from peer */ - { - long sslopt = SSL_OP_SINGLE_DH_USE | SSL_OP_NO_TICKET | SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3; - int tls_ver_max = TLS_VER_UNSPEC; - const int tls_ver_min = - (ssl_flags >> SSLF_TLS_VERSION_MIN_SHIFT) & SSLF_TLS_VERSION_MIN_MASK; - - tls_ver_max = - (ssl_flags >> SSLF_TLS_VERSION_MAX_SHIFT) & SSLF_TLS_VERSION_MAX_MASK; - if (tls_ver_max <= TLS_VER_UNSPEC) - { - tls_ver_max = tls_version_max(); - } - - if (tls_ver_min > TLS_VER_1_0 || tls_ver_max < TLS_VER_1_0) - { - sslopt |= SSL_OP_NO_TLSv1; - } -#ifdef SSL_OP_NO_TLSv1_1 - if (tls_ver_min > TLS_VER_1_1 || tls_ver_max < TLS_VER_1_1) - { - sslopt |= SSL_OP_NO_TLSv1_1; - } -#endif -#ifdef SSL_OP_NO_TLSv1_2 - if (tls_ver_min > TLS_VER_1_2 || tls_ver_max < TLS_VER_1_2) - { - sslopt |= SSL_OP_NO_TLSv1_2; - } + /* process SSL options */ + long sslopt = SSL_OP_SINGLE_DH_USE | SSL_OP_NO_TICKET; +#ifdef SSL_OP_CIPHER_SERVER_PREFERENCE + sslopt |= SSL_OP_CIPHER_SERVER_PREFERENCE; #endif #ifdef SSL_OP_NO_COMPRESSION - /* Disable compression - flag not available in OpenSSL 0.9.8 */ - sslopt |= SSL_OP_NO_COMPRESSION; + /* Disable compression - flag not available in OpenSSL 0.9.8 */ + sslopt |= SSL_OP_NO_COMPRESSION; #endif - SSL_CTX_set_options(ctx->ctx, sslopt); + + SSL_CTX_set_options(ctx->ctx, sslopt); + + if (!tls_ctx_set_tls_versions(ctx, ssl_flags)) + { + return false; } #ifdef SSL_MODE_RELEASE_BUFFERS @@ -280,6 +317,8 @@ tls_ctx_set_options(struct tls_root_ctx *ctx, unsigned int ssl_flags) SSL_CTX_set_verify(ctx->ctx, flags, verify_callback); SSL_CTX_set_info_callback(ctx->ctx, info_callback); + + return true; } void @@ -384,6 +423,40 @@ tls_ctx_restrict_ciphers(struct tls_root_ctx *ctx, const char *ciphers) } void +tls_ctx_set_cert_profile(struct tls_root_ctx *ctx, const char *profile) +{ +#ifdef HAVE_SSL_CTX_SET_SECURITY_LEVEL + /* OpenSSL does not have certificate profiles, but a complex set of + * callbacks that we could try to implement to achieve something similar. + * For now, use OpenSSL's security levels to achieve similar (but not equal) + * behaviour. */ + if (!profile || 0 == strcmp(profile, "legacy")) + { + SSL_CTX_set_security_level(ctx->ctx, 1); + } + else if (0 == strcmp(profile, "preferred")) + { + SSL_CTX_set_security_level(ctx->ctx, 2); + } + else if (0 == strcmp(profile, "suiteb")) + { + SSL_CTX_set_security_level(ctx->ctx, 3); + SSL_CTX_set_cipher_list(ctx->ctx, "SUITEB128"); + } + else + { + msg(M_FATAL, "ERROR: Invalid cert profile: %s", profile); + } +#else + if (profile) + { + msg(M_WARN, "WARNING: OpenSSL 1.0.1 does not support --tls-cert-profile" + ", ignoring user-set profile: '%s'", profile); + } +#endif +} + +void tls_ctx_check_cert_time(const struct tls_root_ctx *ctx) { int ret; @@ -487,15 +560,7 @@ tls_ctx_load_ecdh_params(struct tls_root_ctx *ctx, const char *curve_name /* Generate a new ECDH key for each SSL session (for non-ephemeral ECDH) */ SSL_CTX_set_options(ctx->ctx, SSL_OP_SINGLE_ECDH_USE); -#if OPENSSL_VERSION_NUMBER >= 0x10002000L - /* OpenSSL 1.0.2 and newer can automatically handle ECDH parameter loading */ - if (NULL == curve_name) - { - SSL_CTX_set_ecdh_auto(ctx->ctx, 1); - return; - } -#endif - /* For older OpenSSL, we'll have to do the parameter loading on our own */ + if (curve_name != NULL) { /* Use user supplied curve if given */ @@ -504,14 +569,17 @@ tls_ctx_load_ecdh_params(struct tls_root_ctx *ctx, const char *curve_name } else { - /* Extract curve from key */ +#if OPENSSL_VERSION_NUMBER >= 0x10002000L + /* OpenSSL 1.0.2 and newer can automatically handle ECDH parameter + * loading */ + SSL_CTX_set_ecdh_auto(ctx->ctx, 1); + return; +#else + /* For older OpenSSL we have to extract the curve from key on our own */ EC_KEY *eckey = NULL; const EC_GROUP *ecgrp = NULL; EVP_PKEY *pkey = NULL; -#if OPENSSL_VERSION_NUMBER >= 0x10002000L && !defined(LIBRESSL_VERSION_NUMBER) - pkey = SSL_CTX_get0_privatekey(ctx->ctx); -#else /* Little hack to get private key ref from SSL_CTX, yay OpenSSL... */ SSL *ssl = SSL_new(ctx->ctx); if (!ssl) @@ -520,7 +588,6 @@ tls_ctx_load_ecdh_params(struct tls_root_ctx *ctx, const char *curve_name } pkey = SSL_get_privatekey(ssl); SSL_free(ssl); -#endif msg(D_TLS_DEBUG, "Extracting ECDH curve from private key"); @@ -529,6 +596,7 @@ tls_ctx_load_ecdh_params(struct tls_root_ctx *ctx, const char *curve_name { nid = EC_GROUP_get_curve_name(ecgrp); } +#endif } /* Translate NID back to name , just for kicks */ @@ -713,7 +781,7 @@ tls_ctx_add_extra_certs(struct tls_root_ctx *ctx, BIO *bio) for (;; ) { cert = NULL; - if (!PEM_read_bio_X509(bio, &cert, 0, NULL)) /* takes ownership of cert */ + if (!PEM_read_bio_X509(bio, &cert, NULL, NULL)) /* takes ownership of cert */ { break; } @@ -811,12 +879,6 @@ tls_ctx_load_cert_file(struct tls_root_ctx *ctx, const char *cert_file, tls_ctx_load_cert_file_and_copy(ctx, cert_file, cert_file_inline, NULL); } -void -tls_ctx_free_cert_file(X509 *x509) -{ - X509_free(x509); -} - int tls_ctx_load_priv_file(struct tls_root_ctx *ctx, const char *priv_key_file, const char *priv_key_file_inline @@ -1080,6 +1142,13 @@ tls_ctx_use_external_private_key(struct tls_root_ctx *ctx, ASSERT(pkey); /* NULL before SSL_CTX_use_certificate() is called */ pub_rsa = EVP_PKEY_get0_RSA(pkey); + /* Certificate might not be RSA but DSA or EC */ + if (!pub_rsa) + { + crypto_msg(M_WARN, "management-external-key requires a RSA certificate"); + goto err; + } + /* initialize RSA object */ const BIGNUM *n = NULL; const BIGNUM *e = NULL; @@ -1114,7 +1183,7 @@ err: { if (rsa_meth) { - free(rsa_meth); + RSA_meth_free(rsa_meth); } } crypto_msg(M_FATAL, "Cannot enable SSL external private key capability"); @@ -1330,7 +1399,7 @@ static time_t biofp_last_open; /* GLOBAL */ static const int biofp_reopen_interval = 600; /* GLOBAL */ static void -close_biofp() +close_biofp(void) { if (biofp) { @@ -1340,7 +1409,7 @@ close_biofp() } static void -open_biofp() +open_biofp(void) { const time_t current = time(NULL); const pid_t pid = getpid(); @@ -1386,23 +1455,6 @@ bio_debug_oc(const char *mode, BIO *bio) #endif /* ifdef BIO_DEBUG */ /* - * OpenVPN's interface to SSL/TLS authentication, - * encryption, and decryption is exclusively - * through "memory BIOs". - */ -static BIO * -getbio(BIO_METHOD *type, const char *desc) -{ - BIO *ret; - ret = BIO_new(type); - if (!ret) - { - crypto_msg(M_FATAL, "Error creating %s BIO", desc); - } - return ret; -} - -/* * Write to an OpenSSL BIO in non-blocking mode. */ static int @@ -1543,9 +1595,9 @@ key_state_ssl_init(struct key_state_ssl *ks_ssl, const struct tls_root_ctx *ssl_ * from verify callback*/ SSL_set_ex_data(ks_ssl->ssl, mydata_index, session); - ks_ssl->ssl_bio = getbio(BIO_f_ssl(), "ssl_bio"); - ks_ssl->ct_in = getbio(BIO_s_mem(), "ct_in"); - ks_ssl->ct_out = getbio(BIO_s_mem(), "ct_out"); + ASSERT((ks_ssl->ssl_bio = BIO_new(BIO_f_ssl()))); + ASSERT((ks_ssl->ct_in = BIO_new(BIO_s_mem()))); + ASSERT((ks_ssl->ct_out = BIO_new(BIO_s_mem()))); #ifdef BIO_DEBUG bio_debug_oc("open ssl_bio", ks_ssl->ssl_bio); @@ -1686,18 +1738,36 @@ print_details(struct key_state_ssl *ks_ssl, const char *prefix) EVP_PKEY *pkey = X509_get_pubkey(cert); if (pkey != NULL) { - if (EVP_PKEY_id(pkey) == EVP_PKEY_RSA && EVP_PKEY_get0_RSA(pkey) != NULL) + if ((EVP_PKEY_id(pkey) == EVP_PKEY_RSA) && (EVP_PKEY_get0_RSA(pkey) != NULL)) { RSA *rsa = EVP_PKEY_get0_RSA(pkey); openvpn_snprintf(s2, sizeof(s2), ", %d bit RSA", RSA_bits(rsa)); } - else if (EVP_PKEY_id(pkey) == EVP_PKEY_DSA && EVP_PKEY_get0_DSA(pkey) != NULL) + else if ((EVP_PKEY_id(pkey) == EVP_PKEY_DSA) && (EVP_PKEY_get0_DSA(pkey) != NULL)) { DSA *dsa = EVP_PKEY_get0_DSA(pkey); openvpn_snprintf(s2, sizeof(s2), ", %d bit DSA", DSA_bits(dsa)); } +#ifndef OPENSSL_NO_EC + else if ((EVP_PKEY_id(pkey) == EVP_PKEY_EC) && (EVP_PKEY_get0_EC_KEY(pkey) != NULL)) + { + EC_KEY *ec = EVP_PKEY_get0_EC_KEY(pkey); + const EC_GROUP *group = EC_KEY_get0_group(ec); + const char* curve; + + int nid = EC_GROUP_get_curve_name(group); + if (nid == 0 || (curve = OBJ_nid2sn(nid)) == NULL) + { + curve = "Error getting curve name"; + } + + openvpn_snprintf(s2, sizeof(s2), ", %d bit EC, curve: %s", + EC_GROUP_order_bits(group), curve); + + } +#endif EVP_PKEY_free(pkey); } X509_free(cert); @@ -1708,7 +1778,8 @@ print_details(struct key_state_ssl *ks_ssl, const char *prefix) } void -show_available_tls_ciphers(const char *cipher_list) +show_available_tls_ciphers(const char *cipher_list, + const char *tls_cert_profile) { struct tls_root_ctx tls_ctx; SSL *ssl; @@ -1728,6 +1799,7 @@ show_available_tls_ciphers(const char *cipher_list) crypto_msg(M_FATAL, "Cannot create SSL object"); } + tls_ctx_set_cert_profile(&tls_ctx, tls_cert_profile); tls_ctx_restrict_ciphers(&tls_ctx, cipher_list); printf("Available TLS Ciphers,\n"); @@ -1758,7 +1830,7 @@ show_available_tls_ciphers(const char *cipher_list) * in the OpenSSL library. */ void -show_available_curves() +show_available_curves(void) { #ifndef OPENSSL_NO_EC EC_builtin_curve *curves = NULL; diff --git a/src/openvpn/ssl_openssl.h b/src/openvpn/ssl_openssl.h index db4e1da..dabb941 100644 --- a/src/openvpn/ssl_openssl.h +++ b/src/openvpn/ssl_openssl.h @@ -5,8 +5,8 @@ * packet encryption, packet authentication, and * packet compression. * - * Copyright (C) 2002-2017 OpenVPN Technologies, Inc. <sales@openvpn.net> - * Copyright (C) 2010-2017 Fox Crypto B.V. <openvpn@fox-it.com> + * Copyright (C) 2002-2018 OpenVPN Inc <sales@openvpn.net> + * Copyright (C) 2010-2018 Fox Crypto B.V. <openvpn@fox-it.com> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 diff --git a/src/openvpn/ssl_verify.c b/src/openvpn/ssl_verify.c index 9cd36d7..c7e595e 100644 --- a/src/openvpn/ssl_verify.c +++ b/src/openvpn/ssl_verify.c @@ -5,8 +5,8 @@ * packet encryption, packet authentication, and * packet compression. * - * Copyright (C) 2002-2017 OpenVPN Technologies, Inc. <sales@openvpn.net> - * Copyright (C) 2010-2017 Fox Crypto B.V. <openvpn@fox-it.com> + * Copyright (C) 2002-2018 OpenVPN Inc <sales@openvpn.net> + * Copyright (C) 2010-2018 Fox Crypto B.V. <openvpn@fox-it.com> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 @@ -547,14 +547,14 @@ verify_cert_export_cert(openvpn_x509_cert_t *peercert, const char *tmp_dir, stru FILE *peercert_file; const char *peercert_filename = ""; - if (!tmp_dir) + /* create tmp file to store peer cert */ + if (!tmp_dir + || !(peercert_filename = create_temp_file(tmp_dir, "pcf", gc))) { + msg (M_WARN, "Failed to create peer cert file"); return NULL; } - /* create tmp file to store peer cert */ - peercert_filename = create_temp_file(tmp_dir, "pcf", gc); - /* write peer-cert in tmp-file */ peercert_file = fopen(peercert_filename, "w+"); if (!peercert_file) @@ -589,10 +589,13 @@ verify_cert_call_command(const char *verify_command, struct env_set *es, if (verify_export_cert) { - if ((tmp_file = verify_cert_export_cert(cert, verify_export_cert, &gc))) + tmp_file = verify_cert_export_cert(cert, verify_export_cert, &gc); + if (!tmp_file) { - setenv_str(es, "peer_cert", tmp_file); + ret = false; + goto cleanup; } + setenv_str(es, "peer_cert", tmp_file); } argv_parse_cmd(&argv, verify_command); @@ -609,6 +612,7 @@ verify_cert_call_command(const char *verify_command, struct env_set *es, } } +cleanup: gc_free(&gc); argv_reset(&argv); @@ -879,21 +883,21 @@ key_state_rm_auth_control_file(struct key_state *ks) } } -static void +static bool key_state_gen_auth_control_file(struct key_state *ks, const struct tls_options *opt) { struct gc_arena gc = gc_new(); - const char *acf; key_state_rm_auth_control_file(ks); - acf = create_temp_file(opt->tmp_dir, "acf", &gc); + const char *acf = create_temp_file(opt->tmp_dir, "acf", &gc); if (acf) { ks->auth_control_file = string_alloc(acf, NULL); setenv_str(opt->es, "auth_control_file", ks->auth_control_file); - } /* FIXME: Should have better error handling? */ + } gc_free(&gc); + return acf; } static unsigned int @@ -1184,7 +1188,12 @@ verify_user_pass_plugin(struct tls_session *session, const struct user_pass *up, #ifdef PLUGIN_DEF_AUTH /* generate filename for deferred auth control file */ - key_state_gen_auth_control_file(ks, session->opt); + if (!key_state_gen_auth_control_file(ks, session->opt)) + { + msg (D_TLS_ERRORS, "TLS Auth Error (%s): " + "could not create deferred auth control file", __func__); + goto cleanup; + } #endif /* call command */ @@ -1209,6 +1218,7 @@ verify_user_pass_plugin(struct tls_session *session, const struct user_pass *up, msg(D_TLS_ERRORS, "TLS Auth Error (verify_user_pass_plugin): peer provided a blank username"); } +cleanup: return retval; } diff --git a/src/openvpn/ssl_verify.h b/src/openvpn/ssl_verify.h index f2d0d6c..3e2267a 100644 --- a/src/openvpn/ssl_verify.h +++ b/src/openvpn/ssl_verify.h @@ -5,8 +5,8 @@ * packet encryption, packet authentication, and * packet compression. * - * Copyright (C) 2002-2017 OpenVPN Technologies, Inc. <sales@openvpn.net> - * Copyright (C) 2010-2017 Fox Crypto B.V. <openvpn@fox-it.com> + * Copyright (C) 2002-2018 OpenVPN Inc <sales@openvpn.net> + * Copyright (C) 2010-2018 Fox Crypto B.V. <openvpn@fox-it.com> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 diff --git a/src/openvpn/ssl_verify_backend.h b/src/openvpn/ssl_verify_backend.h index e8eaabe..2a9e8bb 100644 --- a/src/openvpn/ssl_verify_backend.h +++ b/src/openvpn/ssl_verify_backend.h @@ -5,8 +5,8 @@ * packet encryption, packet authentication, and * packet compression. * - * Copyright (C) 2002-2017 OpenVPN Technologies, Inc. <sales@openvpn.net> - * Copyright (C) 2010-2017 Fox Crypto B.V. <openvpn@fox-it.com> + * Copyright (C) 2002-2018 OpenVPN Inc <sales@openvpn.net> + * Copyright (C) 2010-2018 Fox Crypto B.V. <openvpn@fox-it.com> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 diff --git a/src/openvpn/ssl_verify_mbedtls.c b/src/openvpn/ssl_verify_mbedtls.c index 838c217..2d019ab 100644 --- a/src/openvpn/ssl_verify_mbedtls.c +++ b/src/openvpn/ssl_verify_mbedtls.c @@ -5,8 +5,8 @@ * packet encryption, packet authentication, and * packet compression. * - * Copyright (C) 2002-2017 OpenVPN Technologies, Inc. <sales@openvpn.net> - * Copyright (C) 2010-2017 Fox Crypto B.V. <openvpn@fox-it.com> + * Copyright (C) 2002-2018 OpenVPN Inc <sales@openvpn.net> + * Copyright (C) 2010-2018 Fox Crypto B.V. <openvpn@fox-it.com> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 diff --git a/src/openvpn/ssl_verify_mbedtls.h b/src/openvpn/ssl_verify_mbedtls.h index 8b0a5ae..00dc8a3 100644 --- a/src/openvpn/ssl_verify_mbedtls.h +++ b/src/openvpn/ssl_verify_mbedtls.h @@ -5,8 +5,8 @@ * packet encryption, packet authentication, and * packet compression. * - * Copyright (C) 2002-2017 OpenVPN Technologies, Inc. <sales@openvpn.net> - * Copyright (C) 2010-2017 Fox Crypto B.V. <openvpn@fox-it.com> + * Copyright (C) 2002-2018 OpenVPN Inc <sales@openvpn.net> + * Copyright (C) 2010-2018 Fox Crypto B.V. <openvpn@fox-it.com> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 @@ -48,9 +48,9 @@ typedef mbedtls_x509_crt openvpn_x509_cert_t; * This callback function is called when a new TLS session is being setup to * determine whether the remote OpenVPN peer's certificate is allowed to * connect. It is called for once for every certificate in the chain. The - * callback functionality is configured in the \c init_ssl() function, which - * calls the mbed TLS library's \c ssl_set_verify_callback() function with \c - * verify_callback() as its callback argument. + * callback functionality is configured in the \c key_state_ssl_init() function, + * which calls the mbed TLS library's \c mbedtls_ssl_conf_verify() function with + * \c verify_callback() as its callback argument. * * It checks *flags and registers the certificate hash. If these steps succeed, * it calls the \c verify_cert() function, which performs OpenVPN-specific diff --git a/src/openvpn/ssl_verify_openssl.c b/src/openvpn/ssl_verify_openssl.c index 468b495..b1ce06b 100644 --- a/src/openvpn/ssl_verify_openssl.c +++ b/src/openvpn/ssl_verify_openssl.c @@ -5,8 +5,8 @@ * packet encryption, packet authentication, and * packet compression. * - * Copyright (C) 2002-2017 OpenVPN Technologies, Inc. <sales@openvpn.net> - * Copyright (C) 2010-2017 Fox Crypto B.V. <openvpn@fox-it.com> + * Copyright (C) 2002-2018 OpenVPN Inc <sales@openvpn.net> + * Copyright (C) 2010-2018 Fox Crypto B.V. <openvpn@fox-it.com> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 @@ -129,8 +129,7 @@ extract_x509_extension(X509 *cert, char *fieldname, char *out, int size) if (!x509_username_field_ext_supported(fieldname)) { msg(D_TLS_ERRORS, - "ERROR: --x509-alt-username field 'ext:%s' not supported", - fieldname); + "ERROR: --x509-username-field 'ext:%s' not supported", fieldname); return false; } @@ -203,8 +202,8 @@ extract_x509_field_ssl(X509_NAME *x509, const char *field_name, char *out, { int lastpos = -1; int tmp = -1; - X509_NAME_ENTRY *x509ne = 0; - ASN1_STRING *asn1 = 0; + X509_NAME_ENTRY *x509ne = NULL; + ASN1_STRING *asn1 = NULL; unsigned char *buf = NULL; ASN1_OBJECT *field_name_obj = OBJ_txt2obj(field_name, 0); diff --git a/src/openvpn/ssl_verify_openssl.h b/src/openvpn/ssl_verify_openssl.h index 4c8dbeb..118e16f 100644 --- a/src/openvpn/ssl_verify_openssl.h +++ b/src/openvpn/ssl_verify_openssl.h @@ -5,8 +5,8 @@ * packet encryption, packet authentication, and * packet compression. * - * Copyright (C) 2002-2017 OpenVPN Technologies, Inc. <sales@openvpn.net> - * Copyright (C) 2010-2017 Fox Crypto B.V. <openvpn@fox-it.com> + * Copyright (C) 2002-2018 OpenVPN Inc <sales@openvpn.net> + * Copyright (C) 2010-2018 Fox Crypto B.V. <openvpn@fox-it.com> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 diff --git a/src/openvpn/status.c b/src/openvpn/status.c index a163408..91391d1 100644 --- a/src/openvpn/status.c +++ b/src/openvpn/status.c @@ -5,7 +5,7 @@ * packet encryption, packet authentication, and * packet compression. * - * Copyright (C) 2002-2017 OpenVPN Technologies, Inc. <sales@openvpn.net> + * Copyright (C) 2002-2018 OpenVPN Inc <sales@openvpn.net> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 @@ -178,7 +178,7 @@ status_flush(struct status_output *so) const off_t off = lseek(so->fd, (off_t)0, SEEK_CUR); if (ftruncate(so->fd, off) != 0) { - msg(M_WARN, "Failed to truncate status file: %s", strerror(errno)); + msg(M_WARN | M_ERRNO, "Failed to truncate status file"); } } #elif defined(HAVE_CHSIZE) diff --git a/src/openvpn/status.h b/src/openvpn/status.h index 8199935..2a399d7 100644 --- a/src/openvpn/status.h +++ b/src/openvpn/status.h @@ -5,7 +5,7 @@ * packet encryption, packet authentication, and * packet compression. * - * Copyright (C) 2002-2017 OpenVPN Technologies, Inc. <sales@openvpn.net> + * Copyright (C) 2002-2018 OpenVPN Inc <sales@openvpn.net> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 diff --git a/src/openvpn/syshead.h b/src/openvpn/syshead.h index 2973b5a..3ac9d70 100644 --- a/src/openvpn/syshead.h +++ b/src/openvpn/syshead.h @@ -5,7 +5,7 @@ * packet encryption, packet authentication, and * packet compression. * - * Copyright (C) 2002-2017 OpenVPN Technologies, Inc. <sales@openvpn.net> + * Copyright (C) 2002-2018 OpenVPN Inc <sales@openvpn.net> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 @@ -513,7 +513,7 @@ socket_defined(const socket_descriptor_t sd) * Do we have point-to-multipoint capability? */ -#if defined(ENABLE_CLIENT_SERVER) && defined(ENABLE_CRYPTO) && defined(HAVE_GETTIMEOFDAY_NANOSECONDS) +#if defined(ENABLE_CRYPTO) && defined(HAVE_GETTIMEOFDAY_NANOSECONDS) #define P2MP 1 #else #define P2MP 0 diff --git a/src/openvpn/tls_crypt.c b/src/openvpn/tls_crypt.c index e13bb4e..ecc654e 100644 --- a/src/openvpn/tls_crypt.c +++ b/src/openvpn/tls_crypt.c @@ -5,7 +5,7 @@ * packet encryption, packet authentication, and * packet compression. * - * Copyright (C) 2016-2017 Fox Crypto B.V. <openvpn@fox-it.com> + * Copyright (C) 2016-2018 Fox Crypto B.V. <openvpn@fox-it.com> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 @@ -35,35 +35,47 @@ #include "tls_crypt.h" -int -tls_crypt_buf_overhead(void) -{ - return packet_id_size(true) + TLS_CRYPT_TAG_SIZE + TLS_CRYPT_BLOCK_SIZE; -} - -void -tls_crypt_init_key(struct key_ctx_bi *key, const char *key_file, - const char *key_inline, bool tls_server) +static struct key_type +tls_crypt_kt(void) { - const int key_direction = tls_server ? - KEY_DIRECTION_NORMAL : KEY_DIRECTION_INVERSE; - struct key_type kt; kt.cipher = cipher_kt_get("AES-256-CTR"); kt.digest = md_kt_get("SHA256"); if (!kt.cipher) { - msg(M_FATAL, "ERROR: --tls-crypt requires AES-256-CTR support."); + msg(M_WARN, "ERROR: --tls-crypt requires AES-256-CTR support."); + return (struct key_type) { 0 }; } if (!kt.digest) { - msg(M_FATAL, "ERROR: --tls-crypt requires HMAC-SHA-256 support."); + msg(M_WARN, "ERROR: --tls-crypt requires HMAC-SHA-256 support."); + return (struct key_type) { 0 }; } kt.cipher_length = cipher_kt_key_size(kt.cipher); kt.hmac_length = md_kt_size(kt.digest); + return kt; +} + +int +tls_crypt_buf_overhead(void) +{ + return packet_id_size(true) + TLS_CRYPT_TAG_SIZE + TLS_CRYPT_BLOCK_SIZE; +} + +void +tls_crypt_init_key(struct key_ctx_bi *key, const char *key_file, + const char *key_inline, bool tls_server) +{ + const int key_direction = tls_server ? + KEY_DIRECTION_NORMAL : KEY_DIRECTION_INVERSE; + struct key_type kt = tls_crypt_kt(); + if (!kt.cipher || !kt.digest) + { + msg (M_FATAL, "ERROR: --tls-crypt not supported"); + } crypto_read_openvpn_key(&kt, key, key_file, key_inline, key_direction, "Control Channel Encryption", "tls-crypt"); } diff --git a/src/openvpn/tls_crypt.h b/src/openvpn/tls_crypt.h index e8080df..05fcc4e 100644 --- a/src/openvpn/tls_crypt.h +++ b/src/openvpn/tls_crypt.h @@ -5,7 +5,7 @@ * packet encryption, packet authentication, and * packet compression. * - * Copyright (C) 2016-2017 Fox Crypto B.V. <openvpn@fox-it.com> + * Copyright (C) 2016-2018 Fox Crypto B.V. <openvpn@fox-it.com> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 @@ -74,6 +74,8 @@ #ifndef TLSCRYPT_H #define TLSCRYPT_H +#ifdef ENABLE_CRYPTO + #include "buffer.h" #include "crypto.h" #include "session_id.h" @@ -140,4 +142,6 @@ bool tls_crypt_unwrap(const struct buffer *src, struct buffer *dst, /** @} */ +#endif /* ENABLE_CRYPTO */ + #endif /* TLSCRYPT_H */ diff --git a/src/openvpn/tun.c b/src/openvpn/tun.c index 75a156c..b071823 100644 --- a/src/openvpn/tun.c +++ b/src/openvpn/tun.c @@ -5,7 +5,7 @@ * packet encryption, packet authentication, and * packet compression. * - * Copyright (C) 2002-2017 OpenVPN Technologies, Inc. <sales@openvpn.net> + * Copyright (C) 2002-2018 OpenVPN Inc <sales@openvpn.net> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 @@ -45,6 +45,7 @@ #include "manage.h" #include "route.h" #include "win32.h" +#include "block_dns.h" #include "memdbg.h" @@ -124,7 +125,7 @@ do_address_service(const bool add, const short family, const struct tuntap *tt) if (ack.error_number != NO_ERROR) { - msg(M_WARN, "TUN: %s address failed using service: %s [status=%u if_index=%lu]", + msg(M_WARN, "TUN: %s address failed using service: %s [status=%u if_index=%d]", (add ? "adding" : "deleting"), strerror_win32(ack.error_number, &gc), ack.error_number, addr.iface.index); goto out; @@ -838,6 +839,7 @@ delete_route_connected_v6_net(struct tuntap *tt, r6.gateway = tt->local_ipv6; r6.metric = 0; /* connected route */ r6.flags = RT_DEFINED | RT_ADDED | RT_METRIC_DEFINED; + route_ipv6_clear_host_bits(&r6); delete_route_ipv6(&r6, tt, 0, es); } #endif /* if defined(_WIN32) || defined(TARGET_DARWIN) || defined(TARGET_NETBSD) || defined(TARGET_OPENBSD) */ @@ -1862,7 +1864,7 @@ open_tun(const char *dev, const char *dev_type, const char *dev_node, struct tun if (oldtunfd >=0 && android_method == ANDROID_OPEN_AFTER_CLOSE) { close(oldtunfd); - openvpn_sleep(2); + management_sleep(2); } if (oldtunfd >=0 && android_method == ANDROID_KEEP_OLD_TUN) @@ -2563,8 +2565,7 @@ open_tun(const char *dev, const char *dev_type, const char *dev_node, struct tun if (ioctl(tt->fd, TUNGIFINFO, &info) < 0) { - msg(M_WARN | M_ERRNO, "Can't get interface info: %s", - strerror(errno)); + msg(M_WARN | M_ERRNO, "Can't get interface info"); } #ifdef IFF_MULTICAST /* openbsd 4.x doesn't have this */ @@ -2573,8 +2574,7 @@ open_tun(const char *dev, const char *dev_type, const char *dev_node, struct tun if (ioctl(tt->fd, TUNSIFINFO, &info) < 0) { - msg(M_WARN | M_ERRNO, "Can't set interface info: %s", - strerror(errno)); + msg(M_WARN | M_ERRNO, "Can't set interface info"); } } } @@ -2663,7 +2663,7 @@ open_tun(const char *dev, const char *dev_type, const char *dev_node, struct tun i = 1; if (ioctl(tt->fd, TUNSIFHEAD, &i) < 0) /* multi-af mode on */ { - msg(M_WARN | M_ERRNO, "ioctl(TUNSIFHEAD): %s", strerror(errno)); + msg(M_WARN | M_ERRNO, "ioctl(TUNSIFHEAD)"); } } } @@ -2796,12 +2796,12 @@ open_tun(const char *dev, const char *dev_type, const char *dev_node, struct tun if (ioctl(tt->fd, TUNSIFMODE, &i) < 0) { - msg(M_WARN | M_ERRNO, "ioctl(TUNSIFMODE): %s", strerror(errno)); + msg(M_WARN | M_ERRNO, "ioctl(TUNSIFMODE)"); } i = 1; if (ioctl(tt->fd, TUNSIFHEAD, &i) < 0) { - msg(M_WARN | M_ERRNO, "ioctl(TUNSIFHEAD): %s", strerror(errno)); + msg(M_WARN | M_ERRNO, "ioctl(TUNSIFHEAD)"); } } } @@ -3022,16 +3022,14 @@ utun_open_helper(struct ctl_info ctlInfo, int utunnum) if (fd < 0) { - msg(M_INFO, "Opening utun (%s): %s", "socket(SYSPROTO_CONTROL)", - strerror(errno)); + msg(M_INFO | M_ERRNO, "Opening utun (socket(SYSPROTO_CONTROL))"); return -2; } if (ioctl(fd, CTLIOCGINFO, &ctlInfo) == -1) { close(fd); - msg(M_INFO, "Opening utun (%s): %s", "ioctl(CTLIOCGINFO)", - strerror(errno)); + msg(M_INFO | M_ERRNO, "Opening utun (ioctl(CTLIOCGINFO))"); return -2; } @@ -3049,8 +3047,7 @@ utun_open_helper(struct ctl_info ctlInfo, int utunnum) if (connect(fd, (struct sockaddr *)&sc, sizeof(sc)) < 0) { - msg(M_INFO, "Opening utun (%s): %s", "connect(AF_SYS_CONTROL)", - strerror(errno)); + msg(M_INFO | M_ERRNO, "Opening utun (connect(AF_SYS_CONTROL))"); close(fd); return -1; } @@ -3795,7 +3792,7 @@ get_panel_reg(struct gc_arena *gc) if (status != ERROR_SUCCESS || name_type != REG_SZ) { - dmsg(D_REGISTRY, "Error opening registry key: %s\\%s\\%s", + dmsg(D_REGISTRY, "Error opening registry key: %s\\%s\\%ls", NETWORK_CONNECTIONS_KEY, connection_string, name_string); } else @@ -4183,15 +4180,12 @@ get_adapter_info_list(struct gc_arena *gc) else { pi = (PIP_ADAPTER_INFO) gc_malloc(size, false, gc); - if ((status = GetAdaptersInfo(pi, &size)) == NO_ERROR) - { - return pi; - } - else + if ((status = GetAdaptersInfo(pi, &size)) != NO_ERROR) { msg(M_INFO, "GetAdaptersInfo #2 failed (status=%u) : %s", (unsigned int)status, strerror_win32(status, gc)); + pi = NULL; } } return pi; @@ -4488,6 +4482,7 @@ adapter_index_of_ip(const IP_ADAPTER_INFO *list, struct gc_arena gc = gc_new(); DWORD ret = TUN_ADAPTER_INDEX_INVALID; in_addr_t highest_netmask = 0; + int lowest_metric = INT_MAX; bool first = true; if (count) @@ -4501,9 +4496,14 @@ adapter_index_of_ip(const IP_ADAPTER_INFO *list, if (is_ip_in_adapter_subnet(list, ip, &hn)) { + int metric = get_interface_metric(list->Index, AF_INET, NULL); if (first || hn > highest_netmask) { highest_netmask = hn; + if (metric >= 0) + { + lowest_metric = metric; + } if (count) { *count = 1; @@ -4517,16 +4517,22 @@ adapter_index_of_ip(const IP_ADAPTER_INFO *list, { ++*count; } + if (metric >= 0 && metric < lowest_metric) + { + ret = list->Index; + lowest_metric = metric; + } } } list = list->Next; } - dmsg(D_ROUTE_DEBUG, "DEBUG: IP Locate: ip=%s nm=%s index=%d count=%d", + dmsg(D_ROUTE_DEBUG, "DEBUG: IP Locate: ip=%s nm=%s index=%d count=%d metric=%d", print_in_addr_t(ip, 0, &gc), print_in_addr_t(highest_netmask, 0, &gc), (int)ret, - count ? *count : -1); + count ? *count : -1, + lowest_metric); if (ret == TUN_ADAPTER_INDEX_INVALID && count) { @@ -4627,7 +4633,7 @@ get_adapter_index_method_1(const char *guid) DWORD index; ULONG aindex; wchar_t wbuf[256]; - _snwprintf(wbuf, SIZE(wbuf), L"\\DEVICE\\TCPIP_%S", guid); + swprintf(wbuf, SIZE(wbuf), L"\\DEVICE\\TCPIP_%S", guid); wbuf [SIZE(wbuf) - 1] = 0; if (GetAdapterIndex(wbuf, &aindex) != NO_ERROR) { @@ -5004,7 +5010,7 @@ netsh_command(const struct argv *a, int n, int msglevel) for (i = 0; i < n; ++i) { bool status; - openvpn_sleep(1); + management_sleep(1); netcmd_semaphore_lock(); argv_msg_prefix(M_INFO, a, "NETSH"); status = openvpn_execve_check(a, NULL, 0, "ERROR: netsh command failed"); @@ -5013,7 +5019,7 @@ netsh_command(const struct argv *a, int n, int msglevel) { return; } - openvpn_sleep(4); + management_sleep(4); } msg(msglevel, "NETSH: command failed"); } @@ -5996,7 +6002,7 @@ open_tun(const char *dev, const char *dev_type, const char *dev_node, struct tun if (s > 0) { msg(M_INFO, "Sleeping for %d seconds...", s); - openvpn_sleep(s); + management_sleep(s); } } diff --git a/src/openvpn/tun.h b/src/openvpn/tun.h index 8782d69..6c57ad0 100644 --- a/src/openvpn/tun.h +++ b/src/openvpn/tun.h @@ -5,7 +5,7 @@ * packet encryption, packet authentication, and * packet compression. * - * Copyright (C) 2002-2017 OpenVPN Technologies, Inc. <sales@openvpn.net> + * Copyright (C) 2002-2018 OpenVPN Inc <sales@openvpn.net> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 diff --git a/src/openvpn/win32.c b/src/openvpn/win32.c index d0b10ba..29bbb84 100644 --- a/src/openvpn/win32.c +++ b/src/openvpn/win32.c @@ -5,7 +5,7 @@ * packet encryption, packet authentication, and * packet compression. * - * Copyright (C) 2002-2017 OpenVPN Technologies, Inc. <sales@openvpn.net> + * Copyright (C) 2002-2018 OpenVPN Inc <sales@openvpn.net> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 @@ -1235,7 +1235,7 @@ set_win_sys_path_via_env(struct env_set *es) const char * -win_get_tempdir() +win_get_tempdir(void) { static char tmpdir[MAX_PATH]; WCHAR wtmpdir[MAX_PATH]; @@ -1344,17 +1344,16 @@ win_wfp_block_dns(const NET_IFINDEX index, const HANDLE msg_channel) block_dns_msg_handler); if (status == 0) { - tap_metric_v4 = get_interface_metric(index, AF_INET); - tap_metric_v6 = get_interface_metric(index, AF_INET6); - if (tap_metric_v4 < 0) + int is_auto = 0; + tap_metric_v4 = get_interface_metric(index, AF_INET, &is_auto); + if (is_auto) { - /* error, should not restore metric */ - tap_metric_v4 = -1; + tap_metric_v4 = 0; } - if (tap_metric_v6 < 0) + tap_metric_v6 = get_interface_metric(index, AF_INET6, &is_auto); + if (is_auto) { - /* error, should not restore metric */ - tap_metric_v6 = -1; + tap_metric_v6 = 0; } status = set_interface_metric(index, AF_INET, BLOCK_DNS_IFACE_METRIC); if (!status) @@ -1398,7 +1397,7 @@ win_wfp_uninit(const NET_IFINDEX index, const HANDLE msg_channel) } int -win32_version_info() +win32_version_info(void) { if (!IsWindowsXPOrGreater()) { @@ -1426,7 +1425,7 @@ win32_version_info() } bool -win32_is_64bit() +win32_is_64bit(void) { #if defined(_WIN64) return true; /* 64-bit programs run only on Win64 */ diff --git a/src/openvpn/win32.h b/src/openvpn/win32.h index 21a1021..4b99a5e 100644 --- a/src/openvpn/win32.h +++ b/src/openvpn/win32.h @@ -5,7 +5,7 @@ * packet encryption, packet authentication, and * packet compression. * - * Copyright (C) 2002-2017 OpenVPN Technologies, Inc. <sales@openvpn.net> + * Copyright (C) 2002-2018 OpenVPN Inc <sales@openvpn.net> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 @@ -285,7 +285,7 @@ char *get_win_sys_path(void); void fork_to_self(const char *cmdline); /* Find temporary directory */ -const char *win_get_tempdir(); +const char *win_get_tempdir(void); /* Convert a string from UTF-8 to UCS-2 */ WCHAR *wide_string(const char *utf8, struct gc_arena *gc); @@ -299,7 +299,7 @@ bool win_wfp_uninit(const NET_IFINDEX index, const HANDLE msg_channel); #define WIN_7 2 #define WIN_8 3 -int win32_version_info(); +int win32_version_info(void); /* * String representation of Windows version number and name, see diff --git a/src/openvpnserv/Makefile.am b/src/openvpnserv/Makefile.am index 21efc7c..bc65070 100644 --- a/src/openvpnserv/Makefile.am +++ b/src/openvpnserv/Makefile.am @@ -5,7 +5,7 @@ # packet encryption, packet authentication, and # packet compression. # -# Copyright (C) 2002-2017 OpenVPN Technologies, Inc. <sales@openvpn.net> +# Copyright (C) 2002-2018 OpenVPN Inc <sales@openvpn.net> # Copyright (C) 2006-2012 Alon Bar-Lev <alon.barlev@gmail.com> # diff --git a/src/openvpnserv/Makefile.in b/src/openvpnserv/Makefile.in index 234a927..0dd9792 100644 --- a/src/openvpnserv/Makefile.in +++ b/src/openvpnserv/Makefile.in @@ -21,7 +21,7 @@ # packet encryption, packet authentication, and # packet compression. # -# Copyright (C) 2002-2017 OpenVPN Technologies, Inc. <sales@openvpn.net> +# Copyright (C) 2002-2018 OpenVPN Inc <sales@openvpn.net> # Copyright (C) 2006-2012 Alon Bar-Lev <alon.barlev@gmail.com> # @@ -376,6 +376,7 @@ plugindir = @plugindir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ +runstatedir = @runstatedir@ sampledir = @sampledir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ diff --git a/src/openvpnserv/automatic.c b/src/openvpnserv/automatic.c index 4123d0f..5569ce9 100644 --- a/src/openvpnserv/automatic.c +++ b/src/openvpnserv/automatic.c @@ -5,7 +5,7 @@ * packet encryption, packet authentication, and * packet compression. * - * Copyright (C) 2002-2017 OpenVPN Technologies, Inc. <sales@openvpn.net> + * Copyright (C) 2002-2018 OpenVPN Inc <sales@openvpn.net> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 @@ -44,7 +44,7 @@ #define false 0 static SERVICE_STATUS_HANDLE service; -static SERVICE_STATUS status; +static SERVICE_STATUS status = { .dwServiceType = SERVICE_WIN32_SHARE_PROCESS }; openvpn_service_t automatic_service = { automatic, @@ -60,12 +60,6 @@ struct security_attributes SECURITY_DESCRIPTOR sd; }; -/* - * Which registry key in HKLM should - * we get config info from? - */ -#define REG_KEY "SOFTWARE\\" PACKAGE_NAME - static HANDLE exit_event = NULL; /* clear an object */ @@ -91,15 +85,6 @@ init_security_attributes_allow_all(struct security_attributes *obj) return true; } -/* - * This event is initially created in the non-signaled - * state. It will transition to the signaled state when - * we have received a terminate signal from the Service - * Control Manager which will cause an asynchronous call - * of ServiceStop below. - */ -#define EXIT_EVENT_NAME TEXT(PACKAGE "_exit_1") - HANDLE create_event(LPCTSTR name, bool allow_all, bool initial_state, bool manual_reset) { @@ -212,10 +197,19 @@ ServiceCtrlAutomatic(DWORD ctrl_code, DWORD event, LPVOID data, LPVOID ctx) VOID WINAPI +ServiceStartAutomaticOwn(DWORD dwArgc, LPTSTR *lpszArgv) +{ + status.dwServiceType = SERVICE_WIN32_OWN_PROCESS; + ServiceStartAutomatic(dwArgc, lpszArgv); +} + + +VOID WINAPI ServiceStartAutomatic(DWORD dwArgc, LPTSTR *lpszArgv) { DWORD error = NO_ERROR; settings_t settings; + TCHAR event_name[256]; service = RegisterServiceCtrlHandlerEx(automatic_service.name, ServiceCtrlAutomatic, &status); if (!service) @@ -223,7 +217,6 @@ ServiceStartAutomatic(DWORD dwArgc, LPTSTR *lpszArgv) return; } - status.dwServiceType = SERVICE_WIN32_SHARE_PROCESS; status.dwCurrentState = SERVICE_START_PENDING; status.dwServiceSpecificExitCode = NO_ERROR; status.dwWin32ExitCode = NO_ERROR; @@ -237,8 +230,15 @@ ServiceStartAutomatic(DWORD dwArgc, LPTSTR *lpszArgv) /* * Create our exit event + * This event is initially created in the non-signaled + * state. It will transition to the signaled state when + * we have received a terminate signal from the Service + * Control Manager which will cause an asynchronous call + * of ServiceStop below. */ - exit_event = create_event(EXIT_EVENT_NAME, false, false, true); + + openvpn_sntprintf(event_name, _countof(event_name), TEXT(PACKAGE "%s_exit_1"), service_instance); + exit_event = create_event(event_name, false, false, true); if (!exit_event) { MsgToEventLog(M_ERR, TEXT("CreateEvent failed")); @@ -327,8 +327,8 @@ ServiceStartAutomatic(DWORD dwArgc, LPTSTR *lpszArgv) TEXT("%s\\%s"), settings.log_dir, log_file); /* construct command line */ - openvpn_sntprintf(command_line, _countof(command_line), TEXT(PACKAGE " --service %s 1 --config \"%s\""), - EXIT_EVENT_NAME, + openvpn_sntprintf(command_line, _countof(command_line), TEXT("openvpn --service \"" PACKAGE "%s_exit_1\" 1 --config \"%s\""), + service_instance, find_obj.cFileName); /* Make security attributes struct for logfile handle so it can diff --git a/src/openvpnserv/common.c b/src/openvpnserv/common.c index 0c9098f..dc47666 100644 --- a/src/openvpnserv/common.c +++ b/src/openvpnserv/common.c @@ -5,7 +5,7 @@ * packet encryption, packet authentication, and * packet compression. * - * Copyright (C) 2011-2017 Heiko Hund <heiko.hund@sophos.com> + * Copyright (C) 2011-2018 Heiko Hund <heiko.hund@sophos.com> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 @@ -21,8 +21,12 @@ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ -#include <service.h> -#include <validate.h> +#include "service.h" +#include "validate.h" + +LPCTSTR service_instance = TEXT(""); + + /* * These are necessary due to certain buggy implementations of (v)snprintf, * that don't guarantee null termination for size > 0. @@ -52,23 +56,25 @@ openvpn_sntprintf(LPTSTR str, size_t size, LPCTSTR format, ...) return len; } -#define REG_KEY TEXT("SOFTWARE\\" PACKAGE_NAME) - static DWORD -GetRegString(HKEY key, LPCTSTR value, LPTSTR data, DWORD size) +GetRegString(HKEY key, LPCTSTR value, LPTSTR data, DWORD size, LPCTSTR default_value) { - DWORD type; - LONG status = RegQueryValueEx(key, value, NULL, &type, (LPBYTE) data, &size); + LONG status = RegGetValue(key, NULL, value, RRF_RT_REG_SZ, + NULL, (LPBYTE) data, &size); - if (status == ERROR_SUCCESS && type != REG_SZ) + if (status == ERROR_FILE_NOT_FOUND && default_value) { - status = ERROR_DATATYPE_MISMATCH; + size_t len = size/sizeof(data[0]); + if (openvpn_sntprintf(data, len, default_value) > 0) + { + status = ERROR_SUCCESS; + } } if (status != ERROR_SUCCESS) { SetLastError(status); - return MsgToEventLog(M_SYSERR, TEXT("Error querying registry value: HKLM\\%s\\%s"), REG_KEY, value); + return MsgToEventLog(M_SYSERR, TEXT("Error querying registry value: HKLM\\SOFTWARE\\" PACKAGE_NAME "%s\\%s"), service_instance, value); } return ERROR_SUCCESS; @@ -78,60 +84,78 @@ GetRegString(HKEY key, LPCTSTR value, LPTSTR data, DWORD size) DWORD GetOpenvpnSettings(settings_t *s) { + TCHAR reg_path[256]; TCHAR priority[64]; TCHAR append[2]; DWORD error; HKEY key; + TCHAR install_path[MAX_PATH]; + TCHAR default_value[MAX_PATH]; + + openvpn_sntprintf(reg_path, _countof(reg_path), TEXT("SOFTWARE\\" PACKAGE_NAME "%s"), service_instance); - LONG status = RegOpenKeyEx(HKEY_LOCAL_MACHINE, REG_KEY, 0, KEY_READ, &key); + LONG status = RegOpenKeyEx(HKEY_LOCAL_MACHINE, reg_path, 0, KEY_READ, &key); if (status != ERROR_SUCCESS) { SetLastError(status); - return MsgToEventLog(M_SYSERR, TEXT("Could not open Registry key HKLM\\%s not found"), REG_KEY); + return MsgToEventLog(M_SYSERR, TEXT("Could not open Registry key HKLM\\%s not found"), reg_path); } - error = GetRegString(key, TEXT("exe_path"), s->exe_path, sizeof(s->exe_path)); + /* The default value of REG_KEY is the install path */ + if (GetRegString(key, NULL, install_path, sizeof(install_path), NULL) != ERROR_SUCCESS) + { + goto out; + } + + openvpn_sntprintf(default_value, _countof(default_value), TEXT("%s\\bin\\openvpn.exe"), + install_path); + error = GetRegString(key, TEXT("exe_path"), s->exe_path, sizeof(s->exe_path), default_value); if (error != ERROR_SUCCESS) { goto out; } - error = GetRegString(key, TEXT("config_dir"), s->config_dir, sizeof(s->config_dir)); + openvpn_sntprintf(default_value, _countof(default_value), TEXT("%s\\config"), install_path); + error = GetRegString(key, TEXT("config_dir"), s->config_dir, sizeof(s->config_dir), + default_value); if (error != ERROR_SUCCESS) { goto out; } - error = GetRegString(key, TEXT("config_ext"), s->ext_string, sizeof(s->ext_string)); + error = GetRegString(key, TEXT("config_ext"), s->ext_string, sizeof(s->ext_string), + TEXT(".ovpn")); if (error != ERROR_SUCCESS) { goto out; } - error = GetRegString(key, TEXT("log_dir"), s->log_dir, sizeof(s->log_dir)); + openvpn_sntprintf(default_value, _countof(default_value), TEXT("%s\\log"), install_path); + error = GetRegString(key, TEXT("log_dir"), s->log_dir, sizeof(s->log_dir), default_value); if (error != ERROR_SUCCESS) { goto out; } - error = GetRegString(key, TEXT("priority"), priority, sizeof(priority)); + error = GetRegString(key, TEXT("priority"), priority, sizeof(priority), + TEXT("NORMAL_PRIORITY_CLASS")); if (error != ERROR_SUCCESS) { goto out; } - error = GetRegString(key, TEXT("log_append"), append, sizeof(append)); + error = GetRegString(key, TEXT("log_append"), append, sizeof(append), TEXT("0")); if (error != ERROR_SUCCESS) { goto out; } /* read if present, else use default */ - error = GetRegString(key, TEXT("ovpn_admin_group"), s->ovpn_admin_group, sizeof(s->ovpn_admin_group)); + error = GetRegString(key, TEXT("ovpn_admin_group"), s->ovpn_admin_group, + sizeof(s->ovpn_admin_group), OVPN_ADMIN_GROUP); if (error != ERROR_SUCCESS) { - openvpn_sntprintf(s->ovpn_admin_group, _countof(s->ovpn_admin_group), OVPN_ADMIN_GROUP); - error = 0; /* this error is not fatal */ + goto out; } /* set process priority */ if (!_tcsicmp(priority, TEXT("IDLE_PRIORITY_CLASS"))) @@ -231,7 +255,7 @@ MsgToEventLog(DWORD flags, LPCTSTR format, ...) if (hEventSource != NULL) { openvpn_sntprintf(msg[0], _countof(msg[0]), - TEXT("%s%s: %s"), APPNAME, + TEXT("%s%s%s: %s"), APPNAME, service_instance, (flags & MSG_FLAGS_ERROR) ? TEXT(" error") : TEXT(""), err_msg); va_start(arglist, format); diff --git a/src/openvpnserv/interactive.c b/src/openvpnserv/interactive.c index 607c8a9..19be0db 100644 --- a/src/openvpnserv/interactive.c +++ b/src/openvpnserv/interactive.c @@ -5,7 +5,7 @@ * packet encryption, packet authentication, and * packet compression. * - * Copyright (C) 2012-2017 Heiko Hund <heiko.hund@sophos.com> + * Copyright (C) 2012-2018 Heiko Hund <heiko.hund@sophos.com> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 @@ -33,6 +33,7 @@ #include <stdio.h> #include <sddl.h> #include <shellapi.h> +#include <mstcpip.h> #ifdef HAVE_VERSIONHELPERS_H #include <versionhelpers.h> @@ -52,7 +53,7 @@ #define ERROR_MESSAGE_TYPE 0x20000003 static SERVICE_STATUS_HANDLE service; -static SERVICE_STATUS status; +static SERVICE_STATUS status = { .dwServiceType = SERVICE_WIN32_SHARE_PROCESS }; static HANDLE exit_event = NULL; static settings_t settings; static HANDLE rdns_semaphore = NULL; @@ -276,7 +277,7 @@ ReturnProcessId(HANDLE pipe, DWORD pid, DWORD count, LPHANDLE events) * Same format as error messages (3 line string) with error = 0 in * 0x%08x format, PID on line 2 and a description "Process ID" on line 3 */ - _snwprintf(buf, _countof(buf), L"0x%08x\n0x%08x\n%s", 0, pid, msg); + swprintf(buf, _countof(buf), L"0x%08x\n0x%08x\n%s", 0, pid, msg); buf[_countof(buf) - 1] = '\0'; WritePipeAsync(pipe, buf, wcslen(buf) * 2, count, events); @@ -370,12 +371,12 @@ ValidateOptions(HANDLE pipe, const WCHAR *workdir, const WCHAR *options) BOOL ret = FALSE; int i; const WCHAR *msg1 = L"You have specified a config file location (%s relative to %s)" - " that requires admin approval. This error may be avoided" - " by adding your account to the \"%s\" group"; + L" that requires admin approval. This error may be avoided" + L" by adding your account to the \"%s\" group"; const WCHAR *msg2 = L"You have specified an option (%s) that may be used" - " only with admin approval. This error may be avoided" - " by adding your account to the \"%s\" group"; + L" only with admin approval. This error may be avoided" + L" by adding your account to the \"%s\" group"; argv = CommandLineToArgvW(options, &argc); @@ -402,8 +403,8 @@ ValidateOptions(HANDLE pipe, const WCHAR *workdir, const WCHAR *options) if (!CheckOption(workdir, 2, argv_tmp, &settings)) { - snwprintf(buf, _countof(buf), msg1, argv[0], workdir, - settings.ovpn_admin_group); + swprintf(buf, _countof(buf), msg1, argv[0], workdir, + settings.ovpn_admin_group); buf[_countof(buf) - 1] = L'\0'; ReturnError(pipe, ERROR_STARTUP_DATA, buf, 1, &exit_event); } @@ -421,15 +422,15 @@ ValidateOptions(HANDLE pipe, const WCHAR *workdir, const WCHAR *options) { if (wcscmp(L"--config", argv[i]) == 0 && argc-i > 1) { - snwprintf(buf, _countof(buf), msg1, argv[i+1], workdir, - settings.ovpn_admin_group); + swprintf(buf, _countof(buf), msg1, argv[i+1], workdir, + settings.ovpn_admin_group); buf[_countof(buf) - 1] = L'\0'; ReturnError(pipe, ERROR_STARTUP_DATA, buf, 1, &exit_event); } else { - snwprintf(buf, _countof(buf), msg2, argv[i], - settings.ovpn_admin_group); + swprintf(buf, _countof(buf), msg2, argv[i], + settings.ovpn_admin_group); buf[_countof(buf) - 1] = L'\0'; ReturnError(pipe, ERROR_STARTUP_DATA, buf, 1, &exit_event); } @@ -465,6 +466,13 @@ GetStartupData(HANDLE pipe, STARTUP_DATA *sud) } size = bytes / sizeof(*data); + if (size == 0) + { + MsgToEventLog(M_SYSERR, TEXT("malformed startup data: 1 byte received")); + ReturnError(pipe, ERROR_STARTUP_DATA, L"GetStartupData", 1, &exit_event); + goto out; + } + data = malloc(bytes); if (data == NULL) { @@ -546,32 +554,17 @@ static DWORD InterfaceLuid(const char *iface_name, PNET_LUID luid) { NETIO_STATUS status; - LPWSTR wide_name; - int n; + LPWSTR wide_name = utf8to16(iface_name); - typedef NETIO_STATUS WINAPI (*ConvertInterfaceAliasToLuidFn) (LPCWSTR, PNET_LUID); - static ConvertInterfaceAliasToLuidFn ConvertInterfaceAliasToLuid = NULL; - if (!ConvertInterfaceAliasToLuid) + if (wide_name) { - HMODULE iphlpapi = GetModuleHandle(TEXT("iphlpapi.dll")); - if (iphlpapi == NULL) - { - return GetLastError(); - } - - ConvertInterfaceAliasToLuid = (ConvertInterfaceAliasToLuidFn) GetProcAddress(iphlpapi, "ConvertInterfaceAliasToLuid"); - if (!ConvertInterfaceAliasToLuid) - { - return GetLastError(); - } + status = ConvertInterfaceAliasToLuid(wide_name, luid); + free(wide_name); + } + else + { + status = ERROR_OUTOFMEMORY; } - - n = MultiByteToWideChar(CP_UTF8, 0, iface_name, -1, NULL, 0); - wide_name = malloc(n * sizeof(WCHAR)); - MultiByteToWideChar(CP_UTF8, 0, iface_name, -1, wide_name, n); - status = ConvertInterfaceAliasToLuid(wide_name, luid); - free(wide_name); - return status; } @@ -584,24 +577,6 @@ CmpAddress(LPVOID item, LPVOID address) static DWORD DeleteAddress(PMIB_UNICASTIPADDRESS_ROW addr_row) { - typedef NETIOAPI_API (*DeleteUnicastIpAddressEntryFn) (const PMIB_UNICASTIPADDRESS_ROW); - static DeleteUnicastIpAddressEntryFn DeleteUnicastIpAddressEntry = NULL; - - if (!DeleteUnicastIpAddressEntry) - { - HMODULE iphlpapi = GetModuleHandle(TEXT("iphlpapi.dll")); - if (iphlpapi == NULL) - { - return GetLastError(); - } - - DeleteUnicastIpAddressEntry = (DeleteUnicastIpAddressEntryFn) GetProcAddress(iphlpapi, "DeleteUnicastIpAddressEntry"); - if (!DeleteUnicastIpAddressEntry) - { - return GetLastError(); - } - } - return DeleteUnicastIpAddressEntry(addr_row); } @@ -612,32 +587,6 @@ HandleAddressMessage(address_message_t *msg, undo_lists_t *lists) PMIB_UNICASTIPADDRESS_ROW addr_row; BOOL add = msg->header.type == msg_add_address; - typedef NETIOAPI_API (*CreateUnicastIpAddressEntryFn) (const PMIB_UNICASTIPADDRESS_ROW); - typedef NETIOAPI_API (*InitializeUnicastIpAddressEntryFn) (PMIB_UNICASTIPADDRESS_ROW); - static CreateUnicastIpAddressEntryFn CreateUnicastIpAddressEntry = NULL; - static InitializeUnicastIpAddressEntryFn InitializeUnicastIpAddressEntry = NULL; - - if (!CreateUnicastIpAddressEntry || !InitializeUnicastIpAddressEntry) - { - HMODULE iphlpapi = GetModuleHandle(TEXT("iphlpapi.dll")); - if (iphlpapi == NULL) - { - return GetLastError(); - } - - CreateUnicastIpAddressEntry = (CreateUnicastIpAddressEntryFn) GetProcAddress(iphlpapi, "CreateUnicastIpAddressEntry"); - if (!CreateUnicastIpAddressEntry) - { - return GetLastError(); - } - - InitializeUnicastIpAddressEntry = (InitializeUnicastIpAddressEntryFn) GetProcAddress(iphlpapi, "InitializeUnicastIpAddressEntry"); - if (!InitializeUnicastIpAddressEntry) - { - return GetLastError(); - } - } - addr_row = malloc(sizeof(*addr_row)); if (addr_row == NULL) { @@ -706,24 +655,6 @@ CmpRoute(LPVOID item, LPVOID route) static DWORD DeleteRoute(PMIB_IPFORWARD_ROW2 fwd_row) { - typedef NETIOAPI_API (*DeleteIpForwardEntry2Fn) (PMIB_IPFORWARD_ROW2); - static DeleteIpForwardEntry2Fn DeleteIpForwardEntry2 = NULL; - - if (!DeleteIpForwardEntry2) - { - HMODULE iphlpapi = GetModuleHandle(TEXT("iphlpapi.dll")); - if (iphlpapi == NULL) - { - return GetLastError(); - } - - DeleteIpForwardEntry2 = (DeleteIpForwardEntry2Fn) GetProcAddress(iphlpapi, "DeleteIpForwardEntry2"); - if (!DeleteIpForwardEntry2) - { - return GetLastError(); - } - } - return DeleteIpForwardEntry2(fwd_row); } @@ -734,24 +665,6 @@ HandleRouteMessage(route_message_t *msg, undo_lists_t *lists) PMIB_IPFORWARD_ROW2 fwd_row; BOOL add = msg->header.type == msg_add_route; - typedef NETIOAPI_API (*CreateIpForwardEntry2Fn) (PMIB_IPFORWARD_ROW2); - static CreateIpForwardEntry2Fn CreateIpForwardEntry2 = NULL; - - if (!CreateIpForwardEntry2) - { - HMODULE iphlpapi = GetModuleHandle(TEXT("iphlpapi.dll")); - if (iphlpapi == NULL) - { - return GetLastError(); - } - - CreateIpForwardEntry2 = (CreateIpForwardEntry2Fn) GetProcAddress(iphlpapi, "CreateIpForwardEntry2"); - if (!CreateIpForwardEntry2) - { - return GetLastError(); - } - } - fwd_row = malloc(sizeof(*fwd_row)); if (fwd_row == NULL) { @@ -820,36 +733,12 @@ out: static DWORD HandleFlushNeighborsMessage(flush_neighbors_message_t *msg) { - typedef NETIOAPI_API (*FlushIpNetTable2Fn) (ADDRESS_FAMILY, NET_IFINDEX); - static FlushIpNetTable2Fn flush_fn = NULL; - if (msg->family == AF_INET) { return FlushIpNetTable(msg->iface.index); } - if (!flush_fn) - { - HMODULE iphlpapi = GetModuleHandle(TEXT("iphlpapi.dll")); - if (iphlpapi == NULL) - { - return GetLastError(); - } - - flush_fn = (FlushIpNetTable2Fn) GetProcAddress(iphlpapi, "FlushIpNetTable2"); - if (!flush_fn) - { - if (GetLastError() == ERROR_PROC_NOT_FOUND) - { - return WSAEPFNOSUPPORT; - } - else - { - return GetLastError(); - } - } - } - return flush_fn(msg->family, msg->iface.index); + return FlushIpNetTable2(msg->family, msg->iface.index); } static void @@ -915,17 +804,18 @@ HandleBlockDNSMessage(const block_dns_message_t *msg, undo_lists_t *lists) } interface_data->engine = engine; interface_data->index = msg->iface.index; + int is_auto = 0; interface_data->metric_v4 = get_interface_metric(msg->iface.index, - AF_INET); - if (interface_data->metric_v4 < 0) + AF_INET, &is_auto); + if (is_auto) { - interface_data->metric_v4 = -1; + interface_data->metric_v4 = 0; } interface_data->metric_v6 = get_interface_metric(msg->iface.index, - AF_INET6); - if (interface_data->metric_v6 < 0) + AF_INET6, &is_auto); + if (is_auto) { - interface_data->metric_v6 = -1; + interface_data->metric_v6 = 0; } err = AddListItem(&(*lists)[block_dns], interface_data); if (!err) @@ -1066,7 +956,7 @@ RegisterDNS(LPVOID unused) if (GetSystemDirectory(sys_path, MAX_PATH)) { - _snwprintf(ipcfg, MAX_PATH, L"%s\\%s", sys_path, L"ipconfig.exe"); + swprintf(ipcfg, MAX_PATH, L"%s\\%s", sys_path, L"ipconfig.exe"); ipcfg[MAX_PATH-1] = L'\0'; } @@ -1436,7 +1326,7 @@ RunOpenvpn(LPVOID p) STARTUPINFOW startup_info; PROCESS_INFORMATION proc_info; LPVOID user_env = NULL; - TCHAR ovpn_pipe_name[36]; + TCHAR ovpn_pipe_name[256]; /* The entire pipe name string can be up to 256 characters long according to MSDN. */ LPCWSTR exe_path; WCHAR *cmdline = NULL; size_t cmdline_size; @@ -1598,7 +1488,7 @@ RunOpenvpn(LPVOID p) } openvpn_sntprintf(ovpn_pipe_name, _countof(ovpn_pipe_name), - TEXT("\\\\.\\pipe\\openvpn\\service_%lu"), GetCurrentThreadId()); + TEXT("\\\\.\\pipe\\" PACKAGE "%s\\service_%lu"), service_instance, GetCurrentThreadId()); ovpn_pipe = CreateNamedPipe(ovpn_pipe_name, PIPE_ACCESS_DUPLEX | FILE_FLAG_FIRST_PIPE_INSTANCE | FILE_FLAG_OVERLAPPED, PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE | PIPE_WAIT, 1, 128, 128, 0, NULL); @@ -1706,8 +1596,8 @@ RunOpenvpn(LPVOID p) else if (exit_code != 0) { WCHAR buf[256]; - int len = _snwprintf(buf, _countof(buf), - L"OpenVPN exited with error: exit code = %lu", exit_code); + swprintf(buf, _countof(buf), + L"OpenVPN exited with error: exit code = %lu", exit_code); buf[_countof(buf) - 1] = L'\0'; ReturnError(pipe, ERROR_OPENVPN_STARTUP, buf, 1, &exit_event); } @@ -1765,6 +1655,7 @@ ServiceCtrlInteractive(DWORD ctrl_code, DWORD event, LPVOID data, LPVOID ctx) static HANDLE CreateClientPipeInstance(VOID) { + TCHAR pipe_name[256]; /* The entire pipe name string can be up to 256 characters long according to MSDN. */ HANDLE pipe = NULL; PACL old_dacl, new_dacl; PSECURITY_DESCRIPTOR sd; @@ -1801,7 +1692,8 @@ CreateClientPipeInstance(VOID) initialized = TRUE; } - pipe = CreateNamedPipe(TEXT("\\\\.\\pipe\\openvpn\\service"), flags, + openvpn_sntprintf(pipe_name, _countof(pipe_name), TEXT("\\\\.\\pipe\\" PACKAGE "%s\\service"), service_instance); + pipe = CreateNamedPipe(pipe_name, flags, PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE, PIPE_UNLIMITED_INSTANCES, 1024, 1024, 0, NULL); if (pipe == INVALID_HANDLE_VALUE) @@ -1890,6 +1782,20 @@ FreeWaitHandles(LPHANDLE h) free(h); } +static BOOL +CmpHandle(LPVOID item, LPVOID hnd) +{ + return item == hnd; +} + + +VOID WINAPI +ServiceStartInteractiveOwn(DWORD dwArgc, LPTSTR *lpszArgv) +{ + status.dwServiceType = SERVICE_WIN32_OWN_PROCESS; + ServiceStartInteractive(dwArgc, lpszArgv); +} + VOID WINAPI ServiceStartInteractive(DWORD dwArgc, LPTSTR *lpszArgv) @@ -1900,11 +1806,6 @@ ServiceStartInteractive(DWORD dwArgc, LPTSTR *lpszArgv) list_item_t *threads = NULL; PHANDLE handles = NULL; DWORD handle_count; - BOOL - CmpHandle(LPVOID item, LPVOID hnd) - { - return item == hnd; - } service = RegisterServiceCtrlHandlerEx(interactive_service.name, ServiceCtrlInteractive, &status); if (!service) @@ -1912,7 +1813,6 @@ ServiceStartInteractive(DWORD dwArgc, LPTSTR *lpszArgv) return; } - status.dwServiceType = SERVICE_WIN32_SHARE_PROCESS; status.dwCurrentState = SERVICE_START_PENDING; status.dwServiceSpecificExitCode = NO_ERROR; status.dwWin32ExitCode = NO_ERROR; diff --git a/src/openvpnserv/service.c b/src/openvpnserv/service.c index b79e999..7157bea 100644 --- a/src/openvpnserv/service.c +++ b/src/openvpnserv/service.c @@ -223,46 +223,81 @@ out: int _tmain(int argc, TCHAR *argv[]) { - SERVICE_TABLE_ENTRY dispatchTable[] = { + /* + * Automatic + Interactive service (as a SERVICE_WIN32_SHARE_PROCESS) + * This is the default. + */ + const SERVICE_TABLE_ENTRY dispatchTable_shared[] = { { automatic_service.name, ServiceStartAutomatic }, { interactive_service.name, ServiceStartInteractive }, { NULL, NULL } }; + /* Automatic service only (as a SERVICE_WIN32_OWN_PROCESS) */ + const SERVICE_TABLE_ENTRY dispatchTable_automatic[] = { + { TEXT(""), ServiceStartAutomaticOwn }, + { NULL, NULL } + }; + + /* Interactive service only (as a SERVICE_WIN32_OWN_PROCESS) */ + const SERVICE_TABLE_ENTRY dispatchTable_interactive[] = { + { TEXT(""), ServiceStartInteractiveOwn }, + { NULL, NULL } + }; + + const SERVICE_TABLE_ENTRY *dispatchTable = dispatchTable_shared; + openvpn_service[0] = automatic_service; openvpn_service[1] = interactive_service; - if (argc > 1 && (*argv[1] == TEXT('-') || *argv[1] == TEXT('/'))) + for (int i = 1; i < argc; i++) { - if (_tcsicmp(TEXT("install"), argv[1] + 1) == 0) - { - return CmdInstallServices(); - } - else if (_tcsicmp(TEXT("remove"), argv[1] + 1) == 0) - { - return CmdRemoveServices(); - } - else if (_tcsicmp(TEXT("start"), argv[1] + 1) == 0) - { - BOOL is_auto = argc < 3 || _tcsicmp(TEXT("interactive"), argv[2]) != 0; - return CmdStartService(is_auto ? automatic : interactive); - } - else + if (*argv[i] == TEXT('-') || *argv[i] == TEXT('/')) { - goto dispatch; - } + if (_tcsicmp(TEXT("install"), argv[i] + 1) == 0) + { + return CmdInstallServices(); + } + else if (_tcsicmp(TEXT("remove"), argv[i] + 1) == 0) + { + return CmdRemoveServices(); + } + else if (_tcsicmp(TEXT("start"), argv[i] + 1) == 0) + { + BOOL is_auto = argc < i + 2 || _tcsicmp(TEXT("interactive"), argv[i + 1]) != 0; + return CmdStartService(is_auto ? automatic : interactive); + } + else if (argc > i + 2 && _tcsicmp(TEXT("instance"), argv[i] + 1) == 0) + { + dispatchTable = _tcsicmp(TEXT("interactive"), argv[i + 1]) != 0 ? + dispatchTable_automatic : + dispatchTable_interactive; - return 0; + service_instance = argv[i + 2]; + i += 2; + } + else + { + _tprintf(TEXT("%s -install to install the services\n"), APPNAME); + _tprintf(TEXT("%s -start <name> to start a service (\"automatic\" or \"interactive\")\n"), APPNAME); + _tprintf(TEXT("%s -remove to remove the services\n"), APPNAME); + + _tprintf(TEXT("\nService run-time parameters:\n")); + _tprintf(TEXT("-instance <name> <id>\n") + TEXT(" Runs the service as an alternate instance. <name> can be \"automatic\" or\n") + TEXT(" \"interactive\". The service settings will be loaded from\n") + TEXT(" HKLM\\Software\\" PACKAGE_NAME "<id> registry key, and the interactive service will accept\n") + TEXT(" requests on \\\\.\\pipe\\" PACKAGE "<id>\\service named pipe.\n")); + + return 0; + } + } } /* If it doesn't match any of the above parameters * the service control manager may be starting the service * so we must call StartServiceCtrlDispatcher */ -dispatch: - _tprintf(TEXT("%s -install to install the services\n"), APPNAME); - _tprintf(TEXT("%s -start <name> to start a service (\"automatic\" or \"interactive\")\n"), APPNAME); - _tprintf(TEXT("%s -remove to remove the services\n"), APPNAME); _tprintf(TEXT("\nStartServiceCtrlDispatcher being called.\n")); _tprintf(TEXT("This may take several seconds. Please wait.\n")); diff --git a/src/openvpnserv/service.h b/src/openvpnserv/service.h index 9fe573e..af8f37f 100644 --- a/src/openvpnserv/service.h +++ b/src/openvpnserv/service.h @@ -5,7 +5,7 @@ * packet encryption, packet authentication, and * packet compression. * - * Copyright (C) 2013-2017 Heiko Hund <heiko.hund@sophos.com> + * Copyright (C) 2013-2018 Heiko Hund <heiko.hund@sophos.com> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 @@ -73,10 +73,12 @@ typedef struct { extern openvpn_service_t automatic_service; extern openvpn_service_t interactive_service; +extern LPCTSTR service_instance; - +VOID WINAPI ServiceStartAutomaticOwn(DWORD argc, LPTSTR *argv); VOID WINAPI ServiceStartAutomatic(DWORD argc, LPTSTR *argv); +VOID WINAPI ServiceStartInteractiveOwn(DWORD argc, LPTSTR *argv); VOID WINAPI ServiceStartInteractive(DWORD argc, LPTSTR *argv); int openvpn_vsntprintf(LPTSTR str, size_t size, LPCTSTR format, va_list arglist); diff --git a/src/openvpnserv/validate.c b/src/openvpnserv/validate.c index f6a97e9..653bd12 100644 --- a/src/openvpnserv/validate.c +++ b/src/openvpnserv/validate.c @@ -65,7 +65,7 @@ CheckConfigPath(const WCHAR *workdir, const WCHAR *fname, const settings_t *s) /* convert fname to full path */ if (PathIsRelativeW(fname) ) { - snwprintf(tmp, _countof(tmp), L"%s\\%s", workdir, fname); + swprintf(tmp, _countof(tmp), L"%s\\%s", workdir, fname); tmp[_countof(tmp)-1] = L'\0'; config_file = tmp; } diff --git a/src/plugins/Makefile.am b/src/plugins/Makefile.am index ca90496..f346178 100644 --- a/src/plugins/Makefile.am +++ b/src/plugins/Makefile.am @@ -5,7 +5,7 @@ # packet encryption, packet authentication, and # packet compression. # -# Copyright (C) 2002-2017 OpenVPN Technologies, Inc. <sales@openvpn.net> +# Copyright (C) 2002-2018 OpenVPN Inc <sales@openvpn.net> # Copyright (C) 2006-2012 Alon Bar-Lev <alon.barlev@gmail.com> # diff --git a/src/plugins/Makefile.in b/src/plugins/Makefile.in index d63b407..ca48312 100644 --- a/src/plugins/Makefile.in +++ b/src/plugins/Makefile.in @@ -21,7 +21,7 @@ # packet encryption, packet authentication, and # packet compression. # -# Copyright (C) 2002-2017 OpenVPN Technologies, Inc. <sales@openvpn.net> +# Copyright (C) 2002-2018 OpenVPN Inc <sales@openvpn.net> # Copyright (C) 2006-2012 Alon Bar-Lev <alon.barlev@gmail.com> # VPATH = @srcdir@ @@ -365,6 +365,7 @@ plugindir = @plugindir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ +runstatedir = @runstatedir@ sampledir = @sampledir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ diff --git a/src/plugins/auth-pam/Makefile.in b/src/plugins/auth-pam/Makefile.in index 50b7523..20d7731 100644 --- a/src/plugins/auth-pam/Makefile.in +++ b/src/plugins/auth-pam/Makefile.in @@ -389,6 +389,7 @@ plugindir = @plugindir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ +runstatedir = @runstatedir@ sampledir = @sampledir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ diff --git a/src/plugins/auth-pam/auth-pam.c b/src/plugins/auth-pam/auth-pam.c index ae514d7..26b0eeb 100644 --- a/src/plugins/auth-pam/auth-pam.c +++ b/src/plugins/auth-pam/auth-pam.c @@ -5,7 +5,7 @@ * packet encryption, packet authentication, and * packet compression. * - * Copyright (C) 2002-2017 OpenVPN Technologies, Inc. <sales@openvpn.net> + * Copyright (C) 2002-2018 OpenVPN Inc <sales@openvpn.net> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 diff --git a/src/plugins/auth-pam/utils.c b/src/plugins/auth-pam/utils.c index 4b900c7..4e0c5bf 100644 --- a/src/plugins/auth-pam/utils.c +++ b/src/plugins/auth-pam/utils.c @@ -5,7 +5,7 @@ * packet encryption, packet authentication, and * packet compression. * - * Copyright (C) 2002-2017 OpenVPN Technologies, Inc. <sales@openvpn.net> + * Copyright (C) 2002-2018 OpenVPN Inc <sales@openvpn.net> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 diff --git a/src/plugins/auth-pam/utils.h b/src/plugins/auth-pam/utils.h index c0b4b10..90fff66 100644 --- a/src/plugins/auth-pam/utils.h +++ b/src/plugins/auth-pam/utils.h @@ -5,7 +5,7 @@ * packet encryption, packet authentication, and * packet compression. * - * Copyright (C) 2002-2017 OpenVPN Technologies, Inc. <sales@openvpn.net> + * Copyright (C) 2002-2018 OpenVPN Inc <sales@openvpn.net> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 diff --git a/src/plugins/down-root/Makefile.in b/src/plugins/down-root/Makefile.in index f1a840a..7069108 100644 --- a/src/plugins/down-root/Makefile.in +++ b/src/plugins/down-root/Makefile.in @@ -388,6 +388,7 @@ plugindir = @plugindir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ +runstatedir = @runstatedir@ sampledir = @sampledir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ diff --git a/src/plugins/down-root/down-root.c b/src/plugins/down-root/down-root.c index 4198184..c5e5023 100644 --- a/src/plugins/down-root/down-root.c +++ b/src/plugins/down-root/down-root.c @@ -5,7 +5,7 @@ * packet encryption, packet authentication, and * packet compression. * - * Copyright (C) 2002-2017 OpenVPN Technologies, Inc. <sales@openvpn.net> + * Copyright (C) 2002-2018 OpenVPN Inc <sales@openvpn.net> * Copyright (C) 2013 David Sommerseth <davids@redhat.com> * * This program is free software; you can redistribute it and/or modify |