1
0
mirror of https://github.com/SoftEtherVPN/SoftEtherVPN.git synced 2025-06-27 19:35:09 +03:00

v4.44-9807-rtm

This commit is contained in:
dnobori 2025-04-16 15:11:53 +09:00
parent 556bc0afe2
commit ed17437af9
45 changed files with 548 additions and 206 deletions

View File

@ -13190,7 +13190,6 @@ void InRpcEnumLink(RPC_ENUM_LINK *t, PACK *p)
e->ConnectedTime = PackGetInt64Ex(p, "ConnectedTime", i);
e->Connected = PackGetBoolEx(p, "Connected", i);
e->LastError = PackGetIntEx(p, "LastError", i);
PackGetStrEx(p, "LinkHubName", e->HubName, sizeof(e->HubName), i);
}
}
void OutRpcEnumLink(PACK *p, RPC_ENUM_LINK *t)

View File

@ -126,10 +126,10 @@
// Version number
#define CEDAR_VER 443
#define CEDAR_VER 444
// Build Number
#define CEDAR_BUILD 9799
#define CEDAR_BUILD 9807
// Beta number
//#define BETA_NUMBER 3
@ -148,12 +148,12 @@
#endif // BUILD_PLACE
// Specifies the build date
#define BUILD_DATE_Y 2023
#define BUILD_DATE_M 8
#define BUILD_DATE_D 31
#define BUILD_DATE_HO 10
#define BUILD_DATE_Y 2025
#define BUILD_DATE_M 4
#define BUILD_DATE_D 16
#define BUILD_DATE_HO 4
#define BUILD_DATE_MI 30
#define BUILD_DATE_SE 0
#define BUILD_DATE_SE 26
// Tolerable time difference
#define ALLOW_TIMESTAMP_DIFF (UINT64)(3 * 24 * 60 * 60 * 1000)

View File

