Browse Source

v4.44-9807-rtm

dnobori 6 months ago
parent
commit
ed17437af9
45 changed files with 546 additions and 204 deletions
  1. 0 1
      src/Cedar/Admin.c
  2. 7 7
      src/Cedar/Cedar.h
  3. 10 7
      src/Cedar/Command.c
  4. 9 1
      src/Cedar/Hub.c
  5. 1 0
      src/Cedar/Hub.h
  6. 9 30
      src/Cedar/IPsec_IKE.c
  7. 166 93
      src/Cedar/Interop_OpenVPN.c
  8. 4 7
      src/Cedar/Interop_OpenVPN.h
  9. 191 4
      src/Cedar/Radius.c
  10. 2 1
      src/Cedar/Radius.h
  11. 1 1
      src/Cedar/Sam.c
  12. 2 0
      src/Cedar/Server.c
  13. 4 4
      src/CurrentBuild.txt
  14. 69 0
      src/Mayaqua/Encrypt.c
  15. 2 1
      src/Mayaqua/Encrypt.h
  16. 13 1
      src/Mayaqua/Internat.c
  17. 10 0
      src/bin/hamcore/openvpn_sample.ovpn
  18. 1 1
      src/bin/hamcore/strtable_cn.stb
  19. 1 1
      src/bin/hamcore/strtable_en.stb
  20. 1 1
      src/bin/hamcore/strtable_ja.stb
  21. BIN
      src/bin/vpnweb.cab
  22. BIN
      src/bin/vpnweb.ocx
  23. 2 2
      src/makefiles/freebsd_32bit.mak
  24. 2 2
      src/makefiles/freebsd_32bit_nobits.mak
  25. 2 2
      src/makefiles/freebsd_64bit.mak
  26. 2 2
      src/makefiles/freebsd_64bit_nobits.mak
  27. 2 2
      src/makefiles/linux_32bit.mak
  28. 2 2
      src/makefiles/linux_32bit_nobits.mak
  29. 2 2
      src/makefiles/linux_64bit.mak
  30. 2 2
      src/makefiles/linux_64bit_nobits.mak
  31. 2 2
      src/makefiles/macos_32bit.mak
  32. 2 2
      src/makefiles/macos_32bit_nobits.mak
  33. 2 2
      src/makefiles/macos_64bit.mak
  34. 2 2
      src/makefiles/macos_64bit_nobits.mak
  35. 2 2
      src/makefiles/openbsd_32bit.mak
  36. 2 2
      src/makefiles/openbsd_32bit_nobits.mak
  37. 2 2
      src/makefiles/openbsd_64bit.mak
  38. 2 2
      src/makefiles/openbsd_64bit_nobits.mak
  39. 2 2
      src/makefiles/solaris_32bit.mak
  40. 2 2
      src/makefiles/solaris_32bit_nobits.mak
  41. 2 2
      src/makefiles/solaris_64bit.mak
  42. 2 2
      src/makefiles/solaris_64bit_nobits.mak
  43. 1 1
      src/vpnweb/vpnweb.h
  44. 1 1
      src/vpnweb/vpnweb_i.c
  45. 1 1
      src/vpnweb/vpnweb_p.c

+ 0 - 1
src/Cedar/Admin.c

@@ -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)

+ 7 - 7
src/Cedar/Cedar.h

@@ -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)

+ 10 - 7
src/Cedar/Command.c

@@ -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)
 			{

+ 9 - 1
src/Cedar/Hub.c

@@ -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))
 	{

+ 1 - 0
src/Cedar/Hub.h

@@ -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

+ 9 - 30
src/Cedar/IPsec_IKE.c

@@ -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;
 	}
 

+ 166 - 93
src/Cedar/Interop_OpenVPN.c

@@ -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)
-						{
-							// 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))
-							{
-								UINT data_packet_id;
-
-								// Decryption
-								size = CipherProcess(c->CipherDecrypt, iv, s->TmpBuf, data, size);
+						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);
+					}
 
-								data = s->TmpBuf;
+					// Update of last communication time
+					se->LastCommTick = s->Now;
 
