vlmcsd-1106-2016-12-06-Hotbird64

This commit is contained in:
Wind4
2016-12-11 12:25:30 +08:00
parent 9bd3e9c470
commit af593fc11b
36 changed files with 1254 additions and 323 deletions

View File

@ -192,6 +192,12 @@ ifneq ($(NOLIBS),1)
endif
endif
ifneq ($(NOLIBS),1)
ifeq ($(CYGWIN),1)
BASELDFLAGS += -liphlpapi
endif
endif
ifneq ($(NO_DNS),1)
ifneq ($(ANDROID),1)
ifneq ($(NOLRESOLV),1)
@ -441,9 +447,9 @@ endif
endif
ifeq "$(WIN)" "1"
VLMCSD_SRCS += ntservice.c
MULTI_SRCS += ntservice.c
../build/MULTI_OBJS += ntservice.o
VLMCSD_SRCS += ntservice.c wintap.c
MULTI_SRCS += ntservice.c wintap.c
MULTI_OBJS += ../build/ntservice.o ../build/wintap.o
endif
ifeq ($(CRYPTO), openssl_with_aes)

View File

@ -230,6 +230,35 @@ int_fast8_t string2UuidLE(const char *const restrict input, GUID *const restrict
}
__pure DWORD timeSpanString2Seconds(const char *const restrict argument)
{
char *unitId;
long long val = vlmcsd_strtoll(argument, &unitId, 10);
switch (toupper((int)*unitId))
{
case 'W':
val *= 7;
case 'D':
val *= 24;
case 'H':
val *= 60;
case 0:
case 'M':
val *= 60;
case 'S':
break;
default:
return 0;
}
if (*unitId && unitId[1]) return 0;
if (val < 1) val = 1;
return (DWORD)(val & UINT_MAX);
}
#if !IS_LIBRARY
//Checks a command line argument if it is numeric and between min and max. Returns the numeric value or exits on error
__pure unsigned int getOptionArgumentInt(const char o, const unsigned int min, const unsigned int max)
@ -261,7 +290,7 @@ void optReset(void)
}
#endif // !IS_LIBRARY
#if defined(_WIN32) || defined(USE_MSRPC)
#if _WIN32 || __CYGWIN__
// Returns a static message buffer containing text for a given Win32 error. Not thread safe (same as strerror)
char* win_strerror(const int message)
@ -273,7 +302,7 @@ char* win_strerror(const int message)
return buffer;
}
#endif // defined(_WIN32) || defined(USE_MSRPC)
#endif // _WIN32 || __CYGWIN__
/*
@ -493,11 +522,11 @@ void getExeName()
#ifdef _WIN32
static void getDefaultDataFile()
{
char fileName[512];
char fileName[MAX_PATH];
getExeName();
strcpy(fileName, fn_exe);
strncpy(fileName, fn_exe, MAX_PATH);
PathRemoveFileSpec(fileName);
strncat(fileName, "\\vlmcsd.kmd", 512);
strncat(fileName, "\\vlmcsd.kmd", MAX_PATH);
fn_data = vlmcsd_strdup(fileName);
}
#else // !_WIN32

View File

@ -20,6 +20,8 @@
BOOL stringToInt(const char *const szValue, const unsigned int min, const unsigned int max, unsigned int *const value);
unsigned int getOptionArgumentInt(const char o, const unsigned int min, const unsigned int max);
void optReset(void);
__pure DWORD timeSpanString2Seconds(const char *const restrict argument);
#define timeSpanString2Minutes(x) (timeSpanString2Seconds(x) / 60)
char* win_strerror(const int message);
int ucs2_to_utf8_char (const WCHAR ucs2_le, char *utf8);
size_t utf8_to_ucs2(WCHAR* const ucs2_le, const char* const utf8, const size_t maxucs2, const size_t maxutf8);

View File

@ -763,36 +763,36 @@ uint8_t DefaultKmsData[] =
uint8_t DefaultKmsData[] =
{
0x4B, 0x4D, 0x44, 0x00, 0x02, 0x00, 0x01, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x90, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x90, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x10, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xCE, 0x00, 0x00, 0x00, 0xC0, 0xE3, 0x12, 0x1C,
0xBF, 0x6A, 0xA6, 0x1F, 0x32, 0x00, 0x00, 0x00, 0x42, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x60, 0x00, 0x00, 0x00, 0xC0, 0x7F, 0xDC, 0x0B, 0x7F, 0x6A, 0xFE, 0x0C, 0x0A, 0x00, 0x00, 0x00,
0x74, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xCE, 0x00, 0x00, 0x00, 0x80, 0x8E, 0xF2, 0x0D,
0xFF, 0x3F, 0x42, 0x0F, 0x0A, 0x00, 0x00, 0x00, 0xA6, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0xCE, 0x00, 0x00, 0x00, 0x40, 0x17, 0x0C, 0x1A, 0xBF, 0xC8, 0x5B, 0x1B, 0x0A, 0x00, 0x00, 0x00,
0x46, 0xF9, 0x5A, 0xE8, 0x25, 0x2E, 0xB7, 0x47, 0x83, 0xE1, 0xBE, 0xBC, 0xEB, 0xEA, 0xC6, 0x11,
0xD8, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x05, 0x00, 0x00, 0x01, 0x00,
0xBF, 0xF1, 0xA6, 0xE6, 0x40, 0x9D, 0xC3, 0x40, 0xAA, 0x9F, 0xC7, 0x7B, 0xA2, 0x15, 0x78, 0xC0,
0xD8, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x05, 0x00, 0x00, 0x02, 0x00,
0x68, 0x79, 0x4C, 0xAA, 0xDA, 0xB9, 0x80, 0x46, 0x92, 0xB6, 0xAC, 0xB2, 0x5E, 0x2F, 0x86, 0x6C,
0xD8, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x05, 0x00, 0x01, 0x02, 0x00,
0x1B, 0xF6, 0xB5, 0x85, 0x0B, 0x32, 0xE3, 0x4B, 0x81, 0x4A, 0xB7, 0x6B, 0x2B, 0xFA, 0xFC, 0x82,
0xD8, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x05, 0x00, 0x00, 0x03, 0x00,
0x30, 0x33, 0x36, 0x31, 0x32, 0x2D, 0x30, 0x30, 0x32, 0x30, 0x36, 0x2D, 0x34, 0x37, 0x31, 0x2D,
0x31, 0x30, 0x34, 0x33, 0x39, 0x35, 0x2D, 0x30, 0x33, 0x2D, 0x31, 0x30, 0x33, 0x33, 0x2D, 0x31,
0x34, 0x33, 0x39, 0x33, 0x2E, 0x30, 0x30, 0x30, 0x30, 0x2D, 0x32, 0x39, 0x33, 0x32, 0x30, 0x31,
0x36, 0x00, 0x30, 0x33, 0x36, 0x31, 0x32, 0x2D, 0x30, 0x30, 0x30, 0x39, 0x36, 0x2D, 0x31, 0x39,
0x39, 0x2D, 0x31, 0x39, 0x34, 0x38, 0x39, 0x33, 0x2D, 0x30, 0x33, 0x2D, 0x31, 0x30, 0x33, 0x33,
0x2D, 0x31, 0x34, 0x33, 0x39, 0x33, 0x2E, 0x30, 0x30, 0x30, 0x30, 0x2D, 0x32, 0x39, 0x33, 0x32,
0x30, 0x31, 0x36, 0x00, 0x30, 0x33, 0x36, 0x31, 0x32, 0x2D, 0x30, 0x30, 0x32, 0x30, 0x36, 0x2D,
0x32, 0x33, 0x34, 0x2D, 0x31, 0x30, 0x39, 0x34, 0x38, 0x33, 0x2D, 0x30, 0x33, 0x2D, 0x31, 0x30,
0x33, 0x33, 0x2D, 0x31, 0x34, 0x33, 0x39, 0x33, 0x2E, 0x30, 0x30, 0x30, 0x30, 0x2D, 0x32, 0x39,
0x33, 0x32, 0x30, 0x31, 0x36, 0x00, 0x30, 0x33, 0x36, 0x31, 0x32, 0x2D, 0x30, 0x30, 0x32, 0x30,
0x36, 0x2D, 0x34, 0x33, 0x37, 0x2D, 0x31, 0x38, 0x34, 0x37, 0x33, 0x34, 0x2D, 0x30, 0x33, 0x2D,
0x31, 0x30, 0x33, 0x33, 0x2D, 0x31, 0x34, 0x33, 0x39, 0x33, 0x2E, 0x30, 0x30, 0x30, 0x30, 0x2D,
0x32, 0x39, 0x33, 0x32, 0x30, 0x31, 0x36, 0x00, 0x55, 0x6E, 0x6B, 0x6E, 0x6F, 0x77, 0x6E, 0x00,
0x4B, 0x4D, 0x44, 0x00, 0x02, 0x00, 0x01, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x90, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x90, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x10, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xCE, 0x00, 0x00, 0x00, 0xC0, 0xE3, 0x12, 0x1C,
0xBF, 0x6A, 0xA6, 0x1F, 0x32, 0x00, 0x00, 0x00, 0x42, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x60, 0x00, 0x00, 0x00, 0xC0, 0x7F, 0xDC, 0x0B, 0x7F, 0x6A, 0xFE, 0x0C, 0x0A, 0x00, 0x00, 0x00,
0x74, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xCE, 0x00, 0x00, 0x00, 0x80, 0x8E, 0xF2, 0x0D,
0xFF, 0x3F, 0x42, 0x0F, 0x0A, 0x00, 0x00, 0x00, 0xA6, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0xCE, 0x00, 0x00, 0x00, 0x40, 0x17, 0x0C, 0x1A, 0xBF, 0xC8, 0x5B, 0x1B, 0x0A, 0x00, 0x00, 0x00,
0x46, 0xF9, 0x5A, 0xE8, 0x25, 0x2E, 0xB7, 0x47, 0x83, 0xE1, 0xBE, 0xBC, 0xEB, 0xEA, 0xC6, 0x11,
0xD8, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x05, 0x00, 0x00, 0x01, 0x00,
0xBF, 0xF1, 0xA6, 0xE6, 0x40, 0x9D, 0xC3, 0x40, 0xAA, 0x9F, 0xC7, 0x7B, 0xA2, 0x15, 0x78, 0xC0,
0xD8, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x05, 0x00, 0x00, 0x02, 0x00,
0x68, 0x79, 0x4C, 0xAA, 0xDA, 0xB9, 0x80, 0x46, 0x92, 0xB6, 0xAC, 0xB2, 0x5E, 0x2F, 0x86, 0x6C,
0xD8, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x05, 0x00, 0x01, 0x02, 0x00,
0x1B, 0xF6, 0xB5, 0x85, 0x0B, 0x32, 0xE3, 0x4B, 0x81, 0x4A, 0xB7, 0x6B, 0x2B, 0xFA, 0xFC, 0x82,
0xD8, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x05, 0x00, 0x00, 0x03, 0x00,
0x30, 0x33, 0x36, 0x31, 0x32, 0x2D, 0x30, 0x30, 0x32, 0x30, 0x36, 0x2D, 0x34, 0x37, 0x31, 0x2D,
0x31, 0x30, 0x34, 0x33, 0x39, 0x35, 0x2D, 0x30, 0x33, 0x2D, 0x31, 0x30, 0x33, 0x33, 0x2D, 0x31,
0x34, 0x33, 0x39, 0x33, 0x2E, 0x30, 0x30, 0x30, 0x30, 0x2D, 0x32, 0x39, 0x33, 0x32, 0x30, 0x31,
0x36, 0x00, 0x30, 0x33, 0x36, 0x31, 0x32, 0x2D, 0x30, 0x30, 0x30, 0x39, 0x36, 0x2D, 0x31, 0x39,
0x39, 0x2D, 0x31, 0x39, 0x34, 0x38, 0x39, 0x33, 0x2D, 0x30, 0x33, 0x2D, 0x31, 0x30, 0x33, 0x33,
0x2D, 0x31, 0x34, 0x33, 0x39, 0x33, 0x2E, 0x30, 0x30, 0x30, 0x30, 0x2D, 0x32, 0x39, 0x33, 0x32,
0x30, 0x31, 0x36, 0x00, 0x30, 0x33, 0x36, 0x31, 0x32, 0x2D, 0x30, 0x30, 0x32, 0x30, 0x36, 0x2D,
0x32, 0x33, 0x34, 0x2D, 0x31, 0x30, 0x39, 0x34, 0x38, 0x33, 0x2D, 0x30, 0x33, 0x2D, 0x31, 0x30,
0x33, 0x33, 0x2D, 0x31, 0x34, 0x33, 0x39, 0x33, 0x2E, 0x30, 0x30, 0x30, 0x30, 0x2D, 0x32, 0x39,
0x33, 0x32, 0x30, 0x31, 0x36, 0x00, 0x30, 0x33, 0x36, 0x31, 0x32, 0x2D, 0x30, 0x30, 0x32, 0x30,
0x36, 0x2D, 0x34, 0x33, 0x37, 0x2D, 0x31, 0x38, 0x34, 0x37, 0x33, 0x34, 0x2D, 0x30, 0x33, 0x2D,
0x31, 0x30, 0x33, 0x33, 0x2D, 0x31, 0x34, 0x33, 0x39, 0x33, 0x2E, 0x30, 0x30, 0x30, 0x30, 0x2D,
0x32, 0x39, 0x33, 0x32, 0x30, 0x31, 0x36, 0x00, 0x55, 0x6E, 0x6B, 0x6E, 0x6F, 0x77, 0x6E, 0x00,
};
#else // !defined(NO_STRICT_MODES)

View File

@ -643,6 +643,10 @@ void printServerFlags()
" SUPPORT_WINE"
# endif // (_WIN32 || __CYGWIN__) && (!defined(USE_MSRPC) || defined(SUPPORT_WINE))
# if (_WIN32 || __CYGWIN__) && defined(NO_TAP)
" NO_TAP"
# endif // (_WIN32 || __CYGWIN__) && defined(NO_TAP)
# if !HAVE_FREEBIND
" NO_FREEBIND"
# endif //!HAVE_FREEBIND

77
src/tap-windows.h Normal file
View File

@ -0,0 +1,77 @@
/*
* TAP-Windows -- A kernel driver to provide virtual tap
* device functionality on Windows.
*
* This code was inspired by the CIPE-Win32 driver by Damion K. Wilson.
*
* This source code is Copyright (C) 2002-2014 OpenVPN Technologies, Inc.,
* and is released under the GPL version 2 (see below). This particular file
* (tap-windows.h) is also licensed using the MIT license (see COPYRIGHT.MIT).
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2
* as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program (see the file COPYING included with this
* distribution); if not, write to the Free Software Foundation, Inc.,
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef __TAP_WIN_H
#define __TAP_WIN_H
/*
* =============
* TAP IOCTLs
* =============
*/
#define TAP_WIN_CONTROL_CODE(request,method) \
CTL_CODE (FILE_DEVICE_UNKNOWN, request, method, FILE_ANY_ACCESS)
/* Present in 8.1 */
#define TAP_WIN_IOCTL_GET_MAC TAP_WIN_CONTROL_CODE (1, METHOD_BUFFERED)
#define TAP_WIN_IOCTL_GET_VERSION TAP_WIN_CONTROL_CODE (2, METHOD_BUFFERED)
#define TAP_WIN_IOCTL_GET_MTU TAP_WIN_CONTROL_CODE (3, METHOD_BUFFERED)
#define TAP_WIN_IOCTL_GET_INFO TAP_WIN_CONTROL_CODE (4, METHOD_BUFFERED)
#define TAP_WIN_IOCTL_CONFIG_POINT_TO_POINT TAP_WIN_CONTROL_CODE (5, METHOD_BUFFERED)
#define TAP_WIN_IOCTL_SET_MEDIA_STATUS TAP_WIN_CONTROL_CODE (6, METHOD_BUFFERED)
#define TAP_WIN_IOCTL_CONFIG_DHCP_MASQ TAP_WIN_CONTROL_CODE (7, METHOD_BUFFERED)
#define TAP_WIN_IOCTL_GET_LOG_LINE TAP_WIN_CONTROL_CODE (8, METHOD_BUFFERED)
#define TAP_WIN_IOCTL_CONFIG_DHCP_SET_OPT TAP_WIN_CONTROL_CODE (9, METHOD_BUFFERED)
/* Added in 8.2 */
/* obsoletes TAP_WIN_IOCTL_CONFIG_POINT_TO_POINT */
#define TAP_WIN_IOCTL_CONFIG_TUN TAP_WIN_CONTROL_CODE (10, METHOD_BUFFERED)
/*
* =================
* Registry keys
* =================
*/
#define ADAPTER_KEY "SYSTEM\\CurrentControlSet\\Control\\Class\\{4D36E972-E325-11CE-BFC1-08002BE10318}"
#define NETWORK_CONNECTIONS_KEY "SYSTEM\\CurrentControlSet\\Control\\Network\\{4D36E972-E325-11CE-BFC1-08002BE10318}"
/*
* ======================
* Filesystem prefixes
* ======================
*/
#define USERMODEDEVICEDIR "\\\\.\\Global\\"
#define SYSDEVICEDIR "\\Device\\"
#define USERDEVICEDIR "\\DosDevices\\Global\\"
#define TAP_WIN_SUFFIX ".tap"
#endif // __TAP_WIN_H