@ -196,6 +196,8 @@ void CheckNetworkAcceptThread(THREAD *thread, void *param)
Disconnect(s);
ReleaseSock(s);
Free(c);
}
@ -239,15 +241,16 @@ void CheckNetworkListenThread(THREAD *thread, void *param)
}
else
{
CHECK_NETWORK_2 c;
CHECK_NETWORK_2 *c;
THREAD *t;
Zero(&c, sizeof(c));
c.s = new_sock;
c.k = pri;
c.x = x;
c = ZeroMalloc(sizeof(CHECK_NETWORK_2));
c->s = new_sock;
c->k = pri;
c->x = x;
t = NewThread(CheckNetworkAcceptThread, &c);
t = NewThread(CheckNetworkAcceptThread, c);
Insert(o, t);
}
}
@ -14986,7 +14989,7 @@ bool ParseTcpState(char *src, bool *check_tcp_state, bool *established)
if (IsEmptyStr(src) == false)
{
if (StartWith("Established", src) == 0)
if (StartWith("Established", src))
{
if(ok != false)
{
@ -14994,7 +14997,7 @@ bool ParseTcpState(char *src, bool *check_tcp_state, bool *established)
*established = true;
}
}
else if (StartWith("Unestablished", src) == 0)
else if (StartWith("Unestablished", src))
{
if(ok != false)
{

View File

@ -5336,7 +5336,10 @@ L_SKIP_TO_DISCARD:
{
PKT *pkt2 = ParsePacket(data, size);
DeleteIPv6DefaultRouterInRA(pkt2);
if (pkt2 != NULL)
{
DeleteIPv6DefaultRouterInRA(pkt2);
}
FreePacket(pkt2);
}
@ -5680,6 +5683,11 @@ void StorePacketToHubPa(HUB_PA *dest, SESSION *src, void *data, UINT size, PKT *
// Remove the default router specification from the IPv6 router advertisement
bool DeleteIPv6DefaultRouterInRA(PKT *p)
{
if (p == NULL)
{
return false;
}
if (p->TypeL3 == L3_IPV6 && p->TypeL4 == L4_ICMPV6 &&
(p->ICMPv6HeaderPacketInfo.Type == ICMPV6_TYPE_ROUTER_ADVERTISEMENT))
{

View File

@ -381,6 +381,7 @@ struct HUB
char RadiusRealm[MAX_SIZE]; // Radius realm (optional)
bool RadiusConvertAllMsChapv2AuthRequestToEap; // Convert all MS-CHAPv2 auth request to EAP
bool RadiusUsePeapInsteadOfEap; // Use PEAP instead of EAP
bool RadiusRequireMessageAuthenticator; // Enforce use the Message-Authenticator attribute when non-EAP auth request and response
volatile bool Halt; // Halting flag
bool Offline; // Offline
bool BeingOffline; // Be Doing Offline

View File

@ -597,36 +597,15 @@ void ProcIPsecEspPacketRecv(IKE_SERVER *ike, UDPPACKET *p)
ipsec_sa = SearchClientToServerIPsecSaBySpi(ike, spi);
if (ipsec_sa == NULL)
{
// Invalid SPI
UINT64 init_cookie = Rand64();
UINT64 resp_cookie = 0;
IKE_CLIENT *c = NULL;
IKE_CLIENT t;
Copy(&t.ClientIP, &p->SrcIP, sizeof(IP));
t.ClientPort = p->SrcPort;
Copy(&t.ServerIP, &p->DstIP, sizeof(IP));
t.ServerPort = p->DestPort;
t.CurrentIkeSa = NULL;
if (p->DestPort == IPSEC_PORT_IPSEC_ESP_RAW)
{
t.ClientPort = t.ServerPort = IPSEC_PORT_IPSEC_ISAKMP;
}
c = Search(ike->ClientList, &t);
if (c != NULL && c->CurrentIkeSa != NULL)
{
init_cookie = c->CurrentIkeSa->InitiatorCookie;
resp_cookie = c->CurrentIkeSa->ResponderCookie;
}
SendInformationalExchangePacketEx(ike, (c == NULL ? &t : c), IkeNewNoticeErrorInvalidSpiPayload(spi), false,
init_cookie, resp_cookie);
SendDeleteIPsecSaPacket(ike, (c == NULL ? &t : c), spi);
// Do nothing: see https://github.com/SoftEtherVPN/SoftEtherVPN/security/advisories/GHSA-j35p-p8pj-vqxq
// RFC4303, in 3.4.2
// If no valid Security Association exists for this packet, the receiver
// MUST discard the packet; this is an auditable event. The audit log
// entry for this event SHOULD include the SPI value, date/time
// received, Source Address, Destination Address, Sequence Number, and
// (in IPv6) the cleartext Flow ID.
//
// Thank you for phillibert, Amazon Web Services, Inc.
return;
}

View File

@ -294,12 +294,39 @@ void OvsProceccRecvPacket(OPENVPN_SERVER *s, UDPPACKET *p, UINT protocol)
data = recv_packet->Data;
size = recv_packet->DataSize;
if (size >= (c->MdRecv->Size + c->CipherDecrypt->IvSize + sizeof(UINT)))
if(c->CipherDecrypt->IsAeadCipher)
{
UCHAR *tag;
// Update variable part (packet ID) of IV
Copy(c->IvRecv, data, sizeof(recv_packet->PacketId));
data += sizeof(UINT);
size -= sizeof(UINT);
// tag data
tag = data;
if(size < OPENVPN_TAG_SIZE) goto decode_error;
data += OPENVPN_TAG_SIZE;
size -= OPENVPN_TAG_SIZE;
// Decryption
if (size == 0 || (c->CipherDecrypt->BlockSize != 0 && (size % c->CipherDecrypt->BlockSize) != 0)) goto decode_error;
size = CipherProcessAead(c->CipherDecrypt, c->IvRecv, tag, OPENVPN_TAG_SIZE, s->TmpBuf, data, size, c->IvRecv, sizeof(UINT));
if (size == 0)
{
Debug("OvsDecrypt(): CipherProcessAead() failed!\n");
goto decode_error;
}
data = s->TmpBuf;
}
else // Non AEAD cipher
{
UCHAR *hmac;
UCHAR *iv;
UCHAR hmac_test[128];
if (size < (c->MdRecv->Size + c->CipherDecrypt->IvSize + sizeof(UINT))) goto decode_error;
// HMAC
hmac = data;
data += c->MdRecv->Size;
@ -307,67 +334,59 @@ void OvsProceccRecvPacket(OPENVPN_SERVER *s, UDPPACKET *p, UINT protocol)
// Confirmation of HMAC
MdProcess(c->MdRecv, hmac_test, data, size);
if (Cmp(hmac_test, hmac, c->MdRecv->Size) == 0)
if (Cmp(hmac_test, hmac, c->MdRecv->Size) != 0) goto decode_error;
// IV
iv = data;
data += c->CipherDecrypt->IvSize;
size -= c->CipherDecrypt->IvSize;
// Decryption
if (size == 0 || (c->CipherDecrypt->BlockSize != 0 && (size % c->CipherDecrypt->BlockSize) != 0)) goto decode_error;
size = CipherProcess(c->CipherDecrypt, iv, s->TmpBuf, data, size);
if(size == 0) goto decode_error;
data = s->TmpBuf;
// Seek buffer after the packet ID
data += sizeof(UINT);
size -= sizeof(UINT);
}
// Update of last communication time
se->LastCommTick = s->Now;
if (size < sizeof(UINT)){
goto decode_error;
}
if (size >= sizeof(ping_signature) &&
Cmp(data, ping_signature, sizeof(ping_signature)) == 0)
{
// Ignore since a ping packet has been received
DoNothing();
}
else
{
// Receive a valid data packet!!
if (se->Ipc != NULL)
{
// Update of last communication time
se->LastCommTick = s->Now;
// IV
iv = data;
data += c->CipherDecrypt->IvSize;
size -= c->CipherDecrypt->IvSize;
// Payload
if (size >= 1 && (c->CipherDecrypt->BlockSize == 0 || (size % c->CipherDecrypt->BlockSize) == 0))
switch (se->Mode)
{
UINT data_packet_id;
case OPENVPN_MODE_L2: // Send an Ethernet packet to a session
IPCSendL2(se->Ipc, data, size);
break;
// Decryption
size = CipherProcess(c->CipherDecrypt, iv, s->TmpBuf, data, size);
data = s->TmpBuf;
if (size >= sizeof(UINT))
{
data_packet_id = READ_UINT(data);
data += sizeof(UINT);
size -= sizeof(UINT);
if (size >= sizeof(ping_signature) &&
Cmp(data, ping_signature, sizeof(ping_signature)) == 0)
{
// Ignore since a ping packet has been received
DoNothing();
}
else
{
// Receive a packet!!
if (se->Ipc != NULL)
{
switch (se->Mode)
{
case OPENVPN_MODE_L2: // Send an Ethernet packet to a session
IPCSendL2(se->Ipc, data, size);
break;
case OPENVPN_MODE_L3: // Send an IPv4 packet to a session
IPCSendIPv4(se->Ipc, data, size);
break;
}
}
}
}
case OPENVPN_MODE_L3: // Send an IPv4 packet to a session
IPCSendIPv4(se->Ipc, data, size);
break;
}
}
else
{
// Debug("HMAC Failed (c=%u)\n", c->KeyId);
}
}
}
}
}
decode_error:
OvsFreePacket(recv_packet);
}
@ -770,6 +789,7 @@ void OvsSetupSessionParameters(OPENVPN_SERVER *s, OPENVPN_SESSION *se, OPENVPN_C
LIST *o;
BUF *b;
char opt_str[MAX_SIZE];
char *cipher_name, *md_name;
// Validate arguments
if (s == NULL || se == NULL || c == NULL || data == NULL)
{
@ -871,14 +891,6 @@ void OvsSetupSessionParameters(OPENVPN_SERVER *s, OPENVPN_SESSION *se, OPENVPN_C
}
}
// Encryption algorithm
c->CipherEncrypt = OvsGetCipher(IniStrValue(o, "cipher"));
c->CipherDecrypt = NewCipher(c->CipherEncrypt->Name);
// Hash algorithm
c->MdSend = OvsGetMd(IniStrValue(o, "auth"));
c->MdRecv = NewMd(c->MdSend->Name);
// Random number generation
Rand(c->ServerKey.Random1, sizeof(c->ServerKey.Random1));
Rand(c->ServerKey.Random2, sizeof(c->ServerKey.Random2));
@ -904,13 +916,45 @@ void OvsSetupSessionParameters(OPENVPN_SERVER *s, OPENVPN_SESSION *se, OPENVPN_C
c->ExpansionKey, sizeof(c->ExpansionKey));
FreeBuf(b);
// Set the key
// Encryption algorithm
cipher_name = IniStrValue(o, "cipher");
c->CipherEncrypt = OvsGetCipher(cipher_name);
c->CipherDecrypt = OvsGetCipher(cipher_name);
SetCipherKey(c->CipherDecrypt, c->ExpansionKey + 0, false);
SetCipherKey(c->CipherEncrypt, c->ExpansionKey + 128, true);
SetMdKey(c->MdRecv, c->ExpansionKey + 64, c->MdRecv->Size);
SetMdKey(c->MdSend, c->ExpansionKey + 192, c->MdSend->Size);
OvsFreeOptions(o);
md_name = IniStrValue(o, "auth");
if(c->CipherDecrypt->IsAeadCipher){
// In AEAD mode the IV is composed by the packet ID and a part of the HMAC key
Copy(c->IvRecv + sizeof(c->LastDataPacketId), c->ExpansionKey + 64, c->CipherDecrypt->IvSize - sizeof(c->LastDataPacketId));
Copy(c->IvSend + sizeof(c->LastDataPacketId), c->ExpansionKey + 192, c->CipherEncrypt->IvSize - sizeof(c->LastDataPacketId));
c->MdSend = NULL;
c->MdRecv = NULL;
}else{
// Hash algorithm
c->MdSend = OvsGetMd(md_name);
c->MdRecv = OvsGetMd(md_name);
SetMdKey(c->MdRecv, c->ExpansionKey + 64, c->MdRecv->Size);
SetMdKey(c->MdSend, c->ExpansionKey + 192, c->MdSend->Size);
}
// We pass the cipher name sent from the OpenVPN client, unless it's a different cipher, to prevent a message such as:
// WARNING: 'cipher' is used inconsistently, local='cipher AES-128-GCM', remote='cipher aes-128-gcm'
// It happens because OpenVPN uses "strcmp()" to compare the local and remote parameters:
// https://github.com/OpenVPN/openvpn/blob/a6fd48ba36ede465b0905a95568c3ec0d425ca71/src/openvpn/options.c#L3819-L3831
if (StrCmpi(cipher_name, c->CipherEncrypt->Name) != 0)
{
cipher_name = c->CipherEncrypt->Name;
}
if(c->MdSend != NULL){
if (StrCmpi(md_name, c->MdSend->Name) != 0)
{
md_name = c->MdSend->Name;
}
}else{
md_name = "[null-digest]";
}
// Generate the response option string
Format(c->ServerKey.OptionString, sizeof(c->ServerKey.OptionString),
@ -920,9 +964,11 @@ void OvsSetupSessionParameters(OPENVPN_SERVER *s, OPENVPN_SESSION *se, OPENVPN_C
se->LinkMtu,
se->TunMtu,
c->Proto,
c->CipherEncrypt->Name, c->MdSend->Name, c->CipherEncrypt->KeySize * 8);
cipher_name, md_name, c->CipherEncrypt->KeySize * 8);
Debug("Building OptionStr: %s\n", c->ServerKey.OptionString);
OvsFreeOptions(o);
OvsLog(s, se, c, "LO_OPTION_STR_SEND", c->ServerKey.OptionString);
}
@ -931,7 +977,7 @@ CIPHER *OvsGetCipher(char *name)
{
CIPHER *c = NULL;
if (IsEmptyStr(name) == false && IsStrInStrTokenList(OPENVPN_CIPHER_LIST, name, NULL, false))
if (IsEmptyStr(name) == false)
{
c = NewCipher(name);
}
@ -949,7 +995,7 @@ MD *OvsGetMd(char *name)
{
MD *m = NULL;
if (IsEmptyStr(name) == false && IsStrInStrTokenList(OPENVPN_MD_LIST, name, NULL, false))
if (IsEmptyStr(name) == false)
{
m = NewMd(name);
}
@ -1419,7 +1465,8 @@ OPENVPN_CHANNEL *OvsNewChannel(OPENVPN_SESSION *se, UCHAR key_id)
c->KeyId = key_id;
Rand(c->NextIv, sizeof(c->NextIv));
Rand(c->IvSend, sizeof(c->IvSend));
Rand(c->IvRecv, sizeof(c->IvRecv));
//c->NextRekey = se->Server->Now + (UINT64)5000;
@ -1467,9 +1514,7 @@ UINT64 OvsNewServerSessionId(OPENVPN_SERVER *s)
// Build and submit the OpenVPN data packet
void OvsSendDataPacket(OPENVPN_CHANNEL *c, UCHAR key_id, UINT data_packet_id, void *data, UINT data_size)
{
UCHAR uc;
UCHAR *encrypted_data;
UINT encrypted_size;
const UCHAR op = ((OPENVPN_P_DATA_V1 << 3) & 0xF8) | (key_id & 0x07);
UCHAR *dest_data;
UINT dest_size;
UINT r;
@ -1480,40 +1525,68 @@ void OvsSendDataPacket(OPENVPN_CHANNEL *c, UCHAR key_id, UINT data_packet_id, vo
return;
}
uc = ((OPENVPN_P_DATA_V1 << 3) & 0xF8) | (key_id & 0x07);
// Generate the data to be encrypted
if (c->CipherEncrypt->IsAeadCipher){
// [ opcode ] [ - packet ID - ] [ TAG ] [ * packet payload * ]
UCHAR tag[16];
UINT ret;
encrypted_size = sizeof(UINT) + data_size;
encrypted_data = ZeroMalloc(encrypted_size);
// Update variable part (packet ID) of IV
WRITE_UINT(c->IvSend, data_packet_id);
WRITE_UINT(encrypted_data, data_packet_id);
Copy(encrypted_data + sizeof(UINT), data, data_size);
// Prepare a buffer to store the results
dest_data = Malloc(sizeof(op) + sizeof(data_packet_id) + sizeof(tag) + data_size + 256);
// Prepare a buffer to store the results
dest_data = Malloc(sizeof(UCHAR) + c->MdSend->Size + c->CipherEncrypt->IvSize + encrypted_size + 256);
// Set data size to the maximum known
dest_size = sizeof(op) + sizeof(data_packet_id) + sizeof(tag);
// Encrypt
r = CipherProcess(c->CipherEncrypt, c->NextIv, dest_data + sizeof(UCHAR) + c->MdSend->Size + c->CipherEncrypt->IvSize,
encrypted_data, encrypted_size);
dest_size = sizeof(UCHAR) + c->MdSend->Size + c->CipherEncrypt->IvSize + r;
// Write opcode
dest_data[0] = op;
// Copy the IV
Copy(dest_data + sizeof(UCHAR) + c->MdSend->Size, c->NextIv, c->CipherEncrypt->IvSize);
// Write packet ID
WRITE_UINT(dest_data + sizeof(op), data_packet_id);
// Calculate the HMAC
MdProcess(c->MdSend, dest_data + sizeof(UCHAR), dest_data + sizeof(UCHAR) + c->MdSend->Size,
dest_size - sizeof(UCHAR) - c->MdSend->Size);
// Write encrypted payload
ret = CipherProcessAead(c->CipherEncrypt, c->IvSend, tag, 16, dest_data + dest_size, data, data_size, c->IvSend, sizeof(data_packet_id));
if (ret == 0)
{
Debug("OvsEncrypt(): CipherProcessAead() failed!\n");
return;
}
dest_size += ret;
// Update the NextIV
Copy(c->NextIv, dest_data + dest_size - c->CipherEncrypt->IvSize, c->CipherEncrypt->IvSize);
// Write authentication tag
Copy(dest_data + sizeof(op) + sizeof(data_packet_id), tag, sizeof(tag));
}else{
// [ opcode ] [ HMAC ] [ - IV - ] [ * packet ID * ] [ * packet payload * ]
UINT encrypted_size = sizeof(data_packet_id) + data_size;
UCHAR *encrypted_data = ZeroMalloc(encrypted_size);
WRITE_UINT(encrypted_data, data_packet_id);
Copy(encrypted_data + sizeof(data_packet_id), data, data_size);
// Op-code
dest_data[0] = uc;
// Prepare a buffer to store the results
dest_data = Malloc(sizeof(op) + c->MdSend->Size + c->CipherEncrypt->IvSize + encrypted_size + 256);
dest_data[0] = op;
// Encrypt
r = CipherProcess(c->CipherEncrypt, c->IvSend, dest_data + sizeof(op) + c->MdSend->Size + c->CipherEncrypt->IvSize,
encrypted_data, encrypted_size);
Free(encrypted_data);
dest_size = sizeof(op) + c->MdSend->Size + c->CipherEncrypt->IvSize + r;
// Copy the IV
Copy(dest_data + sizeof(op) + c->MdSend->Size, c->IvSend, c->CipherEncrypt->IvSize);
// Calculate the HMAC
MdProcess(c->MdSend, dest_data + sizeof(op), dest_data + sizeof(op) + c->MdSend->Size,
dest_size - sizeof(op) - c->MdSend->Size);
// Update the IV for next
Copy(c->IvSend, dest_data + dest_size - c->CipherEncrypt->IvSize, c->CipherEncrypt->IvSize);
}
OvsSendPacketRawNow(c->Server, c->Session, dest_data, dest_size);
Free(encrypted_data);
}
// Build an OpenVPN control packet

View File

@ -118,6 +118,7 @@
#define OPENVPN_MAX_SSL_RECV_BUF_SIZE (256 * 1024) // SSL receive buffer maximum length
#define OPENVPN_MAX_KEY_SIZE 64 // Maximum key size
#define OPENVPN_TAG_SIZE 16 // Tag size (for packet authentication in AEAD mode)
#define OPENVPN_TMP_BUFFER_SIZE (65536 + 256) // Temporary buffer size
@ -142,12 +143,6 @@
#define OPENVPN_IPC_POSTFIX_L2 "OPENVPN_L2"
#define OPENVPN_IPC_POSTFIX_L3 "OPENVPN_L3"
// List of supported encryption algorithms
#define OPENVPN_CIPHER_LIST "[NULL-CIPHER] NULL AES-128-CBC AES-192-CBC AES-256-CBC BF-CBC CAST-CBC CAST5-CBC DES-CBC DES-EDE-CBC DES-EDE3-CBC DESX-CBC RC2-40-CBC RC2-64-CBC RC2-CBC CAMELLIA-128-CBC CAMELLIA-192-CBC CAMELLIA-256-CBC"
// List of the supported hash algorithm
#define OPENVPN_MD_LIST "SHA SHA1 SHA256 SHA384 SHA512 MD5 MD4 RMD160"
// MTU
#define OPENVPN_MTU_LINK 1514 // Ethernet MTU
#define OPENVPN_MTU_TUN 1500 // Tun MTU
@ -163,6 +158,7 @@
#define OPENVPN_P_DATA_V1 6 // Data packet
#define OPENVPN_P_CONTROL_HARD_RESET_CLIENT_V2 7 // Connection request from client
#define OPENVPN_P_CONTROL_HARD_RESET_SERVER_V2 8 // Connection response from server
#define OPENVPN_P_DATA_V2 9 // Data packet v2
// State of OpenVPN channel
#define OPENVPN_CHANNEL_STATUS_INIT 0 // Initialization phase
@ -240,9 +236,10 @@ struct OPENVPN_CHANNEL
CIPHER *CipherDecrypt; // Decryption algorithm
MD *MdSend; // Transmission MD algorithm
MD *MdRecv; // Reception MD algorithm
UCHAR IvSend[64]; // Transmission IV
UCHAR IvRecv[64]; // Reception IV
UCHAR MasterSecret[48]; // Master Secret
UCHAR ExpansionKey[256]; // Expansion Key
UCHAR NextIv[64]; // Next IV
UINT LastDataPacketId; // Previous Data Packet ID
UINT64 EstablishedTick; // Established time
UCHAR KeyId; // KEY ID

View File

@ -1721,7 +1721,7 @@ LABEL_ERROR:
// Attempts Radius authentication (with specifying retry interval and multiple server)
bool RadiusLogin(CONNECTION *c, char *server, UINT port, UCHAR *secret, UINT secret_size, wchar_t *username, char *password, UINT interval, UCHAR *mschap_v2_server_response_20,
RADIUS_LOGIN_OPTION *opt, char *hubname)
RADIUS_LOGIN_OPTION *opt, char *hubname, bool RadiusRequireMessageAuthenticator)
{
UCHAR random[MD5_SIZE];
UCHAR id;
@ -1890,6 +1890,10 @@ bool RadiusLogin(CONNECTION *c, char *server, UINT port, UCHAR *secret, UINT sec
USHORT sz = 0;
UINT pos = 0;
BOOL *finish = ZeroMallocEx(sizeof(BOOL) * LIST_NUM(ip_list), true);
// Message-Authenticator
UCHAR zero16[16] = {0};
UCHAR msg_auth[16] = {0};
UINT msg_auth_pos = 0;
Zero(tmp, sizeof(tmp));
@ -2015,9 +2019,27 @@ bool RadiusLogin(CONNECTION *c, char *server, UINT port, UCHAR *secret, UINT sec
RadiusAddValue(p, RADIUS_ATTRIBUTE_PROXY_STATE, 0, 0, opt->In_VpnProtocolState, StrLen(opt->In_VpnProtocolState));
}
SeekBuf(p, 0, 0);
if (RadiusRequireMessageAuthenticator == false)
{
SeekBuf(p, 0, 0);
WRITE_USHORT(((UCHAR *)p->Buf) + 2, (USHORT)p->Size);
WRITE_USHORT(((UCHAR *)p->Buf) + 2, (USHORT)p->Size);
}
else
{
// Message-Authenticator zero-filled
msg_auth_pos = p->Current;
Zero(zero16, sizeof(zero16));
RadiusAddValue(p, RADIUS_ATTRIBUTE_EAP_AUTHENTICATOR, 0, 0, zero16, sizeof(zero16));
// Length
SeekBuf(p, 0, 0);
WRITE_USHORT(((UCHAR *)p->Buf) + 2, (USHORT)p->Size);
// generate Message-Authenticator value
HMacMd5(msg_auth, secret, secret_size, p->Buf, p->Size);
Copy( ((UCHAR *)p->Buf) + msg_auth_pos + 2, msg_auth, 16 );
}
// Create a socket
sock = NewUDPEx(0, IsIP6(LIST_DATA(ip_list, pos)));
@ -2108,7 +2130,22 @@ RECV_RETRY:
LIST *o;
BUF *buf = NewBufFromMemory(recv_buf, recv_size);
ret = true;
if (RadiusRequireMessageAuthenticator == false)
{
ret = true;
}
else
{
// Validate Response Authenticator header and Message-Authenticator
if ( recv_size < 20 )
{
ret = false;
}
else
{
ret = RadiusValidateAuthenticator(buf, (char *)secret, (char *)random, RadiusRequireMessageAuthenticator);
}
}
if (is_mschap && mschap_v2_server_response_20 != NULL)
{
@ -2221,6 +2258,156 @@ RECV_RETRY:
return ret;
}
// Validate Response Authenticator header and Message-Authenticator
bool RadiusValidateAuthenticator(BUF *b, char *secret, char *request_authenticator, bool RadiusRequireMessageAuthenticator)
{
bool ret = false;
BUF *tmp = CloneBuf(b);
LIST *o;
UCHAR code;
UCHAR id;
USHORT len;
UCHAR auth0[16];
UCHAR auth1[16];
UINT avp_pos = 0;
// read header from the buffer
if (tmp == NULL)
{
FreeBuf(tmp);
return false;
}
if ( tmp->Size < 20 )
{
FreeBuf(tmp);
return false;
}
ReadBuf(tmp, &code, 1);
ReadBuf(tmp, &id, 1);
len = 0;
ReadBuf(tmp, &len, 2);
len = Endian16(len);
ReadBuf(tmp, auth0, 16);
avp_pos = tmp->Current;
if ( tmp->Size != len )
{
FreeBuf(tmp);
return false;
}
// Validate Response Authenticator header
Copy( ((UCHAR *)tmp->Buf) + tmp->Current - 16 , request_authenticator, 16 );
SeekBufToEnd( tmp );
WriteBuf( tmp, secret, StrLen(secret) );
Md5( auth1, tmp->Buf, tmp->Size );
if (Cmp(auth0, auth1, 16) != 0)
{
FreeBuf(tmp);
return false;
}
else
{
ret = true;
}
// Validate Response Message-Authenticator
SeekBufToBegin(tmp);
o = RadiusParseOptions(tmp);
if (o != NULL)
{
DHCP_OPTION *msg_authenticator = GetDhcpOption(o, RADIUS_ATTRIBUTE_EAP_AUTHENTICATOR);
if (msg_authenticator != NULL)
{
tmp->Current = avp_pos;
while (true)
{
UCHAR attribute_id;
UCHAR size;
UCHAR data[256];
if (ReadBuf(tmp, &attribute_id, 1) != 1)
{
break;
}
if (ReadBuf(tmp, &size, 1) != 1)
{
break;
}
if (size <= 2)
{
break;
}
size -= 2;
if (ReadBuf(tmp, data, size) != size)
{
break;
}
if ( attribute_id == (UCHAR)RADIUS_ATTRIBUTE_EAP_AUTHENTICATOR )
{
UCHAR zero16[16];
UCHAR msg_auth0[16];
UCHAR msg_auth1[16];
Copy(msg_auth0, data, size);
Zero(zero16, sizeof(zero16));
Copy( ((UCHAR *)tmp->Buf) + tmp->Current - sizeof(zero16), zero16, sizeof(zero16) );
HMacMd5(msg_auth1, secret, StrLen(secret), tmp->Buf, tmp->Size - StrLen(secret));
if (Cmp(msg_auth0, msg_auth1, 16) == 0)
{
ret = true;
}
else
{
ret = false;
}
break;
}
}
}
else if ( RadiusRequireMessageAuthenticator )
{
// RadiusRequireMessageAuthenticator == true, Message-Authenticator attribute is missing
FreeBuf(tmp);
FreeDhcpOptions(o);
return false;
}
}
else if ( RadiusRequireMessageAuthenticator )
{
// RadiusRequireMessageAuthenticator == true , avp is missing
FreeBuf(tmp);
FreeDhcpOptions(o);
return false;
}
FreeBuf(tmp);
FreeDhcpOptions(o);
return ret;
}
// Parse RADIUS attributes
LIST *RadiusParseOptions(BUF *b)
{

View File

@ -375,13 +375,14 @@ struct RADIUS_LOGIN_OPTION
// Function prototype
bool RadiusLogin(CONNECTION *c, char *server, UINT port, UCHAR *secret, UINT secret_size, wchar_t *username, char *password, UINT interval, UCHAR *mschap_v2_server_response_20,
RADIUS_LOGIN_OPTION *opt, char *hubname);
RADIUS_LOGIN_OPTION *opt, char *hubname, bool RadiusRequireMessageAuthenticator);
BUF *RadiusEncryptPassword(char *password, UCHAR *random, UCHAR *secret, UINT secret_size);
BUF *RadiusCreateUserName(wchar_t *username);
BUF *RadiusCreateUserPassword(void *data, UINT size);
BUF *RadiusCreateNasId(char *name);
void RadiusAddValue(BUF *b, UCHAR t, UINT v, UCHAR vt, void *data, UINT size);
LIST *RadiusParseOptions(BUF *b);
bool RadiusValidateAuthenticator(BUF *b, char *secret, char *request_authenticator, bool RadiusRequireMessageAuthenticator);
#endif // RADIUS_H

View File

@ -269,7 +269,7 @@ bool SamAuthUserByPlainPassword(CONNECTION *c, HUB *hub, char *username, char *p
// Attempt to login
b = RadiusLogin(c, radius_server_addr, radius_server_port,
radius_secret, StrLen(radius_secret),
name, password, interval, mschap_v2_server_response_20, opt, hub->Name);
name, password, interval, mschap_v2_server_response_20, opt, hub->Name, hub->RadiusRequireMessageAuthenticator);
if (b)
{

View File

@ -5060,6 +5060,7 @@ void SiWriteHubCfg(FOLDER *f, HUB *h)
CfgAddBool(f, "RadiusConvertAllMsChapv2AuthRequestToEap", h->RadiusConvertAllMsChapv2AuthRequestToEap);
CfgAddBool(f, "RadiusUsePeapInsteadOfEap", h->RadiusUsePeapInsteadOfEap);
CfgAddBool(f, "RadiusRequireMessageAuthenticator", h->RadiusRequireMessageAuthenticator);
}
Unlock(h->RadiusOptionLock);
@ -5229,6 +5230,7 @@ void SiLoadHubCfg(SERVER *s, FOLDER *f, char *name)
h->RadiusConvertAllMsChapv2AuthRequestToEap = CfgGetBool(f, "RadiusConvertAllMsChapv2AuthRequestToEap");
h->RadiusUsePeapInsteadOfEap = CfgGetBool(f, "RadiusUsePeapInsteadOfEap");
h->RadiusRequireMessageAuthenticator = CfgGetBool(f, "RadiusRequireMessageAuthenticator");
if (interval == 0)
{

View File

@ -1,4 +1,4 @@
BUILD_NUMBER 9799
VERSION 443
BUILD_NAME beta
BUILD_DATE 20230831_103000
BUILD_NUMBER 9807
VERSION 444
BUILD_NAME rtm
BUILD_DATE 20250416_043026

View File

@ -1307,6 +1307,7 @@ CIPHER *NewCipher(char *name)
EVP_CIPHER_CTX_init(c->Ctx);
#endif
c->IsAeadCipher = (EVP_CIPHER_flags(c->Cipher) & EVP_CIPH_FLAG_AEAD_CIPHER) != 0;
c->BlockSize = EVP_CIPHER_block_size(c->Cipher);
c->KeySize = EVP_CIPHER_key_length(c->Cipher);
c->IvSize = EVP_CIPHER_iv_length(c->Cipher);
@ -1371,6 +1372,74 @@ UINT CipherProcess(CIPHER *c, void *iv, void *dest, void *src, UINT size)
return r + r2;
}
// Process encryption / decryption (AEAD)
UINT CipherProcessAead(CIPHER *c, void *iv, void *tag, UINT tag_size, void *dest, void *src, UINT src_size, void *aad, UINT aad_size)
{
int r = src_size;
int r2 = 0;
// Validate arguments
if (c == NULL)
{
return 0;
}
else if (c->IsNullCipher)
{
Copy(dest, src, src_size);
return src_size;
}
else if (c->IsAeadCipher == false || iv == NULL || tag == NULL || tag_size == 0 || dest == NULL || src == NULL || src_size == 0)
{
return 0;
}
if (EVP_CipherInit_ex(c->Ctx, NULL, NULL, NULL, iv, c->Encrypt) == false)
{
Debug("CipherProcessAead(): EVP_CipherInit_ex() failed with error: %s\n", ERR_error_string(ERR_get_error(),NULL));
return 0;
}
if (c->Encrypt == false)
{
if (EVP_CIPHER_CTX_ctrl(c->Ctx, EVP_CTRL_AEAD_SET_TAG, tag_size, tag) == false)
{
Debug("CipherProcessAead(): EVP_CIPHER_CTX_ctrl() failed to set the tag!\n");
return 0;
}
}
if (aad != NULL && aad_size != 0)
{
if (EVP_CipherUpdate(c->Ctx, NULL, &r, aad, aad_size) == false)
{
Debug("CipherProcessAead(): EVP_CipherUpdate() failed with error: %s\n", ERR_error_string(ERR_get_error(),NULL));
return 0;
}
}
if (EVP_CipherUpdate(c->Ctx, dest, &r, src, src_size) == false)
{
Debug("CipherProcessAead(): EVP_CipherUpdate() failed with error: %s\n", ERR_error_string(ERR_get_error(),NULL));
return 0;
}
if (EVP_CipherFinal_ex(c->Ctx, ((UCHAR *)dest) + (UINT)r, &r2) == false)
{
Debug("CipherProcessAead(): EVP_CipherFinal_ex() failed with error: %s\n", ERR_error_string(ERR_get_error(),NULL));
return 0;
}
if (c->Encrypt)
{
if (EVP_CIPHER_CTX_ctrl(c->Ctx, EVP_CTRL_AEAD_GET_TAG, tag_size, tag) == false)
{
Debug("CipherProcessAead(): EVP_CIPHER_CTX_ctrl() failed to get the tag!\n");
return 0;
}
}
return r + r2;
}
// Release of the cipher object
void FreeCipher(CIPHER *c)
{

View File

@ -354,7 +354,7 @@ struct DH_CTX
struct CIPHER
{
char Name[MAX_PATH];
bool IsNullCipher;
bool IsNullCipher, IsAeadCipher;
const struct evp_cipher_st *Cipher;
struct evp_cipher_ctx_st *Ctx;
bool Encrypt;
@ -631,6 +631,7 @@ CIPHER *NewCipher(char *name);
void FreeCipher(CIPHER *c);
void SetCipherKey(CIPHER *c, void *key, bool enc);
UINT CipherProcess(CIPHER *c, void *iv, void *dest, void *src, UINT size);
UINT CipherProcessAead(CIPHER *c, void *iv, void *tag, UINT tag_size, void *dest, void *src, UINT src_size, void *aad, UINT aad_size);
MD *NewMd(char *name);
void FreeMd(MD *md);

View File

@ -3036,13 +3036,20 @@ UINT UniToInt(wchar_t *str)
void UniToStrForSingleChars(char *dst, UINT dst_size, wchar_t *src)
{
UINT i;
UINT size;
// Validate arguments
if (dst == NULL || src == NULL)
{
return;
}
for (i = 0;i < UniStrLen(src) + 1;i++)
size = UniStrLen(src) + 1;
if (dst_size >= 1 && dst_size < size)
{
size = dst_size;
}
for (i = 0;i < size;i++)
{
wchar_t s = src[i];
char d;
@ -3060,6 +3067,11 @@ void UniToStrForSingleChars(char *dst, UINT dst_size, wchar_t *src)
d = ' ';
}
if (i == (size - 1))
{
d = 0;
}
dst[i] = d;
}
}

View File

@ -83,9 +83,19 @@ $TAG_BEFORE_REMOTE$remote $TAG_HOSTNAME$ $TAG_PORT$
# cipher: [NULL-CIPHER] NULL AES-128-CBC AES-192-CBC AES-256-CBC BF-CBC
# CAST-CBC CAST5-CBC DES-CBC DES-EDE-CBC DES-EDE3-CBC DESX-CBC
# RC2-40-CBC RC2-64-CBC RC2-CBC CAMELLIA-128-CBC CAMELLIA-192-CBC CAMELLIA-256-CBC
# data-ciphers: same as cipher
# auth: SHA SHA1 SHA256 SHA384 SHA512 MD5 MD4 RMD160
#
# Note: To solve OpenVPN compatibility bug
# Recent versions of the OpenVPN app require specifying the "data-ciphers"
# field instead of the "cipher" field. However, older versions of the OpenVPN app
# do not recognize "data-ciphers." Rather than ignoring it, they produce
# a startup error stating that "no such option exists." This is a bug
# in OpenVPN. If you encounter this issue, please comment out
# the "data-ciphers" line.
cipher AES-128-CBC
data-ciphers AES-128-CBC
auth SHA1

View File

@ -730,7 +730,7 @@ POL_EX_18 对有此策略设置的会话,限制虚拟路由器上由内至
POL_19 拒绝更改密码
POL_EX_19 有此密码验证策略设置的用户将无法在 VPN Client 管理器上进行密码的更换。
POL_20 最大多重登录数
POL_EX_20 有此策略设置的用户无法进行多于设置数的并发登录数。 网桥模式会话不适用于此策略。此安全策略仅在 VPN Server 3.0 或以上版本,或具有多重登录限制功能的 VPN Server 2.0 版上有效。
POL_EX_20 有此策略设置的用户无法进行多于设置数的并发登录数。 此安全策略仅在 VPN Server 3.0 或以上版本,或具有多重登录限制功能的 VPN Server 2.0 版上有效。
POL_21 禁止 VoIP / QoS 功能
POL_EX_21 有此策略设置的用户,无法在 VPN 连接会话中使用VoIP / QoS功能。此安全策略仅在 VPN Server 3.0 或以上版本,或具有 VoIP / QoS 功能的 VPN Server 2.0 版上有效。

View File

@ -723,7 +723,7 @@ POL_EX_18 For sessions with this policy setting, this limits the traffic band
POL_19 Deny Changing Password
POL_EX_19 The users which use password authentication with this policy setting are not allowed to change their own password from the VPN Client Manager or similar.
POL_20 Maximum Number of Multiple Logins
POL_EX_20 Users with this policy setting are unable to have more than this number of concurrent logins. Bridge Mode sessions are not subjects to this policy. This security policy is only available on VPN Server 3.0 or greater, or VPN Server 2.0 with the multi-login restriction function.
POL_EX_20 Users with this policy setting are unable to have more than this number of concurrent logins. This security policy is only available on VPN Server 3.0 or greater, or VPN Server 2.0 with the multi-login restriction function.
POL_21 Deny VoIP / QoS Function
POL_EX_21 Users with this security policy are unable to use VoIP / QoS functions in VPN connection sessions. This security policy is only available on VPN Server 3.0 or greater, or VPN Server 2.0 with the VoIP / QoS functions.

View File

@ -726,7 +726,7 @@ POL_EX_18 このポリシーが設定されているセッションにおけ
POL_19 ユーザーはパスワードを変更できない
POL_EX_19 このポリシーが設定されているユーザーがパスワード認証の場合、ユーザーが VPN クライアント接続マネージャなどから自分のパスワードを変更することを禁止します。
POL_20 多重ログイン制限数
POL_EX_20 このポリシーが設定されているユーザーが設定されている数以上の同時ログインを行うことを禁止します。ブリッジモードセッションにはこの制限は適用されません。このセキュリティポリシーは、VPN Server 3.0 以降、または多重ログイン制限機能が搭載されている VPN Server 2.0 でのみ有効です。
POL_EX_20 このポリシーが設定されているユーザーが設定されている数以上の同時ログインを行うことを禁止します。このセキュリティポリシーは、VPN Server 3.0 以降、または多重ログイン制限機能が搭載されている VPN Server 2.0 でのみ有効です。
POL_21 VoIP / QoS 対応機能の使用を禁止
POL_EX_21 このポリシーが設定されているユーザーの VPN 接続セッションにおいて VoIP / QoS 対応機能の使用を禁止します。このセキュリティポリシーは、VPN Server 3.0 以降、または VoIP / QoS 対応機能が搭載されている VPN Server 2.0 でのみ有効です。

Binary file not shown.

Binary file not shown.

View File

@ -1,7 +1,7 @@
# SoftEther VPN Source Code
#
# Copyright (c) 2012-2023 SoftEther VPN Project at University of Tsukuba, Japan.
# Copyright (c) 2012-2023 Daiyuu Nobori.
# Copyright (c) 2012-2025 SoftEther VPN Project at University of Tsukuba, Japan.
# Copyright (c) 2012-2025 Daiyuu Nobori.
# All Rights Reserved.
#
# https://www.softether.org/

View File

@ -1,7 +1,7 @@
# SoftEther VPN Source Code
#
# Copyright (c) 2012-2023 SoftEther VPN Project at University of Tsukuba, Japan.
# Copyright (c) 2012-2023 Daiyuu Nobori.
# Copyright (c) 2012-2025 SoftEther VPN Project at University of Tsukuba, Japan.
# Copyright (c) 2012-2025 Daiyuu Nobori.
# All Rights Reserved.
#
# https://www.softether.org/

View File

@ -1,7 +1,7 @@
# SoftEther VPN Source Code
#
# Copyright (c) 2012-2023 SoftEther VPN Project at University of Tsukuba, Japan.
# Copyright (c) 2012-2023 Daiyuu Nobori.
# Copyright (c) 2012-2025 SoftEther VPN Project at University of Tsukuba, Japan.
# Copyright (c) 2012-2025 Daiyuu Nobori.
# All Rights Reserved.
#
# https://www.softether.org/

View File

@ -1,7 +1,7 @@
# SoftEther VPN Source Code
#
# Copyright (c) 2012-2023 SoftEther VPN Project at University of Tsukuba, Japan.
# Copyright (c) 2012-2023 Daiyuu Nobori.
# Copyright (c) 2012-2025 SoftEther VPN Project at University of Tsukuba, Japan.
# Copyright (c) 2012-2025 Daiyuu Nobori.
# All Rights Reserved.
#
# https://www.softether.org/

View File

@ -1,7 +1,7 @@
# SoftEther VPN Source Code
#
# Copyright (c) 2012-2023 SoftEther VPN Project at University of Tsukuba, Japan.
# Copyright (c) 2012-2023 Daiyuu Nobori.
# Copyright (c) 2012-2025 SoftEther VPN Project at University of Tsukuba, Japan.
# Copyright (c) 2012-2025 Daiyuu Nobori.
# All Rights Reserved.
#
# https://www.softether.org/

View File

@ -1,7 +1,7 @@
# SoftEther VPN Source Code
#
# Copyright (c) 2012-2023 SoftEther VPN Project at University of Tsukuba, Japan.
# Copyright (c) 2012-2023 Daiyuu Nobori.
# Copyright (c) 2012-2025 SoftEther VPN Project at University of Tsukuba, Japan.
# Copyright (c) 2012-2025 Daiyuu Nobori.
# All Rights Reserved.
#
# https://www.softether.org/

View File

@ -1,7 +1,7 @@
# SoftEther VPN Source Code
#
# Copyright (c) 2012-2023 SoftEther VPN Project at University of Tsukuba, Japan.
# Copyright (c) 2012-2023 Daiyuu Nobori.
# Copyright (c) 2012-2025 SoftEther VPN Project at University of Tsukuba, Japan.
# Copyright (c) 2012-2025 Daiyuu Nobori.
# All Rights Reserved.
#
# https://www.softether.org/

View File

@ -1,7 +1,7 @@
# SoftEther VPN Source Code
#
# Copyright (c) 2012-2023 SoftEther VPN Project at University of Tsukuba, Japan.
# Copyright (c) 2012-2023 Daiyuu Nobori.
# Copyright (c) 2012-2025 SoftEther VPN Project at University of Tsukuba, Japan.
# Copyright (c) 2012-2025 Daiyuu Nobori.
# All Rights Reserved.
#
# https://www.softether.org/

View File

@ -1,7 +1,7 @@
# SoftEther VPN Source Code
#
# Copyright (c) 2012-2023 SoftEther VPN Project at University of Tsukuba, Japan.
# Copyright (c) 2012-2023 Daiyuu Nobori.
# Copyright (c) 2012-2025 SoftEther VPN Project at University of Tsukuba, Japan.
# Copyright (c) 2012-2025 Daiyuu Nobori.
# All Rights Reserved.
#
# https://www.softether.org/

View File

@ -1,7 +1,7 @@
# SoftEther VPN Source Code
#
# Copyright (c) 2012-2023 SoftEther VPN Project at University of Tsukuba, Japan.
# Copyright (c) 2012-2023 Daiyuu Nobori.
# Copyright (c) 2012-2025 SoftEther VPN Project at University of Tsukuba, Japan.
# Copyright (c) 2012-2025 Daiyuu Nobori.
# All Rights Reserved.
#
# https://www.softether.org/

View File

@ -1,7 +1,7 @@
# SoftEther VPN Source Code
#
# Copyright (c) 2012-2023 SoftEther VPN Project at University of Tsukuba, Japan.
# Copyright (c) 2012-2023 Daiyuu Nobori.
# Copyright (c) 2012-2025 SoftEther VPN Project at University of Tsukuba, Japan.
# Copyright (c) 2012-2025 Daiyuu Nobori.
# All Rights Reserved.
#
# https://www.softether.org/

View File

@ -1,7 +1,7 @@
# SoftEther VPN Source Code
#
# Copyright (c) 2012-2023 SoftEther VPN Project at University of Tsukuba, Japan.
# Copyright (c) 2012-2023 Daiyuu Nobori.
# Copyright (c) 2012-2025 SoftEther VPN Project at University of Tsukuba, Japan.
# Copyright (c) 2012-2025 Daiyuu Nobori.
# All Rights Reserved.
#
# https://www.softether.org/

View File

@ -1,7 +1,7 @@
# SoftEther VPN Source Code
#
# Copyright (c) 2012-2023 SoftEther VPN Project at University of Tsukuba, Japan.
# Copyright (c) 2012-2023 Daiyuu Nobori.
# Copyright (c) 2012-2025 SoftEther VPN Project at University of Tsukuba, Japan.
# Copyright (c) 2012-2025 Daiyuu Nobori.
# All Rights Reserved.
#
# https://www.softether.org/

View File

@ -1,7 +1,7 @@
# SoftEther VPN Source Code
#
# Copyright (c) 2012-2023 SoftEther VPN Project at University of Tsukuba, Japan.
# Copyright (c) 2012-2023 Daiyuu Nobori.
# Copyright (c) 2012-2025 SoftEther VPN Project at University of Tsukuba, Japan.
# Copyright (c) 2012-2025 Daiyuu Nobori.
# All Rights Reserved.
#
# https://www.softether.org/

View File

@ -1,7 +1,7 @@
# SoftEther VPN Source Code
#
# Copyright (c) 2012-2023 SoftEther VPN Project at University of Tsukuba, Japan.
# Copyright (c) 2012-2023 Daiyuu Nobori.
# Copyright (c) 2012-2025 SoftEther VPN Project at University of Tsukuba, Japan.
# Copyright (c) 2012-2025 Daiyuu Nobori.
# All Rights Reserved.
#
# https://www.softether.org/

View File

@ -1,7 +1,7 @@
# SoftEther VPN Source Code
#
# Copyright (c) 2012-2023 SoftEther VPN Project at University of Tsukuba, Japan.
# Copyright (c) 2012-2023 Daiyuu Nobori.
# Copyright (c) 2012-2025 SoftEther VPN Project at University of Tsukuba, Japan.
# Copyright (c) 2012-2025 Daiyuu Nobori.
# All Rights Reserved.
#
# https://www.softether.org/

View File

@ -1,7 +1,7 @@
# SoftEther VPN Source Code
#
# Copyright (c) 2012-2023 SoftEther VPN Project at University of Tsukuba, Japan.
# Copyright (c) 2012-2023 Daiyuu Nobori.
# Copyright (c) 2012-2025 SoftEther VPN Project at University of Tsukuba, Japan.
# Copyright (c) 2012-2025 Daiyuu Nobori.
# All Rights Reserved.
#
# https://www.softether.org/

View File

@ -1,7 +1,7 @@
# SoftEther VPN Source Code
#
# Copyright (c) 2012-2023 SoftEther VPN Project at University of Tsukuba, Japan.
# Copyright (c) 2012-2023 Daiyuu Nobori.
# Copyright (c) 2012-2025 SoftEther VPN Project at University of Tsukuba, Japan.
# Copyright (c) 2012-2025 Daiyuu Nobori.
# All Rights Reserved.
#
# https://www.softether.org/

View File

@ -1,7 +1,7 @@
# SoftEther VPN Source Code
#
# Copyright (c) 2012-2023 SoftEther VPN Project at University of Tsukuba, Japan.
# Copyright (c) 2012-2023 Daiyuu Nobori.
# Copyright (c) 2012-2025 SoftEther VPN Project at University of Tsukuba, Japan.
# Copyright (c) 2012-2025 Daiyuu Nobori.
# All Rights Reserved.
#
# https://www.softether.org/

View File

@ -1,7 +1,7 @@
# SoftEther VPN Source Code
#
# Copyright (c) 2012-2023 SoftEther VPN Project at University of Tsukuba, Japan.
# Copyright (c) 2012-2023 Daiyuu Nobori.
# Copyright (c) 2012-2025 SoftEther VPN Project at University of Tsukuba, Japan.
# Copyright (c) 2012-2025 Daiyuu Nobori.
# All Rights Reserved.
#
# https://www.softether.org/

View File

@ -4,7 +4,7 @@
/* File created by MIDL compiler version 7.00.0500 */
/* at Thu Aug 31 10:30:18 2023
/* at Wed Apr 16 04:30:42 2025
*/
/* Compiler settings for .\vpnweb.idl:
Oicf, W1, Zp8, env=Win32 (32b run)

View File

@ -6,7 +6,7 @@
/* File created by MIDL compiler version 7.00.0500 */
/* at Thu Aug 31 10:30:18 2023
/* at Wed Apr 16 04:30:42 2025
*/
/* Compiler settings for .\vpnweb.idl:
Oicf, W1, Zp8, env=Win32 (32b run)

View File

@ -4,7 +4,7 @@
/* File created by MIDL compiler version 7.00.0500 */
/* at Thu Aug 31 10:30:18 2023
/* at Wed Apr 16 04:30:42 2025
*/
/* Compiler settings for .\vpnweb.idl:
Oicf, W1, Zp8, env=Win32 (32b run)