-								if (size >= sizeof(UINT))
-								{
-									data_packet_id = READ_UINT(data);
+					if (size < sizeof(UINT)){
+						goto decode_error;
+					}
 
-									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;
+					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)
+						{
+							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;
+
+		// Update variable part (packet ID) of IV
+		WRITE_UINT(c->IvSend, data_packet_id);
+
+		// Prepare a buffer to store the results
+		dest_data = Malloc(sizeof(op) + sizeof(data_packet_id) + sizeof(tag) + data_size + 256);
 
-	encrypted_size = sizeof(UINT) + data_size;
-	encrypted_data = ZeroMalloc(encrypted_size);
+		// Set data size to the maximum known
+		dest_size = sizeof(op) + sizeof(data_packet_id) + sizeof(tag);
 
-	WRITE_UINT(encrypted_data, data_packet_id);
-	Copy(encrypted_data + sizeof(UINT), data, data_size);
+		// Write opcode
+		dest_data[0] = op;
 
-	// Prepare a buffer to store the results
-	dest_data = Malloc(sizeof(UCHAR) + c->MdSend->Size + c->CipherEncrypt->IvSize + encrypted_size + 256);
+		// Write packet ID
+		WRITE_UINT(dest_data + sizeof(op), data_packet_id);
 
-	// 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 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;
 
-	// Copy the IV
-	Copy(dest_data + sizeof(UCHAR) + c->MdSend->Size, c->NextIv, 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);
 
-	// Calculate the HMAC
-	MdProcess(c->MdSend, dest_data + sizeof(UCHAR), dest_data + sizeof(UCHAR) + c->MdSend->Size,
-		dest_size - sizeof(UCHAR) - c->MdSend->Size);
+		// 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;
 
-	// Update the NextIV
-	Copy(c->NextIv, dest_data + dest_size - c->CipherEncrypt->IvSize, c->CipherEncrypt->IvSize);
+		// Encrypt
+		r = CipherProcess(c->CipherEncrypt, c->IvSend, dest_data + sizeof(op) + c->MdSend->Size + c->CipherEncrypt->IvSize,
+			encrypted_data, encrypted_size);
+		Free(encrypted_data);
 
-	// Op-code
-	dest_data[0] = uc;
+		dest_size = sizeof(op) + c->MdSend->Size + c->CipherEncrypt->IvSize + r;
 
-	OvsSendPacketRawNow(c->Server, c->Session, dest_data, dest_size);
+		// 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);
 
-	Free(encrypted_data);
+		// 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);
 }
 
 // Build an OpenVPN control packet

+ 4 - 7
src/Cedar/Interop_OpenVPN.h

@@ -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

+ 191 - 4
src/Cedar/Radius.c

@@ -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)
 {

+ 2 - 1
src/Cedar/Radius.h

@@ -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
 

+ 1 - 1
src/Cedar/Sam.c

@@ -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)
 					{

+ 2 - 0
src/Cedar/Server.c

@@ -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)
 			{

+ 4 - 4
src/CurrentBuild.txt

@@ -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

+ 69 - 0
src/Mayaqua/Encrypt.c

@@ -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)
 {

+ 2 - 1
src/Mayaqua/Encrypt.h

@@ -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);

+ 13 - 1
src/Mayaqua/Internat.c

@@ -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;
 	}
 }

+ 10 - 0
src/bin/hamcore/openvpn_sample.ovpn

@@ -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
 
 

+ 1 - 1
src/bin/hamcore/strtable_cn.stb

@@ -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 版上有效。
 

+ 1 - 1
src/bin/hamcore/strtable_en.stb

@@ -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.
 

+ 1 - 1
src/bin/hamcore/strtable_ja.stb

@@ -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 でのみ有効です。
 

BIN
src/bin/vpnweb.cab


BIN
src/bin/vpnweb.ocx


+ 2 - 2
src/makefiles/freebsd_32bit.mak

@@ -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/

+ 2 - 2
src/makefiles/freebsd_32bit_nobits.mak

@@ -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/

+ 2 - 2
src/makefiles/freebsd_64bit.mak

@@ -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/

+ 2 - 2
src/makefiles/freebsd_64bit_nobits.mak

@@ -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/

+ 2 - 2
src/makefiles/linux_32bit.mak

@@ -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/

+ 2 - 2
src/makefiles/linux_32bit_nobits.mak

@@ -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/

+ 2 - 2
src/makefiles/linux_64bit.mak

@@ -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/

+ 2 - 2
src/makefiles/linux_64bit_nobits.mak

@@ -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/

+ 2 - 2
src/makefiles/macos_32bit.mak

@@ -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/

+ 2 - 2
src/makefiles/macos_32bit_nobits.mak

@@ -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/

+ 2 - 2
src/makefiles/macos_64bit.mak

@@ -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/

+ 2 - 2
src/makefiles/macos_64bit_nobits.mak

@@ -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/

+ 2 - 2
src/makefiles/openbsd_32bit.mak

@@ -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/

+ 2 - 2
src/makefiles/openbsd_32bit_nobits.mak

@@ -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/

+ 2 - 2
src/makefiles/openbsd_64bit.mak

@@ -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/

+ 2 - 2
src/makefiles/openbsd_64bit_nobits.mak

@@ -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/

+ 2 - 2
src/makefiles/solaris_32bit.mak

@@ -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/

+ 2 - 2
src/makefiles/solaris_32bit_nobits.mak

@@ -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/

+ 2 - 2
src/makefiles/solaris_64bit.mak

@@ -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/

+ 2 - 2
src/makefiles/solaris_64bit_nobits.mak

@@ -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/

+ 1 - 1
src/vpnweb/vpnweb.h

@@ -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)

+ 1 - 1
src/vpnweb/vpnweb_i.c

@@ -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)

+ 1 - 1
src/vpnweb/vpnweb_p.c

@@ -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)