View File

@ -227,6 +227,10 @@ typedef struct __packed
#if (defined(_WIN32) || defined(__CYGWIN__)) && !defined(NO_SOCKETS)
#define _NTSERVICE
#else
#ifndef NO_TAP
#define NO_TAP
#endif
#endif
#if (defined(__CYGWIN__) || defined(_WIN32) || defined(NO_SOCKETS)) && !defined(NO_SIGHUP)

View File

@ -854,7 +854,7 @@ int SendActivationRequest(const RpcCtx sock, RESPONSE *baseResponse, REQUEST *ba
else
request = CreateRequestV6(&requestSize, baseRequest);
if (!(status = rpcSendRequest(sock, request, requestSize, &response, &responseSize)))
if (!((status = rpcSendRequest(sock, request, requestSize, &response, &responseSize))))
{
if (LE16(((RESPONSE*)(response))->MajorVer) == 4)
{

View File

@ -80,7 +80,11 @@
#include "ntservice.h"
#include "helpers.h"
static const char* const optstring = "N:B:m:t:w:0:3:6:H:A:R:u:g:L:p:i:P:l:r:U:W:C:c:F:o:T:K:E:M:j:SseDdVvqkZ";
#ifndef NO_TAP
#include "wintap.h"
#endif
static const char* const optstring = "N:B:m:t:w:0:3:6:H:A:R:u:g:L:p:i:P:l:r:U:W:C:c:F:O:o:T:K:E:M:j:SseDdVvqkZ";
#if !defined(NO_SOCKETS) && !defined(USE_MSRPC) && !defined(SIMPLE_SOCKETS)
static uint_fast8_t maxsockets = 0;
@ -105,6 +109,10 @@ static const char *fn_ini = INI_FILE;
static const char *fn_ini = NULL;
#endif // !INI_FILE
#ifndef NO_TAP
char* tapArgument = NULL;
#endif // NO_TAP
static const char* IniFileErrorMessage = "";
char* IniFileErrorBuffer = NULL;
#define INIFILE_ERROR_BUFFERSIZE 256
@ -115,6 +123,9 @@ static IniFileParameter_t IniFileParameterList[] =
{ "Office2010", INI_PARAM_OFFICE2010 },
{ "Office2013", INI_PARAM_OFFICE2013 },
{ "Office2016", INI_PARAM_OFFICE2016 },
# ifndef NO_TAP
{ "VPN", INI_PARAM_VPN },
# endif // NO_TAP
# ifndef NO_EXTERNAL_DATA
{ "KmsData", INI_PARAM_DATA_FILE },
# endif // NO_EXTERNAL_DATA
@ -281,6 +292,9 @@ static __noreturn void usage()
# endif // USE_MSRPC
# endif // !HAVE_GETIFADDR
# endif // !defined(NO_PRIVATE_IP_DETECT)
# ifndef NO_TAP
" -O <v>[=<a>][/<c>]\tuse VPN adapter <v> with IPv4 address <a> and CIDR <c>\n"
# endif
# ifndef NO_SOCKETS
# if !defined(USE_MSRPC) && !defined(SIMPLE_SOCKETS)
" -L <address>[:<port>]\tlisten on IP address <address> with optional <port>\n"
@ -368,43 +382,8 @@ static __noreturn void usage()
#ifndef NO_CUSTOM_INTERVALS
// Convert time span strings (e.g. "2h", "5w") to minutes
__pure static DWORD timeSpanString2Minutes(const char *const restrict argument)
{
char *unitId;
long long val = vlmcsd_strtoll(argument, &unitId, 10);
switch (toupper((int)*unitId))
{
case 0:
case 'M':
break;
case 'H':
val *= 60;
break;
case 'D':
val *= 60 * 24;
break;
case 'W':
val *= 60 * 24 * 7;
break;
case 'S':
val /= 60;
break;
default:
return 0;
}
if (val < 1) val = 1;
if (val > UINT_MAX) val = UINT_MAX;
return (DWORD)val;
}
#ifndef NO_INI_FILE
__pure static BOOL getTimeSpanFromIniFile(DWORD* result, const char *const restrict argument)
{
DWORD val = timeSpanString2Minutes(argument);
@ -417,12 +396,13 @@ __pure static BOOL getTimeSpanFromIniFile(DWORD* result, const char *const restr
*result = val;
return TRUE;
}
#endif // NO_INI_FILE
__pure static DWORD getTimeSpanFromCommandLine(const char *const restrict optarg, const char optchar)
{
long long val = timeSpanString2Minutes(optarg);
DWORD val = timeSpanString2Minutes(optarg);
if (!val)
{
@ -430,7 +410,7 @@ __pure static DWORD getTimeSpanFromCommandLine(const char *const restrict optarg
exit(VLMCSD_EINVAL);
}
return (DWORD)val;
return val;
}
#endif // NO_CUSTOM_INTERVALS
@ -569,6 +549,14 @@ static BOOL setIniFileParameter(uint_fast8_t id, const char *const iniarg)
setHwIdFromIniFileLine(&s, EPID_INDEX_OFFICE2016);
break;
# ifndef NO_TAP
case INI_PARAM_VPN:
tapArgument = (char*)vlmcsd_strdup(iniarg);
break;
# endif // NO_TAP
# if !defined(NO_USER_SWITCH) && !_WIN32
case INI_PARAM_GID:
@ -1078,6 +1066,15 @@ static void parseGeneralArguments() {
break;
# endif // !defined(NO_SOCKETS) && !defined(NO_SIGHUP) && !defined(_WIN32)
# ifndef NO_TAP
case 'O':
ignoreIniFileParameter(INI_PARAM_VPN);
tapArgument = getCommandLineArg(optarg);
break;
# endif // NO_TAP
# ifndef NO_CL_PIDS
case 'w':
@ -1413,16 +1410,16 @@ static void writePidFile()
if (fn_pid && !InetdMode)
{
FILE *_f = fopen(fn_pid, "w");
FILE *file = fopen(fn_pid, "w");
if (_f)
if (file)
{
# if _MSC_VER
fprintf(_f, "%u", (unsigned int)GetCurrentProcessId());
fprintf(file, "%u", (unsigned int)GetCurrentProcessId());
# else
fprintf(_f, "%u", (unsigned int)getpid());
fprintf(file, "%u", (unsigned int)getpid());
# endif
fclose(_f);
fclose(file);
}
# ifndef NO_LOG
@ -1647,10 +1644,6 @@ int setupListeningSockets()
int server_main(int argc, CARGV argv)
{
# if !defined(NO_RANDOM_EPID) || !defined(NO_CL_PIDS) || !defined(NO_INI_FILE)
KmsResponseParameters = (KmsResponseParam_t*)vlmcsd_malloc(sizeof(KmsResponseParam_t) * MIN_CSVLK);
memset(KmsResponseParameters, 0, sizeof(KmsResponseParam_t) * MIN_CSVLK);
# endif // !defined(NO_RANDOM_EPID) || !defined(NO_CL_PIDS) || !defined(NO_INI_FILE)
global_argc = argc;
global_argv = argv;
@ -1672,6 +1665,11 @@ int server_main(int argc, CARGV argv)
int newmain()
{
# if !defined(NO_RANDOM_EPID) || !defined(NO_CL_PIDS) || !defined(NO_INI_FILE)
KmsResponseParameters = (KmsResponseParam_t*)vlmcsd_malloc(sizeof(KmsResponseParam_t) * MIN_CSVLK);
memset(KmsResponseParameters, 0, sizeof(KmsResponseParam_t) * MIN_CSVLK);
# endif // !defined(NO_RANDOM_EPID) || !defined(NO_CL_PIDS) || !defined(NO_INI_FILE)
// Initialize thread synchronization objects for Windows and Cygwin
# ifdef USE_THREADS
@ -1769,6 +1767,10 @@ int newmain()
return NtServiceInstallation(installService, ServiceUser, ServicePassword);
# endif // _NTSERVICE
# ifndef NO_TAP
if (tapArgument && !InetdMode) startTap(tapArgument);
# endif // NO_TAP
# if !defined(NO_SOCKETS) && !defined(USE_MSRPC)
if (!InetdMode)
{

View File

@ -57,6 +57,7 @@ int server_main(int argc, CARGV argv);
#define INI_PARAM_MAINTAIN_CLIENTS 26
#define INI_PARAM_START_EMPTY 27
#define INI_PARAM_DATA_FILE 28
#define INI_PARAM_VPN 29
#define INI_FILE_PASS_1 1
#define INI_FILE_PASS_2 2

367
src/wintap.c Normal file
View File

@ -0,0 +1,367 @@
#ifndef _CRT_SECURE_NO_WARNINGS
#define _CRT_SECURE_NO_WARNINGS
#endif
#ifndef CONFIG
#define CONFIG "config.h"
#endif // CONFIG
#include CONFIG
#include "helpers.h"
#include "wintap.h"
#ifndef NO_TAP
#include "types.h"
#include "endian.h"
#include "output.h"
#include "tap-windows.h"
#include <iphlpapi.h>
static char* szIpAddress = "10.10.10.9";
static char* szMask = "30";
static char* szTapName;
static char *ActiveTapName, *AdapterClass;
static char* szLeaseDuration = "1d";
static uint32_t IpAddress, Mask, Network, Broadcast, DhcpServer; // These are host-endian (=little-endian) for easier calculations
static uint32_t Mtu;
static uint_fast8_t Cidr;
static HANDLE TapHandle;
static TapDriverVersion_t DriverVersion;
static IpPacket_t* IpPacket;
static uint32_t DhcpLeaseDuration;
static BOOL isAddressAssigned()
{
PMIB_IPADDRTABLE pIPAddrTable;
DWORD dwSize = 0;
BOOL result = FALSE;
pIPAddrTable = (PMIB_IPADDRTABLE)vlmcsd_malloc(sizeof(MIB_IPADDRTABLE));
DWORD status = GetIpAddrTable(pIPAddrTable, &dwSize, 0);
free(pIPAddrTable);
if (status != ERROR_INSUFFICIENT_BUFFER) return FALSE;
pIPAddrTable = (MIB_IPADDRTABLE *)vlmcsd_malloc(dwSize);
if (GetIpAddrTable(pIPAddrTable, &dwSize, 0))
{
free(pIPAddrTable);
return FALSE;
}
PMIB_IPADDRROW row;
for (row = pIPAddrTable->table; row < pIPAddrTable->table + pIPAddrTable->dwNumEntries; row++)
{
if (
row->dwAddr == BE32(IpAddress) &&
!(row->wType & (MIB_IPADDR_DELETED | MIB_IPADDR_DISCONNECTED | MIB_IPADDR_TRANSIENT))
)
{
result = TRUE;
break;
}
}
free(pIPAddrTable);
return result;
}
static void parseTapArgument(char* argument)
{
char* equalsignPosition = strchr(argument, (int)'=');
char* slashPosition = strchr(argument, (int)'/');
char* colonPosition = strchr(argument, (int)':');
szTapName = argument;
if (equalsignPosition)
{
*equalsignPosition = 0;
szIpAddress = equalsignPosition + 1;
}
if (slashPosition)
{
*slashPosition = 0;
szMask = slashPosition + 1;
}
if (colonPosition)
{
*colonPosition = 0;
szLeaseDuration = colonPosition + 1;
}
IpAddress = BE32(inet_addr(szIpAddress));
if (IpAddress == BE32(INADDR_NONE))
{
printerrorf("Fatal: %s is not a valid IPv4 address\n", szIpAddress);
exit(VLMCSD_EINVAL);
}
char* next;
Cidr = (uint8_t)strtol(szMask, &next, 10);
if (*next || Cidr < 8 || Cidr > 30)
{
printerrorf("Fatal: /%s is not a valid CIDR mask between /8 and /30\n", szMask);
exit(VLMCSD_EINVAL);
}
if (!((DhcpLeaseDuration = timeSpanString2Seconds(szLeaseDuration))))
{
printerrorf("Fatal: No valid time span specified in option -%c.\n", 'O');
exit(VLMCSD_EINVAL);
}
Mask = (uint32_t)~(UINT_MAX >> Cidr);
Network = IpAddress & Mask;
Broadcast = IpAddress | ~Mask;
DhcpServer = IpAddress + 1;
if (IpAddress <= Network || IpAddress + 1 >= Broadcast)
{
uint32_t lowerIpBE = BE32(Network + 1);
uint32_t upperIpBE = BE32(Broadcast - 2);
const char* szLower = vlmcsd_strdup(inet_ntoa(*(struct in_addr*)&lowerIpBE));
const char* szUpper = vlmcsd_strdup(inet_ntoa(*(struct in_addr*)&upperIpBE));
printerrorf("Fatal: For this subnet the IPv4 address must be ");
if (lowerIpBE == upperIpBE)
{
printerrorf("%s\n", szLower);
}
else
{
printerrorf("between %s and %s\n", szLower, szUpper);
}
exit(VLMCSD_EINVAL);
}
}
__noreturn static void WinErrorExit(DWORD error)
{
printerrorf("Registry read error: %s\n", win_strerror((int)error));
exit(error);
}
static HANDLE OpenTapHandle()
{
HANDLE handle = INVALID_HANDLE_VALUE;
HKEY regAdapterKey;
DWORD regResult;
if ((regResult = RegOpenKeyEx(HKEY_LOCAL_MACHINE, ADAPTER_KEY, 0, KEY_READ | KEY_WOW64_64KEY, &regAdapterKey)) != ERROR_SUCCESS)
{
WinErrorExit(regResult);
}
char subkeyName[TAP_REGISTRY_DATA_SIZE];
DWORD i, subKeySize = sizeof(subkeyName);
for (i = 0; (regResult = RegEnumKeyEx(regAdapterKey, i, subkeyName, &subKeySize, NULL, NULL, NULL, NULL)) != ERROR_NO_MORE_ITEMS; i++)
{
HKEY regSubKey;
DWORD type, regDataSize;
char regData[TAP_REGISTRY_DATA_SIZE];
if (regResult) WinErrorExit(regResult);
if ((regResult = RegOpenKeyEx(regAdapterKey, subkeyName, 0, KEY_READ | KEY_WOW64_64KEY, &regSubKey)) == ERROR_SUCCESS)
{
regDataSize = sizeof(regData);
if (RegQueryValueEx(regSubKey, "ComponentId", NULL, &type, (LPBYTE)regData, &regDataSize) == ERROR_SUCCESS)
{
if (
type == REG_SZ &&
(
!strncmp(regData, "tap0801", sizeof(regData)) ||
!strncmp(regData, "tap0901", sizeof(regData)) ||
!strncmp(regData, "TEAMVIEWERVPN", sizeof(regData))
)
)
{
AdapterClass = vlmcsd_strdup(regData);
regDataSize = sizeof(regData);
if (RegQueryValueEx(regSubKey, "NetCfgInstanceId", NULL, &type, (LPBYTE)regData, &regDataSize) == ERROR_SUCCESS && type == REG_SZ)
{
HKEY connectionKey;
char connectionKeyName[TAP_REGISTRY_DATA_SIZE];
strncpy(connectionKeyName, NETWORK_CONNECTIONS_KEY "\\", sizeof(connectionKeyName));
strncat(connectionKeyName, regData, sizeof(connectionKeyName));
strncat(connectionKeyName, "\\Connection", sizeof(connectionKeyName));
if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, connectionKeyName, 0, KEY_READ | KEY_WOW64_64KEY, &connectionKey) == ERROR_SUCCESS)
{
char deviceName[TAP_REGISTRY_DATA_SIZE];
regDataSize = sizeof(deviceName);
if (RegQueryValueEx(connectionKey, "Name", NULL, &type, (LPBYTE)deviceName, &regDataSize) == ERROR_SUCCESS && type == REG_SZ)
{
if (!strcmp(szTapName, ".") || !strncasecmp(szTapName, deviceName, sizeof(deviceName)))
{
ActiveTapName = vlmcsd_strdup(deviceName);
strncpy(deviceName, USERMODEDEVICEDIR, sizeof(deviceName));
strncat(deviceName, regData, sizeof(deviceName));
strncat(deviceName, strcmp(AdapterClass, "TEAMVIEWERVPN") ? TAP_WIN_SUFFIX : ".dgt", sizeof(deviceName));
handle = CreateFile(deviceName, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_SYSTEM, NULL);
}
}
}
RegCloseKey(connectionKey);
}
if (handle == INVALID_HANDLE_VALUE) free(AdapterClass);
}
}
}
RegCloseKey(regSubKey);
subKeySize = sizeof(subkeyName);
if (handle != INVALID_HANDLE_VALUE) break;
}
RegCloseKey(regAdapterKey);
if (handle == INVALID_HANDLE_VALUE)
{
printerrorf("Fatal: No compatible VPN adapter");
if (!strcmp(szTapName, "."))
{
printerrorf("s");
}
else
{
printerrorf(" with name \"%s\"", szTapName);
}
printerrorf(" available for use\n");
exit(ERROR_DEVICE_NOT_AVAILABLE);
}
return handle;
}
static int DevCtl(DWORD code, void* data, DWORD len)
{
if (!DeviceIoControl(TapHandle, code, data, len, data, len, &len, NULL))
{
DWORD error = GetLastError();
printerrorf("Fatal: VPN adapter error: %s\n", win_strerror(error));
exit(error);
}
return len;
}
static DWORD WINAPI TapMirror(LPVOID data)
{
while (TRUE)
{
DWORD bytesRead, bytesWritten;
if (!ReadFile(TapHandle, IpPacket, Mtu, &bytesRead, NULL)) break;
uint32_t temp = IpPacket->ip_src;
IpPacket->ip_src = IpPacket->ip_dst;
IpPacket->ip_dst = temp;
if (!WriteFile(TapHandle, IpPacket, bytesRead, &bytesWritten, NULL)) break;
# if !defined(NO_LOG) && defined(_PEDANTIC)
if (bytesRead != bytesWritten) logger("Warning: VPN device \"%s\": %u bytes could not be written\n", ActiveTapName, bytesRead - bytesWritten);
# endif // !defined(NO_LOG) && defined(_PEDANTIC)
}
DWORD error = GetLastError();
# ifndef NO_LOG
logger("Warning: VPN thread for device \"%s\" exiting: %s\n", ActiveTapName, win_strerror(error));
# endif // NO_LOG
free(ActiveTapName);
CloseHandle(TapHandle);
return error;
}
void startTap(char* const argument)
{
if (!strcmp(argument, "-")) return;
parseTapArgument(argument);
TapHandle = OpenTapHandle();
// Get MTU and driver version
DevCtl(TAP_WIN_IOCTL_GET_MTU, &Mtu, sizeof(Mtu));
DevCtl(TAP_WIN_IOCTL_GET_VERSION, &DriverVersion, sizeof(DriverVersion));
// Configure TUN mode
TapConfigTun_t tapTunCfg;
tapTunCfg.Address.s_addr = BE32(IpAddress);
tapTunCfg.Network.s_addr = BE32(Network);
tapTunCfg.Mask.s_addr = BE32(Mask);
DevCtl(TAP_WIN_IOCTL_CONFIG_TUN, &tapTunCfg, sizeof(tapTunCfg));
// Setup the drivers internal DHCP server
TapConfigDhcp_t tapDhcpCfg;
tapDhcpCfg.Address.s_addr = BE32(IpAddress);
tapDhcpCfg.Mask.s_addr = BE32(Mask);
tapDhcpCfg.DhcpServer.s_addr = BE32(IpAddress + 1);
tapDhcpCfg.LeaseDuration = DhcpLeaseDuration;
DevCtl(TAP_WIN_IOCTL_CONFIG_DHCP_MASQ, &tapDhcpCfg, sizeof(tapDhcpCfg));
// Connect the virtual network cable
BOOL isCableConnected = TRUE;
DevCtl(TAP_WIN_IOCTL_SET_MEDIA_STATUS, &isCableConnected, sizeof(isCableConnected));
// Allocate buffer and start mirror thread
IpPacket = (IpPacket_t*)vlmcsd_malloc(Mtu);
HANDLE threadHandle = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)TapMirror, NULL, 0, NULL);
if (!threadHandle)
{
DWORD error = GetLastError();
printerrorf("Fatal: Unable to start VPN thread: %s\n", win_strerror(error));
exit(error);
}
CloseHandle(threadHandle);
# ifndef NO_LOG
logger("%s %u.%u.%u device \"%s\" started\n", AdapterClass, DriverVersion.Major, DriverVersion.Minor, DriverVersion.Build, ActiveTapName);
# endif // NO_LOG
DWORD i;
BOOL isAssigned;
// Wait up to 4 seconds until the IP address is up and running
// so vlmcsd can actually bind to and listen on it
for (i = 0; !((isAssigned = isAddressAssigned())) && i < 20; i++) Sleep(200);
if (!isAssigned)
{
printerrorf("Warning: IPv4 address %s not assigned\n", szIpAddress);
}
else
{
# ifndef NO_LOG
logger("IPv4 address %s assigned\n", szIpAddress);
# endif // NO_LOG
}
}
#endif // NO_TAP

50
src/wintap.h Normal file
View File

@ -0,0 +1,50 @@
#ifndef __WINTAP_H
#define __WINTAP_H
#define TAP_REGISTRY_DATA_SIZE 256
// Network-Endian (= Big-Endian)
typedef struct TapConfigTun
{
struct in_addr Address;
struct in_addr Network;
struct in_addr Mask;
} TapConfigTun_t, *PTapConfigTun_t;
// Network-Endian (= Big-Endian), except LeaseDuration
typedef struct TapConfigDhcp
{
struct in_addr Address;
struct in_addr Mask;
struct in_addr DhcpServer;
uint32_t LeaseDuration; // Host-Endian (=Little-Endian). Anything else is Big-Endian
} TapConfigDhcp_t, *PTapConfigDhcp_t;
typedef struct TapDriverVersion
{
uint32_t Major;
uint32_t Minor;
uint32_t Build;
uint32_t Revision;
} TapDriverVersion_t, *PTapDriverVersion_t;
// Network-Endian (= Big-Endian)
typedef struct IpPacket {
uint8_t ip_hl : 4, /* header length */
ip_v : 4; /* version */
uint8_t ip_tos; /* type of service */
int16_t ip_len; /* total length */
uint16_t ip_id; /* identification */
int16_t ip_off; /* fragment offset field */
uint8_t ip_ttl; /* time to live */
uint8_t ip_p; /* protocol */
uint16_t ip_sum; /* checksum */
uint32_t ip_src, ip_dst; /* source and dest address */
uint8_t payload[0];
} IpPacket_t, *PIpPacket_t;
void startTap(char* const argument);
#endif //__WINTAP_H