diff --git a/Installer/Installer.vdproj b/Installer/Installer.vdproj index bc9e283..57eebb7 100644 --- a/Installer/Installer.vdproj +++ b/Installer/Installer.vdproj @@ -76,12 +76,6 @@ "Entry" { "MsmKey" = "8:_UNDEFINED" - "OwnerKey" = "8:_DDDEC90D22B81D6B9D637B1C197520B4" - "MsmSig" = "8:_UNDEFINED" - } - "Entry" - { - "MsmKey" = "8:_UNDEFINED" "OwnerKey" = "8:_9C849F5EE1DB4634B3B8ABAEAD8840E3" "MsmSig" = "8:_UNDEFINED" } @@ -91,6 +85,12 @@ "OwnerKey" = "8:_92E0C26999D59D33D0500624357FF7A1" "MsmSig" = "8:_UNDEFINED" } + "Entry" + { + "MsmKey" = "8:_UNDEFINED" + "OwnerKey" = "8:_DDDEC90D22B81D6B9D637B1C197520B4" + "MsmSig" = "8:_UNDEFINED" + } } "Configurations" { @@ -109,6 +109,27 @@ "PrivateKeyFile" = "8:" "TimeStampServer" = "8:" "InstallerBootstrapper" = "3:2" + "BootstrapperCfg:{63ACBE69-63AA-4F98-B2B6-99F9E24495F2}" + { + "Enabled" = "11:TRUE" + "PromptEnabled" = "11:TRUE" + "PrerequisitesLocation" = "2:1" + "Url" = "8:" + "ComponentsUrl" = "8:" + "Items" + { + "{EDC2488A-8267-493A-A98E-7D9C3B36CDF3}:.NETFramework,Version=v4.7.2" + { + "Name" = "8:Microsoft .NET Framework 4.7.2 (x86 和 x64)" + "ProductCode" = "8:.NETFramework,Version=v4.7.2" + } + "{EDC2488A-8267-493A-A98E-7D9C3B36CDF3}:Microsoft.Visual.C++.14.0.x64" + { + "Name" = "8:Visual C++ \"14\" Runtime Libraries (x64)" + "ProductCode" = "8:Microsoft.Visual.C++.14.0.x64" + } + } + } } "Release" { @@ -125,6 +146,14 @@ "PrivateKeyFile" = "8:" "TimeStampServer" = "8:" "InstallerBootstrapper" = "3:2" + "BootstrapperCfg:{63ACBE69-63AA-4F98-B2B6-99F9E24495F2}" + { + "Enabled" = "11:TRUE" + "PromptEnabled" = "11:TRUE" + "PrerequisitesLocation" = "2:1" + "Url" = "8:" + "ComponentsUrl" = "8:" + } } } "Deployable" @@ -230,7 +259,7 @@ "SharedLegacy" = "11:FALSE" "PackageAs" = "3:1" "Register" = "3:1" - "Exclude" = "11:FALSE" + "Exclude" = "11:TRUE" "IsDependency" = "11:TRUE" "IsolateTo" = "8:" } diff --git a/NetTunnelSDK/NetTunnelSDK.aps b/NetTunnelSDK/NetTunnelSDK.aps new file mode 100644 index 0000000..4041241 Binary files /dev/null and b/NetTunnelSDK/NetTunnelSDK.aps differ diff --git a/NetTunnelSDK/NetTunnelSDK.rc b/NetTunnelSDK/NetTunnelSDK.rc new file mode 100644 index 0000000..f035925 Binary files /dev/null and b/NetTunnelSDK/NetTunnelSDK.rc differ diff --git a/NetTunnelSDK/NetTunnelSDK.vcxproj b/NetTunnelSDK/NetTunnelSDK.vcxproj index c00594a..51422c8 100644 --- a/NetTunnelSDK/NetTunnelSDK.vcxproj +++ b/NetTunnelSDK/NetTunnelSDK.vcxproj @@ -152,11 +152,14 @@ + + + @@ -174,6 +177,11 @@ + + + + + diff --git a/NetTunnelSDK/NetTunnelSDK.vcxproj.filters b/NetTunnelSDK/NetTunnelSDK.vcxproj.filters index ddc8895..6239222 100644 --- a/NetTunnelSDK/NetTunnelSDK.vcxproj.filters +++ b/NetTunnelSDK/NetTunnelSDK.vcxproj.filters @@ -13,6 +13,9 @@ {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms + + {1111b68b-34f2-49fa-8116-de5ae65603b6} + @@ -36,6 +39,9 @@ 头文件 + + 头文件 + @@ -56,8 +62,23 @@ 源文件 + + 源文件\crypto + + + 源文件\crypto + + + 资源文件 + + + + + + 资源文件 + \ No newline at end of file diff --git a/NetTunnelSDK/crypto.cpp b/NetTunnelSDK/crypto.cpp new file mode 100644 index 0000000..1989e1c --- /dev/null +++ b/NetTunnelSDK/crypto.cpp @@ -0,0 +1,9 @@ +#include "pch.h" + +#include "tunnel.h" +#include "usrerr.h" +#include "misc.h" + +#include +#include +#include diff --git a/NetTunnelSDK/globalcfg.h b/NetTunnelSDK/globalcfg.h index 6b0c041..1c5305e 100644 --- a/NetTunnelSDK/globalcfg.h +++ b/NetTunnelSDK/globalcfg.h @@ -22,6 +22,7 @@ typedef struct { * @brief SDK 全局配置项 */ typedef struct { + TCHAR systemDirectory[MAX_PATH]; ///< 操作系统目录 TCHAR workDirectory[MAX_PATH]; ///< SDK 当前工作目录 PROTO_CRYPTO_TYPE proCryptoType; ///< 协议加密类型 TCHAR proKeyBuf[256]; ///< 协议加密秘钥 diff --git a/NetTunnelSDK/hashdigest.cpp b/NetTunnelSDK/hashdigest.cpp new file mode 100644 index 0000000..2ecd91e --- /dev/null +++ b/NetTunnelSDK/hashdigest.cpp @@ -0,0 +1,159 @@ +#include "pch.h" +#include "tunnel.h" +#include "usrerr.h" +#include "misc.h" + +#include +#include +#include + +#pragma comment(lib, "Bcrypt.lib") + +//#define NT_SUCCESS(Status) (((NTSTATUS)(Status)) >= 0) +#define NT_FAILED(s) (((NTSTATUS)(s)) < 0) +//#define STATUS_UNSUCCESSFUL ((NTSTATUS)0xC0000001L) + +static const LPCWSTR g_BcryptHash[] = { + BCRYPT_MD2_ALGORITHM, + BCRYPT_MD4_ALGORITHM, + BCRYPT_MD5_ALGORITHM, + BCRYPT_SHA1_ALGORITHM, + BCRYPT_SHA256_ALGORITHM, + BCRYPT_SHA384_ALGORITHM, + BCRYPT_SHA512_ALGORITHM, +}; + +int CalcFileHash(const HASH_TYPE type, const TCHAR *pPath, TCHAR outHash[]) { + HANDLE hFile; + BYTE rgbFile[1024]; + DWORD cbRead = 0; + BCRYPT_ALG_HANDLE hAlg = nullptr; + BCRYPT_HASH_HANDLE hHash = nullptr; + NTSTATUS status; + DWORD cbData = 0, cbHash = 0, cbHashObject = 0; + PBYTE pbHashObject; + PBYTE pbHash; + + if (pPath == nullptr) { + SPDLOG_ERROR("Input pPath params error: {0}", pPath); + return -ERR_INPUT_PARAMS; + } + + if (!PathFileExists(pPath)) { + SPDLOG_ERROR("File \'{0}\' not found.", pPath); + return -ERR_ITEM_UNEXISTS; + } + + hFile = CreateFile(pPath, + GENERIC_READ, + FILE_SHARE_READ, + nullptr, + OPEN_EXISTING, + FILE_FLAG_SEQUENTIAL_SCAN, + nullptr); + + if (INVALID_HANDLE_VALUE == hFile) { + SPDLOG_ERROR("Error opening file %s\nError: {0}", pPath, GetLastError()); + return -ERR_OPEN_FILE; + } + + //open an algorithm handle + if (NT_FAILED(status = BCryptOpenAlgorithmProvider(&hAlg, g_BcryptHash[type], nullptr, 0))) { + SPDLOG_ERROR(TEXT("Error {0} returned by BCryptOpenAlgorithmProvider"), status); + CloseHandle(hFile); + return -ERR_BCRYPT_OPEN; + } + + //calculate the size of the buffer to hold the hash object + if (NT_FAILED(status = BCryptGetProperty(hAlg, + BCRYPT_OBJECT_LENGTH, + reinterpret_cast(&cbHashObject), + sizeof(DWORD), + &cbData, + 0))) { + SPDLOG_ERROR(TEXT("Error {0} returned by BCryptGetProperty"), status); + CloseHandle(hFile); + BCryptCloseAlgorithmProvider(hAlg, 0); + return -ERR_BCRYPT_GETPROPERTY; + } + + //allocate the hash object on the heap + pbHashObject = static_cast(HeapAlloc(GetProcessHeap(), 0, cbHashObject)); + if (nullptr == pbHashObject) { + SPDLOG_ERROR(TEXT("Malloc {0} bytes memory error"), cbHashObject); + CloseHandle(hFile); + BCryptCloseAlgorithmProvider(hAlg, 0); + return -ERR_MALLOC_MEMORY; + } + + //calculate the length of the hash + if (NT_FAILED(status = BCryptGetProperty(hAlg, + BCRYPT_HASH_LENGTH, + reinterpret_cast(&cbHash), + sizeof(DWORD), + &cbData, + 0))) { + SPDLOG_ERROR(TEXT("Error {0} returned by BCryptGetProperty"), status); + CloseHandle(hFile); + BCryptCloseAlgorithmProvider(hAlg, 0); + HeapFree(GetProcessHeap(), 0, pbHashObject); + return -ERR_BCRYPT_GETPROPERTY; + } + + //allocate the hash buffer on the heap + pbHash = static_cast(HeapAlloc(GetProcessHeap(), 0, cbHash)); + if (nullptr == pbHash) { + SPDLOG_ERROR(TEXT("Malloc {0} bytes memory error"), cbHash); + CloseHandle(hFile); + BCryptCloseAlgorithmProvider(hAlg, 0); + HeapFree(GetProcessHeap(), 0, pbHashObject); + return -ERR_MALLOC_MEMORY; + } + + //create a hash + if (NT_FAILED(status = BCryptCreateHash(hAlg, &hHash, pbHashObject, cbHashObject, nullptr, 0, 0))) { + SPDLOG_ERROR(TEXT("Error {0} returned by BCryptCreateHash"), status); + CloseHandle(hFile); + BCryptCloseAlgorithmProvider(hAlg, 0); + HeapFree(GetProcessHeap(), 0, pbHashObject); + HeapFree(GetProcessHeap(), 0, pbHash); + return -ERR_BCRYPT_CREATEHASH; + } + + while (ReadFile(hFile, rgbFile, 1024, &cbRead, nullptr)) { + if (0 == cbRead) { + break; + } + + if (NT_FAILED(status = BCryptHashData(hHash, rgbFile, cbRead, 0))) { + SPDLOG_ERROR(TEXT("Error {0} returned by BCryptHashData"), status); + CloseHandle(hFile); + BCryptCloseAlgorithmProvider(hAlg, 0); + BCryptDestroyHash(hHash); + HeapFree(GetProcessHeap(), 0, pbHashObject); + HeapFree(GetProcessHeap(), 0, pbHash); + return -ERR_BCRYPT_HASHDATA; + } + } + + //close the hash + if (NT_FAILED(status = BCryptFinishHash(hHash, pbHash, cbHash, 0))) { + SPDLOG_ERROR(TEXT("Error {0} returned by BCryptFinishHash"), status); + CloseHandle(hFile); + BCryptCloseAlgorithmProvider(hAlg, 0); + BCryptDestroyHash(hHash); + HeapFree(GetProcessHeap(), 0, pbHashObject); + HeapFree(GetProcessHeap(), 0, pbHash); + return -ERR_BCRYPT_FINISHHASH; + } + + binToHexString(outHash, pbHash, cbHash); + + BCryptCloseAlgorithmProvider(hAlg, 0); + BCryptDestroyHash(hHash); + HeapFree(GetProcessHeap(), 0, pbHashObject); + HeapFree(GetProcessHeap(), 0, pbHash); + CloseHandle(hFile); + + return ERR_SUCCESS; +} \ No newline at end of file diff --git a/NetTunnelSDK/misc.cpp b/NetTunnelSDK/misc.cpp index 21ade24..1fe2736 100644 --- a/NetTunnelSDK/misc.cpp +++ b/NetTunnelSDK/misc.cpp @@ -1,10 +1,24 @@ #include "pch.h" #include "misc.h" + #include "usrerr.h" #include #include +TCHAR *binToHexString(TCHAR *p, const unsigned char *cp, unsigned int count) { + static const TCHAR hex_asc[] = TEXT("0123456789abcdef"); + while (count) { + const unsigned char c = *cp++; + /* put lowercase hex digits */ + *p++ = static_cast(0x20 | hex_asc[c >> 4]); + *p++ = static_cast(0x20 | hex_asc[c & 0xf]); + count--; + } + + return p; +} + void RemoveTailLineBreak(TCHAR *pInputStr, int strSize) { size_t length; if (pInputStr) { @@ -25,7 +39,7 @@ int RunCommand(TCHAR *pszCmd, TCHAR *pszResultBuffer, int dwResultBufferSize, un DWORD retCode; STARTUPINFO si; PROCESS_INFORMATION pi; - SECURITY_ATTRIBUTES securityAttributes = {}; + SECURITY_ATTRIBUTES securityAttributes; if (pszCmd == nullptr) { SPDLOG_ERROR(TEXT("Input params Error: [{0}]"), pszCmd); diff --git a/NetTunnelSDK/misc.h b/NetTunnelSDK/misc.h index 255d800..58c99b0 100644 --- a/NetTunnelSDK/misc.h +++ b/NetTunnelSDK/misc.h @@ -24,9 +24,10 @@ int __cdecl NetmaskToCIDR(const TCHAR *pNetMask); */ const TCHAR *CIDRToNetmask(const UINT8 cidr); -void ShowWindowsErrorMessage(const TCHAR *pMsgHead); -void StringReplaceAll(TCHAR *pOrigin, const TCHAR *pOldStr, const TCHAR *pNewStr); -void StringRemoveAll(TCHAR *pOrigin, const TCHAR *pString); +void ShowWindowsErrorMessage(const TCHAR *pMsgHead); +void StringReplaceAll(TCHAR *pOrigin, const TCHAR *pOldStr, const TCHAR *pNewStr); +void StringRemoveAll(TCHAR *pOrigin, const TCHAR *pString); +TCHAR *binToHexString(TCHAR *p, const unsigned char *cp, unsigned int count); #ifdef __cplusplus } #endif \ No newline at end of file diff --git a/NetTunnelSDK/network.cpp b/NetTunnelSDK/network.cpp index a07f6bd..991fc5d 100644 --- a/NetTunnelSDK/network.cpp +++ b/NetTunnelSDK/network.cpp @@ -423,73 +423,71 @@ int GetAllNICInfo(PNIC_CONTENT pInfo, int *pItemCounts) { return ERR_SUCCESS; } -#if 0 -int GetAllNICInfo(PNIC_CONTENT pInfo, int *pItemCounts) { - int nRel, id = 0; - IP_ADDR_STRING *pIpAddrString; - PIP_ADAPTER_INFO pIpAdapterInfo; - unsigned long stSize; +int SetInterfacePrivate(const TCHAR *pInterfaceName, bool isPrivate) { + int ret; + TCHAR cmdBuf[MAX_PATH]; + DWORD retCode; - if (pItemCounts == nullptr || pInfo == nullptr) { - return -ERR_INPUT_PARAMS; - } - - pIpAdapterInfo = new IP_ADAPTER_INFO[NET_CARD_MAX]; - stSize = sizeof(IP_ADAPTER_INFO) * NET_CARD_MAX; - - // WIN32 API get net card information - nRel = GetAdaptersInfo(pIpAdapterInfo, &stSize); - - if (ERROR_BUFFER_OVERFLOW == nRel) { - delete[] pIpAdapterInfo; - return -ERR_MALLOC_MEMORY; - } - - PIP_ADAPTER_INFO cur = pIpAdapterInfo; - - while (cur) { - pInfo[id].InterfaceIndex = cur->Index; - StringCbCopy(pInfo[id].NetCardUUID, MAX_ADAPTER_NAME_LENGTH, cur->AdapterName); - StringCbCopy(pInfo[id].NetCardDescription, MAX_ADAPTER_DESCRIPTION_LENGTH, cur->Description); - - switch (cur->Type) { - case MIB_IF_TYPE_ETHERNET: - pIpAddrString = &(cur->IpAddressList); - StringCbCopy(pInfo[id].NetCardIpaddr, MAX_IP_LEN - 1, pIpAddrString->IpAddress.String); - StringCbCopy(pInfo[id].NetCardNetmask, MAX_IP_LEN - 1, pIpAddrString->IpMask.String); - break; - case MIB_IF_TYPE_OTHER: - case MIB_IF_TYPE_TOKENRING: - case MIB_IF_TYPE_FDDI: - case MIB_IF_TYPE_PPP: - case MIB_IF_TYPE_LOOPBACK: - case MIB_IF_TYPE_SLIP: - break; - default: // WIFI ,Unknown type - pIpAddrString = &(cur->IpAddressList); - StringCbCopy(pInfo[id].NetCardIpaddr, MAX_IP_LEN - 1, pIpAddrString->IpAddress.String); - StringCbCopy(pInfo[id].NetCardNetmask, MAX_IP_LEN - 1, pIpAddrString->IpMask.String); - break; + if (isPrivate) { + if (FAILED(StringCbPrintf( + cmdBuf, + MAX_PATH, + "PowerShell -Command \"& {Set-NetConnectionProfile -InterfaceAlias %s -NetworkCategory \"Private\"}\"", + pInterfaceName))) { + SPDLOG_ERROR("Format String Error"); + return -ERR_MEMORY_STR; + } + } else { + if (FAILED(StringCbPrintf( + cmdBuf, + MAX_PATH, + "PowerShell -Command \"& {Set-NetConnectionProfile -InterfaceAlias %s -NetworkCategory \"Public\"}\"", + pInterfaceName))) { + SPDLOG_ERROR("Format String Error"); + return -ERR_MEMORY_STR; } - - StringCbPrintf(pInfo[id].NetCardMacAddr, - 20 - 1, - "%02X:%02X:%02X:%02X:%02X:%02X", - cur->Address[0], - cur->Address[1], - cur->Address[2], - cur->Address[3], - cur->Address[4], - cur->Address[5]); - - id++; - cur = cur->Next; } - *pItemCounts = id; + if ((ret = RunCommand(cmdBuf, nullptr, 0, &retCode)) != ERR_SUCCESS) { + SPDLOG_ERROR("Run command [{0}] error: {1}", cmdBuf, ret); + return -ERR_CALL_SHELL; + } - delete[] pIpAdapterInfo; + if (retCode != 0) { + SPDLOG_ERROR("PowerShell return error({1}): {0}", cmdBuf, retCode); + return -ERR_PROCESS_RETURN; + } return ERR_SUCCESS; } -#endif \ No newline at end of file + +/** + * @brief WireGuard Windows PowerShell ԶǷװ + * @return + * - TRUE Ѿװ + * - FALSE δװ + */ +bool CustomNatPSCmdInstalled() { + TCHAR psCmdPath[MAX_PATH]; + + StringCbPrintf(psCmdPath, + MAX_PATH, + TEXT("%s\\system32\\WindowsPowerShell\\v1.0\\Modules\\wireguard"), + GetGlobalCfgInfo()->systemDirectory); + + // ж WireGuard NAT Ƿװ + if (!PathFileExists(psCmdPath)) { + if (!CreateDirectory(psCmdPath, nullptr)) { + return false; + } + } + + StringCbCat(psCmdPath, MAX_PATH, "\\wireguard.psm1"); + + if (PathFileExists(psCmdPath)) { + // ļ˵Ѿװ + return true; + } + + return false; +} \ No newline at end of file diff --git a/NetTunnelSDK/ps1/wireguard.psm1 b/NetTunnelSDK/ps1/wireguard.psm1 new file mode 100644 index 0000000..15a6f60 --- /dev/null +++ b/NetTunnelSDK/ps1/wireguard.psm1 @@ -0,0 +1,63 @@ +Function Set-NetConnectionSharing +{ + Param + ( + [Parameter(Mandatory=$true)] + [string] + $LocalConnection, + + [Parameter(Mandatory=$true)] + [bool] + $Enabled + ) + + Begin + { + $netShare = $null + + try + { + # Create a NetSharingManager object + $netShare = New-Object -ComObject HNetCfg.HNetShare + } + catch + { + # Register the HNetCfg library (once) + regsvr32 /s hnetcfg.dll + + # Create a NetSharingManager object + $netShare = New-Object -ComObject HNetCfg.HNetShare + } + } + + Process + { + #Clear Existing Share + $oldConnections = $netShare.EnumEveryConnection |? { $netShare.INetSharingConfigurationForINetConnection.Invoke($_).SharingEnabled -eq $true} + foreach($oldShared in $oldConnections) + { + $oldConfig = $netShare.INetSharingConfigurationForINetConnection.Invoke($oldShared) + $oldConfig.DisableSharing() + } + + # Find connections + $InternetConnection = Get-NetRoute | ? DestinationPrefix -eq '0.0.0.0/0' | Get-NetIPInterface | Where ConnectionState -eq 'Connected' + $publicConnection = $netShare.EnumEveryConnection |? { $netShare.NetConnectionProps.Invoke($_).Name -eq $InternetConnection.InterfaceAlias } + $privateConnection = $netShare.EnumEveryConnection |? { $netShare.NetConnectionProps.Invoke($_).Name -eq $LocalConnection } + + # Get sharing configuration + $publicConfig = $netShare.INetSharingConfigurationForINetConnection.Invoke($publicConnection) + $privateConfig = $netShare.INetSharingConfigurationForINetConnection.Invoke($privateConnection) + + if ($Enabled) + { + $publicConfig.EnableSharing(0) + $privateConfig.EnableSharing(1) + } + else + { + $publicConfig.DisableSharing() + $privateConfig.DisableSharing() + } + } +} \ No newline at end of file diff --git a/NetTunnelSDK/resource.h b/NetTunnelSDK/resource.h new file mode 100644 index 0000000..7d61926 --- /dev/null +++ b/NetTunnelSDK/resource.h @@ -0,0 +1,16 @@ +//{{NO_DEPENDENCIES}} +// Microsoft Visual C++ ɵİļ +// NetTunnelSDK.rc ʹ +// +#define IDR_TXT2 102 + +// Next default values for new objects +// +#ifdef APSTUDIO_INVOKED +#ifndef APSTUDIO_READONLY_SYMBOLS +#define _APS_NEXT_RESOURCE_VALUE 103 +#define _APS_NEXT_COMMAND_VALUE 40001 +#define _APS_NEXT_CONTROL_VALUE 1001 +#define _APS_NEXT_SYMED_VALUE 101 +#endif +#endif diff --git a/NetTunnelSDK/tunnel.cpp b/NetTunnelSDK/tunnel.cpp index 6317e92..0b9f641 100644 --- a/NetTunnelSDK/tunnel.cpp +++ b/NetTunnelSDK/tunnel.cpp @@ -1,6 +1,7 @@ #include "pch.h" #include "tunnel.h" +#include #include #include #include @@ -30,6 +31,12 @@ int TunnelSDKInitEnv(const TCHAR *pWorkDir) { spdlog::set_level(spdlog::level::off); } + if (SUCCEEDED( + SHGetFolderPath(NULL, CSIDL_WINDOWS | CSIDL_FLAG_NO_ALIAS, NULL, 0, g_globalConfig.systemDirectory))) { + SPDLOG_ERROR(TEXT("Get Windows system directory error.")); + return -ERR_ITEM_EXISTS; + } + if (pWorkDir == nullptr) { // 获取当前文件默认路径 GetCurrentDirectory(MAX_PATH, g_globalConfig.workDirectory); @@ -121,12 +128,9 @@ void TunnelLogEnable(bool enLog) { } } -int SetProtocolEncryptType(const PROTO_CRYPTO_TYPE type, const TCHAR* pProKey) -{ - if (type > CRYPTO_BASE64 && type < CRYPTO_MAX) - { - if (pProKey == nullptr || strlen(pProKey) < 8) - { +int SetProtocolEncryptType(const PROTO_CRYPTO_TYPE type, const TCHAR *pProKey) { + if (type > CRYPTO_BASE64 && type < CRYPTO_MAX) { + if (pProKey == nullptr || strlen(pProKey) < 8) { return -ERR_INPUT_PARAMS; } } @@ -134,7 +138,8 @@ int SetProtocolEncryptType(const PROTO_CRYPTO_TYPE type, const TCHAR* pProKey) g_globalConfig.proCryptoType = type; StringCbCopy(g_globalConfig.proKeyBuf, 256, pProKey); - SPDLOG_DEBUG(TEXT("Protocol crypto type: {0} with key [{1}]"), static_cast(type), + SPDLOG_DEBUG(TEXT("Protocol crypto type: {0} with key [{1}]"), + static_cast(type), pProKey ? pProKey : TEXT("")); return ERR_SUCCESS; diff --git a/NetTunnelSDK/tunnel.h b/NetTunnelSDK/tunnel.h index 2da8390..fd961d7 100644 --- a/NetTunnelSDK/tunnel.h +++ b/NetTunnelSDK/tunnel.h @@ -50,6 +50,20 @@ enum LOG_LEVEL { LOG_OFF ///< 关闭日志 }; +/** + * @brief Hash 算法类型 + * + */ +typedef enum { + HASH_MD2 = 0, ///< MD2 HASH 算法 + HASH_MD4, ///< MD4 HASH 算法 + HASH_MD5, ///< MD5 HASH 算法 + HASH_SHA1, ///< SHA1 HASH 算法 + HASH_SHA256, ///< SHA256 HASH 算法 + HASH_SHA384, ///< SHA384 HASH 算法 + HASH_SHA512 ///< SHA512 HASH 算法 +} HASH_TYPE; + /** * * @brief 本地计算机网卡信息 @@ -168,7 +182,7 @@ TUNNEL_API int __cdecl GenerateWireguardKeyPairs(TCHAR *pPubKey, int pubkeySize, /** * @brief 创建 WireGuard 服务端配置文件 - * @param pWgConfig 配置文件相关配置项 @see WGSERVER_CONFIG + * @param[in] pWgConfig 配置文件相关配置项 @see WGSERVER_CONFIG * @return 函数执行结果 0: 成功, 小于0 失败 @see USER_ERRNO * - -ERR_INPUT_PARAMS 输入参数错误 * - -ERR_MALLOC_MEMORY 分配内存失败 @@ -180,7 +194,7 @@ TUNNEL_API int __cdecl WireGuardCreateServerConfig(const PWGSERVER_CONFIG pWgCon /** * @brief 创建 WireGuard 客户端配置文件 - * @param pWgConfig 配置文件相关配置项 @see WGCLIENT_CONFIG + * @param[in] pWgConfig 配置文件相关配置项 @see WGCLIENT_CONFIG * @return 函数执行结果 0: 成功, 小于0 失败 @see USER_ERRNO * - -ERR_INPUT_PARAMS 输入参数错误 * - -ERR_MALLOC_MEMORY 分配内存失败 @@ -197,13 +211,15 @@ TUNNEL_API int __cdecl WireGuardCreateClientConfig(const PWGCLIENT_CONFIG pWgCon */ TUNNEL_API int __cdecl WireGuardInstallServerService(bool bInstall); +TUNNEL_API int __cdecl InstallWindowsNATCommand(); + /** * @brief 清理 SDK 运行资源 */ TUNNEL_API void __cdecl TunnelSDKUnInit(); /** * @brief 获取本机网卡信息 - * @param[in,out] pInfo 网卡信息 @see NIC_CONTENT + * @param[out] pInfo 网卡信息 @see NIC_CONTENT * @param[out] pItemCounts 计算机当前操作系统中网卡总数 最大值 32 * @return 函数执行结果 0: 成功, 小于0 失败 @see USER_ERRNO * - -ERR_INPUT_PARAMS 输入参数错误 @@ -214,8 +230,8 @@ TUNNEL_API int __cdecl GetAllNICInfo(PNIC_CONTENT pInfo, int *pItemCounts); /** * @brief 获取网卡接口索引编号 - * @param pInterfaceName 网卡名称 - * @param pIndex 网卡索引 + * @param[in] pInterfaceName 网卡名称 + * @param[out] pIndex 网卡索引 * @return 函数执行结果 0: 成功, 小于0 失败 @see USER_ERRNO * - -ERR_INPUT_PARAMS 输入参数错误 * - -ERR_MALLOC_MEMORY 分配内存失败 @@ -289,8 +305,8 @@ TUNNEL_API int __cdecl EnableWindowsHyperV(bool enabled); /** * @brief 开启 Windows WireGuard NAT 转发功能 - * @param pInterfaceName 网卡名称 - * @param pCidrIpaddr CIDR 网络接口地址 + * @param[in] pInterfaceName 网卡名称 + * @param[in] pCidrIpaddr CIDR 网络接口地址 * @return 函数执行结果 0: 成功, 小于0 失败 @see USER_ERRNO * - -ERR_INPUT_PARAMS 输入参数错误 * - -ERR_MEMORY_STR 字符串处理 @@ -299,6 +315,47 @@ TUNNEL_API int __cdecl EnableWindowsHyperV(bool enabled); * - ERR_SUCCESS 成功 */ TUNNEL_API int __cdecl SetNATRule(const TCHAR *pInterfaceName, const TCHAR *pCidrIpaddr); + +/** + * @brief 设置网卡为 Private/Public 模式 + * @param[in] pInterfaceName 网卡名称 + * @param[in] isPrivate + * - TRUE Private 模式 + * - FALSE Public 模式 + * @return 函数执行结果 0: 成功, 小于0 失败 @see USER_ERRNO + * - -ERR_INPUT_PARAMS 输入参数错误 + * - -ERR_MEMORY_STR 字符串处理 + * - -ERR_CALL_SHELL 调用系统命令行失败 + * - -ERR_PROCESS_RETURN 系统调用执行结束返回失败 + * - ERR_SUCCESS 成功 + */ +TUNNEL_API int __cdecl SetInterfacePrivate(const TCHAR *pInterfaceName, bool isPrivate); + +/** + * @brief WireGuard 服务 Windows PowerShell 自定义命令是否安装 + * @return + * - TRUE 已经安装 + * - FALSE 未安装 + */ +TUNNEL_API bool __cdecl CustomNatPSCmdInstalled(); + +/** + * @brief 计算文件 Hash + * @param[in] type Hash 类型 @see HASH_TYPE + * @param[in] pPath 需要计算 Hash 值的文件路径 + * @param[out] outHash 计算结果 + * @return 函数执行结果 0: 成功, 小于0 失败 @see USER_ERRNO + * - -ERR_INPUT_PARAMS 输入参数错误 + * - -ERR_ITEM_UNEXISTS 文件不存在 + * - -ERR_OPEN_FILE 打开文件失败 + * - -ERR_BCRYPT_OPEN 创建加解密算法失败 + * - -ERR_BCRYPT_GETPROPERTY 获取加解密算法属性失败 + * - -ERR_BCRYPT_CREATEHASH 创建 Hash 算法失败 + * - -ERR_BCRYPT_HASHDATA 计算 Hash 数据失败 + * - -ERR_BCRYPT_FINISHHASH 计算 Hash 结果失败 + * - ERR_SUCCESS 成功 + */ +TUNNEL_API int __cdecl CalcFileHash(const HASH_TYPE type, const TCHAR *pPath, TCHAR outHash[]); #ifdef __cplusplus } #endif \ No newline at end of file diff --git a/NetTunnelSDK/usrerr.h b/NetTunnelSDK/usrerr.h index 5b7b20d..d123411 100644 --- a/NetTunnelSDK/usrerr.h +++ b/NetTunnelSDK/usrerr.h @@ -12,6 +12,7 @@ enum USER_ERRNO { ERR_ITEM_UNEXISTS, ///< 该内容不存在 ERR_SYS_INIT, ///< 系统中断 ERR_SYS_CALL, ///< 系统调用 + ERR_CREATE_FILE, ///< 创建文件/目录失败 ERR_OPEN_FILE, ///< 打开文件失败 ERR_READ_FILE, ///< 读取文件失败 ERR_WRITE_FILE, ///< 写入文件失败 @@ -23,5 +24,10 @@ enum USER_ERRNO { ERR_MMAP_MEMORY, ///< 共享内存失败 ERR_MEMORY_STR, ///< 字符串操作失败 ERR_CREATE_PROCESS, ///< 创建进程失败 - ERR_PROCESS_RETURN ///< 进程调用返回失败 + ERR_PROCESS_RETURN, ///< 进程调用返回失败 + ERR_BCRYPT_OPEN, ///< 创建加密算法失败 + ERR_BCRYPT_GETPROPERTY, ///< 获取加密算法属性失败 + ERR_BCRYPT_CREATEHASH, ///< 创建 Hash 算法失败 + ERR_BCRYPT_HASHDATA, ///< 计算 Hash 数据失败 + ERR_BCRYPT_FINISHHASH, ///< 计算 Hash 结果失败 }; \ No newline at end of file diff --git a/NetTunnelSDK/wireguard.cpp b/NetTunnelSDK/wireguard.cpp index d6423f9..a0bbe4e 100644 --- a/NetTunnelSDK/wireguard.cpp +++ b/NetTunnelSDK/wireguard.cpp @@ -7,6 +7,7 @@ #include "globalcfg.h" #include "misc.h" +#include "resource.h" #pragma comment(lib, "Shlwapi.lib") @@ -17,6 +18,11 @@ constexpr auto WINENVBUF_SIZE = (4096); #define CFG_WGCFG_PATH TEXT("WgCfgPath") #define CFG_WG_PATH TEXT("WgExe") +/** + * @brief 安装/卸载 WireGuard 服务 + * @param[in] bInstall TRUE 安装服务, FALSE 卸载服务 + * @return 函数执行结果 0: 成功, 小于0 失败 @see USER_ERRNO + */ int WireGuardInstallServerService(bool bInstall) { TCHAR cfgVal[MAX_PATH]; DWORD retCode; @@ -29,10 +35,7 @@ int WireGuardInstallServerService(bool bInstall) { GetGlobalCfgInfo()->cfgPath); if (lstrlen(cfgVal) > 0) { - WIN32_FIND_DATA FindFileData; - const HANDLE hFind = FindFirstFile(cfgVal, &FindFileData); - - if (hFind != INVALID_HANDLE_VALUE) { + if (PathFileExists(cfgVal)) { TCHAR cmdBuf[MAX_PATH]; int ret; @@ -76,6 +79,16 @@ int WireGuardInstallServerService(bool bInstall) { } } +/** + * @brief 创建 WireGuard 客户端配置文件 + * @param[in] pWgConfig 配置文件相关配置项 @see WGCLIENT_CONFIG + * @return 函数执行结果 0: 成功, 小于0 失败 @see USER_ERRNO + * - -ERR_INPUT_PARAMS 输入参数错误 + * - -ERR_MALLOC_MEMORY 分配内存失败 + * - -ERR_OPEN_FILE 打开文件失败 + * - -ERR_MEMORY_STR 字符串处理失败 + * - ERR_SUCCESS 成功 + */ int WireGuardCreateClientConfig(const PWGCLIENT_CONFIG pWgConfig) { const size_t bufSize = 4096 * sizeof(TCHAR); const TCHAR cfgFormat[] = TEXT( @@ -188,6 +201,16 @@ int WireGuardCreateClientConfig(const PWGCLIENT_CONFIG pWgConfig) { return ERR_SUCCESS; } +/** + * @brief 创建 WireGuard 服务端配置文件 + * @param[in] pWgConfig 配置文件相关配置项 @see WGSERVER_CONFIG + * @return 函数执行结果 0: 成功, 小于0 失败 @see USER_ERRNO + * - -ERR_INPUT_PARAMS 输入参数错误 + * - -ERR_MALLOC_MEMORY 分配内存失败 + * - -ERR_OPEN_FILE 打开文件失败 + * - -ERR_MEMORY_STR 字符串处理失败 + * - ERR_SUCCESS 成功 + */ int WireGuardCreateServerConfig(const PWGSERVER_CONFIG pWgConfig) { const size_t bufSize = 4096 * sizeof(TCHAR); const TCHAR cfgFormat[] = TEXT( @@ -303,6 +326,17 @@ int WireGuardCreateServerConfig(const PWGSERVER_CONFIG pWgConfig) { return ERR_SUCCESS; } +/** + * @brief 创建 WireGuard 密钥对 + * @param[out] pPubKey 公钥缓冲区 + * @param[in] pubkeySize 公钥缓冲区大小(字节数) + * @param[out] pPrivKey 私钥缓冲区 + * @param[in] privKeySize 私钥缓冲区大小(字节数) + * @return 函数执行结果 0: 成功, 小于0 失败 @see USER_ERRNO + * - -ERR_ITEM_UNEXISTS WireGuard 未配置或未安装 + * - -ERR_CALL_SHELL 调用操作系统命令行工具失败 + * - ERR_SUCCESS 成功 + */ int GenerateWireguardKeyPairs(TCHAR *pPubKey, int pubkeySize, TCHAR *pPrivKey, int privKeySize) { int ret; DWORD retCode; @@ -347,17 +381,20 @@ int GenerateWireguardKeyPairs(TCHAR *pPubKey, int pubkeySize, TCHAR *pPrivKey, i return ERR_SUCCESS; } +/** + * @brief 设置 wireguard.exe 程序路径 + * @param[in] pPath wireguard.exe 程序路径 + * @return 函数执行结果 0: 成功, 小于0 失败 @see USER_ERRNO + * - -ERR_INPUT_PARAMS 输入参数错误 + * - -ERR_ITEM_UNEXISTS 文件不存在 + * - ERR_SUCCESS 成功 + */ int SetWireguardPath(const TCHAR *pPath) { - WIN32_FIND_DATA FindFileData; - HANDLE hFind; - if (pPath == nullptr) { return -ERR_INPUT_PARAMS; } - hFind = FindFirstFile(pPath, &FindFileData); - - if (hFind != INVALID_HANDLE_VALUE) { + if (PathFileExists(pPath)) { TCHAR wgPath[MAX_PATH]; SPDLOG_DEBUG(TEXT("Used configure file:{0}"), GetGlobalCfgInfo()->cfgPath); @@ -381,50 +418,76 @@ int SetWireguardPath(const TCHAR *pPath) { } } +/** + * @brief 查找 WireGuard 运行环境 + * @param[out] pFullPath wireguard.exe 程序路径 + * @param[in] maxSize pFullPath 缓冲区最大字节数 + * @return 函数执行结果 0: 成功, 小于0 失败 @see USER_ERRNO + * - -ERR_INPUT_PARAMS 输入参数错误 + * - -ERR_MALLOC_MEMORY 分配内存失败 + * - -ERR_FILE_NOT_EXISTS 文件不存在 + * - ERR_SUCCESS 成功 + */ int FindWireguardExe(TCHAR *pFullPath, int maxSize) { - TCHAR path[MAX_PATH]; - TCHAR wrieguardPath[MAX_PATH]; - WIN32_FIND_DATA FindFileData; - HANDLE hFind; - DWORD dwRet; - LPSTR pEnvBuf; - TCHAR *token, *p = nullptr; + TCHAR path[MAX_PATH]; + TCHAR wireguardPath[MAX_PATH]; + DWORD dwRet; + LPSTR pEnvBuf; + TCHAR *token, *p = nullptr; GetPrivateProfileString(CFG_WIREGUARD_SECTION, CFG_WIREGUARD_PATH, TEXT(""), - wrieguardPath, + wireguardPath, MAX_PATH, GetGlobalCfgInfo()->cfgPath); - hFind = FindFirstFile(wrieguardPath, &FindFileData); - if (hFind != INVALID_HANDLE_VALUE) { + if (PathFileExists(wireguardPath)) { if (pFullPath && maxSize > 0) { - StringCbCopy(pFullPath, maxSize, wrieguardPath); + StringCbCopy(pFullPath, maxSize, wireguardPath); } - StringCbCopy(GetGlobalCfgInfo()->wireguardCfg.wireguardPath, MAX_PATH, wrieguardPath); + StringCbCopy(GetGlobalCfgInfo()->wireguardCfg.wireguardPath, MAX_PATH, wireguardPath); GetGlobalCfgInfo()->wireguardCfg.wireguardExists = TRUE; - SPDLOG_DEBUG(TEXT("Ini found WireGuard at: {0}"), wrieguardPath); + SPDLOG_DEBUG(TEXT("Ini found WireGuard at: {0}"), wireguardPath); GetPrivateProfileString(CFG_WIREGUARD_SECTION, CFG_WG_PATH, TEXT(""), - wrieguardPath, + wireguardPath, MAX_PATH, GetGlobalCfgInfo()->cfgPath); - hFind = FindFirstFile(wrieguardPath, &FindFileData); - if (hFind != INVALID_HANDLE_VALUE) { - StringCbCopy(GetGlobalCfgInfo()->wireguardCfg.wgPath, MAX_PATH, wrieguardPath); + if (PathFileExists(wireguardPath)) { + StringCbCopy(GetGlobalCfgInfo()->wireguardCfg.wgPath, MAX_PATH, wireguardPath); GetGlobalCfgInfo()->wireguardCfg.wgExists = TRUE; - SPDLOG_DEBUG(TEXT("Ini found WireGuard Tools at: {0}"), wrieguardPath); + SPDLOG_DEBUG(TEXT("Ini found WireGuard Tools at: {0}"), wireguardPath); } return ERR_SUCCESS; } + StringCbCopy(wireguardPath, MAX_PATH, GetGlobalCfgInfo()->systemDirectory); + PathStripToRootA(wireguardPath); + StringCbCat(wireguardPath, MAX_PATH, TEXT("Program Files\\WireGuard\\wireguard.exe")); + + if (PathFileExists(wireguardPath)) { + // 保存路径到配置文件 + SetWireguardPath(wireguardPath); + GetGlobalCfgInfo()->wireguardCfg.wireguardExists = TRUE; + + PathRemoveFileSpec(wireguardPath); + StringCbCat(wireguardPath, MAX_PATH, TEXT("\\wg.exe")); + + if (PathFileExists(wireguardPath)) { + GetGlobalCfgInfo()->wireguardCfg.wgExists = TRUE; + } + + return ERR_SUCCESS; + } + + // 从环境变量中查找 pEnvBuf = static_cast(malloc(WINENVBUF_SIZE)); if (nullptr == pEnvBuf) { SPDLOG_ERROR(TEXT("Malloc {0} bytes memory error"), WINENVBUF_SIZE); @@ -442,7 +505,7 @@ int FindWireguardExe(TCHAR *pFullPath, int maxSize) { return -ERR_FILE_NOT_EXISTS; } } else if (WINENVBUF_SIZE < dwRet) { - LPSTR pBuf = static_cast(realloc(pEnvBuf, dwRet * sizeof(CHAR))); + const auto pBuf = static_cast(realloc(pEnvBuf, dwRet * sizeof(CHAR))); if (nullptr == pBuf) { SPDLOG_ERROR(TEXT("Malloc {0} bytes memory error"), dwRet * sizeof(CHAR)); free(pEnvBuf); @@ -464,9 +527,7 @@ int FindWireguardExe(TCHAR *pFullPath, int maxSize) { memset(path, 0, MAX_PATH); StringCbPrintfA(path, MAX_PATH, TEXT("%s\\wireguard.exe"), token); - hFind = FindFirstFile(path, &FindFileData); - - if (hFind != INVALID_HANDLE_VALUE) { + if (PathFileExists(path)) { if (pFullPath && maxSize > 0) { StringCbCopy(pFullPath, maxSize, path); } @@ -475,7 +536,7 @@ int FindWireguardExe(TCHAR *pFullPath, int maxSize) { SetWireguardPath(path); SPDLOG_DEBUG(TEXT("Path Environment found WireGuard at: {0}"), path); - StringCbCopy(GetGlobalCfgInfo()->wireguardCfg.wireguardPath, MAX_PATH, wrieguardPath); + StringCbCopy(GetGlobalCfgInfo()->wireguardCfg.wireguardPath, MAX_PATH, wireguardPath); GetGlobalCfgInfo()->wireguardCfg.wireguardExists = TRUE; memset(path, 0, MAX_PATH); @@ -483,8 +544,7 @@ int FindWireguardExe(TCHAR *pFullPath, int maxSize) { SPDLOG_DEBUG(TEXT("Find WireGuard tools at: {0}"), path); - hFind = FindFirstFile(path, &FindFileData); - if (hFind != INVALID_HANDLE_VALUE) { + if (PathFileExists(path)) { StringCbCopy(GetGlobalCfgInfo()->wireguardCfg.wgPath, MAX_PATH, path); GetGlobalCfgInfo()->wireguardCfg.wgExists = TRUE; @@ -501,4 +561,80 @@ int FindWireguardExe(TCHAR *pFullPath, int maxSize) { free(pEnvBuf); return -ERR_FILE_NOT_EXISTS; +} + +int InstallWindowsNATCommand() { + TCHAR psCmdPath[MAX_PATH]; + + // 如果已经安装则退出 + if (CustomNatPSCmdInstalled()) { + return ERR_SUCCESS; + } + + StringCbPrintf(psCmdPath, + MAX_PATH, + TEXT("%s\\system32\\WindowsPowerShell\\v1.0\\Modules\\wireguard\\wireguard.psm1"), + GetGlobalCfgInfo()->systemDirectory); + + const HANDLE hFile = CreateFile(psCmdPath, + GENERIC_WRITE | GENERIC_READ, + FILE_SHARE_READ, + nullptr, + CREATE_ALWAYS, + FILE_ATTRIBUTE_NORMAL, + nullptr); + + if (hFile == INVALID_HANDLE_VALUE) { + SPDLOG_ERROR("CreatFile [{0}] error: {1}", psCmdPath, GetLastError()); + return -ERR_OPEN_FILE; + } + + const HMODULE hMod = GetModuleHandle(TEXT("NetTunnelSDK.dll")); + + if (nullptr == hMod) { + SPDLOG_ERROR(TEXT("Load NetTunnelSDK.dll module error")); + ::CloseHandle(hFile); + return -ERR_ITEM_UNEXISTS; + } + + const HRSRC hRsrc = FindResource(hMod, MAKEINTRESOURCE(IDR_TXT2), TEXT("TXT")); + if (nullptr == hRsrc) { + SPDLOG_ERROR(TEXT("Donot found resource {0} of type {1}"), IDR_TXT2, TEXT("TXT")); + ::CloseHandle(hFile); + return -ERR_ITEM_UNEXISTS; + } + + const DWORD resSize = SizeofResource(hMod, hRsrc); + + if (resSize == 0) { + SPDLOG_ERROR(TEXT("Resource {0} of type {1} is empty"), IDR_TXT2, TEXT("TXT")); + ::CloseHandle(hFile); + return -ERR_ITEM_UNEXISTS; + } + + const HGLOBAL hGlobal = LoadResource(hMod, hRsrc); + + if (hGlobal == hRsrc) { + SPDLOG_ERROR(TEXT("Load resource {0} of type {1} error"), IDR_TXT2, TEXT("TXT")); + ::CloseHandle(hFile); + return -ERR_ITEM_UNEXISTS; + } + + if (const LPVOID pBuffer = LockResource(hGlobal)) { + if (!WriteFile(hFile, // open file handle + pBuffer, // start of data to write + static_cast(resSize), // number of bytes to write + nullptr, // number of bytes that were written + nullptr)) { + SPDLOG_ERROR("WriteFile [{0}] error: {1}", psCmdPath, GetLastError()); + GlobalUnlock(hGlobal); + ::CloseHandle(hFile); + return -ERR_OPEN_FILE; + } + } + + GlobalUnlock(hGlobal); + ::CloseHandle(hFile); + + return ERR_SUCCESS; } \ No newline at end of file diff --git a/TestNetTunnelSDK/TestNetTunnelSDK.cpp b/TestNetTunnelSDK/TestNetTunnelSDK.cpp index e1b2674..6440409 100644 --- a/TestNetTunnelSDK/TestNetTunnelSDK.cpp +++ b/TestNetTunnelSDK/TestNetTunnelSDK.cpp @@ -3,6 +3,7 @@ #include "../NetTunnelSDK/tunnel.h" #include "../NetTunnelSDK/usrerr.h" #include "../NetTunnelSDK/misc.h" +#include "../NetTunnelSDK/globalcfg.h" using namespace Microsoft::VisualStudio::CppUnitTestFramework; @@ -11,6 +12,7 @@ TEST_MODULE_INITIALIZE(ModuleInitialize) { Logger::WriteMessage("In Module Initialize"); TunnelSDKInitEnv( TEXT("C:\\Users\\HuangXin\\Documents\\development\\visual_studio\\tunnel_windows\\NetTunnelApp\\bin\\Debug")); + InitTunnelSDKLog(TEXT("C:\\Users\\HuangXin\\Documents\\development\\visual_studio\\tunnel_" "windows\\NetTunnelApp\\bin\\Debug\\utest.log"), LOG_DEBUG); @@ -55,15 +57,12 @@ public: } TEST_METHOD(TestSetInterfaceIpAddressFromCIDR) { - Assert::AreEqual( - RET_OK, - SetInterfaceIpAddressFromCIDR(TEXT("wg_server"), TEXT("192.168.100.250/24"))); + Assert::AreEqual(RET_OK, SetInterfaceIpAddressFromCIDR(TEXT("wg_server"), TEXT("192.168.100.250/24"))); } TEST_METHOD(TestSetInterfaceIpAddress) { - Assert::AreEqual( - RET_OK, - SetInterfaceIpAddress(TEXT("wg_server"), TEXT("192.168.101.250"), TEXT("255.255.0.0"))); + Assert::AreEqual(RET_OK, + SetInterfaceIpAddress(TEXT("wg_server"), TEXT("192.168.101.250"), TEXT("255.255.0.0"))); } TEST_METHOD(TestGetInterfaceIndexByName) { @@ -71,7 +70,7 @@ public: Assert::AreEqual(RET_OK, GetInterfaceIndexByName(TEXT("wg_server"), &index)); } - TEST_METHOD(TestRemoveInterfaceIpAddress) { + TEST_METHOD(TestRemoveInterfaceIpAddress) { Assert::AreEqual(RET_OK, RemoveInterfaceIpAddress(TEXT("wg_server"))); } @@ -80,5 +79,16 @@ public: Assert::AreEqual(RET_OK, GetWindowsHyperVStatus(&enable)); Assert::AreEqual(TRUE, enable); } + + TEST_METHOD(TestInstallWindowsNATCommand) { + Assert::AreEqual(RET_OK, InstallWindowsNATCommand()); + } + + TEST_METHOD(TestCalcFileHash) { + TCHAR outHash[MAX_PATH] = {0}; + + Assert::AreEqual(RET_OK, CalcFileHash(HASH_SHA256, TEXT("E:\\wireguard.psm1"), outHash)); + Assert::AreEqual(TEXT("3ef17a2eb23a148a3fbe14cb4ef38747e0a1e5037b6afa2350a9b18f617bb5db"), outHash); + } }; } \ No newline at end of file